"Das U-Boot" Source Tree
at master 166 lines 3.9 kB view raw
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Copyright (C) 2019-2022 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 /* Disable snoop filter, a bit per snoop filter */ 85 clrbits_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};