kernel: update 4.4 to 4.4.83
[openwrt/openwrt.git] / target / linux / mediatek / patches-4.9 / 0014-soc-mediatek-Refine-scpsys-to-support-multiple-platf.patch
1 From 6078c651947a148c1de543b54fe55af43a63043a Mon Sep 17 00:00:00 2001
2 From: James Liao <jamesjj.liao@mediatek.com>
3 Date: Thu, 20 Oct 2016 16:56:35 +0800
4 Subject: [PATCH 1/2] soc: mediatek: Refine scpsys to support multiple platform
5
6 Refine scpsys driver common code to support multiple SoC / platform.
7
8 Signed-off-by: James Liao <jamesjj.liao@mediatek.com>
9 Reviewed-by: Kevin Hilman <khilman@baylibre.com>
10 Signed-off-by: Matthias Brugger <matthias.bgg@gmail.com>
11 ---
12 drivers/soc/mediatek/mtk-scpsys.c | 348 +++++++++++++++++++++++---------------
13 1 file changed, 210 insertions(+), 138 deletions(-)
14
15 --- a/drivers/soc/mediatek/mtk-scpsys.c
16 +++ b/drivers/soc/mediatek/mtk-scpsys.c
17 @@ -11,17 +11,15 @@
18 * GNU General Public License for more details.
19 */
20 #include <linux/clk.h>
21 -#include <linux/delay.h>
22 +#include <linux/init.h>
23 #include <linux/io.h>
24 -#include <linux/kernel.h>
25 #include <linux/mfd/syscon.h>
26 -#include <linux/init.h>
27 #include <linux/of_device.h>
28 #include <linux/platform_device.h>
29 #include <linux/pm_domain.h>
30 -#include <linux/regmap.h>
31 -#include <linux/soc/mediatek/infracfg.h>
32 #include <linux/regulator/consumer.h>
33 +#include <linux/soc/mediatek/infracfg.h>
34 +
35 #include <dt-bindings/power/mt8173-power.h>
36
37 #define SPM_VDE_PWR_CON 0x0210
38 @@ -34,6 +32,7 @@
39 #define SPM_MFG_2D_PWR_CON 0x02c0
40 #define SPM_MFG_ASYNC_PWR_CON 0x02c4
41 #define SPM_USB_PWR_CON 0x02cc
42 +
43 #define SPM_PWR_STATUS 0x060c
44 #define SPM_PWR_STATUS_2ND 0x0610
45
46 @@ -55,12 +54,21 @@
47 #define PWR_STATUS_USB BIT(25)
48
49 enum clk_id {
50 - MT8173_CLK_NONE,
51 - MT8173_CLK_MM,
52 - MT8173_CLK_MFG,
53 - MT8173_CLK_VENC,
54 - MT8173_CLK_VENC_LT,
55 - MT8173_CLK_MAX,
56 + CLK_NONE,
57 + CLK_MM,
58 + CLK_MFG,
59 + CLK_VENC,
60 + CLK_VENC_LT,
61 + CLK_MAX,
62 +};
63 +
64 +static const char * const clk_names[] = {
65 + NULL,
66 + "mm",
67 + "mfg",
68 + "venc",
69 + "venc_lt",
70 + NULL,
71 };
72
73 #define MAX_CLKS 2
74 @@ -76,98 +84,6 @@ struct scp_domain_data {
75 bool active_wakeup;
76 };
77
78 -static const struct scp_domain_data scp_domain_data[] = {
79 - [MT8173_POWER_DOMAIN_VDEC] = {
80 - .name = "vdec",
81 - .sta_mask = PWR_STATUS_VDEC,
82 - .ctl_offs = SPM_VDE_PWR_CON,
83 - .sram_pdn_bits = GENMASK(11, 8),
84 - .sram_pdn_ack_bits = GENMASK(12, 12),
85 - .clk_id = {MT8173_CLK_MM},
86 - },
87 - [MT8173_POWER_DOMAIN_VENC] = {
88 - .name = "venc",
89 - .sta_mask = PWR_STATUS_VENC,
90 - .ctl_offs = SPM_VEN_PWR_CON,
91 - .sram_pdn_bits = GENMASK(11, 8),
92 - .sram_pdn_ack_bits = GENMASK(15, 12),
93 - .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC},
94 - },
95 - [MT8173_POWER_DOMAIN_ISP] = {
96 - .name = "isp",
97 - .sta_mask = PWR_STATUS_ISP,
98 - .ctl_offs = SPM_ISP_PWR_CON,
99 - .sram_pdn_bits = GENMASK(11, 8),
100 - .sram_pdn_ack_bits = GENMASK(13, 12),
101 - .clk_id = {MT8173_CLK_MM},
102 - },
103 - [MT8173_POWER_DOMAIN_MM] = {
104 - .name = "mm",
105 - .sta_mask = PWR_STATUS_DISP,
106 - .ctl_offs = SPM_DIS_PWR_CON,
107 - .sram_pdn_bits = GENMASK(11, 8),
108 - .sram_pdn_ack_bits = GENMASK(12, 12),
109 - .clk_id = {MT8173_CLK_MM},
110 - .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
111 - MT8173_TOP_AXI_PROT_EN_MM_M1,
112 - },
113 - [MT8173_POWER_DOMAIN_VENC_LT] = {
114 - .name = "venc_lt",
115 - .sta_mask = PWR_STATUS_VENC_LT,
116 - .ctl_offs = SPM_VEN2_PWR_CON,
117 - .sram_pdn_bits = GENMASK(11, 8),
118 - .sram_pdn_ack_bits = GENMASK(15, 12),
119 - .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC_LT},
120 - },
121 - [MT8173_POWER_DOMAIN_AUDIO] = {
122 - .name = "audio",
123 - .sta_mask = PWR_STATUS_AUDIO,
124 - .ctl_offs = SPM_AUDIO_PWR_CON,
125 - .sram_pdn_bits = GENMASK(11, 8),
126 - .sram_pdn_ack_bits = GENMASK(15, 12),
127 - .clk_id = {MT8173_CLK_NONE},
128 - },
129 - [MT8173_POWER_DOMAIN_USB] = {
130 - .name = "usb",
131 - .sta_mask = PWR_STATUS_USB,
132 - .ctl_offs = SPM_USB_PWR_CON,
133 - .sram_pdn_bits = GENMASK(11, 8),
134 - .sram_pdn_ack_bits = GENMASK(15, 12),
135 - .clk_id = {MT8173_CLK_NONE},
136 - .active_wakeup = true,
137 - },
138 - [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
139 - .name = "mfg_async",
140 - .sta_mask = PWR_STATUS_MFG_ASYNC,
141 - .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
142 - .sram_pdn_bits = GENMASK(11, 8),
143 - .sram_pdn_ack_bits = 0,
144 - .clk_id = {MT8173_CLK_MFG},
145 - },
146 - [MT8173_POWER_DOMAIN_MFG_2D] = {
147 - .name = "mfg_2d",
148 - .sta_mask = PWR_STATUS_MFG_2D,
149 - .ctl_offs = SPM_MFG_2D_PWR_CON,
150 - .sram_pdn_bits = GENMASK(11, 8),
151 - .sram_pdn_ack_bits = GENMASK(13, 12),
152 - .clk_id = {MT8173_CLK_NONE},
153 - },
154 - [MT8173_POWER_DOMAIN_MFG] = {
155 - .name = "mfg",
156 - .sta_mask = PWR_STATUS_MFG,
157 - .ctl_offs = SPM_MFG_PWR_CON,
158 - .sram_pdn_bits = GENMASK(13, 8),
159 - .sram_pdn_ack_bits = GENMASK(21, 16),
160 - .clk_id = {MT8173_CLK_NONE},
161 - .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
162 - MT8173_TOP_AXI_PROT_EN_MFG_M0 |
163 - MT8173_TOP_AXI_PROT_EN_MFG_M1 |
164 - MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
165 - },
166 -};
167 -
168 -#define NUM_DOMAINS ARRAY_SIZE(scp_domain_data)
169 -
170 struct scp;
171
172 struct scp_domain {
173 @@ -179,7 +95,7 @@ struct scp_domain {
174 };
175
176 struct scp {
177 - struct scp_domain domains[NUM_DOMAINS];
178 + struct scp_domain *domains;
179 struct genpd_onecell_data pd_data;
180 struct device *dev;
181 void __iomem *base;
182 @@ -408,57 +324,55 @@ static bool scpsys_active_wakeup(struct
183 return scpd->data->active_wakeup;
184 }
185
186 -static int scpsys_probe(struct platform_device *pdev)
187 +static void init_clks(struct platform_device *pdev, struct clk **clk)
188 +{
189 + int i;
190 +
191 + for (i = CLK_NONE + 1; i < CLK_MAX; i++)
192 + clk[i] = devm_clk_get(&pdev->dev, clk_names[i]);
193 +}
194 +
195 +static struct scp *init_scp(struct platform_device *pdev,
196 + const struct scp_domain_data *scp_domain_data, int num)
197 {
198 struct genpd_onecell_data *pd_data;
199 struct resource *res;
200 - int i, j, ret;
201 + int i, j;
202 struct scp *scp;
203 - struct clk *clk[MT8173_CLK_MAX];
204 + struct clk *clk[CLK_MAX];
205
206 scp = devm_kzalloc(&pdev->dev, sizeof(*scp), GFP_KERNEL);
207 if (!scp)
208 - return -ENOMEM;
209 + return ERR_PTR(-ENOMEM);
210
211 scp->dev = &pdev->dev;
212
213 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
214 scp->base = devm_ioremap_resource(&pdev->dev, res);
215 if (IS_ERR(scp->base))
216 - return PTR_ERR(scp->base);
217 + return ERR_CAST(scp->base);
218 +
219 + scp->domains = devm_kzalloc(&pdev->dev,
220 + sizeof(*scp->domains) * num, GFP_KERNEL);
221 + if (!scp->domains)
222 + return ERR_PTR(-ENOMEM);
223
224 pd_data = &scp->pd_data;
225
226 pd_data->domains = devm_kzalloc(&pdev->dev,
227 - sizeof(*pd_data->domains) * NUM_DOMAINS, GFP_KERNEL);
228 + sizeof(*pd_data->domains) * num, GFP_KERNEL);
229 if (!pd_data->domains)
230 - return -ENOMEM;
231 -
232 - clk[MT8173_CLK_MM] = devm_clk_get(&pdev->dev, "mm");
233 - if (IS_ERR(clk[MT8173_CLK_MM]))
234 - return PTR_ERR(clk[MT8173_CLK_MM]);
235 -
236 - clk[MT8173_CLK_MFG] = devm_clk_get(&pdev->dev, "mfg");
237 - if (IS_ERR(clk[MT8173_CLK_MFG]))
238 - return PTR_ERR(clk[MT8173_CLK_MFG]);
239 -
240 - clk[MT8173_CLK_VENC] = devm_clk_get(&pdev->dev, "venc");
241 - if (IS_ERR(clk[MT8173_CLK_VENC]))
242 - return PTR_ERR(clk[MT8173_CLK_VENC]);
243 -
244 - clk[MT8173_CLK_VENC_LT] = devm_clk_get(&pdev->dev, "venc_lt");
245 - if (IS_ERR(clk[MT8173_CLK_VENC_LT]))
246 - return PTR_ERR(clk[MT8173_CLK_VENC_LT]);
247 + return ERR_PTR(-ENOMEM);
248
249 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
250 "infracfg");
251 if (IS_ERR(scp->infracfg)) {
252 dev_err(&pdev->dev, "Cannot find infracfg controller: %ld\n",
253 PTR_ERR(scp->infracfg));
254 - return PTR_ERR(scp->infracfg);
255 + return ERR_CAST(scp->infracfg);
256 }
257
258 - for (i = 0; i < NUM_DOMAINS; i++) {
259 + for (i = 0; i < num; i++) {
260 struct scp_domain *scpd = &scp->domains[i];
261 const struct scp_domain_data *data = &scp_domain_data[i];
262
263 @@ -467,13 +381,15 @@ static int scpsys_probe(struct platform_
264 if (PTR_ERR(scpd->supply) == -ENODEV)
265 scpd->supply = NULL;
266 else
267 - return PTR_ERR(scpd->supply);
268 + return ERR_CAST(scpd->supply);
269 }
270 }
271
272 - pd_data->num_domains = NUM_DOMAINS;
273 + pd_data->num_domains = num;
274 +
275 + init_clks(pdev, clk);
276
277 - for (i = 0; i < NUM_DOMAINS; i++) {
278 + for (i = 0; i < num; i++) {
279 struct scp_domain *scpd = &scp->domains[i];
280 struct generic_pm_domain *genpd = &scpd->genpd;
281 const struct scp_domain_data *data = &scp_domain_data[i];
282 @@ -482,13 +398,37 @@ static int scpsys_probe(struct platform_
283 scpd->scp = scp;
284
285 scpd->data = data;
286 - for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++)
287 - scpd->clk[j] = clk[data->clk_id[j]];
288 +
289 + for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++) {
290 + struct clk *c = clk[data->clk_id[j]];
291 +
292 + if (IS_ERR(c)) {
293 + dev_err(&pdev->dev, "%s: clk unavailable\n",
294 + data->name);
295 + return ERR_CAST(c);
296 + }
297 +
298 + scpd->clk[j] = c;
299 + }
300
301 genpd->name = data->name;
302 genpd->power_off = scpsys_power_off;
303 genpd->power_on = scpsys_power_on;
304 genpd->dev_ops.active_wakeup = scpsys_active_wakeup;
305 + }
306 +
307 + return scp;
308 +}
309 +
310 +static void mtk_register_power_domains(struct platform_device *pdev,
311 + struct scp *scp, int num)
312 +{
313 + struct genpd_onecell_data *pd_data;
314 + int i, ret;
315 +
316 + for (i = 0; i < num; i++) {
317 + struct scp_domain *scpd = &scp->domains[i];
318 + struct generic_pm_domain *genpd = &scpd->genpd;
319
320 /*
321 * Initially turn on all domains to make the domains usable
322 @@ -507,6 +447,123 @@ static int scpsys_probe(struct platform_
323 * valid.
324 */
325
326 + pd_data = &scp->pd_data;
327 +
328 + ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
329 + if (ret)
330 + dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
331 +}
332 +
333 +/*
334 + * MT8173 power domain support
335 + */
336 +
337 +static const struct scp_domain_data scp_domain_data_mt8173[] = {
338 + [MT8173_POWER_DOMAIN_VDEC] = {
339 + .name = "vdec",
340 + .sta_mask = PWR_STATUS_VDEC,
341 + .ctl_offs = SPM_VDE_PWR_CON,
342 + .sram_pdn_bits = GENMASK(11, 8),
343 + .sram_pdn_ack_bits = GENMASK(12, 12),
344 + .clk_id = {CLK_MM},
345 + },
346 + [MT8173_POWER_DOMAIN_VENC] = {
347 + .name = "venc",
348 + .sta_mask = PWR_STATUS_VENC,
349 + .ctl_offs = SPM_VEN_PWR_CON,
350 + .sram_pdn_bits = GENMASK(11, 8),
351 + .sram_pdn_ack_bits = GENMASK(15, 12),
352 + .clk_id = {CLK_MM, CLK_VENC},
353 + },
354 + [MT8173_POWER_DOMAIN_ISP] = {
355 + .name = "isp",
356 + .sta_mask = PWR_STATUS_ISP,
357 + .ctl_offs = SPM_ISP_PWR_CON,
358 + .sram_pdn_bits = GENMASK(11, 8),
359 + .sram_pdn_ack_bits = GENMASK(13, 12),
360 + .clk_id = {CLK_MM},
361 + },
362 + [MT8173_POWER_DOMAIN_MM] = {
363 + .name = "mm",
364 + .sta_mask = PWR_STATUS_DISP,
365 + .ctl_offs = SPM_DIS_PWR_CON,
366 + .sram_pdn_bits = GENMASK(11, 8),
367 + .sram_pdn_ack_bits = GENMASK(12, 12),
368 + .clk_id = {CLK_MM},
369 + .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
370 + MT8173_TOP_AXI_PROT_EN_MM_M1,
371 + },
372 + [MT8173_POWER_DOMAIN_VENC_LT] = {
373 + .name = "venc_lt",
374 + .sta_mask = PWR_STATUS_VENC_LT,
375 + .ctl_offs = SPM_VEN2_PWR_CON,
376 + .sram_pdn_bits = GENMASK(11, 8),
377 + .sram_pdn_ack_bits = GENMASK(15, 12),
378 + .clk_id = {CLK_MM, CLK_VENC_LT},
379 + },
380 + [MT8173_POWER_DOMAIN_AUDIO] = {
381 + .name = "audio",
382 + .sta_mask = PWR_STATUS_AUDIO,
383 + .ctl_offs = SPM_AUDIO_PWR_CON,
384 + .sram_pdn_bits = GENMASK(11, 8),
385 + .sram_pdn_ack_bits = GENMASK(15, 12),
386 + .clk_id = {CLK_NONE},
387 + },
388 + [MT8173_POWER_DOMAIN_USB] = {
389 + .name = "usb",
390 + .sta_mask = PWR_STATUS_USB,
391 + .ctl_offs = SPM_USB_PWR_CON,
392 + .sram_pdn_bits = GENMASK(11, 8),
393 + .sram_pdn_ack_bits = GENMASK(15, 12),
394 + .clk_id = {CLK_NONE},
395 + .active_wakeup = true,
396 + },
397 + [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
398 + .name = "mfg_async",
399 + .sta_mask = PWR_STATUS_MFG_ASYNC,
400 + .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
401 + .sram_pdn_bits = GENMASK(11, 8),
402 + .sram_pdn_ack_bits = 0,
403 + .clk_id = {CLK_MFG},
404 + },
405 + [MT8173_POWER_DOMAIN_MFG_2D] = {
406 + .name = "mfg_2d",
407 + .sta_mask = PWR_STATUS_MFG_2D,
408 + .ctl_offs = SPM_MFG_2D_PWR_CON,
409 + .sram_pdn_bits = GENMASK(11, 8),
410 + .sram_pdn_ack_bits = GENMASK(13, 12),
411 + .clk_id = {CLK_NONE},
412 + },
413 + [MT8173_POWER_DOMAIN_MFG] = {
414 + .name = "mfg",
415 + .sta_mask = PWR_STATUS_MFG,
416 + .ctl_offs = SPM_MFG_PWR_CON,
417 + .sram_pdn_bits = GENMASK(13, 8),
418 + .sram_pdn_ack_bits = GENMASK(21, 16),
419 + .clk_id = {CLK_NONE},
420 + .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
421 + MT8173_TOP_AXI_PROT_EN_MFG_M0 |
422 + MT8173_TOP_AXI_PROT_EN_MFG_M1 |
423 + MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT,
424 + },
425 +};
426 +
427 +#define NUM_DOMAINS_MT8173 ARRAY_SIZE(scp_domain_data_mt8173)
428 +
429 +static int __init scpsys_probe_mt8173(struct platform_device *pdev)
430 +{
431 + struct scp *scp;
432 + struct genpd_onecell_data *pd_data;
433 + int ret;
434 +
435 + scp = init_scp(pdev, scp_domain_data_mt8173, NUM_DOMAINS_MT8173);
436 + if (IS_ERR(scp))
437 + return PTR_ERR(scp);
438 +
439 + mtk_register_power_domains(pdev, scp, NUM_DOMAINS_MT8173);
440 +
441 + pd_data = &scp->pd_data;
442 +
443 ret = pm_genpd_add_subdomain(pd_data->domains[MT8173_POWER_DOMAIN_MFG_ASYNC],
444 pd_data->domains[MT8173_POWER_DOMAIN_MFG_2D]);
445 if (ret && IS_ENABLED(CONFIG_PM))
446 @@ -517,21 +574,36 @@ static int scpsys_probe(struct platform_
447 if (ret && IS_ENABLED(CONFIG_PM))
448 dev_err(&pdev->dev, "Failed to add subdomain: %d\n", ret);
449
450 - ret = of_genpd_add_provider_onecell(pdev->dev.of_node, pd_data);
451 - if (ret)
452 - dev_err(&pdev->dev, "Failed to add OF provider: %d\n", ret);
453 -
454 return 0;
455 }
456
457 +/*
458 + * scpsys driver init
459 + */
460 +
461 static const struct of_device_id of_scpsys_match_tbl[] = {
462 {
463 .compatible = "mediatek,mt8173-scpsys",
464 + .data = scpsys_probe_mt8173,
465 }, {
466 /* sentinel */
467 }
468 };
469
470 +static int scpsys_probe(struct platform_device *pdev)
471 +{
472 + int (*probe)(struct platform_device *);
473 + const struct of_device_id *of_id;
474 +
475 + of_id = of_match_node(of_scpsys_match_tbl, pdev->dev.of_node);
476 + if (!of_id || !of_id->data)
477 + return -EINVAL;
478 +
479 + probe = of_id->data;
480 +
481 + return probe(pdev);
482 +}
483 +
484 static struct platform_driver scpsys_drv = {
485 .probe = scpsys_probe,
486 .driver = {