Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
0004  * Copyright 2011-2013 Freescale Semiconductor, Inc.
0005  */
0006 
0007 #include <linux/clk.h>
0008 #include <linux/delay.h>
0009 #include <linux/io.h>
0010 #include <linux/of_device.h>
0011 #include <linux/platform_device.h>
0012 #include <linux/pm_domain.h>
0013 #include <linux/regmap.h>
0014 #include <linux/regulator/consumer.h>
0015 
0016 #define GPC_CNTR        0x000
0017 
0018 #define GPC_PGC_CTRL_OFFS   0x0
0019 #define GPC_PGC_PUPSCR_OFFS 0x4
0020 #define GPC_PGC_PDNSCR_OFFS 0x8
0021 #define GPC_PGC_SW2ISO_SHIFT    0x8
0022 #define GPC_PGC_SW_SHIFT    0x0
0023 
0024 #define GPC_PGC_PCI_PDN     0x200
0025 #define GPC_PGC_PCI_SR      0x20c
0026 
0027 #define GPC_PGC_GPU_PDN     0x260
0028 #define GPC_PGC_GPU_PUPSCR  0x264
0029 #define GPC_PGC_GPU_PDNSCR  0x268
0030 #define GPC_PGC_GPU_SR      0x26c
0031 
0032 #define GPC_PGC_DISP_PDN    0x240
0033 #define GPC_PGC_DISP_SR     0x24c
0034 
0035 #define GPU_VPU_PUP_REQ     BIT(1)
0036 #define GPU_VPU_PDN_REQ     BIT(0)
0037 
0038 #define GPC_CLK_MAX     7
0039 
0040 #define PGC_DOMAIN_FLAG_NO_PD       BIT(0)
0041 
0042 struct imx_pm_domain {
0043     struct generic_pm_domain base;
0044     struct regmap *regmap;
0045     struct regulator *supply;
0046     struct clk *clk[GPC_CLK_MAX];
0047     int num_clks;
0048     unsigned int reg_offs;
0049     signed char cntr_pdn_bit;
0050     unsigned int ipg_rate_mhz;
0051 };
0052 
0053 static inline struct imx_pm_domain *
0054 to_imx_pm_domain(struct generic_pm_domain *genpd)
0055 {
0056     return container_of(genpd, struct imx_pm_domain, base);
0057 }
0058 
0059 static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd)
0060 {
0061     struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
0062     int iso, iso2sw;
0063     u32 val;
0064 
0065     /* Read ISO and ISO2SW power down delays */
0066     regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PDNSCR_OFFS, &val);
0067     iso = val & 0x3f;
0068     iso2sw = (val >> 8) & 0x3f;
0069 
0070     /* Gate off domain when powered down */
0071     regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
0072                0x1, 0x1);
0073 
0074     /* Request GPC to power down domain */
0075     val = BIT(pd->cntr_pdn_bit);
0076     regmap_update_bits(pd->regmap, GPC_CNTR, val, val);
0077 
0078     /* Wait ISO + ISO2SW IPG clock cycles */
0079     udelay(DIV_ROUND_UP(iso + iso2sw, pd->ipg_rate_mhz));
0080 
0081     if (pd->supply)
0082         regulator_disable(pd->supply);
0083 
0084     return 0;
0085 }
0086 
0087 static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
0088 {
0089     struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
0090     int i, ret;
0091     u32 val, req;
0092 
0093     if (pd->supply) {
0094         ret = regulator_enable(pd->supply);
0095         if (ret) {
0096             pr_err("%s: failed to enable regulator: %d\n",
0097                    __func__, ret);
0098             return ret;
0099         }
0100     }
0101 
0102     /* Enable reset clocks for all devices in the domain */
0103     for (i = 0; i < pd->num_clks; i++)
0104         clk_prepare_enable(pd->clk[i]);
0105 
0106     /* Gate off domain when powered down */
0107     regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
0108                0x1, 0x1);
0109 
0110     /* Request GPC to power up domain */
0111     req = BIT(pd->cntr_pdn_bit + 1);
0112     regmap_update_bits(pd->regmap, GPC_CNTR, req, req);
0113 
0114     /* Wait for the PGC to handle the request */
0115     ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req),
0116                        1, 50);
0117     if (ret)
0118         pr_err("powerup request on domain %s timed out\n", genpd->name);
0119 
0120     /* Wait for reset to propagate through peripherals */
0121     usleep_range(5, 10);
0122 
0123     /* Disable reset clocks for all devices in the domain */
0124     for (i = 0; i < pd->num_clks; i++)
0125         clk_disable_unprepare(pd->clk[i]);
0126 
0127     return 0;
0128 }
0129 
0130 static int imx_pgc_get_clocks(struct device *dev, struct imx_pm_domain *domain)
0131 {
0132     int i, ret;
0133 
0134     for (i = 0; ; i++) {
0135         struct clk *clk = of_clk_get(dev->of_node, i);
0136         if (IS_ERR(clk))
0137             break;
0138         if (i >= GPC_CLK_MAX) {
0139             dev_err(dev, "more than %d clocks\n", GPC_CLK_MAX);
0140             ret = -EINVAL;
0141             goto clk_err;
0142         }
0143         domain->clk[i] = clk;
0144     }
0145     domain->num_clks = i;
0146 
0147     return 0;
0148 
0149 clk_err:
0150     while (i--)
0151         clk_put(domain->clk[i]);
0152 
0153     return ret;
0154 }
0155 
0156 static void imx_pgc_put_clocks(struct imx_pm_domain *domain)
0157 {
0158     int i;
0159 
0160     for (i = domain->num_clks - 1; i >= 0; i--)
0161         clk_put(domain->clk[i]);
0162 }
0163 
0164 static int imx_pgc_parse_dt(struct device *dev, struct imx_pm_domain *domain)
0165 {
0166     /* try to get the domain supply regulator */
0167     domain->supply = devm_regulator_get_optional(dev, "power");
0168     if (IS_ERR(domain->supply)) {
0169         if (PTR_ERR(domain->supply) == -ENODEV)
0170             domain->supply = NULL;
0171         else
0172             return PTR_ERR(domain->supply);
0173     }
0174 
0175     /* try to get all clocks needed for reset propagation */
0176     return imx_pgc_get_clocks(dev, domain);
0177 }
0178 
0179 static int imx_pgc_power_domain_probe(struct platform_device *pdev)
0180 {
0181     struct imx_pm_domain *domain = pdev->dev.platform_data;
0182     struct device *dev = &pdev->dev;
0183     int ret;
0184 
0185     /* if this PD is associated with a DT node try to parse it */
0186     if (dev->of_node) {
0187         ret = imx_pgc_parse_dt(dev, domain);
0188         if (ret)
0189             return ret;
0190     }
0191 
0192     /* initially power on the domain */
0193     if (domain->base.power_on)
0194         domain->base.power_on(&domain->base);
0195 
0196     if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
0197         pm_genpd_init(&domain->base, NULL, false);
0198         ret = of_genpd_add_provider_simple(dev->of_node, &domain->base);
0199         if (ret)
0200             goto genpd_err;
0201     }
0202 
0203     device_link_add(dev, dev->parent, DL_FLAG_AUTOREMOVE_CONSUMER);
0204 
0205     return 0;
0206 
0207 genpd_err:
0208     pm_genpd_remove(&domain->base);
0209     imx_pgc_put_clocks(domain);
0210 
0211     return ret;
0212 }
0213 
0214 static int imx_pgc_power_domain_remove(struct platform_device *pdev)
0215 {
0216     struct imx_pm_domain *domain = pdev->dev.platform_data;
0217 
0218     if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
0219         of_genpd_del_provider(pdev->dev.of_node);
0220         pm_genpd_remove(&domain->base);
0221         imx_pgc_put_clocks(domain);
0222     }
0223 
0224     return 0;
0225 }
0226 
0227 static const struct platform_device_id imx_pgc_power_domain_id[] = {
0228     { "imx-pgc-power-domain"},
0229     { },
0230 };
0231 
0232 static struct platform_driver imx_pgc_power_domain_driver = {
0233     .driver = {
0234         .name = "imx-pgc-pd",
0235     },
0236     .probe = imx_pgc_power_domain_probe,
0237     .remove = imx_pgc_power_domain_remove,
0238     .id_table = imx_pgc_power_domain_id,
0239 };
0240 builtin_platform_driver(imx_pgc_power_domain_driver)
0241 
0242 #define GPC_PGC_DOMAIN_ARM  0
0243 #define GPC_PGC_DOMAIN_PU   1
0244 #define GPC_PGC_DOMAIN_DISPLAY  2
0245 #define GPC_PGC_DOMAIN_PCI  3
0246 
0247 static struct genpd_power_state imx6_pm_domain_pu_state = {
0248     .power_off_latency_ns = 25000,
0249     .power_on_latency_ns = 2000000,
0250 };
0251 
0252 static struct imx_pm_domain imx_gpc_domains[] = {
0253     [GPC_PGC_DOMAIN_ARM] = {
0254         .base = {
0255             .name = "ARM",
0256             .flags = GENPD_FLAG_ALWAYS_ON,
0257         },
0258     },
0259     [GPC_PGC_DOMAIN_PU] = {
0260         .base = {
0261             .name = "PU",
0262             .power_off = imx6_pm_domain_power_off,
0263             .power_on = imx6_pm_domain_power_on,
0264             .states = &imx6_pm_domain_pu_state,
0265             .state_count = 1,
0266         },
0267         .reg_offs = 0x260,
0268         .cntr_pdn_bit = 0,
0269     },
0270     [GPC_PGC_DOMAIN_DISPLAY] = {
0271         .base = {
0272             .name = "DISPLAY",
0273             .power_off = imx6_pm_domain_power_off,
0274             .power_on = imx6_pm_domain_power_on,
0275         },
0276         .reg_offs = 0x240,
0277         .cntr_pdn_bit = 4,
0278     },
0279     [GPC_PGC_DOMAIN_PCI] = {
0280         .base = {
0281             .name = "PCI",
0282             .power_off = imx6_pm_domain_power_off,
0283             .power_on = imx6_pm_domain_power_on,
0284         },
0285         .reg_offs = 0x200,
0286         .cntr_pdn_bit = 6,
0287     },
0288 };
0289 
0290 struct imx_gpc_dt_data {
0291     int num_domains;
0292     bool err009619_present;
0293     bool err006287_present;
0294 };
0295 
0296 static const struct imx_gpc_dt_data imx6q_dt_data = {
0297     .num_domains = 2,
0298     .err009619_present = false,
0299     .err006287_present = false,
0300 };
0301 
0302 static const struct imx_gpc_dt_data imx6qp_dt_data = {
0303     .num_domains = 2,
0304     .err009619_present = true,
0305     .err006287_present = false,
0306 };
0307 
0308 static const struct imx_gpc_dt_data imx6sl_dt_data = {
0309     .num_domains = 3,
0310     .err009619_present = false,
0311     .err006287_present = true,
0312 };
0313 
0314 static const struct imx_gpc_dt_data imx6sx_dt_data = {
0315     .num_domains = 4,
0316     .err009619_present = false,
0317     .err006287_present = false,
0318 };
0319 
0320 static const struct of_device_id imx_gpc_dt_ids[] = {
0321     { .compatible = "fsl,imx6q-gpc", .data = &imx6q_dt_data },
0322     { .compatible = "fsl,imx6qp-gpc", .data = &imx6qp_dt_data },
0323     { .compatible = "fsl,imx6sl-gpc", .data = &imx6sl_dt_data },
0324     { .compatible = "fsl,imx6sx-gpc", .data = &imx6sx_dt_data },
0325     { }
0326 };
0327 
0328 static const struct regmap_range yes_ranges[] = {
0329     regmap_reg_range(GPC_CNTR, GPC_CNTR),
0330     regmap_reg_range(GPC_PGC_PCI_PDN, GPC_PGC_PCI_SR),
0331     regmap_reg_range(GPC_PGC_GPU_PDN, GPC_PGC_GPU_SR),
0332     regmap_reg_range(GPC_PGC_DISP_PDN, GPC_PGC_DISP_SR),
0333 };
0334 
0335 static const struct regmap_access_table access_table = {
0336     .yes_ranges = yes_ranges,
0337     .n_yes_ranges   = ARRAY_SIZE(yes_ranges),
0338 };
0339 
0340 static const struct regmap_config imx_gpc_regmap_config = {
0341     .reg_bits = 32,
0342     .val_bits = 32,
0343     .reg_stride = 4,
0344     .rd_table = &access_table,
0345     .wr_table = &access_table,
0346     .max_register = 0x2ac,
0347     .fast_io = true,
0348 };
0349 
0350 static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
0351     &imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base,
0352     &imx_gpc_domains[GPC_PGC_DOMAIN_PU].base,
0353 };
0354 
0355 static struct genpd_onecell_data imx_gpc_onecell_data = {
0356     .domains = imx_gpc_onecell_domains,
0357     .num_domains = 2,
0358 };
0359 
0360 static int imx_gpc_old_dt_init(struct device *dev, struct regmap *regmap,
0361                    unsigned int num_domains)
0362 {
0363     struct imx_pm_domain *domain;
0364     int i, ret;
0365 
0366     for (i = 0; i < num_domains; i++) {
0367         domain = &imx_gpc_domains[i];
0368         domain->regmap = regmap;
0369         domain->ipg_rate_mhz = 66;
0370 
0371         if (i == 1) {
0372             domain->supply = devm_regulator_get(dev, "pu");
0373             if (IS_ERR(domain->supply))
0374                 return PTR_ERR(domain->supply);
0375 
0376             ret = imx_pgc_get_clocks(dev, domain);
0377             if (ret)
0378                 goto clk_err;
0379 
0380             domain->base.power_on(&domain->base);
0381         }
0382     }
0383 
0384     for (i = 0; i < num_domains; i++)
0385         pm_genpd_init(&imx_gpc_domains[i].base, NULL, false);
0386 
0387     if (IS_ENABLED(CONFIG_PM_GENERIC_DOMAINS)) {
0388         ret = of_genpd_add_provider_onecell(dev->of_node,
0389                             &imx_gpc_onecell_data);
0390         if (ret)
0391             goto genpd_err;
0392     }
0393 
0394     return 0;
0395 
0396 genpd_err:
0397     for (i = 0; i < num_domains; i++)
0398         pm_genpd_remove(&imx_gpc_domains[i].base);
0399     imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
0400 clk_err:
0401     return ret;
0402 }
0403 
0404 static int imx_gpc_probe(struct platform_device *pdev)
0405 {
0406     const struct of_device_id *of_id =
0407             of_match_device(imx_gpc_dt_ids, &pdev->dev);
0408     const struct imx_gpc_dt_data *of_id_data = of_id->data;
0409     struct device_node *pgc_node;
0410     struct regmap *regmap;
0411     void __iomem *base;
0412     int ret;
0413 
0414     pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
0415 
0416     /* bail out if DT too old and doesn't provide the necessary info */
0417     if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
0418         !pgc_node)
0419         return 0;
0420 
0421     base = devm_platform_ioremap_resource(pdev, 0);
0422     if (IS_ERR(base))
0423         return PTR_ERR(base);
0424 
0425     regmap = devm_regmap_init_mmio_clk(&pdev->dev, NULL, base,
0426                        &imx_gpc_regmap_config);
0427     if (IS_ERR(regmap)) {
0428         ret = PTR_ERR(regmap);
0429         dev_err(&pdev->dev, "failed to init regmap: %d\n",
0430             ret);
0431         return ret;
0432     }
0433 
0434     /*
0435      * Disable PU power down by runtime PM if ERR009619 is present.
0436      *
0437      * The PRE clock will be paused for several cycles when turning on the
0438      * PU domain LDO from power down state. If PRE is in use at that time,
0439      * the IPU/PRG cannot get the correct display data from the PRE.
0440      *
0441      * This is not a concern when the whole system enters suspend state, so
0442      * it's safe to power down PU in this case.
0443      */
0444     if (of_id_data->err009619_present)
0445         imx_gpc_domains[GPC_PGC_DOMAIN_PU].base.flags |=
0446                 GENPD_FLAG_RPM_ALWAYS_ON;
0447 
0448     /* Keep DISP always on if ERR006287 is present */
0449     if (of_id_data->err006287_present)
0450         imx_gpc_domains[GPC_PGC_DOMAIN_DISPLAY].base.flags |=
0451                 GENPD_FLAG_ALWAYS_ON;
0452 
0453     if (!pgc_node) {
0454         ret = imx_gpc_old_dt_init(&pdev->dev, regmap,
0455                       of_id_data->num_domains);
0456         if (ret)
0457             return ret;
0458     } else {
0459         struct imx_pm_domain *domain;
0460         struct platform_device *pd_pdev;
0461         struct device_node *np;
0462         struct clk *ipg_clk;
0463         unsigned int ipg_rate_mhz;
0464         int domain_index;
0465 
0466         ipg_clk = devm_clk_get(&pdev->dev, "ipg");
0467         if (IS_ERR(ipg_clk))
0468             return PTR_ERR(ipg_clk);
0469         ipg_rate_mhz = clk_get_rate(ipg_clk) / 1000000;
0470 
0471         for_each_child_of_node(pgc_node, np) {
0472             ret = of_property_read_u32(np, "reg", &domain_index);
0473             if (ret) {
0474                 of_node_put(np);
0475                 return ret;
0476             }
0477             if (domain_index >= of_id_data->num_domains)
0478                 continue;
0479 
0480             pd_pdev = platform_device_alloc("imx-pgc-power-domain",
0481                             domain_index);
0482             if (!pd_pdev) {
0483                 of_node_put(np);
0484                 return -ENOMEM;
0485             }
0486 
0487             ret = platform_device_add_data(pd_pdev,
0488                                &imx_gpc_domains[domain_index],
0489                                sizeof(imx_gpc_domains[domain_index]));
0490             if (ret) {
0491                 platform_device_put(pd_pdev);
0492                 of_node_put(np);
0493                 return ret;
0494             }
0495             domain = pd_pdev->dev.platform_data;
0496             domain->regmap = regmap;
0497             domain->ipg_rate_mhz = ipg_rate_mhz;
0498 
0499             pd_pdev->dev.parent = &pdev->dev;
0500             pd_pdev->dev.of_node = np;
0501 
0502             ret = platform_device_add(pd_pdev);
0503             if (ret) {
0504                 platform_device_put(pd_pdev);
0505                 of_node_put(np);
0506                 return ret;
0507             }
0508         }
0509     }
0510 
0511     return 0;
0512 }
0513 
0514 static int imx_gpc_remove(struct platform_device *pdev)
0515 {
0516     struct device_node *pgc_node;
0517     int ret;
0518 
0519     pgc_node = of_get_child_by_name(pdev->dev.of_node, "pgc");
0520 
0521     /* bail out if DT too old and doesn't provide the necessary info */
0522     if (!of_property_read_bool(pdev->dev.of_node, "#power-domain-cells") &&
0523         !pgc_node)
0524         return 0;
0525 
0526     /*
0527      * If the old DT binding is used the toplevel driver needs to
0528      * de-register the power domains
0529      */
0530     if (!pgc_node) {
0531         of_genpd_del_provider(pdev->dev.of_node);
0532 
0533         ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_PU].base);
0534         if (ret)
0535             return ret;
0536         imx_pgc_put_clocks(&imx_gpc_domains[GPC_PGC_DOMAIN_PU]);
0537 
0538         ret = pm_genpd_remove(&imx_gpc_domains[GPC_PGC_DOMAIN_ARM].base);
0539         if (ret)
0540             return ret;
0541     }
0542 
0543     return 0;
0544 }
0545 
0546 static struct platform_driver imx_gpc_driver = {
0547     .driver = {
0548         .name = "imx-gpc",
0549         .of_match_table = imx_gpc_dt_ids,
0550     },
0551     .probe = imx_gpc_probe,
0552     .remove = imx_gpc_remove,
0553 };
0554 builtin_platform_driver(imx_gpc_driver)