root/drivers/soc/imx/gpcv2.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. imx_gpc_pu_pgc_sw_pxx_req
  2. imx_gpc_pu_pgc_sw_pup_req
  3. imx_gpc_pu_pgc_sw_pdn_req
  4. imx_pgc_get_clocks
  5. imx_pgc_put_clocks
  6. imx_pgc_domain_probe
  7. imx_pgc_domain_remove
  8. builtin_platform_driver

   1 // SPDX-License-Identifier: GPL-2.0+
   2 /*
   3  * Copyright 2017 Impinj, Inc
   4  * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
   5  *
   6  * Based on the code of analogus driver:
   7  *
   8  * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de>
   9  */
  10 
  11 #include <linux/clk.h>
  12 #include <linux/of_device.h>
  13 #include <linux/platform_device.h>
  14 #include <linux/pm_domain.h>
  15 #include <linux/regmap.h>
  16 #include <linux/regulator/consumer.h>
  17 #include <dt-bindings/power/imx7-power.h>
  18 #include <dt-bindings/power/imx8mq-power.h>
  19 
  20 #define GPC_LPCR_A_CORE_BSC                     0x000
  21 
  22 #define GPC_PGC_CPU_MAPPING             0x0ec
  23 
  24 #define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN         BIT(6)
  25 #define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN         BIT(5)
  26 #define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN         BIT(4)
  27 #define IMX7_PCIE_PHY_A_CORE_DOMAIN             BIT(3)
  28 #define IMX7_MIPI_PHY_A_CORE_DOMAIN             BIT(2)
  29 
  30 #define IMX8M_PCIE2_A53_DOMAIN                  BIT(15)
  31 #define IMX8M_MIPI_CSI2_A53_DOMAIN              BIT(14)
  32 #define IMX8M_MIPI_CSI1_A53_DOMAIN              BIT(13)
  33 #define IMX8M_DISP_A53_DOMAIN                   BIT(12)
  34 #define IMX8M_HDMI_A53_DOMAIN                   BIT(11)
  35 #define IMX8M_VPU_A53_DOMAIN                    BIT(10)
  36 #define IMX8M_GPU_A53_DOMAIN                    BIT(9)
  37 #define IMX8M_DDR2_A53_DOMAIN                   BIT(8)
  38 #define IMX8M_DDR1_A53_DOMAIN                   BIT(7)
  39 #define IMX8M_OTG2_A53_DOMAIN                   BIT(5)
  40 #define IMX8M_OTG1_A53_DOMAIN                   BIT(4)
  41 #define IMX8M_PCIE1_A53_DOMAIN                  BIT(3)
  42 #define IMX8M_MIPI_A53_DOMAIN                   BIT(2)
  43 
  44 #define GPC_PU_PGC_SW_PUP_REQ           0x0f8
  45 #define GPC_PU_PGC_SW_PDN_REQ           0x104
  46 
  47 #define IMX7_USB_HSIC_PHY_SW_Pxx_REQ            BIT(4)
  48 #define IMX7_USB_OTG2_PHY_SW_Pxx_REQ            BIT(3)
  49 #define IMX7_USB_OTG1_PHY_SW_Pxx_REQ            BIT(2)
  50 #define IMX7_PCIE_PHY_SW_Pxx_REQ                BIT(1)
  51 #define IMX7_MIPI_PHY_SW_Pxx_REQ                BIT(0)
  52 
  53 #define IMX8M_PCIE2_SW_Pxx_REQ                  BIT(13)
  54 #define IMX8M_MIPI_CSI2_SW_Pxx_REQ              BIT(12)
  55 #define IMX8M_MIPI_CSI1_SW_Pxx_REQ              BIT(11)
  56 #define IMX8M_DISP_SW_Pxx_REQ                   BIT(10)
  57 #define IMX8M_HDMI_SW_Pxx_REQ                   BIT(9)
  58 #define IMX8M_VPU_SW_Pxx_REQ                    BIT(8)
  59 #define IMX8M_GPU_SW_Pxx_REQ                    BIT(7)
  60 #define IMX8M_DDR2_SW_Pxx_REQ                   BIT(6)
  61 #define IMX8M_DDR1_SW_Pxx_REQ                   BIT(5)
  62 #define IMX8M_OTG2_SW_Pxx_REQ                   BIT(3)
  63 #define IMX8M_OTG1_SW_Pxx_REQ                   BIT(2)
  64 #define IMX8M_PCIE1_SW_Pxx_REQ                  BIT(1)
  65 #define IMX8M_MIPI_SW_Pxx_REQ                   BIT(0)
  66 
  67 #define GPC_M4_PU_PDN_FLG               0x1bc
  68 
  69 #define GPC_PU_PWRHSK                   0x1fc
  70 
  71 #define IMX8M_GPU_HSK_PWRDNREQN                 BIT(6)
  72 #define IMX8M_VPU_HSK_PWRDNREQN                 BIT(5)
  73 #define IMX8M_DISP_HSK_PWRDNREQN                BIT(4)
  74 
  75 /*
  76  * The PGC offset values in Reference Manual
  77  * (Rev. 1, 01/2018 and the older ones) GPC chapter's
  78  * GPC_PGC memory map are incorrect, below offset
  79  * values are from design RTL.
  80  */
  81 #define IMX7_PGC_MIPI                   16
  82 #define IMX7_PGC_PCIE                   17
  83 #define IMX7_PGC_USB_HSIC               20
  84 
  85 #define IMX8M_PGC_MIPI                  16
  86 #define IMX8M_PGC_PCIE1                 17
  87 #define IMX8M_PGC_OTG1                  18
  88 #define IMX8M_PGC_OTG2                  19
  89 #define IMX8M_PGC_DDR1                  21
  90 #define IMX8M_PGC_GPU                   23
  91 #define IMX8M_PGC_VPU                   24
  92 #define IMX8M_PGC_DISP                  26
  93 #define IMX8M_PGC_MIPI_CSI1             27
  94 #define IMX8M_PGC_MIPI_CSI2             28
  95 #define IMX8M_PGC_PCIE2                 29
  96 
  97 #define GPC_PGC_CTRL(n)                 (0x800 + (n) * 0x40)
  98 #define GPC_PGC_SR(n)                   (GPC_PGC_CTRL(n) + 0xc)
  99 
 100 #define GPC_PGC_CTRL_PCR                BIT(0)
 101 
 102 #define GPC_CLK_MAX             6
 103 
 104 struct imx_pgc_domain {
 105         struct generic_pm_domain genpd;
 106         struct regmap *regmap;
 107         struct regulator *regulator;
 108         struct clk *clk[GPC_CLK_MAX];
 109         int num_clks;
 110 
 111         unsigned int pgc;
 112 
 113         const struct {
 114                 u32 pxx;
 115                 u32 map;
 116                 u32 hsk;
 117         } bits;
 118 
 119         const int voltage;
 120         struct device *dev;
 121 };
 122 
 123 struct imx_pgc_domain_data {
 124         const struct imx_pgc_domain *domains;
 125         size_t domains_num;
 126         const struct regmap_access_table *reg_access_table;
 127 };
 128 
 129 static int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd,
 130                                       bool on)
 131 {
 132         struct imx_pgc_domain *domain = container_of(genpd,
 133                                                       struct imx_pgc_domain,
 134                                                       genpd);
 135         unsigned int offset = on ?
 136                 GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ;
 137         const bool enable_power_control = !on;
 138         const bool has_regulator = !IS_ERR(domain->regulator);
 139         int i, ret = 0;
 140         u32 pxx_req;
 141 
 142         regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
 143                            domain->bits.map, domain->bits.map);
 144 
 145         if (has_regulator && on) {
 146                 ret = regulator_enable(domain->regulator);
 147                 if (ret) {
 148                         dev_err(domain->dev, "failed to enable regulator\n");
 149                         goto unmap;
 150                 }
 151         }
 152 
 153         /* Enable reset clocks for all devices in the domain */
 154         for (i = 0; i < domain->num_clks; i++)
 155                 clk_prepare_enable(domain->clk[i]);
 156 
 157         if (enable_power_control)
 158                 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
 159                                    GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR);
 160 
 161         if (domain->bits.hsk)
 162                 regmap_update_bits(domain->regmap, GPC_PU_PWRHSK,
 163                                    domain->bits.hsk, on ? domain->bits.hsk : 0);
 164 
 165         regmap_update_bits(domain->regmap, offset,
 166                            domain->bits.pxx, domain->bits.pxx);
 167 
 168         /*
 169          * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait
 170          * for PUP_REQ/PDN_REQ bit to be cleared
 171          */
 172         ret = regmap_read_poll_timeout(domain->regmap, offset, pxx_req,
 173                                        !(pxx_req & domain->bits.pxx),
 174                                        0, USEC_PER_MSEC);
 175         if (ret) {
 176                 dev_err(domain->dev, "failed to command PGC\n");
 177                 /*
 178                  * If we were in a process of enabling a
 179                  * domain and failed we might as well disable
 180                  * the regulator we just enabled. And if it
 181                  * was the opposite situation and we failed to
 182                  * power down -- keep the regulator on
 183                  */
 184                 on = !on;
 185         }
 186 
 187         if (enable_power_control)
 188                 regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc),
 189                                    GPC_PGC_CTRL_PCR, 0);
 190 
 191         /* Disable reset clocks for all devices in the domain */
 192         for (i = 0; i < domain->num_clks; i++)
 193                 clk_disable_unprepare(domain->clk[i]);
 194 
 195         if (has_regulator && !on) {
 196                 int err;
 197 
 198                 err = regulator_disable(domain->regulator);
 199                 if (err)
 200                         dev_err(domain->dev,
 201                                 "failed to disable regulator: %d\n", err);
 202                 /* Preserve earlier error code */
 203                 ret = ret ?: err;
 204         }
 205 unmap:
 206         regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING,
 207                            domain->bits.map, 0);
 208         return ret;
 209 }
 210 
 211 static int imx_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd)
 212 {
 213         return imx_gpc_pu_pgc_sw_pxx_req(genpd, true);
 214 }
 215 
 216 static int imx_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd)
 217 {
 218         return imx_gpc_pu_pgc_sw_pxx_req(genpd, false);
 219 }
 220 
 221 static const struct imx_pgc_domain imx7_pgc_domains[] = {
 222         [IMX7_POWER_DOMAIN_MIPI_PHY] = {
 223                 .genpd = {
 224                         .name      = "mipi-phy",
 225                 },
 226                 .bits  = {
 227                         .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ,
 228                         .map = IMX7_MIPI_PHY_A_CORE_DOMAIN,
 229                 },
 230                 .voltage   = 1000000,
 231                 .pgc       = IMX7_PGC_MIPI,
 232         },
 233 
 234         [IMX7_POWER_DOMAIN_PCIE_PHY] = {
 235                 .genpd = {
 236                         .name      = "pcie-phy",
 237                 },
 238                 .bits  = {
 239                         .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ,
 240                         .map = IMX7_PCIE_PHY_A_CORE_DOMAIN,
 241                 },
 242                 .voltage   = 1000000,
 243                 .pgc       = IMX7_PGC_PCIE,
 244         },
 245 
 246         [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = {
 247                 .genpd = {
 248                         .name      = "usb-hsic-phy",
 249                 },
 250                 .bits  = {
 251                         .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ,
 252                         .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN,
 253                 },
 254                 .voltage   = 1200000,
 255                 .pgc       = IMX7_PGC_USB_HSIC,
 256         },
 257 };
 258 
 259 static const struct regmap_range imx7_yes_ranges[] = {
 260                 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
 261                                  GPC_M4_PU_PDN_FLG),
 262                 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI),
 263                                  GPC_PGC_SR(IMX7_PGC_MIPI)),
 264                 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE),
 265                                  GPC_PGC_SR(IMX7_PGC_PCIE)),
 266                 regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC),
 267                                  GPC_PGC_SR(IMX7_PGC_USB_HSIC)),
 268 };
 269 
 270 static const struct regmap_access_table imx7_access_table = {
 271         .yes_ranges     = imx7_yes_ranges,
 272         .n_yes_ranges   = ARRAY_SIZE(imx7_yes_ranges),
 273 };
 274 
 275 static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
 276         .domains = imx7_pgc_domains,
 277         .domains_num = ARRAY_SIZE(imx7_pgc_domains),
 278         .reg_access_table = &imx7_access_table,
 279 };
 280 
 281 static const struct imx_pgc_domain imx8m_pgc_domains[] = {
 282         [IMX8M_POWER_DOMAIN_MIPI] = {
 283                 .genpd = {
 284                         .name      = "mipi",
 285                 },
 286                 .bits  = {
 287                         .pxx = IMX8M_MIPI_SW_Pxx_REQ,
 288                         .map = IMX8M_MIPI_A53_DOMAIN,
 289                 },
 290                 .pgc       = IMX8M_PGC_MIPI,
 291         },
 292 
 293         [IMX8M_POWER_DOMAIN_PCIE1] = {
 294                 .genpd = {
 295                         .name = "pcie1",
 296                 },
 297                 .bits  = {
 298                         .pxx = IMX8M_PCIE1_SW_Pxx_REQ,
 299                         .map = IMX8M_PCIE1_A53_DOMAIN,
 300                 },
 301                 .pgc   = IMX8M_PGC_PCIE1,
 302         },
 303 
 304         [IMX8M_POWER_DOMAIN_USB_OTG1] = {
 305                 .genpd = {
 306                         .name = "usb-otg1",
 307                 },
 308                 .bits  = {
 309                         .pxx = IMX8M_OTG1_SW_Pxx_REQ,
 310                         .map = IMX8M_OTG1_A53_DOMAIN,
 311                 },
 312                 .pgc   = IMX8M_PGC_OTG1,
 313         },
 314 
 315         [IMX8M_POWER_DOMAIN_USB_OTG2] = {
 316                 .genpd = {
 317                         .name = "usb-otg2",
 318                 },
 319                 .bits  = {
 320                         .pxx = IMX8M_OTG2_SW_Pxx_REQ,
 321                         .map = IMX8M_OTG2_A53_DOMAIN,
 322                 },
 323                 .pgc   = IMX8M_PGC_OTG2,
 324         },
 325 
 326         [IMX8M_POWER_DOMAIN_DDR1] = {
 327                 .genpd = {
 328                         .name = "ddr1",
 329                 },
 330                 .bits  = {
 331                         .pxx = IMX8M_DDR1_SW_Pxx_REQ,
 332                         .map = IMX8M_DDR2_A53_DOMAIN,
 333                 },
 334                 .pgc   = IMX8M_PGC_DDR1,
 335         },
 336 
 337         [IMX8M_POWER_DOMAIN_GPU] = {
 338                 .genpd = {
 339                         .name = "gpu",
 340                 },
 341                 .bits  = {
 342                         .pxx = IMX8M_GPU_SW_Pxx_REQ,
 343                         .map = IMX8M_GPU_A53_DOMAIN,
 344                         .hsk = IMX8M_GPU_HSK_PWRDNREQN,
 345                 },
 346                 .pgc   = IMX8M_PGC_GPU,
 347         },
 348 
 349         [IMX8M_POWER_DOMAIN_VPU] = {
 350                 .genpd = {
 351                         .name = "vpu",
 352                 },
 353                 .bits  = {
 354                         .pxx = IMX8M_VPU_SW_Pxx_REQ,
 355                         .map = IMX8M_VPU_A53_DOMAIN,
 356                         .hsk = IMX8M_VPU_HSK_PWRDNREQN,
 357                 },
 358                 .pgc   = IMX8M_PGC_VPU,
 359         },
 360 
 361         [IMX8M_POWER_DOMAIN_DISP] = {
 362                 .genpd = {
 363                         .name = "disp",
 364                 },
 365                 .bits  = {
 366                         .pxx = IMX8M_DISP_SW_Pxx_REQ,
 367                         .map = IMX8M_DISP_A53_DOMAIN,
 368                         .hsk = IMX8M_DISP_HSK_PWRDNREQN,
 369                 },
 370                 .pgc   = IMX8M_PGC_DISP,
 371         },
 372 
 373         [IMX8M_POWER_DOMAIN_MIPI_CSI1] = {
 374                 .genpd = {
 375                         .name = "mipi-csi1",
 376                 },
 377                 .bits  = {
 378                         .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ,
 379                         .map = IMX8M_MIPI_CSI1_A53_DOMAIN,
 380                 },
 381                 .pgc   = IMX8M_PGC_MIPI_CSI1,
 382         },
 383 
 384         [IMX8M_POWER_DOMAIN_MIPI_CSI2] = {
 385                 .genpd = {
 386                         .name = "mipi-csi2",
 387                 },
 388                 .bits  = {
 389                         .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ,
 390                         .map = IMX8M_MIPI_CSI2_A53_DOMAIN,
 391                 },
 392                 .pgc   = IMX8M_PGC_MIPI_CSI2,
 393         },
 394 
 395         [IMX8M_POWER_DOMAIN_PCIE2] = {
 396                 .genpd = {
 397                         .name = "pcie2",
 398                 },
 399                 .bits  = {
 400                         .pxx = IMX8M_PCIE2_SW_Pxx_REQ,
 401                         .map = IMX8M_PCIE2_A53_DOMAIN,
 402                 },
 403                 .pgc   = IMX8M_PGC_PCIE2,
 404         },
 405 };
 406 
 407 static const struct regmap_range imx8m_yes_ranges[] = {
 408                 regmap_reg_range(GPC_LPCR_A_CORE_BSC,
 409                                  GPC_PU_PWRHSK),
 410                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI),
 411                                  GPC_PGC_SR(IMX8M_PGC_MIPI)),
 412                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1),
 413                                  GPC_PGC_SR(IMX8M_PGC_PCIE1)),
 414                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1),
 415                                  GPC_PGC_SR(IMX8M_PGC_OTG1)),
 416                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2),
 417                                  GPC_PGC_SR(IMX8M_PGC_OTG2)),
 418                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1),
 419                                  GPC_PGC_SR(IMX8M_PGC_DDR1)),
 420                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU),
 421                                  GPC_PGC_SR(IMX8M_PGC_GPU)),
 422                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU),
 423                                  GPC_PGC_SR(IMX8M_PGC_VPU)),
 424                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP),
 425                                  GPC_PGC_SR(IMX8M_PGC_DISP)),
 426                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1),
 427                                  GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)),
 428                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2),
 429                                  GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)),
 430                 regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2),
 431                                  GPC_PGC_SR(IMX8M_PGC_PCIE2)),
 432 };
 433 
 434 static const struct regmap_access_table imx8m_access_table = {
 435         .yes_ranges     = imx8m_yes_ranges,
 436         .n_yes_ranges   = ARRAY_SIZE(imx8m_yes_ranges),
 437 };
 438 
 439 static const struct imx_pgc_domain_data imx8m_pgc_domain_data = {
 440         .domains = imx8m_pgc_domains,
 441         .domains_num = ARRAY_SIZE(imx8m_pgc_domains),
 442         .reg_access_table = &imx8m_access_table,
 443 };
 444 
 445 static int imx_pgc_get_clocks(struct imx_pgc_domain *domain)
 446 {
 447         int i, ret;
 448 
 449         for (i = 0; ; i++) {
 450                 struct clk *clk = of_clk_get(domain->dev->of_node, i);
 451                 if (IS_ERR(clk))
 452                         break;
 453                 if (i >= GPC_CLK_MAX) {
 454                         dev_err(domain->dev, "more than %d clocks\n",
 455                                 GPC_CLK_MAX);
 456                         ret = -EINVAL;
 457                         goto clk_err;
 458                 }
 459                 domain->clk[i] = clk;
 460         }
 461         domain->num_clks = i;
 462 
 463         return 0;
 464 
 465 clk_err:
 466         while (i--)
 467                 clk_put(domain->clk[i]);
 468 
 469         return ret;
 470 }
 471 
 472 static void imx_pgc_put_clocks(struct imx_pgc_domain *domain)
 473 {
 474         int i;
 475 
 476         for (i = domain->num_clks - 1; i >= 0; i--)
 477                 clk_put(domain->clk[i]);
 478 }
 479 
 480 static int imx_pgc_domain_probe(struct platform_device *pdev)
 481 {
 482         struct imx_pgc_domain *domain = pdev->dev.platform_data;
 483         int ret;
 484 
 485         domain->dev = &pdev->dev;
 486 
 487         domain->regulator = devm_regulator_get_optional(domain->dev, "power");
 488         if (IS_ERR(domain->regulator)) {
 489                 if (PTR_ERR(domain->regulator) != -ENODEV) {
 490                         if (PTR_ERR(domain->regulator) != -EPROBE_DEFER)
 491                                 dev_err(domain->dev, "Failed to get domain's regulator\n");
 492                         return PTR_ERR(domain->regulator);
 493                 }
 494         } else if (domain->voltage) {
 495                 regulator_set_voltage(domain->regulator,
 496                                       domain->voltage, domain->voltage);
 497         }
 498 
 499         ret = imx_pgc_get_clocks(domain);
 500         if (ret) {
 501                 if (ret != -EPROBE_DEFER)
 502                         dev_err(domain->dev, "Failed to get domain's clocks\n");
 503                 return ret;
 504         }
 505 
 506         ret = pm_genpd_init(&domain->genpd, NULL, true);
 507         if (ret) {
 508                 dev_err(domain->dev, "Failed to init power domain\n");
 509                 imx_pgc_put_clocks(domain);
 510                 return ret;
 511         }
 512 
 513         ret = of_genpd_add_provider_simple(domain->dev->of_node,
 514                                            &domain->genpd);
 515         if (ret) {
 516                 dev_err(domain->dev, "Failed to add genpd provider\n");
 517                 pm_genpd_remove(&domain->genpd);
 518                 imx_pgc_put_clocks(domain);
 519         }
 520 
 521         return ret;
 522 }
 523 
 524 static int imx_pgc_domain_remove(struct platform_device *pdev)
 525 {
 526         struct imx_pgc_domain *domain = pdev->dev.platform_data;
 527 
 528         of_genpd_del_provider(domain->dev->of_node);
 529         pm_genpd_remove(&domain->genpd);
 530         imx_pgc_put_clocks(domain);
 531 
 532         return 0;
 533 }
 534 
 535 static const struct platform_device_id imx_pgc_domain_id[] = {
 536         { "imx-pgc-domain", },
 537         { },
 538 };
 539 
 540 static struct platform_driver imx_pgc_domain_driver = {
 541         .driver = {
 542                 .name = "imx-pgc",
 543         },
 544         .probe    = imx_pgc_domain_probe,
 545         .remove   = imx_pgc_domain_remove,
 546         .id_table = imx_pgc_domain_id,
 547 };
 548 builtin_platform_driver(imx_pgc_domain_driver)
 549 
 550 static int imx_gpcv2_probe(struct platform_device *pdev)
 551 {
 552         const struct imx_pgc_domain_data *domain_data =
 553                         of_device_get_match_data(&pdev->dev);
 554 
 555         struct regmap_config regmap_config = {
 556                 .reg_bits       = 32,
 557                 .val_bits       = 32,
 558                 .reg_stride     = 4,
 559                 .rd_table       = domain_data->reg_access_table,
 560                 .wr_table       = domain_data->reg_access_table,
 561                 .max_register   = SZ_4K,
 562         };
 563         struct device *dev = &pdev->dev;
 564         struct device_node *pgc_np, *np;
 565         struct regmap *regmap;
 566         void __iomem *base;
 567         int ret;
 568 
 569         pgc_np = of_get_child_by_name(dev->of_node, "pgc");
 570         if (!pgc_np) {
 571                 dev_err(dev, "No power domains specified in DT\n");
 572                 return -EINVAL;
 573         }
 574 
 575         base = devm_platform_ioremap_resource(pdev, 0);
 576         if (IS_ERR(base))
 577                 return PTR_ERR(base);
 578 
 579         regmap = devm_regmap_init_mmio(dev, base, &regmap_config);
 580         if (IS_ERR(regmap)) {
 581                 ret = PTR_ERR(regmap);
 582                 dev_err(dev, "failed to init regmap (%d)\n", ret);
 583                 return ret;
 584         }
 585 
 586         for_each_child_of_node(pgc_np, np) {
 587                 struct platform_device *pd_pdev;
 588                 struct imx_pgc_domain *domain;
 589                 u32 domain_index;
 590 
 591                 ret = of_property_read_u32(np, "reg", &domain_index);
 592                 if (ret) {
 593                         dev_err(dev, "Failed to read 'reg' property\n");
 594                         of_node_put(np);
 595                         return ret;
 596                 }
 597 
 598                 if (domain_index >= domain_data->domains_num) {
 599                         dev_warn(dev,
 600                                  "Domain index %d is out of bounds\n",
 601                                  domain_index);
 602                         continue;
 603                 }
 604 
 605                 pd_pdev = platform_device_alloc("imx-pgc-domain",
 606                                                 domain_index);
 607                 if (!pd_pdev) {
 608                         dev_err(dev, "Failed to allocate platform device\n");
 609                         of_node_put(np);
 610                         return -ENOMEM;
 611                 }
 612 
 613                 ret = platform_device_add_data(pd_pdev,
 614                                                &domain_data->domains[domain_index],
 615                                                sizeof(domain_data->domains[domain_index]));
 616                 if (ret) {
 617                         platform_device_put(pd_pdev);
 618                         of_node_put(np);
 619                         return ret;
 620                 }
 621 
 622                 domain = pd_pdev->dev.platform_data;
 623                 domain->regmap = regmap;
 624                 domain->genpd.power_on  = imx_gpc_pu_pgc_sw_pup_req;
 625                 domain->genpd.power_off = imx_gpc_pu_pgc_sw_pdn_req;
 626 
 627                 pd_pdev->dev.parent = dev;
 628                 pd_pdev->dev.of_node = np;
 629 
 630                 ret = platform_device_add(pd_pdev);
 631                 if (ret) {
 632                         platform_device_put(pd_pdev);
 633                         of_node_put(np);
 634                         return ret;
 635                 }
 636         }
 637 
 638         return 0;
 639 }
 640 
 641 static const struct of_device_id imx_gpcv2_dt_ids[] = {
 642         { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, },
 643         { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, },
 644         { }
 645 };
 646 
 647 static struct platform_driver imx_gpc_driver = {
 648         .driver = {
 649                 .name = "imx-gpcv2",
 650                 .of_match_table = imx_gpcv2_dt_ids,
 651         },
 652         .probe = imx_gpcv2_probe,
 653 };
 654 builtin_platform_driver(imx_gpc_driver)

/* [<][>][^][v][top][bottom][index][help] */