7ebc28709e9455aba1fc4a88b9af9f2bb7b6a684
[releases.git] / imx8m-blk-ctrl.c
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 #include <dt-bindings/power/imx8mn-power.h>
18 #include <dt-bindings/power/imx8mp-power.h>
19 #include <dt-bindings/power/imx8mq-power.h>
20
21 #define BLK_SFT_RSTN    0x0
22 #define BLK_CLK_EN      0x4
23 #define BLK_MIPI_RESET_DIV      0x8 /* Mini/Nano/Plus DISPLAY_BLK_CTRL only */
24
25 struct imx8m_blk_ctrl_domain;
26
27 struct imx8m_blk_ctrl {
28         struct device *dev;
29         struct notifier_block power_nb;
30         struct device *bus_power_dev;
31         struct regmap *regmap;
32         struct imx8m_blk_ctrl_domain *domains;
33         struct genpd_onecell_data onecell_data;
34 };
35
36 struct imx8m_blk_ctrl_domain_data {
37         const char *name;
38         const char * const *clk_names;
39         int num_clks;
40         const char *gpc_name;
41         u32 rst_mask;
42         u32 clk_mask;
43
44         /*
45          * i.MX8M Mini, Nano and Plus have a third DISPLAY_BLK_CTRL register
46          * which is used to control the reset for the MIPI Phy.
47          * Since it's only present in certain circumstances,
48          * an if-statement should be used before setting and clearing this
49          * register.
50          */
51         u32 mipi_phy_rst_mask;
52 };
53
54 #define DOMAIN_MAX_CLKS 4
55
56 struct imx8m_blk_ctrl_domain {
57         struct generic_pm_domain genpd;
58         const struct imx8m_blk_ctrl_domain_data *data;
59         struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
60         struct device *power_dev;
61         struct imx8m_blk_ctrl *bc;
62 };
63
64 struct imx8m_blk_ctrl_data {
65         int max_reg;
66         notifier_fn_t power_notifier_fn;
67         const struct imx8m_blk_ctrl_domain_data *domains;
68         int num_domains;
69 };
70
71 static inline struct imx8m_blk_ctrl_domain *
72 to_imx8m_blk_ctrl_domain(struct generic_pm_domain *genpd)
73 {
74         return container_of(genpd, struct imx8m_blk_ctrl_domain, genpd);
75 }
76
77 static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
78 {
79         struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
80         const struct imx8m_blk_ctrl_domain_data *data = domain->data;
81         struct imx8m_blk_ctrl *bc = domain->bc;
82         int ret;
83
84         /* make sure bus domain is awake */
85         ret = pm_runtime_get_sync(bc->bus_power_dev);
86         if (ret < 0) {
87                 pm_runtime_put_noidle(bc->bus_power_dev);
88                 dev_err(bc->dev, "failed to power up bus domain\n");
89                 return ret;
90         }
91
92         /* put devices into reset */
93         regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
94         if (data->mipi_phy_rst_mask)
95                 regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
96
97         /* enable upstream and blk-ctrl clocks to allow reset to propagate */
98         ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
99         if (ret) {
100                 dev_err(bc->dev, "failed to enable clocks\n");
101                 goto bus_put;
102         }
103         regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
104
105         /* power up upstream GPC domain */
106         ret = pm_runtime_get_sync(domain->power_dev);
107         if (ret < 0) {
108                 dev_err(bc->dev, "failed to power up peripheral domain\n");
109                 goto clk_disable;
110         }
111
112         /* wait for reset to propagate */
113         udelay(5);
114
115         /* release reset */
116         regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
117         if (data->mipi_phy_rst_mask)
118                 regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
119
120         /* disable upstream clocks */
121         clk_bulk_disable_unprepare(data->num_clks, domain->clks);
122
123         return 0;
124
125 clk_disable:
126         clk_bulk_disable_unprepare(data->num_clks, domain->clks);
127 bus_put:
128         pm_runtime_put(bc->bus_power_dev);
129
130         return ret;
131 }
132
133 static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
134 {
135         struct imx8m_blk_ctrl_domain *domain = to_imx8m_blk_ctrl_domain(genpd);
136         const struct imx8m_blk_ctrl_domain_data *data = domain->data;
137         struct imx8m_blk_ctrl *bc = domain->bc;
138
139         /* put devices into reset and disable clocks */
140         if (data->mipi_phy_rst_mask)
141                 regmap_clear_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
142
143         regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
144         regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
145
146         /* power down upstream GPC domain */
147         pm_runtime_put(domain->power_dev);
148
149         /* allow bus domain to suspend */
150         pm_runtime_put(bc->bus_power_dev);
151
152         return 0;
153 }
154
155 static struct generic_pm_domain *
156 imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data)
157 {
158         struct genpd_onecell_data *onecell_data = data;
159         unsigned int index = args->args[0];
160
161         if (args->args_count != 1 ||
162             index >= onecell_data->num_domains)
163                 return ERR_PTR(-EINVAL);
164
165         return onecell_data->domains[index];
166 }
167
168 static struct lock_class_key blk_ctrl_genpd_lock_class;
169
170 static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
171 {
172         const struct imx8m_blk_ctrl_data *bc_data;
173         struct device *dev = &pdev->dev;
174         struct imx8m_blk_ctrl *bc;
175         void __iomem *base;
176         int i, ret;
177
178         struct regmap_config regmap_config = {
179                 .reg_bits       = 32,
180                 .val_bits       = 32,
181                 .reg_stride     = 4,
182         };
183
184         bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
185         if (!bc)
186                 return -ENOMEM;
187
188         bc->dev = dev;
189
190         bc_data = of_device_get_match_data(dev);
191
192         base = devm_platform_ioremap_resource(pdev, 0);
193         if (IS_ERR(base))
194                 return PTR_ERR(base);
195
196         regmap_config.max_register = bc_data->max_reg;
197         bc->regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
198         if (IS_ERR(bc->regmap))
199                 return dev_err_probe(dev, PTR_ERR(bc->regmap),
200                                      "failed to init regmap\n");
201
202         bc->domains = devm_kcalloc(dev, bc_data->num_domains,
203                                    sizeof(struct imx8m_blk_ctrl_domain),
204                                    GFP_KERNEL);
205         if (!bc->domains)
206                 return -ENOMEM;
207
208         bc->onecell_data.num_domains = bc_data->num_domains;
209         bc->onecell_data.xlate = imx8m_blk_ctrl_xlate;
210         bc->onecell_data.domains =
211                 devm_kcalloc(dev, bc_data->num_domains,
212                              sizeof(struct generic_pm_domain *), GFP_KERNEL);
213         if (!bc->onecell_data.domains)
214                 return -ENOMEM;
215
216         bc->bus_power_dev = genpd_dev_pm_attach_by_name(dev, "bus");
217         if (IS_ERR(bc->bus_power_dev))
218                 return dev_err_probe(dev, PTR_ERR(bc->bus_power_dev),
219                                      "failed to attach power domain\n");
220
221         for (i = 0; i < bc_data->num_domains; i++) {
222                 const struct imx8m_blk_ctrl_domain_data *data = &bc_data->domains[i];
223                 struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
224                 int j;
225
226                 domain->data = data;
227
228                 for (j = 0; j < data->num_clks; j++)
229                         domain->clks[j].id = data->clk_names[j];
230
231                 ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
232                 if (ret) {
233                         dev_err_probe(dev, ret, "failed to get clock\n");
234                         goto cleanup_pds;
235                 }
236
237                 domain->power_dev =
238                         dev_pm_domain_attach_by_name(dev, data->gpc_name);
239                 if (IS_ERR(domain->power_dev)) {
240                         dev_err_probe(dev, PTR_ERR(domain->power_dev),
241                                       "failed to attach power domain\n");
242                         ret = PTR_ERR(domain->power_dev);
243                         goto cleanup_pds;
244                 }
245                 dev_set_name(domain->power_dev, "%s", data->name);
246
247                 domain->genpd.name = data->name;
248                 domain->genpd.power_on = imx8m_blk_ctrl_power_on;
249                 domain->genpd.power_off = imx8m_blk_ctrl_power_off;
250                 domain->bc = bc;
251
252                 ret = pm_genpd_init(&domain->genpd, NULL, true);
253                 if (ret) {
254                         dev_err_probe(dev, ret, "failed to init power domain\n");
255                         dev_pm_domain_detach(domain->power_dev, true);
256                         goto cleanup_pds;
257                 }
258
259                 /*
260                  * We use runtime PM to trigger power on/off of the upstream GPC
261                  * domain, as a strict hierarchical parent/child power domain
262                  * setup doesn't allow us to meet the sequencing requirements.
263                  * This means we have nested locking of genpd locks, without the
264                  * nesting being visible at the genpd level, so we need a
265                  * separate lock class to make lockdep aware of the fact that
266                  * this are separate domain locks that can be nested without a
267                  * self-deadlock.
268                  */
269                 lockdep_set_class(&domain->genpd.mlock,
270                                   &blk_ctrl_genpd_lock_class);
271
272                 bc->onecell_data.domains[i] = &domain->genpd;
273         }
274
275         ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
276         if (ret) {
277                 dev_err_probe(dev, ret, "failed to add power domain provider\n");
278                 goto cleanup_pds;
279         }
280
281         bc->power_nb.notifier_call = bc_data->power_notifier_fn;
282         ret = dev_pm_genpd_add_notifier(bc->bus_power_dev, &bc->power_nb);
283         if (ret) {
284                 dev_err_probe(dev, ret, "failed to add power notifier\n");
285                 goto cleanup_provider;
286         }
287
288         dev_set_drvdata(dev, bc);
289
290         return 0;
291
292 cleanup_provider:
293         of_genpd_del_provider(dev->of_node);
294 cleanup_pds:
295         for (i--; i >= 0; i--) {
296                 pm_genpd_remove(&bc->domains[i].genpd);
297                 dev_pm_domain_detach(bc->domains[i].power_dev, true);
298         }
299
300         dev_pm_domain_detach(bc->bus_power_dev, true);
301
302         return ret;
303 }
304
305 static int imx8m_blk_ctrl_remove(struct platform_device *pdev)
306 {
307         struct imx8m_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
308         int i;
309
310         of_genpd_del_provider(pdev->dev.of_node);
311
312         for (i = 0; bc->onecell_data.num_domains; i++) {
313                 struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
314
315                 pm_genpd_remove(&domain->genpd);
316                 dev_pm_domain_detach(domain->power_dev, true);
317         }
318
319         dev_pm_genpd_remove_notifier(bc->bus_power_dev);
320
321         dev_pm_domain_detach(bc->bus_power_dev, true);
322
323         return 0;
324 }
325
326 #ifdef CONFIG_PM_SLEEP
327 static int imx8m_blk_ctrl_suspend(struct device *dev)
328 {
329         struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
330         int ret, i;
331
332         /*
333          * This may look strange, but is done so the generic PM_SLEEP code
334          * can power down our domains and more importantly power them up again
335          * after resume, without tripping over our usage of runtime PM to
336          * control the upstream GPC domains. Things happen in the right order
337          * in the system suspend/resume paths due to the device parent/child
338          * hierarchy.
339          */
340         ret = pm_runtime_get_sync(bc->bus_power_dev);
341         if (ret < 0) {
342                 pm_runtime_put_noidle(bc->bus_power_dev);
343                 return ret;
344         }
345
346         for (i = 0; i < bc->onecell_data.num_domains; i++) {
347                 struct imx8m_blk_ctrl_domain *domain = &bc->domains[i];
348
349                 ret = pm_runtime_get_sync(domain->power_dev);
350                 if (ret < 0) {
351                         pm_runtime_put_noidle(domain->power_dev);
352                         goto out_fail;
353                 }
354         }
355
356         return 0;
357
358 out_fail:
359         for (i--; i >= 0; i--)
360                 pm_runtime_put(bc->domains[i].power_dev);
361
362         pm_runtime_put(bc->bus_power_dev);
363
364         return ret;
365 }
366
367 static int imx8m_blk_ctrl_resume(struct device *dev)
368 {
369         struct imx8m_blk_ctrl *bc = dev_get_drvdata(dev);
370         int i;
371
372         for (i = 0; i < bc->onecell_data.num_domains; i++)
373                 pm_runtime_put(bc->domains[i].power_dev);
374
375         pm_runtime_put(bc->bus_power_dev);
376
377         return 0;
378 }
379 #endif
380
381 static const struct dev_pm_ops imx8m_blk_ctrl_pm_ops = {
382         SET_SYSTEM_SLEEP_PM_OPS(imx8m_blk_ctrl_suspend, imx8m_blk_ctrl_resume)
383 };
384
385 static int imx8mm_vpu_power_notifier(struct notifier_block *nb,
386                                      unsigned long action, void *data)
387 {
388         struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
389                                                  power_nb);
390
391         if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
392                 return NOTIFY_OK;
393
394         /*
395          * The ADB in the VPUMIX domain has no separate reset and clock
396          * enable bits, but is ungated together with the VPU clocks. To
397          * allow the handshake with the GPC to progress we put the VPUs
398          * in reset and ungate the clocks.
399          */
400         regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1) | BIT(2));
401         regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1) | BIT(2));
402
403         if (action == GENPD_NOTIFY_ON) {
404                 /*
405                  * On power up we have no software backchannel to the GPC to
406                  * wait for the ADB handshake to happen, so we just delay for a
407                  * bit. On power down the GPC driver waits for the handshake.
408                  */
409                 udelay(5);
410
411                 /* set "fuse" bits to enable the VPUs */
412                 regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
413                 regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
414                 regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
415                 regmap_set_bits(bc->regmap, 0x14, 0xffffffff);
416         }
417
418         return NOTIFY_OK;
419 }
420
421 static const struct imx8m_blk_ctrl_domain_data imx8mm_vpu_blk_ctl_domain_data[] = {
422         [IMX8MM_VPUBLK_PD_G1] = {
423                 .name = "vpublk-g1",
424                 .clk_names = (const char *[]){ "g1", },
425                 .num_clks = 1,
426                 .gpc_name = "g1",
427                 .rst_mask = BIT(1),
428                 .clk_mask = BIT(1),
429         },
430         [IMX8MM_VPUBLK_PD_G2] = {
431                 .name = "vpublk-g2",
432                 .clk_names = (const char *[]){ "g2", },
433                 .num_clks = 1,
434                 .gpc_name = "g2",
435                 .rst_mask = BIT(0),
436                 .clk_mask = BIT(0),
437         },
438         [IMX8MM_VPUBLK_PD_H1] = {
439                 .name = "vpublk-h1",
440                 .clk_names = (const char *[]){ "h1", },
441                 .num_clks = 1,
442                 .gpc_name = "h1",
443                 .rst_mask = BIT(2),
444                 .clk_mask = BIT(2),
445         },
446 };
447
448 static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
449         .max_reg = 0x18,
450         .power_notifier_fn = imx8mm_vpu_power_notifier,
451         .domains = imx8mm_vpu_blk_ctl_domain_data,
452         .num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
453 };
454
455 static int imx8mm_disp_power_notifier(struct notifier_block *nb,
456                                       unsigned long action, void *data)
457 {
458         struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
459                                                  power_nb);
460
461         if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
462                 return NOTIFY_OK;
463
464         /* Enable bus clock and deassert bus reset */
465         regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(12));
466         regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(6));
467
468         /*
469          * On power up we have no software backchannel to the GPC to
470          * wait for the ADB handshake to happen, so we just delay for a
471          * bit. On power down the GPC driver waits for the handshake.
472          */
473         if (action == GENPD_NOTIFY_ON)
474                 udelay(5);
475
476
477         return NOTIFY_OK;
478 }
479
480 static const struct imx8m_blk_ctrl_domain_data imx8mm_disp_blk_ctl_domain_data[] = {
481         [IMX8MM_DISPBLK_PD_CSI_BRIDGE] = {
482                 .name = "dispblk-csi-bridge",
483                 .clk_names = (const char *[]){ "csi-bridge-axi", "csi-bridge-apb",
484                                                "csi-bridge-core", },
485                 .num_clks = 3,
486                 .gpc_name = "csi-bridge",
487                 .rst_mask = BIT(0) | BIT(1) | BIT(2),
488                 .clk_mask = BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5),
489         },
490         [IMX8MM_DISPBLK_PD_LCDIF] = {
491                 .name = "dispblk-lcdif",
492                 .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
493                 .num_clks = 3,
494                 .gpc_name = "lcdif",
495                 .clk_mask = BIT(6) | BIT(7),
496         },
497         [IMX8MM_DISPBLK_PD_MIPI_DSI] = {
498                 .name = "dispblk-mipi-dsi",
499                 .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
500                 .num_clks = 2,
501                 .gpc_name = "mipi-dsi",
502                 .rst_mask = BIT(5),
503                 .clk_mask = BIT(8) | BIT(9),
504                 .mipi_phy_rst_mask = BIT(17),
505         },
506         [IMX8MM_DISPBLK_PD_MIPI_CSI] = {
507                 .name = "dispblk-mipi-csi",
508                 .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
509                 .num_clks = 2,
510                 .gpc_name = "mipi-csi",
511                 .rst_mask = BIT(3) | BIT(4),
512                 .clk_mask = BIT(10) | BIT(11),
513                 .mipi_phy_rst_mask = BIT(16),
514         },
515 };
516
517 static const struct imx8m_blk_ctrl_data imx8mm_disp_blk_ctl_dev_data = {
518         .max_reg = 0x2c,
519         .power_notifier_fn = imx8mm_disp_power_notifier,
520         .domains = imx8mm_disp_blk_ctl_domain_data,
521         .num_domains = ARRAY_SIZE(imx8mm_disp_blk_ctl_domain_data),
522 };
523
524
525 static int imx8mn_disp_power_notifier(struct notifier_block *nb,
526                                       unsigned long action, void *data)
527 {
528         struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
529                                                  power_nb);
530
531         if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
532                 return NOTIFY_OK;
533
534         /* Enable bus clock and deassert bus reset */
535         regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
536         regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
537
538         /*
539          * On power up we have no software backchannel to the GPC to
540          * wait for the ADB handshake to happen, so we just delay for a
541          * bit. On power down the GPC driver waits for the handshake.
542          */
543         if (action == GENPD_NOTIFY_ON)
544                 udelay(5);
545
546
547         return NOTIFY_OK;
548 }
549
550 static const struct imx8m_blk_ctrl_domain_data imx8mn_disp_blk_ctl_domain_data[] = {
551         [IMX8MN_DISPBLK_PD_MIPI_DSI] = {
552                 .name = "dispblk-mipi-dsi",
553                 .clk_names = (const char *[]){ "dsi-pclk", "dsi-ref", },
554                 .num_clks = 2,
555                 .gpc_name = "mipi-dsi",
556                 .rst_mask = BIT(0) | BIT(1),
557                 .clk_mask = BIT(0) | BIT(1),
558                 .mipi_phy_rst_mask = BIT(17),
559         },
560         [IMX8MN_DISPBLK_PD_MIPI_CSI] = {
561                 .name = "dispblk-mipi-csi",
562                 .clk_names = (const char *[]){ "csi-aclk", "csi-pclk" },
563                 .num_clks = 2,
564                 .gpc_name = "mipi-csi",
565                 .rst_mask = BIT(2) | BIT(3),
566                 .clk_mask = BIT(2) | BIT(3),
567                 .mipi_phy_rst_mask = BIT(16),
568         },
569         [IMX8MN_DISPBLK_PD_LCDIF] = {
570                 .name = "dispblk-lcdif",
571                 .clk_names = (const char *[]){ "lcdif-axi", "lcdif-apb", "lcdif-pix", },
572                 .num_clks = 3,
573                 .gpc_name = "lcdif",
574                 .rst_mask = BIT(4) | BIT(5),
575                 .clk_mask = BIT(4) | BIT(5),
576         },
577         [IMX8MN_DISPBLK_PD_ISI] = {
578                 .name = "dispblk-isi",
579                 .clk_names = (const char *[]){ "disp_axi", "disp_apb", "disp_axi_root",
580                                                 "disp_apb_root"},
581                 .num_clks = 4,
582                 .gpc_name = "isi",
583                 .rst_mask = BIT(6) | BIT(7),
584                 .clk_mask = BIT(6) | BIT(7),
585         },
586 };
587
588 static const struct imx8m_blk_ctrl_data imx8mn_disp_blk_ctl_dev_data = {
589         .max_reg = 0x84,
590         .power_notifier_fn = imx8mn_disp_power_notifier,
591         .domains = imx8mn_disp_blk_ctl_domain_data,
592         .num_domains = ARRAY_SIZE(imx8mn_disp_blk_ctl_domain_data),
593 };
594
595 static int imx8mp_media_power_notifier(struct notifier_block *nb,
596                                 unsigned long action, void *data)
597 {
598         struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
599                                                  power_nb);
600
601         if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
602                 return NOTIFY_OK;
603
604         /* Enable bus clock and deassert bus reset */
605         regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(8));
606         regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(8));
607
608         /*
609          * On power up we have no software backchannel to the GPC to
610          * wait for the ADB handshake to happen, so we just delay for a
611          * bit. On power down the GPC driver waits for the handshake.
612          */
613         if (action == GENPD_NOTIFY_ON)
614                 udelay(5);
615
616         return NOTIFY_OK;
617 }
618
619 /*
620  * From i.MX 8M Plus Applications Processor Reference Manual, Rev. 1,
621  * section 13.2.2, 13.2.3
622  * isp-ahb and dwe are not in Figure 13-5. Media BLK_CTRL Clocks
623  */
624 static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[] = {
625         [IMX8MP_MEDIABLK_PD_MIPI_DSI_1] = {
626                 .name = "mediablk-mipi-dsi-1",
627                 .clk_names = (const char *[]){ "apb", "phy", },
628                 .num_clks = 2,
629                 .gpc_name = "mipi-dsi1",
630                 .rst_mask = BIT(0) | BIT(1),
631                 .clk_mask = BIT(0) | BIT(1),
632                 .mipi_phy_rst_mask = BIT(17),
633         },
634         [IMX8MP_MEDIABLK_PD_MIPI_CSI2_1] = {
635                 .name = "mediablk-mipi-csi2-1",
636                 .clk_names = (const char *[]){ "apb", "cam1" },
637                 .num_clks = 2,
638                 .gpc_name = "mipi-csi1",
639                 .rst_mask = BIT(2) | BIT(3),
640                 .clk_mask = BIT(2) | BIT(3),
641                 .mipi_phy_rst_mask = BIT(16),
642         },
643         [IMX8MP_MEDIABLK_PD_LCDIF_1] = {
644                 .name = "mediablk-lcdif-1",
645                 .clk_names = (const char *[]){ "disp1", "apb", "axi", },
646                 .num_clks = 3,
647                 .gpc_name = "lcdif1",
648                 .rst_mask = BIT(4) | BIT(5) | BIT(23),
649                 .clk_mask = BIT(4) | BIT(5) | BIT(23),
650         },
651         [IMX8MP_MEDIABLK_PD_ISI] = {
652                 .name = "mediablk-isi",
653                 .clk_names = (const char *[]){ "axi", "apb" },
654                 .num_clks = 2,
655                 .gpc_name = "isi",
656                 .rst_mask = BIT(6) | BIT(7),
657                 .clk_mask = BIT(6) | BIT(7),
658         },
659         [IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
660                 .name = "mediablk-mipi-csi2-2",
661                 .clk_names = (const char *[]){ "apb", "cam2" },
662                 .num_clks = 2,
663                 .gpc_name = "mipi-csi2",
664                 .rst_mask = BIT(9) | BIT(10),
665                 .clk_mask = BIT(9) | BIT(10),
666                 .mipi_phy_rst_mask = BIT(30),
667         },
668         [IMX8MP_MEDIABLK_PD_LCDIF_2] = {
669                 .name = "mediablk-lcdif-2",
670                 .clk_names = (const char *[]){ "disp2", "apb", "axi", },
671                 .num_clks = 3,
672                 .gpc_name = "lcdif2",
673                 .rst_mask = BIT(11) | BIT(12) | BIT(24),
674                 .clk_mask = BIT(11) | BIT(12) | BIT(24),
675         },
676         [IMX8MP_MEDIABLK_PD_ISP] = {
677                 .name = "mediablk-isp",
678                 .clk_names = (const char *[]){ "isp", "axi", "apb" },
679                 .num_clks = 3,
680                 .gpc_name = "isp",
681                 .rst_mask = BIT(16) | BIT(17) | BIT(18),
682                 .clk_mask = BIT(16) | BIT(17) | BIT(18),
683         },
684         [IMX8MP_MEDIABLK_PD_DWE] = {
685                 .name = "mediablk-dwe",
686                 .clk_names = (const char *[]){ "axi", "apb" },
687                 .num_clks = 2,
688                 .gpc_name = "dwe",
689                 .rst_mask = BIT(19) | BIT(20) | BIT(21),
690                 .clk_mask = BIT(19) | BIT(20) | BIT(21),
691         },
692         [IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
693                 .name = "mediablk-mipi-dsi-2",
694                 .clk_names = (const char *[]){ "phy", },
695                 .num_clks = 1,
696                 .gpc_name = "mipi-dsi2",
697                 .rst_mask = BIT(22),
698                 .clk_mask = BIT(22),
699                 .mipi_phy_rst_mask = BIT(29),
700         },
701 };
702
703 static const struct imx8m_blk_ctrl_data imx8mp_media_blk_ctl_dev_data = {
704         .max_reg = 0x138,
705         .power_notifier_fn = imx8mp_media_power_notifier,
706         .domains = imx8mp_media_blk_ctl_domain_data,
707         .num_domains = ARRAY_SIZE(imx8mp_media_blk_ctl_domain_data),
708 };
709
710 static int imx8mq_vpu_power_notifier(struct notifier_block *nb,
711                                      unsigned long action, void *data)
712 {
713         struct imx8m_blk_ctrl *bc = container_of(nb, struct imx8m_blk_ctrl,
714                                                  power_nb);
715
716         if (action != GENPD_NOTIFY_ON && action != GENPD_NOTIFY_PRE_OFF)
717                 return NOTIFY_OK;
718
719         /*
720          * The ADB in the VPUMIX domain has no separate reset and clock
721          * enable bits, but is ungated and reset together with the VPUs. The
722          * reset and clock enable inputs to the ADB is a logical OR of the
723          * VPU bits. In order to set the G2 fuse bits, the G2 clock must
724          * also be enabled.
725          */
726         regmap_set_bits(bc->regmap, BLK_SFT_RSTN, BIT(0) | BIT(1));
727         regmap_set_bits(bc->regmap, BLK_CLK_EN, BIT(0) | BIT(1));
728
729         if (action == GENPD_NOTIFY_ON) {
730                 /*
731                  * On power up we have no software backchannel to the GPC to
732                  * wait for the ADB handshake to happen, so we just delay for a
733                  * bit. On power down the GPC driver waits for the handshake.
734                  */
735                 udelay(5);
736
737                 /* set "fuse" bits to enable the VPUs */
738                 regmap_set_bits(bc->regmap, 0x8, 0xffffffff);
739                 regmap_set_bits(bc->regmap, 0xc, 0xffffffff);
740                 regmap_set_bits(bc->regmap, 0x10, 0xffffffff);
741         }
742
743         return NOTIFY_OK;
744 }
745
746 static const struct imx8m_blk_ctrl_domain_data imx8mq_vpu_blk_ctl_domain_data[] = {
747         [IMX8MQ_VPUBLK_PD_G1] = {
748                 .name = "vpublk-g1",
749                 .clk_names = (const char *[]){ "g1", },
750                 .num_clks = 1,
751                 .gpc_name = "g1",
752                 .rst_mask = BIT(1),
753                 .clk_mask = BIT(1),
754         },
755         [IMX8MQ_VPUBLK_PD_G2] = {
756                 .name = "vpublk-g2",
757                 .clk_names = (const char *[]){ "g2", },
758                 .num_clks = 1,
759                 .gpc_name = "g2",
760                 .rst_mask = BIT(0),
761                 .clk_mask = BIT(0),
762         },
763 };
764
765 static const struct imx8m_blk_ctrl_data imx8mq_vpu_blk_ctl_dev_data = {
766         .max_reg = 0x14,
767         .power_notifier_fn = imx8mq_vpu_power_notifier,
768         .domains = imx8mq_vpu_blk_ctl_domain_data,
769         .num_domains = ARRAY_SIZE(imx8mq_vpu_blk_ctl_domain_data),
770 };
771
772 static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
773         {
774                 .compatible = "fsl,imx8mm-vpu-blk-ctrl",
775                 .data = &imx8mm_vpu_blk_ctl_dev_data
776         }, {
777                 .compatible = "fsl,imx8mm-disp-blk-ctrl",
778                 .data = &imx8mm_disp_blk_ctl_dev_data
779         }, {
780                 .compatible = "fsl,imx8mn-disp-blk-ctrl",
781                 .data = &imx8mn_disp_blk_ctl_dev_data
782         }, {
783                 .compatible = "fsl,imx8mp-media-blk-ctrl",
784                 .data = &imx8mp_media_blk_ctl_dev_data
785         }, {
786                 .compatible = "fsl,imx8mq-vpu-blk-ctrl",
787                 .data = &imx8mq_vpu_blk_ctl_dev_data
788         }, {
789                 /* Sentinel */
790         }
791 };
792 MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
793
794 static struct platform_driver imx8m_blk_ctrl_driver = {
795         .probe = imx8m_blk_ctrl_probe,
796         .remove = imx8m_blk_ctrl_remove,
797         .driver = {
798                 .name = "imx8m-blk-ctrl",
799                 .pm = &imx8m_blk_ctrl_pm_ops,
800                 .of_match_table = imx8m_blk_ctrl_of_match,
801         },
802 };
803 module_platform_driver(imx8m_blk_ctrl_driver);