Skip to content

Commit 3c8f4ad

Browse files
Honghui Zhangjoergroedel
authored andcommitted
memory/mediatek: add support for mt2701
Mediatek SMI has two generations of HW architecture, mt8173 uses the second generation of SMI HW while mt2701 uses the first generation HW of SMI. There's slight differences between the two generations, for generation 2, the register which control the iommu port access PA or IOVA is at each larb's register base. But for generation 1, the register is at smi ao base(smi always on register base). Besides that, the smi async clock should be prepared and enabled for SMI generation 1 HW to transform the smi clock into emi clock domain, but is not needed for SMI generation 2. This patch add SMI driver for mt2701 which use generation 1 SMI HW. Signed-off-by: Honghui Zhang <[email protected]> Signed-off-by: Joerg Roedel <[email protected]>
1 parent 9ca340c commit 3c8f4ad

File tree

1 file changed

+149
-18
lines changed

1 file changed

+149
-18
lines changed

drivers/memory/mtk-smi.c

Lines changed: 149 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,50 @@
2121
#include <linux/platform_device.h>
2222
#include <linux/pm_runtime.h>
2323
#include <soc/mediatek/smi.h>
24+
#include <dt-bindings/memory/mt2701-larb-port.h>
2425

2526
#define SMI_LARB_MMU_EN 0xf00
27+
#define REG_SMI_SECUR_CON_BASE 0x5c0
28+
29+
/* every register control 8 port, register offset 0x4 */
30+
#define REG_SMI_SECUR_CON_OFFSET(id) (((id) >> 3) << 2)
31+
#define REG_SMI_SECUR_CON_ADDR(id) \
32+
(REG_SMI_SECUR_CON_BASE + REG_SMI_SECUR_CON_OFFSET(id))
33+
34+
/*
35+
* every port have 4 bit to control, bit[port + 3] control virtual or physical,
36+
* bit[port + 2 : port + 1] control the domain, bit[port] control the security
37+
* or non-security.
38+
*/
39+
#define SMI_SECUR_CON_VAL_MSK(id) (~(0xf << (((id) & 0x7) << 2)))
40+
#define SMI_SECUR_CON_VAL_VIRT(id) BIT((((id) & 0x7) << 2) + 3)
41+
/* mt2701 domain should be set to 3 */
42+
#define SMI_SECUR_CON_VAL_DOMAIN(id) (0x3 << ((((id) & 0x7) << 2) + 1))
43+
44+
struct mtk_smi_larb_gen {
45+
int port_in_larb[MTK_LARB_NR_MAX + 1];
46+
void (*config_port)(struct device *);
47+
};
2648

2749
struct mtk_smi {
28-
struct device *dev;
29-
struct clk *clk_apb, *clk_smi;
50+
struct device *dev;
51+
struct clk *clk_apb, *clk_smi;
52+
struct clk *clk_async; /*only needed by mt2701*/
53+
void __iomem *smi_ao_base;
3054
};
3155

3256
struct mtk_smi_larb { /* larb: local arbiter */
33-
struct mtk_smi smi;
34-
void __iomem *base;
35-
struct device *smi_common_dev;
36-
u32 *mmu;
57+
struct mtk_smi smi;
58+
void __iomem *base;
59+
struct device *smi_common_dev;
60+
const struct mtk_smi_larb_gen *larb_gen;
61+
int larbid;
62+
u32 *mmu;
63+
};
64+
65+
enum mtk_smi_gen {
66+
MTK_SMI_GEN1,
67+
MTK_SMI_GEN2
3768
};
3869

3970
static int mtk_smi_enable(const struct mtk_smi *smi)
@@ -71,6 +102,7 @@ static void mtk_smi_disable(const struct mtk_smi *smi)
71102
int mtk_smi_larb_get(struct device *larbdev)
72103
{
73104
struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
105+
const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
74106
struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
75107
int ret;
76108

@@ -87,7 +119,7 @@ int mtk_smi_larb_get(struct device *larbdev)
87119
}
88120

89121
/* Configure the iommu info for this larb */
90-
writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
122+
larb_gen->config_port(larbdev);
91123

92124
return 0;
93125
}
@@ -126,6 +158,45 @@ mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
126158
return -ENODEV;
127159
}
128160

