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