iommu/mediatek: Add mt8183 IOMMU support
[linux-2.6-block.git] / drivers / memory / mtk-smi.c
CommitLineData
1802d0be 1// SPDX-License-Identifier: GPL-2.0-only
cc8bbe1a
YW
2/*
3 * Copyright (c) 2015-2016 MediaTek Inc.
4 * Author: Yong Wu <yong.wu@mediatek.com>
cc8bbe1a
YW
5 */
6#include <linux/clk.h>
7#include <linux/component.h>
8#include <linux/device.h>
9#include <linux/err.h>
10#include <linux/io.h>
4f608d38 11#include <linux/module.h>
cc8bbe1a
YW
12#include <linux/of.h>
13#include <linux/of_platform.h>
14#include <linux/platform_device.h>
15#include <linux/pm_runtime.h>
16#include <soc/mediatek/smi.h>
3c8f4ad8 17#include <dt-bindings/memory/mt2701-larb-port.h>
cc8bbe1a 18
e6dec923 19/* mt8173 */
cc8bbe1a 20#define SMI_LARB_MMU_EN 0xf00
e6dec923
YW
21
22/* mt2701 */
3c8f4ad8
HZ
23#define REG_SMI_SECUR_CON_BASE 0x5c0
24
25/* every register control 8 port, register offset 0x4 */
26#define REG_SMI_SECUR_CON_OFFSET(id) (((id) >> 3) << 2)
27#define REG_SMI_SECUR_CON_ADDR(id) \
28 (REG_SMI_SECUR_CON_BASE + REG_SMI_SECUR_CON_OFFSET(id))
29
30/*
31 * every port have 4 bit to control, bit[port + 3] control virtual or physical,
32 * bit[port + 2 : port + 1] control the domain, bit[port] control the security
33 * or non-security.
34 */
35#define SMI_SECUR_CON_VAL_MSK(id) (~(0xf << (((id) & 0x7) << 2)))
36#define SMI_SECUR_CON_VAL_VIRT(id) BIT((((id) & 0x7) << 2) + 3)
37/* mt2701 domain should be set to 3 */
38#define SMI_SECUR_CON_VAL_DOMAIN(id) (0x3 << ((((id) & 0x7) << 2) + 1))
39
e6dec923
YW
40/* mt2712 */
41#define SMI_LARB_NONSEC_CON(id) (0x380 + ((id) * 4))
42#define F_MMU_EN BIT(0)
43
42d42c76
YW
44enum mtk_smi_gen {
45 MTK_SMI_GEN1,
46 MTK_SMI_GEN2
47};
48
49struct mtk_smi_common_plat {
50 enum mtk_smi_gen gen;
64fea74a 51 bool has_gals;
42d42c76
YW
52};
53
3c8f4ad8 54struct mtk_smi_larb_gen {
363932cd 55 bool need_larbid;
3c8f4ad8
HZ
56 int port_in_larb[MTK_LARB_NR_MAX + 1];
57 void (*config_port)(struct device *);
2e9b0908 58 unsigned int larb_direct_to_common_mask;
64fea74a 59 bool has_gals;
3c8f4ad8 60};
cc8bbe1a
YW
61
62struct mtk_smi {
3c8f4ad8
HZ
63 struct device *dev;
64 struct clk *clk_apb, *clk_smi;
64fea74a 65 struct clk *clk_gals0, *clk_gals1;
3c8f4ad8
HZ
66 struct clk *clk_async; /*only needed by mt2701*/
67 void __iomem *smi_ao_base;
42d42c76
YW
68
69 const struct mtk_smi_common_plat *plat;
cc8bbe1a
YW
70};
71
72struct mtk_smi_larb { /* larb: local arbiter */
3c8f4ad8
HZ
73 struct mtk_smi smi;
74 void __iomem *base;
75 struct device *smi_common_dev;
76 const struct mtk_smi_larb_gen *larb_gen;
77 int larbid;
78 u32 *mmu;
79};
80
cc8bbe1a
YW
81static int mtk_smi_enable(const struct mtk_smi *smi)
82{
83 int ret;
84
85 ret = pm_runtime_get_sync(smi->dev);
86 if (ret < 0)
87 return ret;
88
89 ret = clk_prepare_enable(smi->clk_apb);
90 if (ret)
91 goto err_put_pm;
92
93 ret = clk_prepare_enable(smi->clk_smi);
94 if (ret)
95 goto err_disable_apb;
96
64fea74a
YW
97 ret = clk_prepare_enable(smi->clk_gals0);
98 if (ret)
99 goto err_disable_smi;
100
101 ret = clk_prepare_enable(smi->clk_gals1);
102 if (ret)
103 goto err_disable_gals0;
104
cc8bbe1a
YW
105 return 0;
106
64fea74a
YW
107err_disable_gals0:
108 clk_disable_unprepare(smi->clk_gals0);
109err_disable_smi:
110 clk_disable_unprepare(smi->clk_smi);
cc8bbe1a
YW
111err_disable_apb:
112 clk_disable_unprepare(smi->clk_apb);
113err_put_pm:
114 pm_runtime_put_sync(smi->dev);
115 return ret;
116}
117
118static void mtk_smi_disable(const struct mtk_smi *smi)
119{
64fea74a
YW
120 clk_disable_unprepare(smi->clk_gals1);
121 clk_disable_unprepare(smi->clk_gals0);
cc8bbe1a
YW
122 clk_disable_unprepare(smi->clk_smi);
123 clk_disable_unprepare(smi->clk_apb);
124 pm_runtime_put_sync(smi->dev);
125}
126
127int mtk_smi_larb_get(struct device *larbdev)
128{
129 struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
3c8f4ad8 130 const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
cc8bbe1a
YW
131 struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
132 int ret;
133
134 /* Enable the smi-common's power and clocks */
135 ret = mtk_smi_enable(common);
136 if (ret)
137 return ret;
138
139 /* Enable the larb's power and clocks */
140 ret = mtk_smi_enable(&larb->smi);
141 if (ret) {
142 mtk_smi_disable(common);
143 return ret;
144 }
145
146 /* Configure the iommu info for this larb */
3c8f4ad8 147 larb_gen->config_port(larbdev);
cc8bbe1a
YW
148
149 return 0;
150}
cb1b5dff 151EXPORT_SYMBOL_GPL(mtk_smi_larb_get);
cc8bbe1a
YW
152
153void mtk_smi_larb_put(struct device *larbdev)
154{
155 struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
156 struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
157
158 /*
159 * Don't de-configure the iommu info for this larb since there may be
160 * several modules in this larb.
161 * The iommu info will be reset after power off.
162 */
163
164 mtk_smi_disable(&larb->smi);
165 mtk_smi_disable(common);
166}
cb1b5dff 167EXPORT_SYMBOL_GPL(mtk_smi_larb_put);
cc8bbe1a
YW
168
169static int
170mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
171{
172 struct mtk_smi_larb *larb = dev_get_drvdata(dev);
173 struct mtk_smi_iommu *smi_iommu = data;
174 unsigned int i;
175
e6dec923
YW
176 if (larb->larb_gen->need_larbid) {
177 larb->mmu = &smi_iommu->larb_imu[larb->larbid].mmu;
178 return 0;
179 }
180
181 /*
182 * If there is no larbid property, Loop to find the corresponding
183 * iommu information.
184 */
cc8bbe1a
YW
185 for (i = 0; i < smi_iommu->larb_nr; i++) {
186 if (dev == smi_iommu->larb_imu[i].dev) {
187 /* The 'mmu' may be updated in iommu-attach/detach. */
188 larb->mmu = &smi_iommu->larb_imu[i].mmu;
189 return 0;
190 }
191 }
192 return -ENODEV;
193}
194
2e9b0908 195static void mtk_smi_larb_config_port_gen2_general(struct device *dev)
3c8f4ad8
HZ
196{
197 struct mtk_smi_larb *larb = dev_get_drvdata(dev);
e6dec923
YW
198 u32 reg;
199 int i;
3c8f4ad8 200
2e9b0908 201 if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask)
e6dec923
YW
202 return;
203
204 for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
205 reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i));
206 reg |= F_MMU_EN;
207 writel(reg, larb->base + SMI_LARB_NONSEC_CON(i));
208 }
3c8f4ad8
HZ
209}
210
e6dec923
YW
211static void mtk_smi_larb_config_port_mt8173(struct device *dev)
212{
213 struct mtk_smi_larb *larb = dev_get_drvdata(dev);
214
215 writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
216}
3c8f4ad8
HZ
217
218static void mtk_smi_larb_config_port_gen1(struct device *dev)
219{
220 struct mtk_smi_larb *larb = dev_get_drvdata(dev);
221 const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
222 struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
223 int i, m4u_port_id, larb_port_num;
224 u32 sec_con_val, reg_val;
225
226 m4u_port_id = larb_gen->port_in_larb[larb->larbid];
227 larb_port_num = larb_gen->port_in_larb[larb->larbid + 1]
228 - larb_gen->port_in_larb[larb->larbid];
229
230 for (i = 0; i < larb_port_num; i++, m4u_port_id++) {
231 if (*larb->mmu & BIT(i)) {
232 /* bit[port + 3] controls the virtual or physical */
233 sec_con_val = SMI_SECUR_CON_VAL_VIRT(m4u_port_id);
234 } else {
235 /* do not need to enable m4u for this port */
236 continue;
237 }
238 reg_val = readl(common->smi_ao_base
239 + REG_SMI_SECUR_CON_ADDR(m4u_port_id));
240 reg_val &= SMI_SECUR_CON_VAL_MSK(m4u_port_id);
241 reg_val |= sec_con_val;
242 reg_val |= SMI_SECUR_CON_VAL_DOMAIN(m4u_port_id);
243 writel(reg_val,
244 common->smi_ao_base
245 + REG_SMI_SECUR_CON_ADDR(m4u_port_id));
246 }
247}
248
cc8bbe1a
YW
249static void
250mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data)
251{
252 /* Do nothing as the iommu is always enabled. */
253}
254
255static const struct component_ops mtk_smi_larb_component_ops = {
256 .bind = mtk_smi_larb_bind,
257 .unbind = mtk_smi_larb_unbind,
258};
259
3c8f4ad8
HZ
260static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
261 /* mt8173 do not need the port in larb */
e6dec923 262 .config_port = mtk_smi_larb_config_port_mt8173,
3c8f4ad8
HZ
263};
264
265static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
363932cd 266 .need_larbid = true,
3c8f4ad8
HZ
267 .port_in_larb = {
268 LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
269 LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
270 },
271 .config_port = mtk_smi_larb_config_port_gen1,
272};
273
e6dec923
YW
274static const struct mtk_smi_larb_gen mtk_smi_larb_mt2712 = {
275 .need_larbid = true,
2e9b0908
YW
276 .config_port = mtk_smi_larb_config_port_gen2_general,
277 .larb_direct_to_common_mask = BIT(8) | BIT(9), /* bdpsys */
e6dec923
YW
278};
279
907ba6a1
YW
280static const struct mtk_smi_larb_gen mtk_smi_larb_mt8183 = {
281 .has_gals = true,
282 .config_port = mtk_smi_larb_config_port_gen2_general,
283 .larb_direct_to_common_mask = BIT(2) | BIT(3) | BIT(7),
284 /* IPU0 | IPU1 | CCU */
285};
286
3c8f4ad8
HZ
287static const struct of_device_id mtk_smi_larb_of_ids[] = {
288 {
289 .compatible = "mediatek,mt8173-smi-larb",
290 .data = &mtk_smi_larb_mt8173
291 },
292 {
293 .compatible = "mediatek,mt2701-smi-larb",
294 .data = &mtk_smi_larb_mt2701
295 },
e6dec923
YW
296 {
297 .compatible = "mediatek,mt2712-smi-larb",
298 .data = &mtk_smi_larb_mt2712
299 },
907ba6a1
YW
300 {
301 .compatible = "mediatek,mt8183-smi-larb",
302 .data = &mtk_smi_larb_mt8183
303 },
3c8f4ad8
HZ
304 {}
305};
306
cc8bbe1a
YW
307static int mtk_smi_larb_probe(struct platform_device *pdev)
308{
309 struct mtk_smi_larb *larb;
310 struct resource *res;
311 struct device *dev = &pdev->dev;
312 struct device_node *smi_node;
313 struct platform_device *smi_pdev;
363932cd 314 int err;
cc8bbe1a 315
cc8bbe1a
YW
316 larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
317 if (!larb)
318 return -ENOMEM;
319
75487860 320 larb->larb_gen = of_device_get_match_data(dev);
cc8bbe1a
YW
321 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
322 larb->base = devm_ioremap_resource(dev, res);
323 if (IS_ERR(larb->base))
324 return PTR_ERR(larb->base);
325
326 larb->smi.clk_apb = devm_clk_get(dev, "apb");
327 if (IS_ERR(larb->smi.clk_apb))
328 return PTR_ERR(larb->smi.clk_apb);
329
330 larb->smi.clk_smi = devm_clk_get(dev, "smi");
331 if (IS_ERR(larb->smi.clk_smi))
332 return PTR_ERR(larb->smi.clk_smi);
64fea74a
YW
333
334 if (larb->larb_gen->has_gals) {
335 /* The larbs may still haven't gals even if the SoC support.*/
336 larb->smi.clk_gals0 = devm_clk_get(dev, "gals");
337 if (PTR_ERR(larb->smi.clk_gals0) == -ENOENT)
338 larb->smi.clk_gals0 = NULL;
339 else if (IS_ERR(larb->smi.clk_gals0))
340 return PTR_ERR(larb->smi.clk_gals0);
341 }
cc8bbe1a
YW
342 larb->smi.dev = dev;
343
363932cd
HZ
344 if (larb->larb_gen->need_larbid) {
345 err = of_property_read_u32(dev->of_node, "mediatek,larb-id",
346 &larb->larbid);
347 if (err) {
348 dev_err(dev, "missing larbid property\n");
349 return err;
350 }
351 }
352
cc8bbe1a
YW
353 smi_node = of_parse_phandle(dev->of_node, "mediatek,smi", 0);
354 if (!smi_node)
355 return -EINVAL;
356
357 smi_pdev = of_find_device_by_node(smi_node);
358 of_node_put(smi_node);
359 if (smi_pdev) {
4f608d38
YW
360 if (!platform_get_drvdata(smi_pdev))
361 return -EPROBE_DEFER;
cc8bbe1a
YW
362 larb->smi_common_dev = &smi_pdev->dev;
363 } else {
364 dev_err(dev, "Failed to get the smi_common device\n");
365 return -EINVAL;
366 }
367
368 pm_runtime_enable(dev);
369 platform_set_drvdata(pdev, larb);
370 return component_add(dev, &mtk_smi_larb_component_ops);
371}
372
373static int mtk_smi_larb_remove(struct platform_device *pdev)
374{
375 pm_runtime_disable(&pdev->dev);
376 component_del(&pdev->dev, &mtk_smi_larb_component_ops);
377 return 0;
378}
379
cc8bbe1a
YW
380static struct platform_driver mtk_smi_larb_driver = {
381 .probe = mtk_smi_larb_probe,
3c8f4ad8 382 .remove = mtk_smi_larb_remove,
cc8bbe1a
YW
383 .driver = {
384 .name = "mtk-smi-larb",
385 .of_match_table = mtk_smi_larb_of_ids,
386 }
387};
388
42d42c76
YW
389static const struct mtk_smi_common_plat mtk_smi_common_gen1 = {
390 .gen = MTK_SMI_GEN1,
391};
392
393static const struct mtk_smi_common_plat mtk_smi_common_gen2 = {
394 .gen = MTK_SMI_GEN2,
395};
396
907ba6a1
YW
397static const struct mtk_smi_common_plat mtk_smi_common_mt8183 = {
398 .gen = MTK_SMI_GEN2,
399 .has_gals = true,
400};
401
3c8f4ad8
HZ
402static const struct of_device_id mtk_smi_common_of_ids[] = {
403 {
404 .compatible = "mediatek,mt8173-smi-common",
42d42c76 405 .data = &mtk_smi_common_gen2,
3c8f4ad8
HZ
406 },
407 {
408 .compatible = "mediatek,mt2701-smi-common",
42d42c76 409 .data = &mtk_smi_common_gen1,
3c8f4ad8 410 },
e6dec923
YW
411 {
412 .compatible = "mediatek,mt2712-smi-common",
42d42c76 413 .data = &mtk_smi_common_gen2,
e6dec923 414 },
907ba6a1
YW
415 {
416 .compatible = "mediatek,mt8183-smi-common",
417 .data = &mtk_smi_common_mt8183,
418 },
3c8f4ad8
HZ
419 {}
420};
421
cc8bbe1a
YW
422static int mtk_smi_common_probe(struct platform_device *pdev)
423{
424 struct device *dev = &pdev->dev;
425 struct mtk_smi *common;
3c8f4ad8 426 struct resource *res;
46cc815d 427 int ret;
cc8bbe1a 428
cc8bbe1a
YW
429 common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL);
430 if (!common)
431 return -ENOMEM;
432 common->dev = dev;
42d42c76 433 common->plat = of_device_get_match_data(dev);
cc8bbe1a
YW
434
435 common->clk_apb = devm_clk_get(dev, "apb");
436 if (IS_ERR(common->clk_apb))
437 return PTR_ERR(common->clk_apb);
438
439 common->clk_smi = devm_clk_get(dev, "smi");
440 if (IS_ERR(common->clk_smi))
441 return PTR_ERR(common->clk_smi);
442
64fea74a
YW
443 if (common->plat->has_gals) {
444 common->clk_gals0 = devm_clk_get(dev, "gals0");
445 if (IS_ERR(common->clk_gals0))
446 return PTR_ERR(common->clk_gals0);
447
448 common->clk_gals1 = devm_clk_get(dev, "gals1");
449 if (IS_ERR(common->clk_gals1))
450 return PTR_ERR(common->clk_gals1);
451 }
452
3c8f4ad8
HZ
453 /*
454 * for mtk smi gen 1, we need to get the ao(always on) base to config
455 * m4u port, and we need to enable the aync clock for transform the smi
456 * clock into emi clock domain, but for mtk smi gen2, there's no smi ao
457 * base.
458 */
42d42c76 459 if (common->plat->gen == MTK_SMI_GEN1) {
3c8f4ad8
HZ
460 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
461 common->smi_ao_base = devm_ioremap_resource(dev, res);
462 if (IS_ERR(common->smi_ao_base))
463 return PTR_ERR(common->smi_ao_base);
464
465 common->clk_async = devm_clk_get(dev, "async");
466 if (IS_ERR(common->clk_async))
467 return PTR_ERR(common->clk_async);
468
46cc815d
AY
469 ret = clk_prepare_enable(common->clk_async);
470 if (ret)
471 return ret;
3c8f4ad8 472 }
cc8bbe1a
YW
473 pm_runtime_enable(dev);
474 platform_set_drvdata(pdev, common);
475 return 0;
476}
477
478static int mtk_smi_common_remove(struct platform_device *pdev)
479{
480 pm_runtime_disable(&pdev->dev);
481 return 0;
482}
483
cc8bbe1a
YW
484static struct platform_driver mtk_smi_common_driver = {
485 .probe = mtk_smi_common_probe,
486 .remove = mtk_smi_common_remove,
487 .driver = {
488 .name = "mtk-smi-common",
489 .of_match_table = mtk_smi_common_of_ids,
490 }
491};
492
493static int __init mtk_smi_init(void)
494{
495 int ret;
496
497 ret = platform_driver_register(&mtk_smi_common_driver);
498 if (ret != 0) {
499 pr_err("Failed to register SMI driver\n");
500 return ret;
501 }
502
503 ret = platform_driver_register(&mtk_smi_larb_driver);
504 if (ret != 0) {
505 pr_err("Failed to register SMI-LARB driver\n");
506 goto err_unreg_smi;
507 }
508 return ret;
509
510err_unreg_smi:
511 platform_driver_unregister(&mtk_smi_common_driver);
512 return ret;
513}
3c8f4ad8 514
4f608d38 515module_init(mtk_smi_init);