18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0+ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2017 Impinj, Inc 48c2ecf20Sopenharmony_ci * Author: Andrey Smirnov <andrew.smirnov@gmail.com> 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Based on the code of analogus driver: 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * Copyright 2015-2017 Pengutronix, Lucas Stach <kernel@pengutronix.de> 98c2ecf20Sopenharmony_ci */ 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_ci#include <linux/clk.h> 128c2ecf20Sopenharmony_ci#include <linux/of_device.h> 138c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 148c2ecf20Sopenharmony_ci#include <linux/pm_domain.h> 158c2ecf20Sopenharmony_ci#include <linux/regmap.h> 168c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h> 178c2ecf20Sopenharmony_ci#include <linux/sizes.h> 188c2ecf20Sopenharmony_ci#include <dt-bindings/power/imx7-power.h> 198c2ecf20Sopenharmony_ci#include <dt-bindings/power/imx8mq-power.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#define GPC_LPCR_A_CORE_BSC 0x000 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci#define GPC_PGC_CPU_MAPPING 0x0ec 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci#define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN BIT(6) 268c2ecf20Sopenharmony_ci#define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN BIT(5) 278c2ecf20Sopenharmony_ci#define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN BIT(4) 288c2ecf20Sopenharmony_ci#define IMX7_PCIE_PHY_A_CORE_DOMAIN BIT(3) 298c2ecf20Sopenharmony_ci#define IMX7_MIPI_PHY_A_CORE_DOMAIN BIT(2) 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_ci#define IMX8M_PCIE2_A53_DOMAIN BIT(15) 328c2ecf20Sopenharmony_ci#define IMX8M_MIPI_CSI2_A53_DOMAIN BIT(14) 338c2ecf20Sopenharmony_ci#define IMX8M_MIPI_CSI1_A53_DOMAIN BIT(13) 348c2ecf20Sopenharmony_ci#define IMX8M_DISP_A53_DOMAIN BIT(12) 358c2ecf20Sopenharmony_ci#define IMX8M_HDMI_A53_DOMAIN BIT(11) 368c2ecf20Sopenharmony_ci#define IMX8M_VPU_A53_DOMAIN BIT(10) 378c2ecf20Sopenharmony_ci#define IMX8M_GPU_A53_DOMAIN BIT(9) 388c2ecf20Sopenharmony_ci#define IMX8M_DDR2_A53_DOMAIN BIT(8) 398c2ecf20Sopenharmony_ci#define IMX8M_DDR1_A53_DOMAIN BIT(7) 408c2ecf20Sopenharmony_ci#define IMX8M_OTG2_A53_DOMAIN BIT(5) 418c2ecf20Sopenharmony_ci#define IMX8M_OTG1_A53_DOMAIN BIT(4) 428c2ecf20Sopenharmony_ci#define IMX8M_PCIE1_A53_DOMAIN BIT(3) 438c2ecf20Sopenharmony_ci#define IMX8M_MIPI_A53_DOMAIN BIT(2) 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#define GPC_PU_PGC_SW_PUP_REQ 0x0f8 468c2ecf20Sopenharmony_ci#define GPC_PU_PGC_SW_PDN_REQ 0x104 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci#define IMX7_USB_HSIC_PHY_SW_Pxx_REQ BIT(4) 498c2ecf20Sopenharmony_ci#define IMX7_USB_OTG2_PHY_SW_Pxx_REQ BIT(3) 508c2ecf20Sopenharmony_ci#define IMX7_USB_OTG1_PHY_SW_Pxx_REQ BIT(2) 518c2ecf20Sopenharmony_ci#define IMX7_PCIE_PHY_SW_Pxx_REQ BIT(1) 528c2ecf20Sopenharmony_ci#define IMX7_MIPI_PHY_SW_Pxx_REQ BIT(0) 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci#define IMX8M_PCIE2_SW_Pxx_REQ BIT(13) 558c2ecf20Sopenharmony_ci#define IMX8M_MIPI_CSI2_SW_Pxx_REQ BIT(12) 568c2ecf20Sopenharmony_ci#define IMX8M_MIPI_CSI1_SW_Pxx_REQ BIT(11) 578c2ecf20Sopenharmony_ci#define IMX8M_DISP_SW_Pxx_REQ BIT(10) 588c2ecf20Sopenharmony_ci#define IMX8M_HDMI_SW_Pxx_REQ BIT(9) 598c2ecf20Sopenharmony_ci#define IMX8M_VPU_SW_Pxx_REQ BIT(8) 608c2ecf20Sopenharmony_ci#define IMX8M_GPU_SW_Pxx_REQ BIT(7) 618c2ecf20Sopenharmony_ci#define IMX8M_DDR2_SW_Pxx_REQ BIT(6) 628c2ecf20Sopenharmony_ci#define IMX8M_DDR1_SW_Pxx_REQ BIT(5) 638c2ecf20Sopenharmony_ci#define IMX8M_OTG2_SW_Pxx_REQ BIT(3) 648c2ecf20Sopenharmony_ci#define IMX8M_OTG1_SW_Pxx_REQ BIT(2) 658c2ecf20Sopenharmony_ci#define IMX8M_PCIE1_SW_Pxx_REQ BIT(1) 668c2ecf20Sopenharmony_ci#define IMX8M_MIPI_SW_Pxx_REQ BIT(0) 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_ci#define GPC_M4_PU_PDN_FLG 0x1bc 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci#define GPC_PU_PWRHSK 0x1fc 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#define IMX8M_GPU_HSK_PWRDNREQN BIT(6) 738c2ecf20Sopenharmony_ci#define IMX8M_VPU_HSK_PWRDNREQN BIT(5) 748c2ecf20Sopenharmony_ci#define IMX8M_DISP_HSK_PWRDNREQN BIT(4) 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci/* 778c2ecf20Sopenharmony_ci * The PGC offset values in Reference Manual 788c2ecf20Sopenharmony_ci * (Rev. 1, 01/2018 and the older ones) GPC chapter's 798c2ecf20Sopenharmony_ci * GPC_PGC memory map are incorrect, below offset 808c2ecf20Sopenharmony_ci * values are from design RTL. 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci#define IMX7_PGC_MIPI 16 838c2ecf20Sopenharmony_ci#define IMX7_PGC_PCIE 17 848c2ecf20Sopenharmony_ci#define IMX7_PGC_USB_HSIC 20 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_ci#define IMX8M_PGC_MIPI 16 878c2ecf20Sopenharmony_ci#define IMX8M_PGC_PCIE1 17 888c2ecf20Sopenharmony_ci#define IMX8M_PGC_OTG1 18 898c2ecf20Sopenharmony_ci#define IMX8M_PGC_OTG2 19 908c2ecf20Sopenharmony_ci#define IMX8M_PGC_DDR1 21 918c2ecf20Sopenharmony_ci#define IMX8M_PGC_GPU 23 928c2ecf20Sopenharmony_ci#define IMX8M_PGC_VPU 24 938c2ecf20Sopenharmony_ci#define IMX8M_PGC_DISP 26 948c2ecf20Sopenharmony_ci#define IMX8M_PGC_MIPI_CSI1 27 958c2ecf20Sopenharmony_ci#define IMX8M_PGC_MIPI_CSI2 28 968c2ecf20Sopenharmony_ci#define IMX8M_PGC_PCIE2 29 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci#define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40) 998c2ecf20Sopenharmony_ci#define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc) 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#define GPC_PGC_CTRL_PCR BIT(0) 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#define GPC_CLK_MAX 6 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_cistruct imx_pgc_domain { 1068c2ecf20Sopenharmony_ci struct generic_pm_domain genpd; 1078c2ecf20Sopenharmony_ci struct regmap *regmap; 1088c2ecf20Sopenharmony_ci struct regulator *regulator; 1098c2ecf20Sopenharmony_ci struct clk *clk[GPC_CLK_MAX]; 1108c2ecf20Sopenharmony_ci int num_clks; 1118c2ecf20Sopenharmony_ci 1128c2ecf20Sopenharmony_ci unsigned int pgc; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci const struct { 1158c2ecf20Sopenharmony_ci u32 pxx; 1168c2ecf20Sopenharmony_ci u32 map; 1178c2ecf20Sopenharmony_ci u32 hsk; 1188c2ecf20Sopenharmony_ci } bits; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci const int voltage; 1218c2ecf20Sopenharmony_ci struct device *dev; 1228c2ecf20Sopenharmony_ci}; 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistruct imx_pgc_domain_data { 1258c2ecf20Sopenharmony_ci const struct imx_pgc_domain *domains; 1268c2ecf20Sopenharmony_ci size_t domains_num; 1278c2ecf20Sopenharmony_ci const struct regmap_access_table *reg_access_table; 1288c2ecf20Sopenharmony_ci}; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_cistatic int imx_gpc_pu_pgc_sw_pxx_req(struct generic_pm_domain *genpd, 1318c2ecf20Sopenharmony_ci bool on) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci struct imx_pgc_domain *domain = container_of(genpd, 1348c2ecf20Sopenharmony_ci struct imx_pgc_domain, 1358c2ecf20Sopenharmony_ci genpd); 1368c2ecf20Sopenharmony_ci unsigned int offset = on ? 1378c2ecf20Sopenharmony_ci GPC_PU_PGC_SW_PUP_REQ : GPC_PU_PGC_SW_PDN_REQ; 1388c2ecf20Sopenharmony_ci const bool enable_power_control = !on; 1398c2ecf20Sopenharmony_ci const bool has_regulator = !IS_ERR(domain->regulator); 1408c2ecf20Sopenharmony_ci int i, ret = 0; 1418c2ecf20Sopenharmony_ci u32 pxx_req; 1428c2ecf20Sopenharmony_ci 1438c2ecf20Sopenharmony_ci regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING, 1448c2ecf20Sopenharmony_ci domain->bits.map, domain->bits.map); 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci if (has_regulator && on) { 1478c2ecf20Sopenharmony_ci ret = regulator_enable(domain->regulator); 1488c2ecf20Sopenharmony_ci if (ret) { 1498c2ecf20Sopenharmony_ci dev_err(domain->dev, "failed to enable regulator\n"); 1508c2ecf20Sopenharmony_ci goto unmap; 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci } 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci /* Enable reset clocks for all devices in the domain */ 1558c2ecf20Sopenharmony_ci for (i = 0; i < domain->num_clks; i++) 1568c2ecf20Sopenharmony_ci clk_prepare_enable(domain->clk[i]); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci if (enable_power_control) 1598c2ecf20Sopenharmony_ci regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc), 1608c2ecf20Sopenharmony_ci GPC_PGC_CTRL_PCR, GPC_PGC_CTRL_PCR); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci if (domain->bits.hsk) 1638c2ecf20Sopenharmony_ci regmap_update_bits(domain->regmap, GPC_PU_PWRHSK, 1648c2ecf20Sopenharmony_ci domain->bits.hsk, on ? domain->bits.hsk : 0); 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_ci regmap_update_bits(domain->regmap, offset, 1678c2ecf20Sopenharmony_ci domain->bits.pxx, domain->bits.pxx); 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci /* 1708c2ecf20Sopenharmony_ci * As per "5.5.9.4 Example Code 4" in IMX7DRM.pdf wait 1718c2ecf20Sopenharmony_ci * for PUP_REQ/PDN_REQ bit to be cleared 1728c2ecf20Sopenharmony_ci */ 1738c2ecf20Sopenharmony_ci ret = regmap_read_poll_timeout(domain->regmap, offset, pxx_req, 1748c2ecf20Sopenharmony_ci !(pxx_req & domain->bits.pxx), 1758c2ecf20Sopenharmony_ci 0, USEC_PER_MSEC); 1768c2ecf20Sopenharmony_ci if (ret) { 1778c2ecf20Sopenharmony_ci dev_err(domain->dev, "failed to command PGC\n"); 1788c2ecf20Sopenharmony_ci /* 1798c2ecf20Sopenharmony_ci * If we were in a process of enabling a 1808c2ecf20Sopenharmony_ci * domain and failed we might as well disable 1818c2ecf20Sopenharmony_ci * the regulator we just enabled. And if it 1828c2ecf20Sopenharmony_ci * was the opposite situation and we failed to 1838c2ecf20Sopenharmony_ci * power down -- keep the regulator on 1848c2ecf20Sopenharmony_ci */ 1858c2ecf20Sopenharmony_ci on = !on; 1868c2ecf20Sopenharmony_ci } 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (enable_power_control) 1898c2ecf20Sopenharmony_ci regmap_update_bits(domain->regmap, GPC_PGC_CTRL(domain->pgc), 1908c2ecf20Sopenharmony_ci GPC_PGC_CTRL_PCR, 0); 1918c2ecf20Sopenharmony_ci 1928c2ecf20Sopenharmony_ci /* Disable reset clocks for all devices in the domain */ 1938c2ecf20Sopenharmony_ci for (i = 0; i < domain->num_clks; i++) 1948c2ecf20Sopenharmony_ci clk_disable_unprepare(domain->clk[i]); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci if (has_regulator && !on) { 1978c2ecf20Sopenharmony_ci int err; 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci err = regulator_disable(domain->regulator); 2008c2ecf20Sopenharmony_ci if (err) 2018c2ecf20Sopenharmony_ci dev_err(domain->dev, 2028c2ecf20Sopenharmony_ci "failed to disable regulator: %d\n", err); 2038c2ecf20Sopenharmony_ci /* Preserve earlier error code */ 2048c2ecf20Sopenharmony_ci ret = ret ?: err; 2058c2ecf20Sopenharmony_ci } 2068c2ecf20Sopenharmony_ciunmap: 2078c2ecf20Sopenharmony_ci regmap_update_bits(domain->regmap, GPC_PGC_CPU_MAPPING, 2088c2ecf20Sopenharmony_ci domain->bits.map, 0); 2098c2ecf20Sopenharmony_ci return ret; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic int imx_gpc_pu_pgc_sw_pup_req(struct generic_pm_domain *genpd) 2138c2ecf20Sopenharmony_ci{ 2148c2ecf20Sopenharmony_ci return imx_gpc_pu_pgc_sw_pxx_req(genpd, true); 2158c2ecf20Sopenharmony_ci} 2168c2ecf20Sopenharmony_ci 2178c2ecf20Sopenharmony_cistatic int imx_gpc_pu_pgc_sw_pdn_req(struct generic_pm_domain *genpd) 2188c2ecf20Sopenharmony_ci{ 2198c2ecf20Sopenharmony_ci return imx_gpc_pu_pgc_sw_pxx_req(genpd, false); 2208c2ecf20Sopenharmony_ci} 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_cistatic const struct imx_pgc_domain imx7_pgc_domains[] = { 2238c2ecf20Sopenharmony_ci [IMX7_POWER_DOMAIN_MIPI_PHY] = { 2248c2ecf20Sopenharmony_ci .genpd = { 2258c2ecf20Sopenharmony_ci .name = "mipi-phy", 2268c2ecf20Sopenharmony_ci }, 2278c2ecf20Sopenharmony_ci .bits = { 2288c2ecf20Sopenharmony_ci .pxx = IMX7_MIPI_PHY_SW_Pxx_REQ, 2298c2ecf20Sopenharmony_ci .map = IMX7_MIPI_PHY_A_CORE_DOMAIN, 2308c2ecf20Sopenharmony_ci }, 2318c2ecf20Sopenharmony_ci .voltage = 1000000, 2328c2ecf20Sopenharmony_ci .pgc = IMX7_PGC_MIPI, 2338c2ecf20Sopenharmony_ci }, 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci [IMX7_POWER_DOMAIN_PCIE_PHY] = { 2368c2ecf20Sopenharmony_ci .genpd = { 2378c2ecf20Sopenharmony_ci .name = "pcie-phy", 2388c2ecf20Sopenharmony_ci }, 2398c2ecf20Sopenharmony_ci .bits = { 2408c2ecf20Sopenharmony_ci .pxx = IMX7_PCIE_PHY_SW_Pxx_REQ, 2418c2ecf20Sopenharmony_ci .map = IMX7_PCIE_PHY_A_CORE_DOMAIN, 2428c2ecf20Sopenharmony_ci }, 2438c2ecf20Sopenharmony_ci .voltage = 1000000, 2448c2ecf20Sopenharmony_ci .pgc = IMX7_PGC_PCIE, 2458c2ecf20Sopenharmony_ci }, 2468c2ecf20Sopenharmony_ci 2478c2ecf20Sopenharmony_ci [IMX7_POWER_DOMAIN_USB_HSIC_PHY] = { 2488c2ecf20Sopenharmony_ci .genpd = { 2498c2ecf20Sopenharmony_ci .name = "usb-hsic-phy", 2508c2ecf20Sopenharmony_ci }, 2518c2ecf20Sopenharmony_ci .bits = { 2528c2ecf20Sopenharmony_ci .pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ, 2538c2ecf20Sopenharmony_ci .map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN, 2548c2ecf20Sopenharmony_ci }, 2558c2ecf20Sopenharmony_ci .voltage = 1200000, 2568c2ecf20Sopenharmony_ci .pgc = IMX7_PGC_USB_HSIC, 2578c2ecf20Sopenharmony_ci }, 2588c2ecf20Sopenharmony_ci}; 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_cistatic const struct regmap_range imx7_yes_ranges[] = { 2618c2ecf20Sopenharmony_ci regmap_reg_range(GPC_LPCR_A_CORE_BSC, 2628c2ecf20Sopenharmony_ci GPC_M4_PU_PDN_FLG), 2638c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_MIPI), 2648c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX7_PGC_MIPI)), 2658c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_PCIE), 2668c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX7_PGC_PCIE)), 2678c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX7_PGC_USB_HSIC), 2688c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX7_PGC_USB_HSIC)), 2698c2ecf20Sopenharmony_ci}; 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_cistatic const struct regmap_access_table imx7_access_table = { 2728c2ecf20Sopenharmony_ci .yes_ranges = imx7_yes_ranges, 2738c2ecf20Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(imx7_yes_ranges), 2748c2ecf20Sopenharmony_ci}; 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_cistatic const struct imx_pgc_domain_data imx7_pgc_domain_data = { 2778c2ecf20Sopenharmony_ci .domains = imx7_pgc_domains, 2788c2ecf20Sopenharmony_ci .domains_num = ARRAY_SIZE(imx7_pgc_domains), 2798c2ecf20Sopenharmony_ci .reg_access_table = &imx7_access_table, 2808c2ecf20Sopenharmony_ci}; 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_cistatic const struct imx_pgc_domain imx8m_pgc_domains[] = { 2838c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_MIPI] = { 2848c2ecf20Sopenharmony_ci .genpd = { 2858c2ecf20Sopenharmony_ci .name = "mipi", 2868c2ecf20Sopenharmony_ci }, 2878c2ecf20Sopenharmony_ci .bits = { 2888c2ecf20Sopenharmony_ci .pxx = IMX8M_MIPI_SW_Pxx_REQ, 2898c2ecf20Sopenharmony_ci .map = IMX8M_MIPI_A53_DOMAIN, 2908c2ecf20Sopenharmony_ci }, 2918c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_MIPI, 2928c2ecf20Sopenharmony_ci }, 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_PCIE1] = { 2958c2ecf20Sopenharmony_ci .genpd = { 2968c2ecf20Sopenharmony_ci .name = "pcie1", 2978c2ecf20Sopenharmony_ci }, 2988c2ecf20Sopenharmony_ci .bits = { 2998c2ecf20Sopenharmony_ci .pxx = IMX8M_PCIE1_SW_Pxx_REQ, 3008c2ecf20Sopenharmony_ci .map = IMX8M_PCIE1_A53_DOMAIN, 3018c2ecf20Sopenharmony_ci }, 3028c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_PCIE1, 3038c2ecf20Sopenharmony_ci }, 3048c2ecf20Sopenharmony_ci 3058c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_USB_OTG1] = { 3068c2ecf20Sopenharmony_ci .genpd = { 3078c2ecf20Sopenharmony_ci .name = "usb-otg1", 3088c2ecf20Sopenharmony_ci }, 3098c2ecf20Sopenharmony_ci .bits = { 3108c2ecf20Sopenharmony_ci .pxx = IMX8M_OTG1_SW_Pxx_REQ, 3118c2ecf20Sopenharmony_ci .map = IMX8M_OTG1_A53_DOMAIN, 3128c2ecf20Sopenharmony_ci }, 3138c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_OTG1, 3148c2ecf20Sopenharmony_ci }, 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_USB_OTG2] = { 3178c2ecf20Sopenharmony_ci .genpd = { 3188c2ecf20Sopenharmony_ci .name = "usb-otg2", 3198c2ecf20Sopenharmony_ci }, 3208c2ecf20Sopenharmony_ci .bits = { 3218c2ecf20Sopenharmony_ci .pxx = IMX8M_OTG2_SW_Pxx_REQ, 3228c2ecf20Sopenharmony_ci .map = IMX8M_OTG2_A53_DOMAIN, 3238c2ecf20Sopenharmony_ci }, 3248c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_OTG2, 3258c2ecf20Sopenharmony_ci }, 3268c2ecf20Sopenharmony_ci 3278c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_DDR1] = { 3288c2ecf20Sopenharmony_ci .genpd = { 3298c2ecf20Sopenharmony_ci .name = "ddr1", 3308c2ecf20Sopenharmony_ci }, 3318c2ecf20Sopenharmony_ci .bits = { 3328c2ecf20Sopenharmony_ci .pxx = IMX8M_DDR1_SW_Pxx_REQ, 3338c2ecf20Sopenharmony_ci .map = IMX8M_DDR2_A53_DOMAIN, 3348c2ecf20Sopenharmony_ci }, 3358c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_DDR1, 3368c2ecf20Sopenharmony_ci }, 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_GPU] = { 3398c2ecf20Sopenharmony_ci .genpd = { 3408c2ecf20Sopenharmony_ci .name = "gpu", 3418c2ecf20Sopenharmony_ci }, 3428c2ecf20Sopenharmony_ci .bits = { 3438c2ecf20Sopenharmony_ci .pxx = IMX8M_GPU_SW_Pxx_REQ, 3448c2ecf20Sopenharmony_ci .map = IMX8M_GPU_A53_DOMAIN, 3458c2ecf20Sopenharmony_ci .hsk = IMX8M_GPU_HSK_PWRDNREQN, 3468c2ecf20Sopenharmony_ci }, 3478c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_GPU, 3488c2ecf20Sopenharmony_ci }, 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_VPU] = { 3518c2ecf20Sopenharmony_ci .genpd = { 3528c2ecf20Sopenharmony_ci .name = "vpu", 3538c2ecf20Sopenharmony_ci }, 3548c2ecf20Sopenharmony_ci .bits = { 3558c2ecf20Sopenharmony_ci .pxx = IMX8M_VPU_SW_Pxx_REQ, 3568c2ecf20Sopenharmony_ci .map = IMX8M_VPU_A53_DOMAIN, 3578c2ecf20Sopenharmony_ci .hsk = IMX8M_VPU_HSK_PWRDNREQN, 3588c2ecf20Sopenharmony_ci }, 3598c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_VPU, 3608c2ecf20Sopenharmony_ci }, 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_DISP] = { 3638c2ecf20Sopenharmony_ci .genpd = { 3648c2ecf20Sopenharmony_ci .name = "disp", 3658c2ecf20Sopenharmony_ci }, 3668c2ecf20Sopenharmony_ci .bits = { 3678c2ecf20Sopenharmony_ci .pxx = IMX8M_DISP_SW_Pxx_REQ, 3688c2ecf20Sopenharmony_ci .map = IMX8M_DISP_A53_DOMAIN, 3698c2ecf20Sopenharmony_ci .hsk = IMX8M_DISP_HSK_PWRDNREQN, 3708c2ecf20Sopenharmony_ci }, 3718c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_DISP, 3728c2ecf20Sopenharmony_ci }, 3738c2ecf20Sopenharmony_ci 3748c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_MIPI_CSI1] = { 3758c2ecf20Sopenharmony_ci .genpd = { 3768c2ecf20Sopenharmony_ci .name = "mipi-csi1", 3778c2ecf20Sopenharmony_ci }, 3788c2ecf20Sopenharmony_ci .bits = { 3798c2ecf20Sopenharmony_ci .pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ, 3808c2ecf20Sopenharmony_ci .map = IMX8M_MIPI_CSI1_A53_DOMAIN, 3818c2ecf20Sopenharmony_ci }, 3828c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_MIPI_CSI1, 3838c2ecf20Sopenharmony_ci }, 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_MIPI_CSI2] = { 3868c2ecf20Sopenharmony_ci .genpd = { 3878c2ecf20Sopenharmony_ci .name = "mipi-csi2", 3888c2ecf20Sopenharmony_ci }, 3898c2ecf20Sopenharmony_ci .bits = { 3908c2ecf20Sopenharmony_ci .pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ, 3918c2ecf20Sopenharmony_ci .map = IMX8M_MIPI_CSI2_A53_DOMAIN, 3928c2ecf20Sopenharmony_ci }, 3938c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_MIPI_CSI2, 3948c2ecf20Sopenharmony_ci }, 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ci [IMX8M_POWER_DOMAIN_PCIE2] = { 3978c2ecf20Sopenharmony_ci .genpd = { 3988c2ecf20Sopenharmony_ci .name = "pcie2", 3998c2ecf20Sopenharmony_ci }, 4008c2ecf20Sopenharmony_ci .bits = { 4018c2ecf20Sopenharmony_ci .pxx = IMX8M_PCIE2_SW_Pxx_REQ, 4028c2ecf20Sopenharmony_ci .map = IMX8M_PCIE2_A53_DOMAIN, 4038c2ecf20Sopenharmony_ci }, 4048c2ecf20Sopenharmony_ci .pgc = IMX8M_PGC_PCIE2, 4058c2ecf20Sopenharmony_ci }, 4068c2ecf20Sopenharmony_ci}; 4078c2ecf20Sopenharmony_ci 4088c2ecf20Sopenharmony_cistatic const struct regmap_range imx8m_yes_ranges[] = { 4098c2ecf20Sopenharmony_ci regmap_reg_range(GPC_LPCR_A_CORE_BSC, 4108c2ecf20Sopenharmony_ci GPC_PU_PWRHSK), 4118c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI), 4128c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_MIPI)), 4138c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE1), 4148c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_PCIE1)), 4158c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG1), 4168c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_OTG1)), 4178c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_OTG2), 4188c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_OTG2)), 4198c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DDR1), 4208c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_DDR1)), 4218c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_GPU), 4228c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_GPU)), 4238c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_VPU), 4248c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_VPU)), 4258c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_DISP), 4268c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_DISP)), 4278c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI1), 4288c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_MIPI_CSI1)), 4298c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_MIPI_CSI2), 4308c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_MIPI_CSI2)), 4318c2ecf20Sopenharmony_ci regmap_reg_range(GPC_PGC_CTRL(IMX8M_PGC_PCIE2), 4328c2ecf20Sopenharmony_ci GPC_PGC_SR(IMX8M_PGC_PCIE2)), 4338c2ecf20Sopenharmony_ci}; 4348c2ecf20Sopenharmony_ci 4358c2ecf20Sopenharmony_cistatic const struct regmap_access_table imx8m_access_table = { 4368c2ecf20Sopenharmony_ci .yes_ranges = imx8m_yes_ranges, 4378c2ecf20Sopenharmony_ci .n_yes_ranges = ARRAY_SIZE(imx8m_yes_ranges), 4388c2ecf20Sopenharmony_ci}; 4398c2ecf20Sopenharmony_ci 4408c2ecf20Sopenharmony_cistatic const struct imx_pgc_domain_data imx8m_pgc_domain_data = { 4418c2ecf20Sopenharmony_ci .domains = imx8m_pgc_domains, 4428c2ecf20Sopenharmony_ci .domains_num = ARRAY_SIZE(imx8m_pgc_domains), 4438c2ecf20Sopenharmony_ci .reg_access_table = &imx8m_access_table, 4448c2ecf20Sopenharmony_ci}; 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_cistatic int imx_pgc_get_clocks(struct imx_pgc_domain *domain) 4478c2ecf20Sopenharmony_ci{ 4488c2ecf20Sopenharmony_ci int i, ret; 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci for (i = 0; ; i++) { 4518c2ecf20Sopenharmony_ci struct clk *clk = of_clk_get(domain->dev->of_node, i); 4528c2ecf20Sopenharmony_ci if (IS_ERR(clk)) 4538c2ecf20Sopenharmony_ci break; 4548c2ecf20Sopenharmony_ci if (i >= GPC_CLK_MAX) { 4558c2ecf20Sopenharmony_ci dev_err(domain->dev, "more than %d clocks\n", 4568c2ecf20Sopenharmony_ci GPC_CLK_MAX); 4578c2ecf20Sopenharmony_ci ret = -EINVAL; 4588c2ecf20Sopenharmony_ci goto clk_err; 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci domain->clk[i] = clk; 4618c2ecf20Sopenharmony_ci } 4628c2ecf20Sopenharmony_ci domain->num_clks = i; 4638c2ecf20Sopenharmony_ci 4648c2ecf20Sopenharmony_ci return 0; 4658c2ecf20Sopenharmony_ci 4668c2ecf20Sopenharmony_ciclk_err: 4678c2ecf20Sopenharmony_ci while (i--) 4688c2ecf20Sopenharmony_ci clk_put(domain->clk[i]); 4698c2ecf20Sopenharmony_ci 4708c2ecf20Sopenharmony_ci return ret; 4718c2ecf20Sopenharmony_ci} 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_cistatic void imx_pgc_put_clocks(struct imx_pgc_domain *domain) 4748c2ecf20Sopenharmony_ci{ 4758c2ecf20Sopenharmony_ci int i; 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci for (i = domain->num_clks - 1; i >= 0; i--) 4788c2ecf20Sopenharmony_ci clk_put(domain->clk[i]); 4798c2ecf20Sopenharmony_ci} 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_cistatic int imx_pgc_domain_probe(struct platform_device *pdev) 4828c2ecf20Sopenharmony_ci{ 4838c2ecf20Sopenharmony_ci struct imx_pgc_domain *domain = pdev->dev.platform_data; 4848c2ecf20Sopenharmony_ci int ret; 4858c2ecf20Sopenharmony_ci 4868c2ecf20Sopenharmony_ci domain->dev = &pdev->dev; 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_ci domain->regulator = devm_regulator_get_optional(domain->dev, "power"); 4898c2ecf20Sopenharmony_ci if (IS_ERR(domain->regulator)) { 4908c2ecf20Sopenharmony_ci if (PTR_ERR(domain->regulator) != -ENODEV) 4918c2ecf20Sopenharmony_ci return dev_err_probe(domain->dev, PTR_ERR(domain->regulator), 4928c2ecf20Sopenharmony_ci "Failed to get domain's regulator\n"); 4938c2ecf20Sopenharmony_ci } else if (domain->voltage) { 4948c2ecf20Sopenharmony_ci regulator_set_voltage(domain->regulator, 4958c2ecf20Sopenharmony_ci domain->voltage, domain->voltage); 4968c2ecf20Sopenharmony_ci } 4978c2ecf20Sopenharmony_ci 4988c2ecf20Sopenharmony_ci ret = imx_pgc_get_clocks(domain); 4998c2ecf20Sopenharmony_ci if (ret) 5008c2ecf20Sopenharmony_ci return dev_err_probe(domain->dev, ret, "Failed to get domain's clocks\n"); 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci ret = pm_genpd_init(&domain->genpd, NULL, true); 5038c2ecf20Sopenharmony_ci if (ret) { 5048c2ecf20Sopenharmony_ci dev_err(domain->dev, "Failed to init power domain\n"); 5058c2ecf20Sopenharmony_ci imx_pgc_put_clocks(domain); 5068c2ecf20Sopenharmony_ci return ret; 5078c2ecf20Sopenharmony_ci } 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci ret = of_genpd_add_provider_simple(domain->dev->of_node, 5108c2ecf20Sopenharmony_ci &domain->genpd); 5118c2ecf20Sopenharmony_ci if (ret) { 5128c2ecf20Sopenharmony_ci dev_err(domain->dev, "Failed to add genpd provider\n"); 5138c2ecf20Sopenharmony_ci pm_genpd_remove(&domain->genpd); 5148c2ecf20Sopenharmony_ci imx_pgc_put_clocks(domain); 5158c2ecf20Sopenharmony_ci } 5168c2ecf20Sopenharmony_ci 5178c2ecf20Sopenharmony_ci return ret; 5188c2ecf20Sopenharmony_ci} 5198c2ecf20Sopenharmony_ci 5208c2ecf20Sopenharmony_cistatic int imx_pgc_domain_remove(struct platform_device *pdev) 5218c2ecf20Sopenharmony_ci{ 5228c2ecf20Sopenharmony_ci struct imx_pgc_domain *domain = pdev->dev.platform_data; 5238c2ecf20Sopenharmony_ci 5248c2ecf20Sopenharmony_ci of_genpd_del_provider(domain->dev->of_node); 5258c2ecf20Sopenharmony_ci pm_genpd_remove(&domain->genpd); 5268c2ecf20Sopenharmony_ci imx_pgc_put_clocks(domain); 5278c2ecf20Sopenharmony_ci 5288c2ecf20Sopenharmony_ci return 0; 5298c2ecf20Sopenharmony_ci} 5308c2ecf20Sopenharmony_ci 5318c2ecf20Sopenharmony_cistatic const struct platform_device_id imx_pgc_domain_id[] = { 5328c2ecf20Sopenharmony_ci { "imx-pgc-domain", }, 5338c2ecf20Sopenharmony_ci { }, 5348c2ecf20Sopenharmony_ci}; 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_cistatic struct platform_driver imx_pgc_domain_driver = { 5378c2ecf20Sopenharmony_ci .driver = { 5388c2ecf20Sopenharmony_ci .name = "imx-pgc", 5398c2ecf20Sopenharmony_ci }, 5408c2ecf20Sopenharmony_ci .probe = imx_pgc_domain_probe, 5418c2ecf20Sopenharmony_ci .remove = imx_pgc_domain_remove, 5428c2ecf20Sopenharmony_ci .id_table = imx_pgc_domain_id, 5438c2ecf20Sopenharmony_ci}; 5448c2ecf20Sopenharmony_cibuiltin_platform_driver(imx_pgc_domain_driver) 5458c2ecf20Sopenharmony_ci 5468c2ecf20Sopenharmony_cistatic int imx_gpcv2_probe(struct platform_device *pdev) 5478c2ecf20Sopenharmony_ci{ 5488c2ecf20Sopenharmony_ci const struct imx_pgc_domain_data *domain_data = 5498c2ecf20Sopenharmony_ci of_device_get_match_data(&pdev->dev); 5508c2ecf20Sopenharmony_ci 5518c2ecf20Sopenharmony_ci struct regmap_config regmap_config = { 5528c2ecf20Sopenharmony_ci .reg_bits = 32, 5538c2ecf20Sopenharmony_ci .val_bits = 32, 5548c2ecf20Sopenharmony_ci .reg_stride = 4, 5558c2ecf20Sopenharmony_ci .rd_table = domain_data->reg_access_table, 5568c2ecf20Sopenharmony_ci .wr_table = domain_data->reg_access_table, 5578c2ecf20Sopenharmony_ci .max_register = SZ_4K, 5588c2ecf20Sopenharmony_ci }; 5598c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 5608c2ecf20Sopenharmony_ci struct device_node *pgc_np, *np; 5618c2ecf20Sopenharmony_ci struct regmap *regmap; 5628c2ecf20Sopenharmony_ci void __iomem *base; 5638c2ecf20Sopenharmony_ci int ret; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci pgc_np = of_get_child_by_name(dev->of_node, "pgc"); 5668c2ecf20Sopenharmony_ci if (!pgc_np) { 5678c2ecf20Sopenharmony_ci dev_err(dev, "No power domains specified in DT\n"); 5688c2ecf20Sopenharmony_ci return -EINVAL; 5698c2ecf20Sopenharmony_ci } 5708c2ecf20Sopenharmony_ci 5718c2ecf20Sopenharmony_ci base = devm_platform_ioremap_resource(pdev, 0); 5728c2ecf20Sopenharmony_ci if (IS_ERR(base)) 5738c2ecf20Sopenharmony_ci return PTR_ERR(base); 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci regmap = devm_regmap_init_mmio(dev, base, ®map_config); 5768c2ecf20Sopenharmony_ci if (IS_ERR(regmap)) { 5778c2ecf20Sopenharmony_ci ret = PTR_ERR(regmap); 5788c2ecf20Sopenharmony_ci dev_err(dev, "failed to init regmap (%d)\n", ret); 5798c2ecf20Sopenharmony_ci return ret; 5808c2ecf20Sopenharmony_ci } 5818c2ecf20Sopenharmony_ci 5828c2ecf20Sopenharmony_ci for_each_child_of_node(pgc_np, np) { 5838c2ecf20Sopenharmony_ci struct platform_device *pd_pdev; 5848c2ecf20Sopenharmony_ci struct imx_pgc_domain *domain; 5858c2ecf20Sopenharmony_ci u32 domain_index; 5868c2ecf20Sopenharmony_ci 5878c2ecf20Sopenharmony_ci ret = of_property_read_u32(np, "reg", &domain_index); 5888c2ecf20Sopenharmony_ci if (ret) { 5898c2ecf20Sopenharmony_ci dev_err(dev, "Failed to read 'reg' property\n"); 5908c2ecf20Sopenharmony_ci of_node_put(np); 5918c2ecf20Sopenharmony_ci return ret; 5928c2ecf20Sopenharmony_ci } 5938c2ecf20Sopenharmony_ci 5948c2ecf20Sopenharmony_ci if (domain_index >= domain_data->domains_num) { 5958c2ecf20Sopenharmony_ci dev_warn(dev, 5968c2ecf20Sopenharmony_ci "Domain index %d is out of bounds\n", 5978c2ecf20Sopenharmony_ci domain_index); 5988c2ecf20Sopenharmony_ci continue; 5998c2ecf20Sopenharmony_ci } 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_ci pd_pdev = platform_device_alloc("imx-pgc-domain", 6028c2ecf20Sopenharmony_ci domain_index); 6038c2ecf20Sopenharmony_ci if (!pd_pdev) { 6048c2ecf20Sopenharmony_ci dev_err(dev, "Failed to allocate platform device\n"); 6058c2ecf20Sopenharmony_ci of_node_put(np); 6068c2ecf20Sopenharmony_ci return -ENOMEM; 6078c2ecf20Sopenharmony_ci } 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci ret = platform_device_add_data(pd_pdev, 6108c2ecf20Sopenharmony_ci &domain_data->domains[domain_index], 6118c2ecf20Sopenharmony_ci sizeof(domain_data->domains[domain_index])); 6128c2ecf20Sopenharmony_ci if (ret) { 6138c2ecf20Sopenharmony_ci platform_device_put(pd_pdev); 6148c2ecf20Sopenharmony_ci of_node_put(np); 6158c2ecf20Sopenharmony_ci return ret; 6168c2ecf20Sopenharmony_ci } 6178c2ecf20Sopenharmony_ci 6188c2ecf20Sopenharmony_ci domain = pd_pdev->dev.platform_data; 6198c2ecf20Sopenharmony_ci domain->regmap = regmap; 6208c2ecf20Sopenharmony_ci domain->genpd.power_on = imx_gpc_pu_pgc_sw_pup_req; 6218c2ecf20Sopenharmony_ci domain->genpd.power_off = imx_gpc_pu_pgc_sw_pdn_req; 6228c2ecf20Sopenharmony_ci 6238c2ecf20Sopenharmony_ci pd_pdev->dev.parent = dev; 6248c2ecf20Sopenharmony_ci pd_pdev->dev.of_node = np; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci ret = platform_device_add(pd_pdev); 6278c2ecf20Sopenharmony_ci if (ret) { 6288c2ecf20Sopenharmony_ci platform_device_put(pd_pdev); 6298c2ecf20Sopenharmony_ci of_node_put(np); 6308c2ecf20Sopenharmony_ci return ret; 6318c2ecf20Sopenharmony_ci } 6328c2ecf20Sopenharmony_ci } 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci return 0; 6358c2ecf20Sopenharmony_ci} 6368c2ecf20Sopenharmony_ci 6378c2ecf20Sopenharmony_cistatic const struct of_device_id imx_gpcv2_dt_ids[] = { 6388c2ecf20Sopenharmony_ci { .compatible = "fsl,imx7d-gpc", .data = &imx7_pgc_domain_data, }, 6398c2ecf20Sopenharmony_ci { .compatible = "fsl,imx8mq-gpc", .data = &imx8m_pgc_domain_data, }, 6408c2ecf20Sopenharmony_ci { } 6418c2ecf20Sopenharmony_ci}; 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_cistatic struct platform_driver imx_gpc_driver = { 6448c2ecf20Sopenharmony_ci .driver = { 6458c2ecf20Sopenharmony_ci .name = "imx-gpcv2", 6468c2ecf20Sopenharmony_ci .of_match_table = imx_gpcv2_dt_ids, 6478c2ecf20Sopenharmony_ci }, 6488c2ecf20Sopenharmony_ci .probe = imx_gpcv2_probe, 6498c2ecf20Sopenharmony_ci}; 6508c2ecf20Sopenharmony_cibuiltin_platform_driver(imx_gpc_driver) 651