1 // SPDX-License-Identifier: GPL-2.0+
2
3 /*
4 * Copyright 2021 Pengutronix, Lucas Stach <kernel@pengutronix.de>
5 */
6
7 #include <linux/device.h>
8 #include <linux/module.h>
9 #include <linux/of_device.h>
10 #include <linux/platform_device.h>
11 #include <linux/pm_domain.h>
12 #include <linux/pm_runtime.h>
13 #include <linux/regmap.h>
14 #include <linux/clk.h>
15
16 #include <dt-bindings/power/imx8mm-power.h>
17
18 #define BLK_SFT_RSTN 0x0
19 #define BLK_CLK_EN 0x4
20 #define BLK_MIPI_RESET_DIV 0x8 /* Mini/Nano DISPLAY_BLK_CTRL only */
21
22 struct imx8m_blk_ctrl_domain;
23
24 struct imx8m_blk_ctrl {
25 struct device *dev;
26 struct notifier_block power_nb;
27 struct device *bus_power_dev;
28 struct regmap *regmap;
29 struct imx8m_blk_ctrl_domain *domains;
30 struct genpd_onecell_data onecell_data;
31 };
32
33 struct imx8m_blk_ctrl_domain_data {
34 const char *name;
35 const char * const *clk_names;
36 int num_clks;
37 const char *gpc_name;
38 u32 rst_mask;
39 u32 clk_mask;
40
41 /*
42 * i.MX8M Mini and Nano have a third DISPLAY_BLK_CTRL register
43 * which is used to control the reset for the MIPI Phy.
44 * Since it's only present in certain circumstances,
45 * an if-statement should be used before setting and clearing this
46 * register.
47 */
48 u32 mipi_phy_rst_mask;
49 };
50
51 #define DOMAIN_MAX_CLKS 3
52
53 struct imx8m_blk_ctrl_domain {
54 struct generic_pm_domain genpd;
55 const struct imx8m_blk_ctrl_domain_data *data;
56 struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
57 struct device *power_dev;
58 struct imx8m_blk_ctrl *bc;
59 };
60
61 struct imx8m_blk_ctrl_data {
62 int max_reg;
63 notifier_fn_t power_notifier_fn;
64 const struct imx8m_blk_ctrl_domain_data *domains;
65 int num_domains;
66 };
67
68 static inline struct imx8m_blk_ctrl_domain *
to_imx8m_blk_ctrl_domain(struct generic_pm_domain * genpd)69 to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
70 {
71 return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
72 }
73
imx8m_blk_ctrl_power_on(struct generic_pm_domain * genpd)74 static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
75 {
76 struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
77 const struct imx8m_blk_ctrl_domain_data *data = domain->data;
78 struct imx8m_blk_ctrl *bc = domain->bc;
79 int ret;
80
81 /* make sure bus domain is awake */
82 ret = pm_runtime_get_sync(bc->bus_power_dev);
83 if (ret < 0) {
84 pm_runtime_put_noidle(bc->bus_power_dev);
85 dev_err(bc->dev, "failed to power up bus domain\n");
86 return ret;
87 }
88
89 /* put devices into reset */
90 regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
91 if (data->mipi_phy_rst_mask)
92 regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
93
94 /* enable upstream and blk-ctrl clocks to allow reset to propagate */
95 ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
96 if (ret) {
97 dev_err(bc->dev, "failed to enable clocks\n");
98 goto bus_put;
99 }
100 regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
101
102 /* power up upstream GPC domain */
103 ret = pm_runtime_get_sync(domain->power_dev);
104 if (ret < 0) {
105 dev_err(bc->dev, "failed to power up peripheral domain\n");
106 goto clk_disable;
107 }
108
109 /* wait for reset to propagate */
110 udelay(5);
111
112 /* release reset */
113 regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
114 if (data->mipi_phy_rst_mask)
115 regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
116
117 /* disable upstream clocks */
118 clk_bulk_disable_unprepare(data->num_clks, domain->clks);
119
120 return 0;
121
122 clk_disable:
123 clk_bulk_disable_unprepare(data->num_clks, domain->clks);
124 bus_put:
125 pm_runtime_put(bc->bus_power_dev);
126
127 return ret;
128 }
129
imx8m_blk_ctrl_power_off(struct generic_pm_domain * genpd)130 static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
131 {
132 struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
133 const struct imx8m_blk_ctrl_domain_data *data = domain->data;
134 struct imx8m_blk_ctrl *bc = domain->bc;
135
136 /* put devices into reset and disable clocks */
137 if (data->mipi_phy_rst_mask)
138 regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
139
140 regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
141 regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
142
143 /* power down upstream GPC domain */
144 pm_runtime_put(domain->power_dev);
145
146 /* allow bus domain to suspend */
147 pm_runtime_put(bc->bus_power_dev);
148
149 return 0;
150 }
151
152 static struct generic_pm_domain *
imx8m_blk_ctrl_xlate(struct of_phandle_args * args,void * data)153 imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data)
154 {
155 struct genpd_onecell_data *onecell_data = data;
156 unsigned int index = args->args[0];
157
158 if (args->args_count != 1 ||
159 index >= onecell_data->num_domains)
160 return ERR_PTR(-EINVAL);
161
162 return onecell_data->domains[index];
163 }
164
165 static struct lock_class_key blk_ctrl_genpd_lock_class;
166
imx8m_blk_ctrl_probe(struct platform_device * pdev)167 static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
168 {
169 const struct imx8m_blk_ctrl_data *bc_data;
170 struct device *dev = &pdev->dev;
171 struct imx8m_blk_ctrl *bc;
172 void __iomem *base;
173 int i, ret;
174
175 struct regmap_config regmap_config = {
176 .reg_bits = 32,
177 .val_bits = 32,
178 .reg_stride = 4,
179 };
180
181 bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
182 if (!bc)
183 return -ENOMEM;
184
185 bc->dev = dev;
186
187 bc_data = of_device_get_match_data(dev);
188
189 base = devm_platform_ioremap_resource(pdev, 0);
190 if (IS_ERR(base))
191 return PTR_ERR(base);
192
193 regmap_config.max_register = bc_data->max_reg;
194 bc->regmap = devm_regmap_init_mmio(dev, base, ®map_config);
195 if (IS_ERR(bc->regmap))
196 return dev_err_probe(dev, PTR_ERR(bc->regmap),
197 "failed to init regmap\n");
198
199 bc->domains = devm_kcalloc(dev, bc_data->num_domains,
200 sizeof(struct imx8m_blk_ctrl_domain),
201 GFP_KERNEL);
202 if (!bc->domains)
203 return -ENOMEM;
204
205 bc->onecell_data.num_domains = bc_data->num_domains;
206 bc->onecell_data.xlate = imx8m_blk_ctrl_xlate;
207 bc->onecell_data.domains =
208 devm_kcalloc(dev, bc_data->num_domains,
209 sizeof(struct generic_pm_domain *), GFP_KERNEL);
210 if (!bc->onecell_data.domains)
211 return -ENOMEM;
212
213 bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
214 if (IS_ERR(bc->bus_power_dev))
215 return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
216 "failed to attach power domain\n");
217
218 for (i = 0; i < bc_data->num_domains; i++) {
219 const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
220 struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
221 int j;
222
223 domain->data = data;
224
225 for (j = 0; j < data->num_clks; j++)
226 domain->clks[j].id = data->clk_names[j];
227
228 ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
229 if (ret) {
230 dev_err_probe(dev, ret, "failed to get clock\n");
231 goto cleanup_pds;
232 }
233
234 domain->power_dev =
235 dev_pm_domain_attach_by_name(dev, data->gpc_name);
236 if (IS_ERR(domain->power_dev)) {
237 dev_err_probe(dev, PTR_ERR(domain->power_dev),
238 "failed to attach power domain\n");
239 ret = PTR_ERR(domain->power_dev);
240 goto cleanup_pds;
241 }
242
243 domain->genpd.name = data->name;
244 domain->genpd.power_on = imx8m_blk_ctrl_power_on;
245 domain->genpd.power_off = imx8m_blk_ctrl_power_off;
246 domain->bc = bc;
247
248 ret = pm_genpd_init(&domain->genpd, NULL, true);
249 if (ret) {
250 dev_err_probe(dev, ret, "failed to init power domain\n");
251 dev_pm_domain_detach(domain->power_dev, true);
252 goto cleanup_pds;
253 }
254
255 /*
256 * We use runtime PM to trigger power on/off of the upstream GPC
257 * domain, as a strict hierarchical parent/child power domain
258 * setup doesn't allow us to meet the sequencing requirements.
259 * This means we have nested locking of genpd locks, without the
260 * nesting being visible at the genpd level, so we need a
261 * separate lock class to make lockdep aware of the fact that
262 * this are separate domain locks that can be nested without a
263 * self-deadlock.
264 */
265 lockdep_set_class(&domain->genpd.mlock,
266 &blk_ctrl_genpd_lock_class);
267
268 bc->onecell_data.domains[i] = &domain->genpd;
269 }
270
271 ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
272 if (ret) {
273 dev_err_probe(dev, ret, "failed to add power domain provider\n");
274 goto cleanup_pds;
275 }
276
277 bc->power_nb.notifier_call = bc_data->power_notifier_fn;
278 ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
279 if (ret) {
280 dev_err_probe(dev, ret, "failed to add power notifier\n");
281 goto cleanup_provider;
282 }
283
284 dev_set_drvdata(dev, bc);
285
286 return 0;
287
288 cleanup_provider:
289 of_genpd_del_provider(dev->of_node);
290 cleanup_pds:
291 for (i--; i >= 0; i--) {
292 pm_genpd_remove(&bc->domains[i].genpd);
293 dev_pm_domain_detach(bc->domains[i].power_dev, true);
294 }
295
296 dev_pm_domain_detach(bc->bus_power_dev, true);
297
298 return ret;
299 }
300
imx8m_blk_ctrl_remove(struct platform_device * pdev)301 static int imx8m_blk_ctrl_remove(struct platform_device *pdev)
302 {
303 struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
304 int i;
305
306 of_genpd_del_provider(pdev->dev.of_node);
307
308 for (i = 0; bc->onecell_data.num_domains; i++) {
309 struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
310
311 pm_genpd_remove(&domain->genpd);
312 dev_pm_domain_detach(domain->power_dev, true);
313 }
314
315 dev_pm_genpd_remove_notifier(bc->bus_power_dev);
316
317 dev_pm_domain_detach(bc->bus_power_dev, true);
318
319 return 0;
320 }
321
322 #ifdef CONFIG_PM_SLEEP
imx8m_blk_ctrl_suspend(struct device * dev)323 static int imx8m_blk_ctrl_suspend(struct device *dev)
324 {
325 struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
326 int ret, i;
327
328 /*
329 * This may look strange, but is done so the generic PM_SLEEP code
330 * can power down our domains and more importantly power them up again
331 * after resume, without tripping over our usage of runtime PM to
332 * control the upstream GPC domains. Things happen in the right order
333 * in the system suspend/resume paths due to the device parent/child
334 * hierarchy.
335 */
336 ret = pm_runtime_get_sync(bc->bus_power_dev);
337 if (ret < 0) {
338 pm_runtime_put_noidle(bc->bus_power_dev);
339 return ret;
340 }
341
342 for (i = 0; i < bc->onecell_data.num_domains; i++) {
343 struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
344
345 ret = pm_runtime_get_sync(domain->power_dev);
346 if (ret < 0) {
347 pm_runtime_put_noidle(domain->power_dev);
348 goto out_fail;
349 }
350 }
351
352 return 0;
353
354 out_fail:
355 for (i--; i >= 0; i--)
356 pm_runtime_put(bc->domains[i].power_dev);
357
358 pm_runtime_put(bc->bus_power_dev);
359
360 return ret;
361 }
362
imx8m_blk_ctrl_resume(struct device * dev)363 static int imx8m_blk_ctrl_resume(struct device *dev)
364 {
365 struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
366 int i;
367
368 for (i = 0; i < bc->onecell_data.num_domains; i++)
369 pm_runtime_put(bc->domains[i].power_dev);
370
371 pm_runtime_put(bc->bus_power_dev);
372
373 return 0;
374 }
375 #endif
376
377 static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = {
378 SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume)
379 };
380
imx8mm_vpu_power_notifier(struct notifier_block * nb,unsigned long action,void * data)381 static int imx8mm_vpu_power_notifier(struct notifier_block *nb,
382 unsigned long action, void *data)
383 {
384 struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
385 power_nb);
386
387 if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
388 return NOTIFY_OK;
389
390 /*
391 * The ADB in the VPUMIX domain has no separate reset and clock
392 * enable bits, but is ungated together with the VPU clocks. To
393 * allow the handshake with the GPC to progress we put the VPUs
394 * in reset and ungate the clocks.
395 */
396 regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2));
397 regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2));
398
399 if (action == GENPD_NOTIFY_ON) {
400 /*
401 * On power up we have no software backchannel to the GPC to
402 * wait for the ADB handshake to happen, so we just delay for a
403 * bit. On power down the GPC driver waits for the handshake.
404 */
405 udelay(5);
406
407 /* set "fuse" bits to enable the VPUs */
408 regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
409 regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
410 regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
411 regmap_set_bits(bc->regmap, 0x14, 0xffffffff);
412 }
413
414 return NOTIFY_OK;
415 }
416
417 static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = {
418 [IMX8MM_VPUBLK_PD_G1] = {
419 .name = "vpublk-g1",
420 .clk_names = (const char *[]){ "g1", },
421 .num_clks = 1,
422 .gpc_name = "g1",
423 .rst_mask = BIT(1),
424 .clk_mask = BIT(1),
425 },
426 [IMX8MM_VPUBLK_PD_G2] = {
427 .name = "vpublk-g2",
428 .clk_names = (const char *[]){ "g2", },
429 .num_clks = 1,
430 .gpc_name = "g2",
431 .rst_mask = BIT(0),
432 .clk_mask = BIT(0),
433 },
434 [IMX8MM_VPUBLK_PD_H1] = {
435 .name = "vpublk-h1",
436 .clk_names = (const char *[]){ "h1", },
437 .num_clks = 1,
438 .gpc_name = "h1",
439 .rst_mask = BIT(2),
440 .clk_mask = BIT(2),
441 },
442 };
443
444 static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
445 .max_reg = 0x18,
446 .power_notifier_fn = imx8mm_vpu_power_notifier,
447 .domains = imx8mm_vpu_blk_ctl_domain_data,
448 .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
449 };
450
imx8mm_disp_power_notifier(struct notifier_block * nb,unsigned long action,void * data)451 static int imx8mm_disp_power_notifier(struct notifier_block *nb,
452 unsigned long action, void *data)
453 {
454 struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
455 power_nb);
456
457 if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
458 return NOTIFY_OK;
459
460 /* Enable bus clock and deassert bus reset */
461 regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12));
462 regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6));
463
464 /*
465 * On power up we have no software backchannel to the GPC to
466 * wait for the ADB handshake to happen, so we just delay for a
467 * bit. On power down the GPC driver waits for the handshake.
468 */
469 if (action == GENPD_NOTIFY_ON)
470 udelay(5);
471
472
473 return NOTIFY_OK;
474 }
475
476 static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
477 [IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
478 .name = "dispblk-csi-bridge",
479 .clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
480 "csi-bridge-core", },
481 .num_clks = 3,
482 .gpc_name = "csi-bridge",
483 .rst_mask = BIT(0) | BIT(1) | BIT(2),
484 .clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
485 },
486 [IMX8MM_DISPBLK_PD_LCDIF] = {
487 .name = "dispblk-lcdif",
488 .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
489 .num_clks = 3,
490 .gpc_name = "lcdif",
491 .clk_mask = BIT(6) | BIT(7),
492 },
493 [IMX8MM_DISPBLK_PD_MIPI_DSI] = {
494 .name = "dispblk-mipi-dsi",
495 .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
496 .num_clks = 2,
497 .gpc_name = "mipi-dsi",
498 .rst_mask = BIT(5),
499 .clk_mask = BIT(8) | BIT(9),
500 .mipi_phy_rst_mask = BIT(17),
501 },
502 [IMX8MM_DISPBLK_PD_MIPI_CSI] = {
503 .name = "dispblk-mipi-csi",
504 .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
505 .num_clks = 2,
506 .gpc_name = "mipi-csi",
507 .rst_mask = BIT(3) | BIT(4),
508 .clk_mask = BIT(10) | BIT(11),
509 .mipi_phy_rst_mask = BIT(16),
510 },
511 };
512
513 static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
514 .max_reg = 0x2c,
515 .power_notifier_fn = imx8mm_disp_power_notifier,
516 .domains = imx8mm_disp_blk_ctl_domain_data,
517 .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
518 };
519
520 static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
521 {
522 .compatible = "fsl,imx8mm-vpu-blk-ctrl",
523 .data = &imx8mm_vpu_blk_ctl_dev_data
524 }, {
525 .compatible = "fsl,imx8mm-disp-blk-ctrl",
526 .data = &imx8mm_disp_blk_ctl_dev_data
527 } ,{
528 /* Sentinel */
529 }
530 };
531 MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
532
533 static struct platform_driver imx8m_blk_ctrl_driver = {
534 .probe = imx8m_blk_ctrl_probe,
535 .remove = imx8m_blk_ctrl_remove,
536 .driver = {
537 .name = "imx8m-blk-ctrl",
538 .pm = &imx8m_blk_ctrl_pm_ops,
539 .of_match_table = imx8m_blk_ctrl_of_match,
540 },
541 };
542 module_platform_driver(imx8m_blk_ctrl_driver);
543