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