uboot/drivers/cache/cache-ncore.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2019 Intel Corporation <www.intel.com>
   4 *
   5 */
   6#include <dm.h>
   7#include <hang.h>
   8#include <wait_bit.h>
   9
  10#include <asm/io.h>
  11#include <linux/bitops.h>
  12
  13/* Directory */
  14#define DIRUSFER                0x80010
  15#define DIRUCASER0              0x80040
  16#define DIRUSFMCR               0x80080
  17#define DIRUSFMAR               0x80084
  18
  19#define DIRUSFMCR_SFID_SHIFT    16
  20
  21/* Coherent cache agent interface */
  22#define CAIUIDR                 0x00ffc
  23
  24#define CAIUIDR_CA_GET(v)       (((v) & 0x00008000) >> 15)
  25#define CAIUIDR_TYPE_GET(v)     (((v) & 0x000f0000) >> 16)
  26#define CAIUIDR_TYPE_ACE_CAI_DVM_SUPPORT        0
  27#define CAIUIDR_TYPE_ACELITE_CAI_DVM_SUPPORT    1
  28
  29/* Coherent subsystem */
  30#define CSADSER0                0xff040
  31#define CSUIDR                  0xffff8
  32#define CSIDR                   0xffffc
  33
  34#define CSUIDR_NUMCAIUS_GET(v)  (((v) & 0x0000007f) >> 0)
  35#define CSUIDR_NUMDIRUS_GET(v)  (((v) & 0x003f0000) >> 16)
  36#define CSUIDR_NUMCMIUS_GET(v)  (((v) & 0x3f000000) >> 24)
  37
  38#define CSIDR_NUMSFS_GET(v)     (((v) & 0x007c0000) >> 18)
  39
  40#define DIR_REG_SZ              0x1000
  41#define CAIU_REG_SZ             0x1000
  42
  43#define CCU_DIR_REG_ADDR(base, reg, dir)        \
  44                ((base) + (reg) + ((dir) * DIR_REG_SZ))
  45
  46/* OCRAM firewall register */
  47#define OCRAM_FW_01                     0x100204
  48#define OCRAM_SECURE_REGIONS            4
  49
  50#define OCRAM_PRIVILEGED_MASK           BIT(29)
  51#define OCRAM_SECURE_MASK               BIT(30)
  52
  53static void ncore_ccu_init_dirs(void __iomem *base)
  54{
  55        ulong i, f;
  56        int ret;
  57        u32 num_of_dirs;
  58        u32 num_of_snoop_filters;
  59        u32 reg;
  60
  61        num_of_dirs = CSUIDR_NUMDIRUS_GET(readl(base + CSUIDR));
  62        num_of_snoop_filters =
  63                CSIDR_NUMSFS_GET(readl(base + CSIDR)) + 1;
  64
  65        /* Initialize each snoop filter in each directory */
  66        for (f = 0; f < num_of_snoop_filters; f++) {
  67                reg = f << DIRUSFMCR_SFID_SHIFT;
  68                for (i = 0; i < num_of_dirs; i++) {
  69                        /* Initialize all entries */
  70                        writel(reg, CCU_DIR_REG_ADDR(base, DIRUSFMCR, i));
  71
  72                        /* Poll snoop filter maintenance operation active
  73                         * bit become 0.
  74                         */
  75                        ret = wait_for_bit_le32((const void *)
  76                                                CCU_DIR_REG_ADDR(base,
  77                                                                 DIRUSFMAR, i),
  78                                                BIT(0), false, 1000, false);
  79                        if (ret) {
  80                                puts("CCU: Directory initialization failed!\n");
  81                                hang();
  82                        }
  83
  84                        /* Enable snoop filter, a bit per snoop filter */
  85                        setbits_le32((ulong)CCU_DIR_REG_ADDR(base, DIRUSFER, i),
  86                                     BIT(f));
  87                }
  88        }
  89}
  90
  91static void ncore_ccu_init_coh_agent(void __iomem *base)
  92{
  93        u32 num_of_coh_agent_intf;
  94        u32 num_of_dirs;
  95        u32 reg;
  96        u32 type;
  97        u32 i, dir;
  98
  99        num_of_coh_agent_intf =
 100                CSUIDR_NUMCAIUS_GET(readl(base + CSUIDR));
 101        num_of_dirs = CSUIDR_NUMDIRUS_GET(readl(base + CSUIDR));
 102
 103        for (i = 0; i < num_of_coh_agent_intf; i++) {
 104                reg = readl(base + CAIUIDR + (i * CAIU_REG_SZ));
 105                if (CAIUIDR_CA_GET(reg)) {
 106                        /* Caching agent bit is enabled, enable caching agent
 107                         * snoop in each directory
 108                         */
 109                        for (dir = 0; dir < num_of_dirs; dir++) {
 110                                setbits_le32((ulong)
 111                                             CCU_DIR_REG_ADDR(base, DIRUCASER0,
 112                                                              dir),
 113                                             BIT(i));
 114                        }
 115                }
 116
 117                type = CAIUIDR_TYPE_GET(reg);
 118                if (type == CAIUIDR_TYPE_ACE_CAI_DVM_SUPPORT ||
 119                    type == CAIUIDR_TYPE_ACELITE_CAI_DVM_SUPPORT) {
 120                        /* DVM support is enabled, enable ACE DVM snoop*/
 121                        setbits_le32((ulong)(base + CSADSER0),
 122                                     BIT(i));
 123                }
 124        }
 125}
 126
 127static void ocram_bypass_firewall(void __iomem *base)
 128{
 129        int i;
 130
 131        for (i = 0; i < OCRAM_SECURE_REGIONS; i++) {
 132                clrbits_le32(base + OCRAM_FW_01 + (i * sizeof(u32)),
 133                             OCRAM_PRIVILEGED_MASK | OCRAM_SECURE_MASK);
 134        }
 135}
 136
 137static int ncore_ccu_probe(struct udevice *dev)
 138{
 139        void __iomem *base;
 140        fdt_addr_t addr;
 141
 142        addr = dev_read_addr(dev);
 143        if (addr == FDT_ADDR_T_NONE)
 144                return -EINVAL;
 145
 146        base = (void __iomem *)addr;
 147
 148        ncore_ccu_init_dirs(base);
 149        ncore_ccu_init_coh_agent(base);
 150        ocram_bypass_firewall(base);
 151
 152        return 0;
 153}
 154
 155static const struct udevice_id ncore_ccu_ids[] = {
 156        { .compatible = "arteris,ncore-ccu" },
 157        {}
 158};
 159
 160U_BOOT_DRIVER(ncore_ccu) = {
 161        .name   = "ncore_ccu",
 162        .id     = UCLASS_CACHE,
 163        .of_match = ncore_ccu_ids,
 164        .probe  = ncore_ccu_probe,
 165        .flags  = DM_FLAG_PRE_RELOC,
 166};
 167