soc: imx: gpcv2: add PGC control register indirection
authorLucas Stach <l.stach@pengutronix.de>
Wed, 30 Mar 2022 10:46:16 +0000 (12:46 +0200)
committerShawn Guo <shawnguo@kernel.org>
Fri, 8 Apr 2022 12:01:46 +0000 (20:01 +0800)
The PGC control registers in the shared (not per-PGC) region of the
GPC address space have different offsets on i.MX8MP to make space for
additional interrupt control registers.

Signed-off-by: Lucas Stach <l.stach@pengutronix.de>
Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Tested-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Shawn Guo <shawnguo@kernel.org>
drivers/soc/imx/gpcv2.c

index 3cb123016b3ec5ee0b939054eb8eddafa8595349..677c5c581521b817b2c53051fb0c7f3dd2c1ef80 100644 (file)
 
 #define GPC_PGC_CTRL_PCR               BIT(0)
 
+struct imx_pgc_regs {
+       u16 map;
+       u16 pup;
+       u16 pdn;
+       u16 hsk;
+};
+
 struct imx_pgc_domain {
        struct generic_pm_domain genpd;
        struct regmap *regmap;
+       const struct imx_pgc_regs *regs;
        struct regulator *regulator;
        struct reset_control *reset;
        struct clk_bulk_data *clks;
@@ -210,6 +218,7 @@ struct imx_pgc_domain_data {
        const struct imx_pgc_domain *domains;
        size_t domains_num;
        const struct regmap_access_table *reg_access_table;
+       const struct imx_pgc_regs *pgc_regs;
 };
 
 static inline struct imx_pgc_domain *
@@ -249,14 +258,14 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
 
        if (domain->bits.pxx) {
                /* request the domain to power up */
-               regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PUP_REQ,
+               regmap_update_bits(domain->regmap, domain->regs->pup,
                                   domain->bits.pxx, domain->bits.pxx);
                /*
                 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
                 * for PUP_REQ/PDN_REQ bit to be cleared
                 */
                ret = regmap_read_poll_timeout(domain->regmap,
-                                              GPC_PU_PGC_SW_PUP_REQ, reg_val,
+                                              domain->regs->pup, reg_val,
                                               !(reg_val & domain->bits.pxx),
                                               0, USEC_PER_MSEC);
                if (ret) {
@@ -278,11 +287,11 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
 
        /* request the ADB400 to power up */
        if (domain->bits.hskreq) {
-               regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
+               regmap_update_bits(domain->regmap, domain->regs->hsk,
                                   domain->bits.hskreq, domain->bits.hskreq);
 
                /*
-                * ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK, reg_val,
+                * ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk, reg_val,
                 *                                (reg_val & domain->bits.hskack), 0,
                 *                                USEC_PER_MSEC);
                 * Technically we need the commented code to wait handshake. But that needs
@@ -329,10 +338,10 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
 
        /* request the ADB400 to power down */
        if (domain->bits.hskreq) {
-               regmap_clear_bits(domain->regmap, GPC_PU_PWRHSK,
+               regmap_clear_bits(domain->regmap, domain->regs->hsk,
                                  domain->bits.hskreq);
 
-               ret = regmap_read_poll_timeout(domain->regmap, GPC_PU_PWRHSK,
+               ret = regmap_read_poll_timeout(domain->regmap, domain->regs->hsk,
                                               reg_val,
                                               !(reg_val & domain->bits.hskack),
                                               0, USEC_PER_MSEC);
@@ -350,14 +359,14 @@ static int imx_pgc_power_down(struct generic_pm_domain *genpd)
                }
 
                /* request the domain to power down */
-               regmap_update_bits(domain->regmap, GPC_PU_PGC_SW_PDN_REQ,
+               regmap_update_bits(domain->regmap, domain->regs->pdn,
                                   domain->bits.pxx, domain->bits.pxx);
                /*
                 * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
                 * for PUP_REQ/PDN_REQ bit to be cleared
                 */
                ret = regmap_read_poll_timeout(domain->regmap,
-                                              GPC_PU_PGC_SW_PDN_REQ, reg_val,
+                                              domain->regs->pdn, reg_val,
                                               !(reg_val & domain->bits.pxx),
                                               0, USEC_PER_MSEC);
                if (ret) {
@@ -442,10 +451,18 @@ static const struct regmap_access_table imx7_access_table = {
        .n_yes_ranges   = ARRAY_SIZE(imx7_yes_ranges),
 };
 
+static const struct imx_pgc_regs imx7_pgc_regs = {
+       .map = GPC_PGC_CPU_MAPPING,
+       .pup = GPC_PU_PGC_SW_PUP_REQ,
+       .pdn = GPC_PU_PGC_SW_PDN_REQ,
+       .hsk = GPC_PU_PWRHSK,
+};
+
 static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
        .domains = imx7_pgc_domains,
        .domains_num = ARRAY_SIZE(imx7_pgc_domains),
        .reg_access_table = &imx7_access_table,
+       .pgc_regs = &imx7_pgc_regs,
 };
 
 static const struct imx_pgc_domain imx8m_pgc_domains[] = {
@@ -614,6 +631,7 @@ static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
        .domains = imx8m_pgc_domains,
        .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
        .reg_access_table = &imx8m_access_table,
+       .pgc_regs = &imx7_pgc_regs,
 };
 
 static const struct imx_pgc_domain imx8mm_pgc_domains[] = {
@@ -804,6 +822,7 @@ static const struct imx_pgc_domain_data imx8mm_pgc_domain_data = {
        .domains = imx8mm_pgc_domains,
        .domains_num = ARRAY_SIZE(imx8mm_pgc_domains),
        .reg_access_table = &imx8mm_access_table,
+       .pgc_regs = &imx7_pgc_regs,
 };
 
 static const struct imx_pgc_domain imx8mn_pgc_domains[] = {
@@ -895,6 +914,7 @@ static const struct imx_pgc_domain_data imx8mn_pgc_domain_data = {
        .domains = imx8mn_pgc_domains,
        .domains_num = ARRAY_SIZE(imx8mn_pgc_domains),
        .reg_access_table = &imx8mn_access_table,
+       .pgc_regs = &imx7_pgc_regs,
 };
 
 static int imx_pgc_domain_probe(struct platform_device *pdev)
@@ -927,7 +947,7 @@ static int imx_pgc_domain_probe(struct platform_device *pdev)
        pm_runtime_enable(domain->dev);
 
        if (domain->bits.map)
-               regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
+               regmap_update_bits(domain->regmap, domain->regs->map,
                                   domain->bits.map, domain->bits.map);
 
        ret = pm_genpd_init(&domain->genpd, NULL, true);
@@ -953,7 +973,7 @@ out_genpd_remove:
        pm_genpd_remove(&domain->genpd);
 out_domain_unmap:
        if (domain->bits.map)
-               regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
+               regmap_update_bits(domain->regmap, domain->regs->map,
                                   domain->bits.map, 0);
        pm_runtime_disable(domain->dev);
 
@@ -968,7 +988,7 @@ static int imx_pgc_domain_remove(struct platform_device *pdev)
        pm_genpd_remove(&domain->genpd);
 
        if (domain->bits.map)
-               regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
+               regmap_update_bits(domain->regmap, domain->regs->map,
                                   domain->bits.map, 0);
 
        pm_runtime_disable(domain->dev);
@@ -1099,6 +1119,7 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
 
                domain = pd_pdev->dev.platform_data;
                domain->regmap = regmap;
+               domain->regs = domain_data->pgc_regs;
                domain->genpd.power_on  = imx_pgc_power_up;
                domain->genpd.power_off = imx_pgc_power_down;