161+
static void mtk_smi_larb_config_port(struct device *dev)
162+
{
163+
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
164+
165+
writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
166+
}
167+
168+
169+
static void mtk_smi_larb_config_port_gen1(struct device *dev)
170+
{
171+
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
172+
const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
173+
struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
174+
int i, m4u_port_id, larb_port_num;
175+
u32 sec_con_val, reg_val;
176+
177+
m4u_port_id = larb_gen->port_in_larb[larb->larbid];
178+
larb_port_num = larb_gen->port_in_larb[larb->larbid + 1]
179+
- larb_gen->port_in_larb[larb->larbid];
180+
181+
for (i = 0; i < larb_port_num; i++, m4u_port_id++) {
182+
if (*larb->mmu & BIT(i)) {
183+
/* bit[port + 3] controls the virtual or physical */
184+
sec_con_val = SMI_SECUR_CON_VAL_VIRT(m4u_port_id);
185+
} else {
186+
/* do not need to enable m4u for this port */
187+
continue;
188+
}
189+
reg_val = readl(common->smi_ao_base
190+
+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
191+
reg_val &= SMI_SECUR_CON_VAL_MSK(m4u_port_id);
192+
reg_val |= sec_con_val;
193+
reg_val |= SMI_SECUR_CON_VAL_DOMAIN(m4u_port_id);
194+
writel(reg_val,
195+
common->smi_ao_base
196+
+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
197+
}
198+
}
199+
129200
static void
130201
mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data)
131202
{
@@ -137,21 +208,52 @@ static const struct component_ops mtk_smi_larb_component_ops = {
137208
.unbind = mtk_smi_larb_unbind,
138209
};
139210

211+
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8173 = {
212+
/* mt8173 do not need the port in larb */
213+
.config_port = mtk_smi_larb_config_port,
214+
};
215+
216+
static const struct mtk_smi_larb_gen mtk_smi_larb_mt2701 = {
217+
.port_in_larb = {
218+
LARB0_PORT_OFFSET, LARB1_PORT_OFFSET,
219+
LARB2_PORT_OFFSET, LARB3_PORT_OFFSET
220+
},
221+
.config_port = mtk_smi_larb_config_port_gen1,
222+
};
223+
224+
static const struct of_device_id mtk_smi_larb_of_ids[] = {
225+
{
226+
.compatible = "mediatek,mt8173-smi-larb",
227+
.data = &mtk_smi_larb_mt8173
228+
},
229+
{
230+
.compatible = "mediatek,mt2701-smi-larb",
231+
.data = &mtk_smi_larb_mt2701
232+
},
233+
{}
234+
};
235+
140236
static int mtk_smi_larb_probe(struct platform_device *pdev)
141237
{
142238
struct mtk_smi_larb *larb;
143239
struct resource *res;
144240
struct device *dev = &pdev->dev;
145241
struct device_node *smi_node;
146242
struct platform_device *smi_pdev;
243+
const struct of_device_id *of_id;
147244

148245
if (!dev->pm_domain)
149246
return -EPROBE_DEFER;
150247

248+
of_id = of_match_node(mtk_smi_larb_of_ids, pdev->dev.of_node);
249+
if (!of_id)
250+
return -EINVAL;
251+
151252
larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
152253
if (!larb)
153254
return -ENOMEM;
154255

256+
larb->larb_gen = of_id->data;
155257
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
156258
larb->base = devm_ioremap_resource(dev, res);
157259
if (IS_ERR(larb->base))
@@ -191,24 +293,34 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
191293
return 0;
192294
}
193295

194-
static const struct of_device_id mtk_smi_larb_of_ids[] = {
195-
{ .compatible = "mediatek,mt8173-smi-larb",},
196-
{}
197-
};
198-
199296
static struct platform_driver mtk_smi_larb_driver = {
200297
.probe = mtk_smi_larb_probe,
201-
.remove = mtk_smi_larb_remove,
298+
.remove = mtk_smi_larb_remove,
202299
.driver = {
203300
.name = "mtk-smi-larb",
204301
.of_match_table = mtk_smi_larb_of_ids,
205302
}
206303
};
207304

305+
static const struct of_device_id mtk_smi_common_of_ids[] = {
306+
{
307+
.compatible = "mediatek,mt8173-smi-common",
308+
.data = (void *)MTK_SMI_GEN2
309+
},
310+
{
311+
.compatible = "mediatek,mt2701-smi-common",
312+
.data = (void *)MTK_SMI_GEN1
313+
},
314+
{}
315+
};
316+
208317
static int mtk_smi_common_probe(struct platform_device *pdev)
209318
{
210319
struct device *dev = &pdev->dev;
211320
struct mtk_smi *common;
321+
struct resource *res;
322+
const struct of_device_id *of_id;
323+
enum mtk_smi_gen smi_gen;
212324

213325
if (!dev->pm_domain)
214326
return -EPROBE_DEFER;
@@ -226,6 +338,29 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
226338
if (IS_ERR(common->clk_smi))
227339
return PTR_ERR(common->clk_smi);
228340

341+
of_id = of_match_node(mtk_smi_common_of_ids, pdev->dev.of_node);
342+
if (!of_id)
343+
return -EINVAL;
344+
345+
/*
346+
* for mtk smi gen 1, we need to get the ao(always on) base to config
347+
* m4u port, and we need to enable the aync clock for transform the smi
348+
* clock into emi clock domain, but for mtk smi gen2, there's no smi ao
349+
* base.
350+
*/
351+
smi_gen = (enum mtk_smi_gen)of_id->data;
352+
if (smi_gen == MTK_SMI_GEN1) {
353+
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
354+
common->smi_ao_base = devm_ioremap_resource(dev, res);
355+
if (IS_ERR(common->smi_ao_base))
356+
return PTR_ERR(common->smi_ao_base);
357+
358+
common->clk_async = devm_clk_get(dev, "async");
359+
if (IS_ERR(common->clk_async))
360+
return PTR_ERR(common->clk_async);
361+
362+
clk_prepare_enable(common->clk_async);
363+
}
229364
pm_runtime_enable(dev);
230365
platform_set_drvdata(pdev, common);
231366
return 0;
@@ -237,11 +372,6 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
237372
return 0;
238373
}
239374

240-
static const struct of_device_id mtk_smi_common_of_ids[] = {
241-
{ .compatible = "mediatek,mt8173-smi-common", },
242-
{}
243-
};
244-
245375
static struct platform_driver mtk_smi_common_driver = {
246376
.probe = mtk_smi_common_probe,
247377
.remove = mtk_smi_common_remove,
@@ -272,4 +402,5 @@ static int __init mtk_smi_init(void)
272402
platform_driver_unregister(&mtk_smi_common_driver);
273403
return ret;
274404
}
405+
275406
subsys_initcall(mtk_smi_init);

0 commit comments

Comments
 (0)