aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHonghui Zhang <honghui.zhang@mediatek.com>2016-06-08 05:50:59 -0400
committerJoerg Roedel <jroedel@suse.de>2016-06-21 05:36:19 -0400
commit3c8f4ad85c4b61fcf2c56e1d281d691ac595243a (patch)
treef60034edaa42624c7f3d6329798e390d9654ff18
parent9ca340c98c0dc6cb60b5ebd7847302f57648f0ba (diff)
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 <honghui.zhang@mediatek.com> Signed-off-by: Joerg Roedel <jroedel@suse.de>
-rw-r--r--drivers/memory/mtk-smi.c167
1 files changed, 149 insertions, 18 deletions
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index f6b57579185a..4afbc412f959 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -21,19 +21,50 @@
21#include <linux/platform_device.h> 21#include <linux/platform_device.h>
22#include <linux/pm_runtime.h> 22#include <linux/pm_runtime.h>
23#include <soc/mediatek/smi.h> 23#include <soc/mediatek/smi.h>
24#include <dt-bindings/memory/mt2701-larb-port.h>
24 25
25#define SMI_LARB_MMU_EN 0xf00 26#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
44struct mtk_smi_larb_gen {
45 int port_in_larb[MTK_LARB_NR_MAX + 1];
46 void (*config_port)(struct device *);
47};
26 48
27struct mtk_smi { 49struct mtk_smi {
28 struct device *dev; 50 struct device *dev;
29 struct clk *clk_apb, *clk_smi; 51 struct clk *clk_apb, *clk_smi;
52 struct clk *clk_async; /*only needed by mt2701*/
53 void __iomem *smi_ao_base;
30}; 54};
31 55
32struct mtk_smi_larb { /* larb: local arbiter */ 56struct mtk_smi_larb { /* larb: local arbiter */
33 struct mtk_smi smi; 57 struct mtk_smi smi;
34 void __iomem *base; 58 void __iomem *base;
35 struct device *smi_common_dev; 59 struct device *smi_common_dev;
36 u32 *mmu; 60 const struct mtk_smi_larb_gen *larb_gen;
61 int larbid;
62 u32 *mmu;
63};
64
65enum mtk_smi_gen {
66 MTK_SMI_GEN1,
67 MTK_SMI_GEN2
37}; 68};
38 69
39static int mtk_smi_enable(const struct mtk_smi *smi) 70static int mtk_smi_enable(const struct mtk_smi *smi)
@@ -71,6 +102,7 @@ static void mtk_smi_disable(const struct mtk_smi *smi)
71int mtk_smi_larb_get(struct device *larbdev) 102int mtk_smi_larb_get(struct device *larbdev)
72{ 103{
73 struct mtk_smi_larb *larb = dev_get_drvdata(larbdev); 104 struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
105 const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
74 struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev); 106 struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
75 int ret; 107 int ret;
76 108
@@ -87,7 +119,7 @@ int mtk_smi_larb_get(struct device *larbdev)
87 } 119 }
88 120
89 /* Configure the iommu info for this larb */ 121 /* Configure the iommu info for this larb */
90 writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN); 122 larb_gen->config_port(larbdev);
91 123
92 return 0; 124 return 0;
93} 125}
@@ -126,6 +158,45 @@ mtk_smi_larb_bind(struct device *dev, struct device *master, void *data)
126 return -ENODEV; 158 return -ENODEV;
127} 159}
128 160
161static 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
169static 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
129static void 200static void
130mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data) 201mtk_smi_larb_unbind(struct device *dev, struct device *master, void *data)
131{ 202{
@@ -137,6 +208,31 @@ static const struct component_ops mtk_smi_larb_component_ops = {
137 .unbind = mtk_smi_larb_unbind, 208 .unbind = mtk_smi_larb_unbind,
138}; 209};
139 210
211static 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
216static 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
224static 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
140static int mtk_smi_larb_probe(struct platform_device *pdev) 236static int mtk_smi_larb_probe(struct platform_device *pdev)
141{ 237{
142 struct mtk_smi_larb *larb; 238 struct mtk_smi_larb *larb;
@@ -144,14 +240,20 @@ static int mtk_smi_larb_probe(struct platform_device *pdev)
144 struct device *dev = &pdev->dev; 240 struct device *dev = &pdev->dev;
145 struct device_node *smi_node; 241 struct device_node *smi_node;
146 struct platform_device *smi_pdev; 242 struct platform_device *smi_pdev;
243 const struct of_device_id *of_id;
147 244
148 if (!dev->pm_domain) 245 if (!dev->pm_domain)
149 return -EPROBE_DEFER; 246 return -EPROBE_DEFER;
150 247
248 of_id = of_match_node(mtk_smi_larb_of_ids, pdev->dev.of_node);
249 if (!of_id)
250 return -EINVAL;
251
151 larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL); 252 larb = devm_kzalloc(dev, sizeof(*larb), GFP_KERNEL);
152 if (!larb) 253 if (!larb)
153 return -ENOMEM; 254 return -ENOMEM;
154 255
256 larb->larb_gen = of_id->data;
155 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 257 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
156 larb->base = devm_ioremap_resource(dev, res); 258 larb->base = devm_ioremap_resource(dev, res);
157 if (IS_ERR(larb->base)) 259 if (IS_ERR(larb->base))
@@ -191,24 +293,34 @@ static int mtk_smi_larb_remove(struct platform_device *pdev)
191 return 0; 293 return 0;
192} 294}
193 295
194static const struct of_device_id mtk_smi_larb_of_ids[] = {
195 { .compatible = "mediatek,mt8173-smi-larb",},
196 {}
197};
198
199static struct platform_driver mtk_smi_larb_driver = { 296static struct platform_driver mtk_smi_larb_driver = {
200 .probe = mtk_smi_larb_probe, 297 .probe = mtk_smi_larb_probe,
201 .remove = mtk_smi_larb_remove, 298 .remove = mtk_smi_larb_remove,
202 .driver = { 299 .driver = {
203 .name = "mtk-smi-larb", 300 .name = "mtk-smi-larb",
204 .of_match_table = mtk_smi_larb_of_ids, 301 .of_match_table = mtk_smi_larb_of_ids,
205 } 302 }
206}; 303};
207 304
305static 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
208static int mtk_smi_common_probe(struct platform_device *pdev) 317static int mtk_smi_common_probe(struct platform_device *pdev)
209{ 318{
210 struct device *dev = &pdev->dev; 319 struct device *dev = &pdev->dev;
211 struct mtk_smi *common; 320 struct mtk_smi *common;
321 struct resource *res;
322 const struct of_device_id *of_id;
323 enum mtk_smi_gen smi_gen;
212 324
213 if (!dev->pm_domain) 325 if (!dev->pm_domain)
214 return -EPROBE_DEFER; 326 return -EPROBE_DEFER;
@@ -226,6 +338,29 @@ static int mtk_smi_common_probe(struct platform_device *pdev)
226 if (IS_ERR(common->clk_smi)) 338 if (IS_ERR(common->clk_smi))
227 return PTR_ERR(common->clk_smi); 339 return PTR_ERR(common->clk_smi);
228 340
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 }
229 pm_runtime_enable(dev); 364 pm_runtime_enable(dev);
230 platform_set_drvdata(pdev, common); 365 platform_set_drvdata(pdev, common);
231 return 0; 366 return 0;
@@ -237,11 +372,6 @@ static int mtk_smi_common_remove(struct platform_device *pdev)
237 return 0; 372 return 0;
238} 373}
239 374
240static const struct of_device_id mtk_smi_common_of_ids[] = {
241 { .compatible = "mediatek,mt8173-smi-common", },
242 {}
243};
244
245static struct platform_driver mtk_smi_common_driver = { 375static struct platform_driver mtk_smi_common_driver = {
246 .probe = mtk_smi_common_probe, 376 .probe = mtk_smi_common_probe,
247 .remove = mtk_smi_common_remove, 377 .remove = mtk_smi_common_remove,
@@ -272,4 +402,5 @@ err_unreg_smi:
272 platform_driver_unregister(&mtk_smi_common_driver); 402 platform_driver_unregister(&mtk_smi_common_driver);
273 return ret; 403 return ret;
274} 404}
405
275subsys_initcall(mtk_smi_init); 406subsys_initcall(mtk_smi_init);