blob: 42c13380a299ebe296b5b45b2b77caf9aa18a13e [file] [log] [blame]
Caleb Connolly14b8ab22023-09-12 23:38:58 +01001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (C) 2023 Linaro Ltd.
4 * Basic ARM SMMU-500 driver, assuming a pre-initialised SMMU and only IDENTITY domains
5 * this driver only implements the bare minimum to configure stream mappings for periphals
6 * used by u-boot on platforms where the SMMU can't be disabled.
7 */
8
9#include <common.h>
10#include <log.h>
11#include <cpu_func.h>
12#include <dm.h>
13#include <iommu.h>
14#include <linux/bitfield.h>
15#include <linux/list.h>
16#include <linux/err.h>
17#include <lmb.h>
18#include <memalign.h>
19#include <asm/io.h>
20
21#define ARM_SMMU_GR0 0
22#define ARM_SMMU_GR1 1
23
24#define ARM_SMMU_GR0_ID0 0x20
25#define ARM_SMMU_ID0_NUMSMRG GENMASK(7, 0) /* Number of stream mapping groups */
26#define ARM_SMMU_GR0_ID1 0x24
27#define ARM_SMMU_ID1_PAGESIZE BIT(31) /* Page shift is 16 bits when set, otherwise 23 */
28#define ARM_SMMU_ID1_NUMPAGENDXB GENMASK(30, 28) /* Number of pages before context banks */
29#define ARM_SMMU_ID1_NUMCB GENMASK(7, 0) /* Number of context banks supported */
30
31#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
32#define ARM_SMMU_CBAR_TYPE GENMASK(17, 16)
33#define ARM_SMMU_CBAR_VMID GENMASK(7, 0)
34enum arm_smmu_cbar_type {
35 CBAR_TYPE_S2_TRANS,
36 CBAR_TYPE_S1_TRANS_S2_BYPASS,
37 CBAR_TYPE_S1_TRANS_S2_FAULT,
38 CBAR_TYPE_S1_TRANS_S2_TRANS,
39};
40
41#define ARM_SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2))
42#define ARM_SMMU_CBA2R_VA64 BIT(0)
43
44/* Per-CB system control register */
45#define ARM_SMMU_CB_SCTLR 0x0
46#define ARM_SMMU_SCTLR_CFCFG BIT(7) /* Stall on context fault */
47#define ARM_SMMU_SCTLR_CFIE BIT(6) /* Context fault interrupt enable */
48#define ARM_SMMU_SCTLR_CFRE BIT(5) /* Abort on context fault */
49
50/* Translation Table Base, holds address of translation table in memory to be used
51 * for this context bank. Or 0 for bypass
52 */
53#define ARM_SMMU_CB_TTBR0 0x20
54#define ARM_SMMU_CB_TTBR1 0x28
55/* Translation Control Register, configured TTBR/TLB behaviour (0 for bypass) */
56#define ARM_SMMU_CB_TCR 0x30
57/* Memory Attribute Indirection, also 0 for bypass */
58#define ARM_SMMU_CB_S1_MAIR0 0x38
59#define ARM_SMMU_CB_S1_MAIR1 0x3c
60
61#define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2))
62#define ARM_SMMU_SMR_VALID BIT(31)
63#define ARM_SMMU_SMR_MASK GENMASK(31, 16) // Always 0 for now??
64#define ARM_SMMU_SMR_ID GENMASK(15, 0)
65
66#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2))
67#define ARM_SMMU_S2CR_PRIVCFG GENMASK(25, 24)
68enum arm_smmu_s2cr_privcfg {
69 S2CR_PRIVCFG_DEFAULT,
70 S2CR_PRIVCFG_DIPAN,
71 S2CR_PRIVCFG_UNPRIV,
72 S2CR_PRIVCFG_PRIV,
73};
74#define ARM_SMMU_S2CR_TYPE GENMASK(17, 16)
75enum arm_smmu_s2cr_type {
76 S2CR_TYPE_TRANS,
77 S2CR_TYPE_BYPASS,
78 S2CR_TYPE_FAULT,
79};
80#define ARM_SMMU_S2CR_EXIDVALID BIT(10)
81#define ARM_SMMU_S2CR_CBNDX GENMASK(7, 0)
82
83#define VMID_UNUSED 0xff
84
85
86struct arm_smmu_priv {
87 phys_addr_t base;
88 struct list_head devices;
89 struct udevice *dev;
90
91 /* Read-once config */
92 int num_cb;
93 int num_smr;
94 uint32_t pgshift;
95 uint32_t cb_pg_offset;
96};
97
98struct mmu_dev {
99 struct list_head li;
100 struct udevice *dev;
101 uint16_t sid;
102 uint16_t cbx;
103 uint16_t smr;
104};
105
106
107#define page_addr(priv, page) \
108 ((priv)->base + ((page) << (priv)->pgshift))
109
110#define smmu_readl(priv, page, offset) \
111 readl(page_addr(priv, page) + offset)
112#define gr0_readl(priv, offset) smmu_readl(priv, ARM_SMMU_GR0, offset)
113#define gr1_readl(priv, offset) smmu_readl(priv, ARM_SMMU_GR1, offset)
114#define cbx_readl(priv, cbx, offset) \
115 smmu_readl(priv, (priv->cb_pg_offset) + cbx, offset)
116
117#define smmu_writel(priv, page, offset, value) \
118 writel((value), page_addr(priv, page) + offset)
119#define gr0_writel(priv, offset, value) \
120 smmu_writel(priv, ARM_SMMU_GR0, offset, (value))
121#define gr1_writel(priv, offset, value) \
122 smmu_writel(priv, ARM_SMMU_GR1, offset, (value))
123#define cbx_writel(priv, cbx, offset, value) \
124 smmu_writel(priv, (priv->cb_pg_offset) + cbx, offset, value)
125
126#define gr1_setbits(priv, offset, value) \
127 gr1_writel(priv, offset, gr1_readl(priv, offset) | (value))
128
129
130static int get_stream_id(struct udevice *dev)
131{
132 ofnode node = dev_ofnode(dev);
133 struct ofnode_phandle_args args;
134 int count = ofnode_parse_phandle_with_args(node, "iommus",
135 "#iommu-cells", 0, 0, &args);
136
137 if (count < 0 || args.args[0] == 0) {
138 printf("Error: %s: iommus property not found or wrong number of cells\n",
139 __func__);
140 return -EINVAL;
141 }
142
143 return args.args[0]; // Some mask from bit 16 onward?
144}
145
146static struct mmu_dev *alloc_dev(struct udevice *dev)
147{
148 struct arm_smmu_priv *priv = dev_get_priv(dev->iommu);
149 struct mmu_dev *mmu_dev;
150 int sid;
151
152 sid = get_stream_id(dev);
153 debug("%s %s has SID %#x\n", dev->iommu->name, dev->name, sid);
154 if (sid < 0 || sid > 0xffff) {
155 printf("\tSMMU: Invalid stream ID for %s\n", dev->name);
156 return ERR_PTR(-EINVAL);
157 }
158
159 /* We only support a single SID per device for now */
160 list_for_each_entry(mmu_dev, &priv->devices, li) {
161 if (mmu_dev->sid == sid)
162 return ERR_PTR(-EEXIST);
163 }
164
165 mmu_dev = calloc(sizeof(*mmu_dev), 1);
166 if (!mmu_dev)
167 return ERR_PTR(-ENOMEM);
168
169 mmu_dev->dev = dev;
170
171 mmu_dev->sid = sid;
172
173 list_add_tail(&mmu_dev->li, &priv->devices);
174
175 return mmu_dev;
176}
177
178/* Find and init the first free context bank */
179static int alloc_cb(struct arm_smmu_priv *priv)
180{
181 uint32_t cbar, type, vmid, val;
182
183 for (int i = 0; i < priv->num_cb; i++) {
184 cbar = gr1_readl(priv, ARM_SMMU_GR1_CBAR(i));
185 type = FIELD_GET(ARM_SMMU_CBAR_TYPE, cbar);
186 vmid = FIELD_GET(ARM_SMMU_CBAR_VMID, cbar);
187
188 /* Check that the context bank is available. We haven't reset the SMMU so
189 * we just make a best guess.
190 */
191 if (type != CBAR_TYPE_S2_TRANS &&
192 (type != CBAR_TYPE_S1_TRANS_S2_BYPASS ||
193 vmid != VMID_UNUSED))
194 continue;
195
196 debug("%s: Found free context bank %d (cbar %#x)\n", priv->dev->name, i, cbar);
197 type = CBAR_TYPE_S1_TRANS_S2_BYPASS;
198 vmid = 0;
199 cbar &= ~ARM_SMMU_CBAR_TYPE & ~ARM_SMMU_CBAR_VMID;
200 cbar |= FIELD_PREP(ARM_SMMU_CBAR_TYPE, type) |
201 FIELD_PREP(ARM_SMMU_CBAR_VMID, vmid);
202 gr1_writel(priv, ARM_SMMU_GR1_CBAR(i), cbar);
203
204 val = IS_ENABLED(CONFIG_ARM64) == 1 ? ARM_SMMU_CBA2R_VA64 : 0;
205 gr1_setbits(priv, ARM_SMMU_GR1_CBA2R(i), val);
206 return i;
207 }
208
209 return -1;
210}
211
212/* Search for a context bank that is already configured for this stream
213 * returns the context bank index or -ENOENT
214 */
215static int find_smr(struct arm_smmu_priv *priv, uint16_t stream_id)
216{
217 uint32_t val;
218 int i;
219
220 for (i = 0; i < priv->num_smr; i++) {
221 val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i));
222 if (!(val & ARM_SMMU_SMR_VALID) ||
223 FIELD_GET(ARM_SMMU_SMR_ID, val) != stream_id)
224 continue;
225
226 return i;
227 }
228
229 return -ENOENT;
230}
231
232static int configure_smr_s2cr(struct arm_smmu_priv *priv, struct mmu_dev *mdev)
233{
234 uint32_t val;
235 int i;
236
237 for (i = 0; i < priv->num_smr; i++) {
238 /* Configure SMR */
239 val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i));
240 if (val & ARM_SMMU_SMR_VALID)
241 continue;
242
243 val = mdev->sid | ARM_SMMU_SMR_VALID;
244 gr0_writel(priv, ARM_SMMU_GR0_SMR(i), val);
245
246 /*
247 * WARNING: Don't change this to use S2CR_TYPE_BYPASS!
248 * Some Qualcomm boards have angry hypervisor firmware
249 * that converts S2CR type BYPASS to type FAULT on write.
250 * We don't use virtual addressing for these boards in
251 * u-boot so we can get away with using S2CR_TYPE_TRANS
252 * instead
253 */
254 val = FIELD_PREP(ARM_SMMU_S2CR_TYPE, S2CR_TYPE_TRANS) |
255 FIELD_PREP(ARM_SMMU_S2CR_CBNDX, mdev->cbx);
256 gr0_writel(priv, ARM_SMMU_GR0_S2CR(i), val);
257
258 mdev->smr = i;
259 break;
260 }
261
262 return 0;
263}
264
265static int arm_smmu_connect(struct udevice *dev)
266{
267 struct mmu_dev *mdev;
268 struct arm_smmu_priv *priv;
269 int ret;
270
271 debug("%s: %s -> %s\n", __func__, dev->name, dev->iommu->name);
272
273 priv = dev_get_priv(dev->iommu);
274 BUG_ON(!priv);
275
276 mdev = alloc_dev(dev);
277 if (IS_ERR(mdev) && PTR_ERR(mdev) != -EEXIST) {
278 printf("%s: %s Couldn't create mmu context\n", __func__, dev->name);
279 return PTR_ERR(mdev);
280 } else if (IS_ERR(mdev)) { // -EEXIST
281 return 0;
282 }
283
284 if (find_smr(priv, mdev->sid) >= 0) {
285 debug("Found existing context bank for %s, skipping init\n", dev->name);
286 return 0;
287 }
288
289 ret = alloc_cb(priv);
290 if (ret < 0 || ret > 0xff) {
291 printf("Error: %s: failed to allocate context bank for %s\n",
292 __func__, dev->name);
293 return 0;
294 }
295 mdev->cbx = ret;
296
297 /* Configure context bank registers */
298 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TTBR0, 0x0);
299 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TTBR1, 0x0);
300 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_S1_MAIR0, 0x0);
301 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_S1_MAIR1, 0x0);
302 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_SCTLR, ARM_SMMU_SCTLR_CFIE |
303 ARM_SMMU_SCTLR_CFRE |
304 ARM_SMMU_SCTLR_CFCFG);
305 cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TCR, 0x0);
306
307 mb();
308
309 configure_smr_s2cr(priv, mdev);
310
311 mb();
312
313 return 0;
314}
315
316#ifdef DEBUG
317static inline void dump_boot_mappings(struct arm_smmu_priv *priv)
318{
319 uint32_t val;
320 int i;
321
322 debug(" SMMU dump boot mappings:\n");
323 for (i = 0; i < priv->num_smr; i++) {
324 val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i));
325 if (val & ARM_SMMU_SMR_VALID)
326 debug("\tSMR %3d: SID: %#lx\n", i, FIELD_GET(ARM_SMMU_SMR_ID, val));
327 }
328}
329#else
330#define dump_boot_mappings(priv) do {} while (0)
331#endif
332
333static int arm_smmu_probe(struct udevice *dev)
334{
335 struct arm_smmu_priv *priv;
336 uint32_t val;
337
338 priv = dev_get_priv(dev);
339 priv->dev = dev;
340 priv->base = dev_read_addr(dev);
341 INIT_LIST_HEAD(&priv->devices);
342
343 /* Read SMMU config */
344 val = gr0_readl(priv, ARM_SMMU_GR0_ID0);
345 priv->num_smr = FIELD_GET(ARM_SMMU_ID0_NUMSMRG, val);
346
347 val = gr0_readl(priv, ARM_SMMU_GR0_ID1);
348 priv->num_cb = FIELD_GET(ARM_SMMU_ID1_NUMCB, val);
349 priv->pgshift = FIELD_GET(ARM_SMMU_ID1_PAGESIZE, val) ? 16 : 12;
350 priv->cb_pg_offset = 1 << (FIELD_GET(ARM_SMMU_ID1_NUMPAGENDXB, val) + 1);
351
352 dump_boot_mappings(priv);
353
354 return 0;
355}
356
357static int arm_smmu_remove(struct udevice *dev)
358{
359 struct mmu_dev *mdev;
360 struct arm_smmu_priv *priv;
361 uint32_t cbar;
362
363 debug("%s: FIXME!\n", __func__);
364 return 0;
365
366 priv = dev_get_priv(dev);
367
368 /* De-configure all the context banks we allocated, ideally everything
369 * is back in the same state it was before
370 */
371 list_for_each_entry(mdev, &priv->devices, li) {
372 debug("%s: de-configuring %s\n", __func__, mdev->dev->name);
373 cbx_writel(priv, mdev->sid, ARM_SMMU_CB_SCTLR, 0x0);
374
375 cbar = FIELD_PREP(ARM_SMMU_CBAR_VMID, VMID_UNUSED);
376 cbar = FIELD_PREP(ARM_SMMU_CBAR_TYPE, CBAR_TYPE_S2_TRANS);
377 debug("%s: setting cbar %#x for cbx %d\n", __func__, cbar, mdev->cbx);
378 gr1_writel(priv, ARM_SMMU_GR1_CBAR(mdev->cbx), cbar);
379
380 debug("%s: clearing smr %d\n", __func__, mdev->smr);
381 gr0_writel(priv, ARM_SMMU_GR0_SMR(mdev->smr), 0);
382 debug("%s: clearing s2cr\n", __func__);
383 gr0_writel(priv, ARM_SMMU_GR0_S2CR(mdev->smr), 0);
384 }
385
386 return 0;
387}
388
389static struct iommu_ops arm_smmu_ops = {
390 .connect = arm_smmu_connect,
391};
392
393static const struct udevice_id arm_smmu500_ids[] = {
394 { .compatible = "qcom,sdm845-smmu-500" },
395 { .compatible = "arm,mmu-500" },
396 { /* sentinel */ }
397};
398
399U_BOOT_DRIVER(arm_smmu500) = {
400 .name = "arm_smmu500",
401 .id = UCLASS_IOMMU,
402 .of_match = arm_smmu500_ids,
403 .priv_auto = sizeof(struct arm_smmu_priv),
404 .ops = &arm_smmu_ops,
405 .probe = arm_smmu_probe,
406 .remove = arm_smmu_remove,
407 .flags = DM_FLAG_OS_PREPARE,
408};