1// 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 <log.h>
10#include <cpu_func.h>
11#include <dm.h>
12#include <iommu.h>
13#include <linux/bitfield.h>
14#include <linux/list.h>
15#include <linux/err.h>
16#include <lmb.h>
17#include <memalign.h>
18#include <asm/io.h>
19
20#define ARM_SMMU_GR0 0
21#define ARM_SMMU_GR1 1
22
23#define ARM_SMMU_GR0_ID0 0x20
24#define ARM_SMMU_ID0_NUMSMRG GENMASK(7, 0) /* Number of stream mapping groups */
25#define ARM_SMMU_GR0_ID1 0x24
26#define ARM_SMMU_ID1_PAGESIZE \
27	BIT(31) /* Page shift is 16 bits when set, otherwise 23 */
28#define ARM_SMMU_ID1_NUMPAGENDXB \
29	GENMASK(30, 28) /* Number of pages before context banks */
30#define ARM_SMMU_ID1_NUMCB GENMASK(7, 0) /* Number of context banks supported */
31
32#define ARM_SMMU_GR1_CBAR(n) (0x0 + ((n) << 2))
33#define ARM_SMMU_CBAR_TYPE GENMASK(17, 16)
34#define ARM_SMMU_CBAR_VMID GENMASK(7, 0)
35enum arm_smmu_cbar_type {
36	CBAR_TYPE_S2_TRANS,
37	CBAR_TYPE_S1_TRANS_S2_BYPASS,
38	CBAR_TYPE_S1_TRANS_S2_FAULT,
39	CBAR_TYPE_S1_TRANS_S2_TRANS,
40};
41
42#define ARM_SMMU_GR1_CBA2R(n) (0x800 + ((n) << 2))
43#define ARM_SMMU_CBA2R_VA64 BIT(0)
44
45/* Per-CB system control register */
46#define ARM_SMMU_CB_SCTLR 0x0
47#define ARM_SMMU_SCTLR_CFCFG BIT(7) /* Stall on context fault */
48#define ARM_SMMU_SCTLR_CFIE BIT(6) /* Context fault interrupt enable */
49#define ARM_SMMU_SCTLR_CFRE BIT(5) /* Abort on context fault */
50
51/* Translation Table Base, holds address of translation table in memory to be used
52 * for this context bank. Or 0 for bypass
53 */
54#define ARM_SMMU_CB_TTBR0 0x20
55#define ARM_SMMU_CB_TTBR1 0x28
56/* Translation Control Register, configured TTBR/TLB behaviour (0 for bypass) */
57#define ARM_SMMU_CB_TCR 0x30
58/* Memory Attribute Indirection, also 0 for bypass */
59#define ARM_SMMU_CB_S1_MAIR0 0x38
60#define ARM_SMMU_CB_S1_MAIR1 0x3c
61
62#define ARM_SMMU_GR0_SMR(n) (0x800 + ((n) << 2))
63#define ARM_SMMU_SMR_VALID BIT(31)
64#define ARM_SMMU_SMR_MASK GENMASK(31, 16) // Always 0 for now??
65#define ARM_SMMU_SMR_ID GENMASK(15, 0)
66
67#define ARM_SMMU_GR0_S2CR(n) (0xc00 + ((n) << 2))
68#define ARM_SMMU_S2CR_PRIVCFG GENMASK(25, 24)
69
70enum arm_smmu_s2cr_privcfg {
71	S2CR_PRIVCFG_DEFAULT,
72	S2CR_PRIVCFG_DIPAN,
73	S2CR_PRIVCFG_UNPRIV,
74	S2CR_PRIVCFG_PRIV,
75};
76
77#define ARM_SMMU_S2CR_TYPE GENMASK(17, 16)
78
79enum arm_smmu_s2cr_type {
80	S2CR_TYPE_TRANS,
81	S2CR_TYPE_BYPASS,
82	S2CR_TYPE_FAULT,
83};
84
85#define ARM_SMMU_S2CR_EXIDVALID BIT(10)
86#define ARM_SMMU_S2CR_CBNDX GENMASK(7, 0)
87
88#define VMID_UNUSED 0xff
89
90struct qcom_smmu_priv {
91	phys_addr_t base;
92	struct list_head devices;
93	struct udevice *dev;
94
95	/* Read-once config */
96	int num_cb;
97	int num_smr;
98	u32 pgshift;
99	u32 cb_pg_offset;
100};
101
102struct mmu_dev {
103	struct list_head li;
104	struct udevice *dev;
105	u16 sid;
106	u16 cbx;
107	u16 smr;
108};
109
110#define page_addr(priv, page) ((priv)->base + ((page) << (priv)->pgshift))
111
112#define smmu_readl(priv, page, offset) readl(page_addr(priv, page) + offset)
113#define gr0_readl(priv, offset) smmu_readl(priv, ARM_SMMU_GR0, offset)
114#define gr1_readl(priv, offset) smmu_readl(priv, ARM_SMMU_GR1, offset)
115#define cbx_readl(priv, cbx, offset) \
116	smmu_readl(priv, (priv->cb_pg_offset) + cbx, offset)
117
118#define smmu_writel(priv, page, offset, value) \
119	writel((value), page_addr(priv, page) + offset)
120#define gr0_writel(priv, offset, value) \
121	smmu_writel(priv, ARM_SMMU_GR0, offset, (value))
122#define gr1_writel(priv, offset, value) \
123	smmu_writel(priv, ARM_SMMU_GR1, offset, (value))
124#define cbx_writel(priv, cbx, offset, value) \
125	smmu_writel(priv, (priv->cb_pg_offset) + cbx, offset, value)
126
127#define gr1_setbits(priv, offset, value) \
128	gr1_writel(priv, offset, gr1_readl(priv, offset) | (value))
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 qcom_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	mmu_dev->sid = sid;
171
172	list_add_tail(&mmu_dev->li, &priv->devices);
173
174	return mmu_dev;
175}
176
177/* Find and init the first free context bank */
178static int alloc_cb(struct qcom_smmu_priv *priv)
179{
180	u32 cbar, type, vmid, val;
181
182	for (int i = 0; i < priv->num_cb; i++) {
183		cbar = gr1_readl(priv, ARM_SMMU_GR1_CBAR(i));
184		type = FIELD_GET(ARM_SMMU_CBAR_TYPE, cbar);
185		vmid = FIELD_GET(ARM_SMMU_CBAR_VMID, cbar);
186
187		/* Check that the context bank is available. We haven't reset the SMMU so
188		 * we just make a best guess.
189		 */
190		if (type != CBAR_TYPE_S2_TRANS &&
191		    (type != CBAR_TYPE_S1_TRANS_S2_BYPASS ||
192		     vmid != VMID_UNUSED))
193			continue;
194
195		debug("%s: Found free context bank %d (cbar %#x)\n",
196		      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 qcom_smmu_priv *priv, u16 stream_id)
216{
217	u32 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 qcom_smmu_priv *priv, struct mmu_dev *mdev)
233{
234	u32 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	/* Make sure our writes went through */
263	mb();
264
265	return 0;
266}
267
268static int qcom_smmu_connect(struct udevice *dev)
269{
270	struct mmu_dev *mdev;
271	struct qcom_smmu_priv *priv;
272	int ret;
273
274	debug("%s: %s -> %s\n", __func__, dev->name, dev->iommu->name);
275
276	priv = dev_get_priv(dev->iommu);
277	if (WARN_ON(!priv))
278		return -EINVAL;
279
280	mdev = alloc_dev(dev);
281	if (IS_ERR(mdev) && PTR_ERR(mdev) != -EEXIST) {
282		printf("%s: %s Couldn't create mmu context\n", __func__,
283		       dev->name);
284		return PTR_ERR(mdev);
285	} else if (IS_ERR(mdev)) { // -EEXIST
286		return 0;
287	}
288
289	if (find_smr(priv, mdev->sid) >= 0) {
290		debug("Found existing context bank for %s, skipping init\n",
291		      dev->name);
292		return 0;
293	}
294
295	ret = alloc_cb(priv);
296	if (ret < 0 || ret > 0xff) {
297		printf("Error: %s: failed to allocate context bank for %s\n",
298		       __func__, dev->name);
299		return 0;
300	}
301	mdev->cbx = ret;
302
303	/* Configure context bank registers */
304	cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TTBR0, 0x0);
305	cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TTBR1, 0x0);
306	cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_S1_MAIR0, 0x0);
307	cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_S1_MAIR1, 0x0);
308	cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_SCTLR,
309		   ARM_SMMU_SCTLR_CFIE | ARM_SMMU_SCTLR_CFRE |
310			   ARM_SMMU_SCTLR_CFCFG);
311	cbx_writel(priv, mdev->cbx, ARM_SMMU_CB_TCR, 0x0);
312
313	/* Ensure that our writes went through */
314	mb();
315
316	configure_smr_s2cr(priv, mdev);
317
318	return 0;
319}
320
321#ifdef DEBUG
322static inline void dump_boot_mappings(struct qcom_smmu_priv *priv)
323{
324	u32 val;
325	int i;
326
327	debug("  SMMU dump boot mappings:\n");
328	for (i = 0; i < priv->num_smr; i++) {
329		val = gr0_readl(priv, ARM_SMMU_GR0_SMR(i));
330		if (val & ARM_SMMU_SMR_VALID)
331			debug("\tSMR %3d: SID: %#lx\n", i,
332			      FIELD_GET(ARM_SMMU_SMR_ID, val));
333	}
334}
335#else
336#define dump_boot_mappings(priv) \
337	do {                     \
338	} while (0)
339#endif
340
341static int qcom_smmu_probe(struct udevice *dev)
342{
343	struct qcom_smmu_priv *priv;
344	u32 val;
345
346	priv = dev_get_priv(dev);
347	priv->dev = dev;
348	priv->base = dev_read_addr(dev);
349	INIT_LIST_HEAD(&priv->devices);
350
351	/* Read SMMU config */
352	val = gr0_readl(priv, ARM_SMMU_GR0_ID0);
353	priv->num_smr = FIELD_GET(ARM_SMMU_ID0_NUMSMRG, val);
354
355	val = gr0_readl(priv, ARM_SMMU_GR0_ID1);
356	priv->num_cb = FIELD_GET(ARM_SMMU_ID1_NUMCB, val);
357	priv->pgshift = FIELD_GET(ARM_SMMU_ID1_PAGESIZE, val) ? 16 : 12;
358	priv->cb_pg_offset = 1
359			     << (FIELD_GET(ARM_SMMU_ID1_NUMPAGENDXB, val) + 1);
360
361	dump_boot_mappings(priv);
362
363	return 0;
364}
365
366static int qcom_smmu_remove(struct udevice *dev)
367{
368	(void)dev;
369	/*
370	 * We should probably try and de-configure things here,
371	 * however I'm yet to find a way to do it without crashing
372	 * and it seems like Linux doesn't care at all anyway.
373	 */
374
375	return 0;
376}
377
378static struct iommu_ops qcom_smmu_ops = {
379	.connect = qcom_smmu_connect,
380};
381
382static const struct udevice_id qcom_smmu500_ids[] = {
383	{ .compatible = "qcom,sdm845-smmu-500" },
384	{ .compatible = "qcom,smmu-500", },
385	{ /* sentinel */ }
386};
387
388U_BOOT_DRIVER(qcom_smmu500) = {
389	.name = "qcom_smmu500",
390	.id = UCLASS_IOMMU,
391	.of_match = qcom_smmu500_ids,
392	.priv_auto = sizeof(struct qcom_smmu_priv),
393	.ops = &qcom_smmu_ops,
394	.probe = qcom_smmu_probe,
395	.remove = qcom_smmu_remove,
396	.flags = DM_FLAG_OS_PREPARE,
397};
398