2018-09-18 14:48:14 -03:00
// SPDX-License-Identifier: GPL-2.0+
2017-03-28 08:19:45 -07:00
/*
* Copyright 2017 Impinj , Inc
* Author : Andrey Smirnov < andrew . smirnov @ gmail . com >
*
* Based on the code of analogus driver :
*
* Copyright 2015 - 2017 Pengutronix , Lucas Stach < kernel @ pengutronix . de >
*/
2018-12-17 16:31:52 +01:00
# include <linux/clk.h>
2018-08-28 16:36:46 +08:00
# include <linux/of_device.h>
2017-03-28 08:19:45 -07:00
# include <linux/platform_device.h>
# include <linux/pm_domain.h>
2021-05-10 12:00:38 +08:00
# include <linux/pm_runtime.h>
2017-03-28 08:19:45 -07:00
# include <linux/regmap.h>
# include <linux/regulator/consumer.h>
2021-05-10 12:00:41 +08:00
# include <linux/reset.h>
2020-01-20 14:51:28 +02:00
# include <linux/sizes.h>
2017-03-28 08:19:45 -07:00
# include <dt-bindings/power/imx7-power.h>
2018-11-16 16:49:27 +01:00
# include <dt-bindings/power/imx8mq-power.h>
2021-05-10 12:00:43 +08:00
# include <dt-bindings/power/imx8mm-power.h>
2021-05-24 20:07:29 -05:00
# include <dt-bindings/power/imx8mn-power.h>
2022-03-30 12:46:18 +02:00
# include <dt-bindings/power/imx8mp-power.h>
2017-03-28 08:19:45 -07:00
2018-08-28 16:36:45 +08:00
# define GPC_LPCR_A_CORE_BSC 0x000
2017-03-28 08:19:45 -07:00
# define GPC_PGC_CPU_MAPPING 0x0ec
2022-03-30 12:46:18 +02:00
# define IMX8MP_GPC_PGC_CPU_MAPPING 0x1cc
2018-11-16 16:49:27 +01:00
2018-11-16 16:49:25 +01:00
# define IMX7_USB_HSIC_PHY_A_CORE_DOMAIN BIT(6)
# define IMX7_USB_OTG2_PHY_A_CORE_DOMAIN BIT(5)
# define IMX7_USB_OTG1_PHY_A_CORE_DOMAIN BIT(4)
# define IMX7_PCIE_PHY_A_CORE_DOMAIN BIT(3)
# define IMX7_MIPI_PHY_A_CORE_DOMAIN BIT(2)
2017-03-28 08:19:45 -07:00
2018-11-16 16:49:27 +01:00
# define IMX8M_PCIE2_A53_DOMAIN BIT(15)
# define IMX8M_MIPI_CSI2_A53_DOMAIN BIT(14)
# define IMX8M_MIPI_CSI1_A53_DOMAIN BIT(13)
# define IMX8M_DISP_A53_DOMAIN BIT(12)
# define IMX8M_HDMI_A53_DOMAIN BIT(11)
# define IMX8M_VPU_A53_DOMAIN BIT(10)
# define IMX8M_GPU_A53_DOMAIN BIT(9)
# define IMX8M_DDR2_A53_DOMAIN BIT(8)
# define IMX8M_DDR1_A53_DOMAIN BIT(7)
# define IMX8M_OTG2_A53_DOMAIN BIT(5)
# define IMX8M_OTG1_A53_DOMAIN BIT(4)
# define IMX8M_PCIE1_A53_DOMAIN BIT(3)
# define IMX8M_MIPI_A53_DOMAIN BIT(2)
2021-05-10 12:00:43 +08:00
# define IMX8MM_VPUH1_A53_DOMAIN BIT(15)
# define IMX8MM_VPUG2_A53_DOMAIN BIT(14)
# define IMX8MM_VPUG1_A53_DOMAIN BIT(13)
# define IMX8MM_DISPMIX_A53_DOMAIN BIT(12)
# define IMX8MM_VPUMIX_A53_DOMAIN BIT(10)
# define IMX8MM_GPUMIX_A53_DOMAIN BIT(9)
# define IMX8MM_GPU_A53_DOMAIN (BIT(8) | BIT(11))
# define IMX8MM_DDR1_A53_DOMAIN BIT(7)
# define IMX8MM_OTG2_A53_DOMAIN BIT(5)
# define IMX8MM_OTG1_A53_DOMAIN BIT(4)
# define IMX8MM_PCIE_A53_DOMAIN BIT(3)
# define IMX8MM_MIPI_A53_DOMAIN BIT(2)
2021-05-24 20:07:29 -05:00
# define IMX8MN_DISPMIX_A53_DOMAIN BIT(12)
# define IMX8MN_GPUMIX_A53_DOMAIN BIT(9)
# define IMX8MN_DDR1_A53_DOMAIN BIT(7)
# define IMX8MN_OTG1_A53_DOMAIN BIT(4)
# define IMX8MN_MIPI_A53_DOMAIN BIT(2)
2022-03-30 12:46:18 +02:00
# define IMX8MP_MEDIA_ISPDWP_A53_DOMAIN BIT(20)
# define IMX8MP_HSIOMIX_A53_DOMAIN BIT(19)
# define IMX8MP_MIPI_PHY2_A53_DOMAIN BIT(18)
# define IMX8MP_HDMI_PHY_A53_DOMAIN BIT(17)
# define IMX8MP_HDMIMIX_A53_DOMAIN BIT(16)
# define IMX8MP_VPU_VC8000E_A53_DOMAIN BIT(15)
# define IMX8MP_VPU_G2_A53_DOMAIN BIT(14)
# define IMX8MP_VPU_G1_A53_DOMAIN BIT(13)
# define IMX8MP_MEDIAMIX_A53_DOMAIN BIT(12)
# define IMX8MP_GPU3D_A53_DOMAIN BIT(11)
# define IMX8MP_VPUMIX_A53_DOMAIN BIT(10)
# define IMX8MP_GPUMIX_A53_DOMAIN BIT(9)
# define IMX8MP_GPU2D_A53_DOMAIN BIT(8)
# define IMX8MP_AUDIOMIX_A53_DOMAIN BIT(7)
# define IMX8MP_MLMIX_A53_DOMAIN BIT(6)
# define IMX8MP_USB2_PHY_A53_DOMAIN BIT(5)
# define IMX8MP_USB1_PHY_A53_DOMAIN BIT(4)
# define IMX8MP_PCIE_PHY_A53_DOMAIN BIT(3)
# define IMX8MP_MIPI_PHY1_A53_DOMAIN BIT(2)
# define IMX8MP_GPC_PU_PGC_SW_PUP_REQ 0x0d8
# define IMX8MP_GPC_PU_PGC_SW_PDN_REQ 0x0e4
2017-03-28 08:19:45 -07:00
# define GPC_PU_PGC_SW_PUP_REQ 0x0f8
# define GPC_PU_PGC_SW_PDN_REQ 0x104
2018-11-16 16:49:27 +01:00
2018-11-16 16:49:25 +01:00
# define IMX7_USB_HSIC_PHY_SW_Pxx_REQ BIT(4)
# define IMX7_USB_OTG2_PHY_SW_Pxx_REQ BIT(3)
# define IMX7_USB_OTG1_PHY_SW_Pxx_REQ BIT(2)
# define IMX7_PCIE_PHY_SW_Pxx_REQ BIT(1)
# define IMX7_MIPI_PHY_SW_Pxx_REQ BIT(0)
2017-03-28 08:19:45 -07:00
2018-11-16 16:49:27 +01:00
# define IMX8M_PCIE2_SW_Pxx_REQ BIT(13)
# define IMX8M_MIPI_CSI2_SW_Pxx_REQ BIT(12)
# define IMX8M_MIPI_CSI1_SW_Pxx_REQ BIT(11)
# define IMX8M_DISP_SW_Pxx_REQ BIT(10)
# define IMX8M_HDMI_SW_Pxx_REQ BIT(9)
# define IMX8M_VPU_SW_Pxx_REQ BIT(8)
# define IMX8M_GPU_SW_Pxx_REQ BIT(7)
# define IMX8M_DDR2_SW_Pxx_REQ BIT(6)
# define IMX8M_DDR1_SW_Pxx_REQ BIT(5)
# define IMX8M_OTG2_SW_Pxx_REQ BIT(3)
# define IMX8M_OTG1_SW_Pxx_REQ BIT(2)
# define IMX8M_PCIE1_SW_Pxx_REQ BIT(1)
# define IMX8M_MIPI_SW_Pxx_REQ BIT(0)
2021-05-10 12:00:43 +08:00
# define IMX8MM_VPUH1_SW_Pxx_REQ BIT(13)
# define IMX8MM_VPUG2_SW_Pxx_REQ BIT(12)
# define IMX8MM_VPUG1_SW_Pxx_REQ BIT(11)
# define IMX8MM_DISPMIX_SW_Pxx_REQ BIT(10)
# define IMX8MM_VPUMIX_SW_Pxx_REQ BIT(8)
# define IMX8MM_GPUMIX_SW_Pxx_REQ BIT(7)
# define IMX8MM_GPU_SW_Pxx_REQ (BIT(6) | BIT(9))
# define IMX8MM_DDR1_SW_Pxx_REQ BIT(5)
# define IMX8MM_OTG2_SW_Pxx_REQ BIT(3)
# define IMX8MM_OTG1_SW_Pxx_REQ BIT(2)
# define IMX8MM_PCIE_SW_Pxx_REQ BIT(1)
# define IMX8MM_MIPI_SW_Pxx_REQ BIT(0)
2021-05-24 20:07:29 -05:00
# define IMX8MN_DISPMIX_SW_Pxx_REQ BIT(10)
# define IMX8MN_GPUMIX_SW_Pxx_REQ BIT(7)
# define IMX8MN_DDR1_SW_Pxx_REQ BIT(5)
# define IMX8MN_OTG1_SW_Pxx_REQ BIT(2)
# define IMX8MN_MIPI_SW_Pxx_REQ BIT(0)
2022-03-30 12:46:18 +02:00
# define IMX8MP_DDRMIX_Pxx_REQ BIT(19)
# define IMX8MP_MEDIA_ISP_DWP_Pxx_REQ BIT(18)
# define IMX8MP_HSIOMIX_Pxx_REQ BIT(17)
# define IMX8MP_MIPI_PHY2_Pxx_REQ BIT(16)
# define IMX8MP_HDMI_PHY_Pxx_REQ BIT(15)
# define IMX8MP_HDMIMIX_Pxx_REQ BIT(14)
# define IMX8MP_VPU_VC8K_Pxx_REQ BIT(13)
# define IMX8MP_VPU_G2_Pxx_REQ BIT(12)
# define IMX8MP_VPU_G1_Pxx_REQ BIT(11)
# define IMX8MP_MEDIMIX_Pxx_REQ BIT(10)
# define IMX8MP_GPU_3D_Pxx_REQ BIT(9)
# define IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ BIT(8)
# define IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ BIT(7)
# define IMX8MP_GPU_2D_Pxx_REQ BIT(6)
# define IMX8MP_AUDIOMIX_Pxx_REQ BIT(5)
# define IMX8MP_MLMIX_Pxx_REQ BIT(4)
# define IMX8MP_USB2_PHY_Pxx_REQ BIT(3)
# define IMX8MP_USB1_PHY_Pxx_REQ BIT(2)
# define IMX8MP_PCIE_PHY_SW_Pxx_REQ BIT(1)
# define IMX8MP_MIPI_PHY1_SW_Pxx_REQ BIT(0)
2017-03-28 08:19:45 -07:00
# define GPC_M4_PU_PDN_FLG 0x1bc
2022-03-30 12:46:18 +02:00
# define IMX8MP_GPC_PU_PWRHSK 0x190
2018-12-17 16:31:51 +01:00
# define GPC_PU_PWRHSK 0x1fc
2021-05-10 12:00:37 +08:00
# define IMX8M_GPU_HSK_PWRDNACKN BIT(26)
# define IMX8M_VPU_HSK_PWRDNACKN BIT(25)
# define IMX8M_DISP_HSK_PWRDNACKN BIT(24)
2018-12-17 16:31:51 +01:00
# define IMX8M_GPU_HSK_PWRDNREQN BIT(6)
# define IMX8M_VPU_HSK_PWRDNREQN BIT(5)
# define IMX8M_DISP_HSK_PWRDNREQN BIT(4)
2021-05-10 12:00:43 +08:00
# define IMX8MM_GPUMIX_HSK_PWRDNACKN BIT(29)
# define IMX8MM_GPU_HSK_PWRDNACKN (BIT(27) | BIT(28))
# define IMX8MM_VPUMIX_HSK_PWRDNACKN BIT(26)
# define IMX8MM_DISPMIX_HSK_PWRDNACKN BIT(25)
# define IMX8MM_HSIO_HSK_PWRDNACKN (BIT(23) | BIT(24))
# define IMX8MM_GPUMIX_HSK_PWRDNREQN BIT(11)
# define IMX8MM_GPU_HSK_PWRDNREQN (BIT(9) | BIT(10))
# define IMX8MM_VPUMIX_HSK_PWRDNREQN BIT(8)
# define IMX8MM_DISPMIX_HSK_PWRDNREQN BIT(7)
# define IMX8MM_HSIO_HSK_PWRDNREQN (BIT(5) | BIT(6))
2021-05-24 20:07:29 -05:00
# define IMX8MN_GPUMIX_HSK_PWRDNACKN (BIT(29) | BIT(27))
# define IMX8MN_DISPMIX_HSK_PWRDNACKN BIT(25)
# define IMX8MN_HSIO_HSK_PWRDNACKN BIT(23)
# define IMX8MN_GPUMIX_HSK_PWRDNREQN (BIT(11) | BIT(9))
# define IMX8MN_DISPMIX_HSK_PWRDNREQN BIT(7)
# define IMX8MN_HSIO_HSK_PWRDNREQN BIT(5)
2022-03-30 12:46:18 +02:00
# define IMX8MP_MEDIAMIX_PWRDNACKN BIT(30)
# define IMX8MP_HDMIMIX_PWRDNACKN BIT(29)
# define IMX8MP_HSIOMIX_PWRDNACKN BIT(28)
# define IMX8MP_VPUMIX_PWRDNACKN BIT(26)
# define IMX8MP_GPUMIX_PWRDNACKN BIT(25)
# define IMX8MP_MLMIX_PWRDNACKN (BIT(23) | BIT(24))
# define IMX8MP_AUDIOMIX_PWRDNACKN (BIT(20) | BIT(31))
# define IMX8MP_MEDIAMIX_PWRDNREQN BIT(14)
# define IMX8MP_HDMIMIX_PWRDNREQN BIT(13)
# define IMX8MP_HSIOMIX_PWRDNREQN BIT(12)
# define IMX8MP_VPUMIX_PWRDNREQN BIT(10)
# define IMX8MP_GPUMIX_PWRDNREQN BIT(9)
# define IMX8MP_MLMIX_PWRDNREQN (BIT(7) | BIT(8))
# define IMX8MP_AUDIOMIX_PWRDNREQN (BIT(4) | BIT(15))
2018-05-30 09:30:42 +08:00
/*
* The PGC offset values in Reference Manual
* ( Rev . 1 , 01 / 2018 and the older ones ) GPC chapter ' s
* GPC_PGC memory map are incorrect , below offset
* values are from design RTL .
*/
2018-11-16 16:49:25 +01:00
# define IMX7_PGC_MIPI 16
# define IMX7_PGC_PCIE 17
# define IMX7_PGC_USB_HSIC 20
2018-11-16 16:49:27 +01:00
# define IMX8M_PGC_MIPI 16
# define IMX8M_PGC_PCIE1 17
# define IMX8M_PGC_OTG1 18
# define IMX8M_PGC_OTG2 19
# define IMX8M_PGC_DDR1 21
# define IMX8M_PGC_GPU 23
# define IMX8M_PGC_VPU 24
# define IMX8M_PGC_DISP 26
# define IMX8M_PGC_MIPI_CSI1 27
# define IMX8M_PGC_MIPI_CSI2 28
# define IMX8M_PGC_PCIE2 29
2021-05-10 12:00:43 +08:00
# define IMX8MM_PGC_MIPI 16
# define IMX8MM_PGC_PCIE 17
# define IMX8MM_PGC_OTG1 18
# define IMX8MM_PGC_OTG2 19
# define IMX8MM_PGC_DDR1 21
# define IMX8MM_PGC_GPU2D 22
# define IMX8MM_PGC_GPUMIX 23
# define IMX8MM_PGC_VPUMIX 24
# define IMX8MM_PGC_GPU3D 25
# define IMX8MM_PGC_DISPMIX 26
# define IMX8MM_PGC_VPUG1 27
# define IMX8MM_PGC_VPUG2 28
# define IMX8MM_PGC_VPUH1 29
2021-05-24 20:07:29 -05:00
# define IMX8MN_PGC_MIPI 16
# define IMX8MN_PGC_OTG1 18
# define IMX8MN_PGC_DDR1 21
# define IMX8MN_PGC_GPUMIX 23
# define IMX8MN_PGC_DISPMIX 26
2022-03-30 12:46:18 +02:00
# define IMX8MP_PGC_NOC 9
# define IMX8MP_PGC_MIPI1 12
# define IMX8MP_PGC_PCIE 13
# define IMX8MP_PGC_USB1 14
# define IMX8MP_PGC_USB2 15
# define IMX8MP_PGC_MLMIX 16
# define IMX8MP_PGC_AUDIOMIX 17
# define IMX8MP_PGC_GPU2D 18
# define IMX8MP_PGC_GPUMIX 19
# define IMX8MP_PGC_VPUMIX 20
# define IMX8MP_PGC_GPU3D 21
# define IMX8MP_PGC_MEDIAMIX 22
# define IMX8MP_PGC_VPU_G1 23
# define IMX8MP_PGC_VPU_G2 24
# define IMX8MP_PGC_VPU_VC8000E 25
# define IMX8MP_PGC_HDMIMIX 26
# define IMX8MP_PGC_HDMI 27
# define IMX8MP_PGC_MIPI2 28
# define IMX8MP_PGC_HSIOMIX 29
# define IMX8MP_PGC_MEDIA_ISP_DWP 30
# define IMX8MP_PGC_DDRMIX 31
2017-03-28 08:19:45 -07:00
# define GPC_PGC_CTRL(n) (0x800 + (n) * 0x40)
# define GPC_PGC_SR(n) (GPC_PGC_CTRL(n) + 0xc)
# define GPC_PGC_CTRL_PCR BIT(0)
2022-03-30 12:46:16 +02:00
struct imx_pgc_regs {
u16 map ;
u16 pup ;
u16 pdn ;
u16 hsk ;
} ;
2018-08-28 16:36:46 +08:00
struct imx_pgc_domain {
2017-03-28 08:19:45 -07:00
struct generic_pm_domain genpd ;
struct regmap * regmap ;
2022-03-30 12:46:16 +02:00
const struct imx_pgc_regs * regs ;
2017-03-28 08:19:45 -07:00
struct regulator * regulator ;
2021-05-10 12:00:41 +08:00
struct reset_control * reset ;
2021-05-10 12:00:35 +08:00
struct clk_bulk_data * clks ;
2018-12-17 16:31:52 +01:00
int num_clks ;
2017-03-28 08:19:45 -07:00
2021-09-07 04:38:29 +02:00
unsigned long pgc ;
2017-03-28 08:19:45 -07:00
const struct {
u32 pxx ;
u32 map ;
2021-05-10 12:00:37 +08:00
u32 hskreq ;
u32 hskack ;
2017-03-28 08:19:45 -07:00
} bits ;
const int voltage ;
2021-10-02 02:59:41 +02:00
const bool keep_clocks ;
2017-03-28 08:19:45 -07:00
struct device * dev ;
2022-03-30 12:46:18 +02:00
unsigned int pgc_sw_pup_reg ;
unsigned int pgc_sw_pdn_reg ;
2017-03-28 08:19:45 -07:00
} ;
2018-08-28 16:36:46 +08:00
struct imx_pgc_domain_data {
const struct imx_pgc_domain * domains ;
size_t domains_num ;
2018-11-16 16:49:26 +01:00
const struct regmap_access_table * reg_access_table ;
2022-03-30 12:46:16 +02:00
const struct imx_pgc_regs * pgc_regs ;
2018-08-28 16:36:46 +08:00
} ;
2021-05-10 12:00:36 +08:00
static inline struct imx_pgc_domain *
to_imx_pgc_domain ( struct generic_pm_domain * genpd )
2017-03-28 08:19:45 -07:00
{
2021-05-10 12:00:36 +08:00
return container_of ( genpd , struct imx_pgc_domain , genpd ) ;
}
static int imx_pgc_power_up ( struct generic_pm_domain * genpd )
{
struct imx_pgc_domain * domain = to_imx_pgc_domain ( genpd ) ;
2021-09-07 04:38:29 +02:00
u32 reg_val , pgc ;
2021-05-10 12:00:36 +08:00
int ret ;
2021-05-10 12:00:38 +08:00
ret = pm_runtime_get_sync ( domain - > dev ) ;
if ( ret < 0 ) {
pm_runtime_put_noidle ( domain - > dev ) ;
return ret ;
}
2021-05-10 12:00:36 +08:00
if ( ! IS_ERR ( domain - > regulator ) ) {
2017-03-28 08:19:45 -07:00
ret = regulator_enable ( domain - > regulator ) ;
if ( ret ) {
dev_err ( domain - > dev , " failed to enable regulator \n " ) ;
2021-05-10 12:00:38 +08:00
goto out_put_pm ;
2017-03-28 08:19:45 -07:00
}
}
2018-12-17 16:31:52 +01:00
/* Enable reset clocks for all devices in the domain */
2021-05-10 12:00:35 +08:00
ret = clk_bulk_prepare_enable ( domain - > num_clks , domain - > clks ) ;
if ( ret ) {
dev_err ( domain - > dev , " failed to enable reset clocks \n " ) ;
2021-05-10 12:00:36 +08:00
goto out_regulator_disable ;
2021-05-10 12:00:35 +08:00
}
2018-12-17 16:31:52 +01:00
2021-10-02 02:59:37 +02:00
reset_control_assert ( domain - > reset ) ;
2021-05-10 12:00:39 +08:00
if ( domain - > bits . pxx ) {
/* request the domain to power up */
2022-03-30 12:46:16 +02:00
regmap_update_bits ( domain - > regmap , domain - > regs - > pup ,
2021-05-10 12:00:39 +08:00
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 ,
2022-03-30 12:46:16 +02:00
domain - > regs - > pup , reg_val ,
2021-05-10 12:00:39 +08:00
! ( reg_val & domain - > bits . pxx ) ,
0 , USEC_PER_MSEC ) ;
if ( ret ) {
dev_err ( domain - > dev , " failed to command PGC \n " ) ;
goto out_clk_disable ;
}
2017-03-28 08:19:45 -07:00
2021-05-10 12:00:39 +08:00
/* disable power control */
2021-09-07 04:38:29 +02:00
for_each_set_bit ( pgc , & domain - > pgc , 32 ) {
regmap_clear_bits ( domain - > regmap , GPC_PGC_CTRL ( pgc ) ,
GPC_PGC_CTRL_PCR ) ;
}
2021-05-10 12:00:39 +08:00
}
2021-05-10 12:00:36 +08:00
2021-05-10 12:00:41 +08:00
/* delay for reset to propagate */
udelay ( 5 ) ;
reset_control_deassert ( domain - > reset ) ;
2021-05-10 12:00:36 +08:00
/* request the ADB400 to power up */
2021-05-10 12:00:37 +08:00
if ( domain - > bits . hskreq ) {
2022-03-30 12:46:16 +02:00
regmap_update_bits ( domain - > regmap , domain - > regs - > hsk ,
2021-05-10 12:00:37 +08:00
domain - > bits . hskreq , domain - > bits . hskreq ) ;
/*
2022-03-30 12:46:16 +02:00
* ret = regmap_read_poll_timeout ( domain - > regmap , domain - > regs - > hsk , reg_val ,
2021-05-10 12:00:37 +08:00
* ( reg_val & domain - > bits . hskack ) , 0 ,
* USEC_PER_MSEC ) ;
* Technically we need the commented code to wait handshake . But that needs
* the BLK - CTL module BUS clk - en bit being set .
*
* There is a separate BLK - CTL module and we will have such a driver for it ,
* that driver will set the BUS clk - en bit and handshake will be triggered
* automatically there . Just add a delay and suppose the handshake finish
* after that .
*/
}
2017-03-28 08:19:45 -07:00
2018-12-17 16:31:52 +01:00
/* Disable reset clocks for all devices in the domain */
2021-10-02 02:59:41 +02:00
if ( ! domain - > keep_clocks )
clk_bulk_disable_unprepare ( domain - > num_clks , domain - > clks ) ;
2018-12-17 16:31:52 +01:00
2021-05-10 12:00:36 +08:00
return 0 ;
2017-03-28 08:19:45 -07:00
2021-05-10 12:00:36 +08:00
out_clk_disable :
clk_bulk_disable_unprepare ( domain - > num_clks , domain - > clks ) ;
out_regulator_disable :
if ( ! IS_ERR ( domain - > regulator ) )
regulator_disable ( domain - > regulator ) ;
2021-05-10 12:00:38 +08:00
out_put_pm :
pm_runtime_put ( domain - > dev ) ;
2021-05-10 12:00:34 +08:00
2017-03-28 08:19:45 -07:00
return ret ;
}
2021-05-10 12:00:36 +08:00
static int imx_pgc_power_down ( struct generic_pm_domain * genpd )
2017-03-28 08:19:45 -07:00
{
2021-05-10 12:00:36 +08:00
struct imx_pgc_domain * domain = to_imx_pgc_domain ( genpd ) ;
2021-09-07 04:38:29 +02:00
u32 reg_val , pgc ;
2021-05-10 12:00:36 +08:00
int ret ;
2017-03-28 08:19:45 -07:00
2021-05-10 12:00:36 +08:00
/* Enable reset clocks for all devices in the domain */
2021-10-02 02:59:41 +02:00
if ( ! domain - > keep_clocks ) {
ret = clk_bulk_prepare_enable ( domain - > num_clks , domain - > clks ) ;
if ( ret ) {
dev_err ( domain - > dev , " failed to enable reset clocks \n " ) ;
return ret ;
}
2021-05-10 12:00:36 +08:00
}
/* request the ADB400 to power down */
2021-05-10 12:00:37 +08:00
if ( domain - > bits . hskreq ) {
2022-03-30 12:46:16 +02:00
regmap_clear_bits ( domain - > regmap , domain - > regs - > hsk ,
2021-05-10 12:00:37 +08:00
domain - > bits . hskreq ) ;
2022-03-30 12:46:16 +02:00
ret = regmap_read_poll_timeout ( domain - > regmap , domain - > regs - > hsk ,
2021-05-10 12:00:37 +08:00
reg_val ,
! ( reg_val & domain - > bits . hskack ) ,
0 , USEC_PER_MSEC ) ;
if ( ret ) {
dev_err ( domain - > dev , " failed to power down ADB400 \n " ) ;
goto out_clk_disable ;
}
}
2021-05-10 12:00:36 +08:00
2021-05-10 12:00:39 +08:00
if ( domain - > bits . pxx ) {
/* enable power control */
2021-09-07 04:38:29 +02:00
for_each_set_bit ( pgc , & domain - > pgc , 32 ) {
regmap_update_bits ( domain - > regmap , GPC_PGC_CTRL ( pgc ) ,
GPC_PGC_CTRL_PCR , GPC_PGC_CTRL_PCR ) ;
}
2021-05-10 12:00:39 +08:00
/* request the domain to power down */
2022-03-30 12:46:16 +02:00
regmap_update_bits ( domain - > regmap , domain - > regs - > pdn ,
2021-05-10 12:00:39 +08:00
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 ,
2022-03-30 12:46:16 +02:00
domain - > regs - > pdn , reg_val ,
2021-05-10 12:00:39 +08:00
! ( reg_val & domain - > bits . pxx ) ,
0 , USEC_PER_MSEC ) ;
if ( ret ) {
dev_err ( domain - > dev , " failed to command PGC \n " ) ;
goto out_clk_disable ;
}
2021-05-10 12:00:36 +08:00
}
/* Disable reset clocks for all devices in the domain */
clk_bulk_disable_unprepare ( domain - > num_clks , domain - > clks ) ;
if ( ! IS_ERR ( domain - > regulator ) ) {
ret = regulator_disable ( domain - > regulator ) ;
if ( ret ) {
dev_err ( domain - > dev , " failed to disable regulator \n " ) ;
return ret ;
}
}
2021-10-16 23:05:47 +02:00
pm_runtime_put_sync_suspend ( domain - > dev ) ;
2021-05-10 12:00:38 +08:00
2021-05-10 12:00:36 +08:00
return 0 ;
out_clk_disable :
2022-02-18 23:57:20 +02:00
if ( ! domain - > keep_clocks )
clk_bulk_disable_unprepare ( domain - > num_clks , domain - > clks ) ;
2021-05-10 12:00:36 +08:00
return ret ;
2017-03-28 08:19:45 -07:00
}
2018-08-28 16:36:46 +08:00
static const struct imx_pgc_domain imx7_pgc_domains [ ] = {
2017-03-28 08:19:45 -07:00
[ IMX7_POWER_DOMAIN_MIPI_PHY ] = {
. genpd = {
. name = " mipi-phy " ,
} ,
. bits = {
2018-11-16 16:49:25 +01:00
. pxx = IMX7_MIPI_PHY_SW_Pxx_REQ ,
. map = IMX7_MIPI_PHY_A_CORE_DOMAIN ,
2017-03-28 08:19:45 -07:00
} ,
. voltage = 1000000 ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX7_PGC_MIPI ) ,
2017-03-28 08:19:45 -07:00
} ,
[ IMX7_POWER_DOMAIN_PCIE_PHY ] = {
. genpd = {
. name = " pcie-phy " ,
} ,
. bits = {
2018-11-16 16:49:25 +01:00
. pxx = IMX7_PCIE_PHY_SW_Pxx_REQ ,
. map = IMX7_PCIE_PHY_A_CORE_DOMAIN ,
2017-03-28 08:19:45 -07:00
} ,
. voltage = 1000000 ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX7_PGC_PCIE ) ,
2017-03-28 08:19:45 -07:00
} ,
[ IMX7_POWER_DOMAIN_USB_HSIC_PHY ] = {
. genpd = {
. name = " usb-hsic-phy " ,
} ,
. bits = {
2018-11-16 16:49:25 +01:00
. pxx = IMX7_USB_HSIC_PHY_SW_Pxx_REQ ,
. map = IMX7_USB_HSIC_PHY_A_CORE_DOMAIN ,
2017-03-28 08:19:45 -07:00
} ,
. voltage = 1200000 ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX7_PGC_USB_HSIC ) ,
2017-03-28 08:19:45 -07:00
} ,
} ;
2018-11-16 16:49:26 +01:00
static const struct regmap_range imx7_yes_ranges [ ] = {
regmap_reg_range ( GPC_LPCR_A_CORE_BSC ,
GPC_M4_PU_PDN_FLG ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX7_PGC_MIPI ) ,
GPC_PGC_SR ( IMX7_PGC_MIPI ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX7_PGC_PCIE ) ,
GPC_PGC_SR ( IMX7_PGC_PCIE ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX7_PGC_USB_HSIC ) ,
GPC_PGC_SR ( IMX7_PGC_USB_HSIC ) ) ,
} ;
static const struct regmap_access_table imx7_access_table = {
. yes_ranges = imx7_yes_ranges ,
. n_yes_ranges = ARRAY_SIZE ( imx7_yes_ranges ) ,
} ;
2022-03-30 12:46:16 +02:00
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 ,
} ;
2018-08-28 16:36:46 +08:00
static const struct imx_pgc_domain_data imx7_pgc_domain_data = {
. domains = imx7_pgc_domains ,
. domains_num = ARRAY_SIZE ( imx7_pgc_domains ) ,
2018-11-16 16:49:26 +01:00
. reg_access_table = & imx7_access_table ,
2022-03-30 12:46:16 +02:00
. pgc_regs = & imx7_pgc_regs ,
2018-08-28 16:36:46 +08:00
} ;
2018-11-16 16:49:27 +01:00
static const struct imx_pgc_domain imx8m_pgc_domains [ ] = {
[ IMX8M_POWER_DOMAIN_MIPI ] = {
. genpd = {
. name = " mipi " ,
} ,
. bits = {
. pxx = IMX8M_MIPI_SW_Pxx_REQ ,
. map = IMX8M_MIPI_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_MIPI ) ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_PCIE1 ] = {
. genpd = {
. name = " pcie1 " ,
} ,
. bits = {
. pxx = IMX8M_PCIE1_SW_Pxx_REQ ,
. map = IMX8M_PCIE1_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_PCIE1 ) ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_USB_OTG1 ] = {
. genpd = {
. name = " usb-otg1 " ,
} ,
. bits = {
. pxx = IMX8M_OTG1_SW_Pxx_REQ ,
. map = IMX8M_OTG1_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_OTG1 ) ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_USB_OTG2 ] = {
. genpd = {
. name = " usb-otg2 " ,
} ,
. bits = {
. pxx = IMX8M_OTG2_SW_Pxx_REQ ,
. map = IMX8M_OTG2_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_OTG2 ) ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_DDR1 ] = {
. genpd = {
. name = " ddr1 " ,
} ,
. bits = {
. pxx = IMX8M_DDR1_SW_Pxx_REQ ,
. map = IMX8M_DDR2_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_DDR1 ) ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_GPU ] = {
. genpd = {
. name = " gpu " ,
} ,
. bits = {
. pxx = IMX8M_GPU_SW_Pxx_REQ ,
. map = IMX8M_GPU_A53_DOMAIN ,
2021-05-10 12:00:37 +08:00
. hskreq = IMX8M_GPU_HSK_PWRDNREQN ,
. hskack = IMX8M_GPU_HSK_PWRDNACKN ,
2018-11-16 16:49:27 +01:00
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_GPU ) ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_VPU ] = {
. genpd = {
. name = " vpu " ,
} ,
. bits = {
. pxx = IMX8M_VPU_SW_Pxx_REQ ,
. map = IMX8M_VPU_A53_DOMAIN ,
2021-05-10 12:00:37 +08:00
. hskreq = IMX8M_VPU_HSK_PWRDNREQN ,
. hskack = IMX8M_VPU_HSK_PWRDNACKN ,
2018-11-16 16:49:27 +01:00
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_VPU ) ,
2021-10-02 02:59:42 +02:00
. keep_clocks = true ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_DISP ] = {
. genpd = {
. name = " disp " ,
} ,
. bits = {
. pxx = IMX8M_DISP_SW_Pxx_REQ ,
. map = IMX8M_DISP_A53_DOMAIN ,
2021-05-10 12:00:37 +08:00
. hskreq = IMX8M_DISP_HSK_PWRDNREQN ,
. hskack = IMX8M_DISP_HSK_PWRDNACKN ,
2018-11-16 16:49:27 +01:00
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_DISP ) ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_MIPI_CSI1 ] = {
. genpd = {
. name = " mipi-csi1 " ,
} ,
. bits = {
. pxx = IMX8M_MIPI_CSI1_SW_Pxx_REQ ,
. map = IMX8M_MIPI_CSI1_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_MIPI_CSI1 ) ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_MIPI_CSI2 ] = {
. genpd = {
. name = " mipi-csi2 " ,
} ,
. bits = {
. pxx = IMX8M_MIPI_CSI2_SW_Pxx_REQ ,
. map = IMX8M_MIPI_CSI2_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_MIPI_CSI2 ) ,
2018-11-16 16:49:27 +01:00
} ,
[ IMX8M_POWER_DOMAIN_PCIE2 ] = {
. genpd = {
. name = " pcie2 " ,
} ,
. bits = {
. pxx = IMX8M_PCIE2_SW_Pxx_REQ ,
. map = IMX8M_PCIE2_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8M_PGC_PCIE2 ) ,
2018-11-16 16:49:27 +01:00
} ,
} ;
static const struct regmap_range imx8m_yes_ranges [ ] = {
regmap_reg_range ( GPC_LPCR_A_CORE_BSC ,
2018-12-17 16:31:51 +01:00
GPC_PU_PWRHSK ) ,
2018-11-16 16:49:27 +01:00
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_MIPI ) ,
GPC_PGC_SR ( IMX8M_PGC_MIPI ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_PCIE1 ) ,
GPC_PGC_SR ( IMX8M_PGC_PCIE1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_OTG1 ) ,
GPC_PGC_SR ( IMX8M_PGC_OTG1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_OTG2 ) ,
GPC_PGC_SR ( IMX8M_PGC_OTG2 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_DDR1 ) ,
GPC_PGC_SR ( IMX8M_PGC_DDR1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_GPU ) ,
GPC_PGC_SR ( IMX8M_PGC_GPU ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_VPU ) ,
GPC_PGC_SR ( IMX8M_PGC_VPU ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_DISP ) ,
GPC_PGC_SR ( IMX8M_PGC_DISP ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_MIPI_CSI1 ) ,
GPC_PGC_SR ( IMX8M_PGC_MIPI_CSI1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_MIPI_CSI2 ) ,
GPC_PGC_SR ( IMX8M_PGC_MIPI_CSI2 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8M_PGC_PCIE2 ) ,
GPC_PGC_SR ( IMX8M_PGC_PCIE2 ) ) ,
} ;
static const struct regmap_access_table imx8m_access_table = {
. yes_ranges = imx8m_yes_ranges ,
. n_yes_ranges = ARRAY_SIZE ( imx8m_yes_ranges ) ,
} ;
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 ,
2022-03-30 12:46:16 +02:00
. pgc_regs = & imx7_pgc_regs ,
2018-11-16 16:49:27 +01:00
} ;
2021-05-10 12:00:43 +08:00
static const struct imx_pgc_domain imx8mm_pgc_domains [ ] = {
[ IMX8MM_POWER_DOMAIN_HSIOMIX ] = {
. genpd = {
. name = " hsiomix " ,
} ,
. bits = {
. pxx = 0 , /* no power sequence control */
. map = 0 , /* no power sequence control */
. hskreq = IMX8MM_HSIO_HSK_PWRDNREQN ,
. hskack = IMX8MM_HSIO_HSK_PWRDNACKN ,
} ,
2021-10-02 02:59:42 +02:00
. keep_clocks = true ,
2021-05-10 12:00:43 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_PCIE ] = {
. genpd = {
. name = " pcie " ,
} ,
. bits = {
. pxx = IMX8MM_PCIE_SW_Pxx_REQ ,
. map = IMX8MM_PCIE_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_PCIE ) ,
2021-05-10 12:00:43 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_OTG1 ] = {
. genpd = {
. name = " usb-otg1 " ,
} ,
. bits = {
. pxx = IMX8MM_OTG1_SW_Pxx_REQ ,
. map = IMX8MM_OTG1_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_OTG1 ) ,
2021-05-10 12:00:43 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_OTG2 ] = {
. genpd = {
. name = " usb-otg2 " ,
} ,
. bits = {
. pxx = IMX8MM_OTG2_SW_Pxx_REQ ,
. map = IMX8MM_OTG2_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_OTG2 ) ,
2021-05-10 12:00:43 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_GPUMIX ] = {
. genpd = {
. name = " gpumix " ,
} ,
. bits = {
. pxx = IMX8MM_GPUMIX_SW_Pxx_REQ ,
. map = IMX8MM_GPUMIX_A53_DOMAIN ,
. hskreq = IMX8MM_GPUMIX_HSK_PWRDNREQN ,
. hskack = IMX8MM_GPUMIX_HSK_PWRDNACKN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_GPUMIX ) ,
2021-10-02 02:59:42 +02:00
. keep_clocks = true ,
2021-05-10 12:00:43 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_GPU ] = {
. genpd = {
. name = " gpu " ,
} ,
. bits = {
. pxx = IMX8MM_GPU_SW_Pxx_REQ ,
. map = IMX8MM_GPU_A53_DOMAIN ,
. hskreq = IMX8MM_GPU_HSK_PWRDNREQN ,
. hskack = IMX8MM_GPU_HSK_PWRDNACKN ,
} ,
2021-09-07 04:38:30 +02:00
. pgc = BIT ( IMX8MM_PGC_GPU2D ) | BIT ( IMX8MM_PGC_GPU3D ) ,
2021-05-10 12:00:43 +08:00
} ,
2021-05-10 12:00:44 +08:00
[ IMX8MM_POWER_DOMAIN_VPUMIX ] = {
. genpd = {
. name = " vpumix " ,
} ,
. bits = {
. pxx = IMX8MM_VPUMIX_SW_Pxx_REQ ,
. map = IMX8MM_VPUMIX_A53_DOMAIN ,
. hskreq = IMX8MM_VPUMIX_HSK_PWRDNREQN ,
. hskack = IMX8MM_VPUMIX_HSK_PWRDNACKN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_VPUMIX ) ,
2021-10-02 02:59:42 +02:00
. keep_clocks = true ,
2021-05-10 12:00:44 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_VPUG1 ] = {
. genpd = {
. name = " vpu-g1 " ,
} ,
. bits = {
. pxx = IMX8MM_VPUG1_SW_Pxx_REQ ,
. map = IMX8MM_VPUG1_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_VPUG1 ) ,
2021-05-10 12:00:44 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_VPUG2 ] = {
. genpd = {
. name = " vpu-g2 " ,
} ,
. bits = {
. pxx = IMX8MM_VPUG2_SW_Pxx_REQ ,
. map = IMX8MM_VPUG2_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_VPUG2 ) ,
2021-05-10 12:00:44 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_VPUH1 ] = {
. genpd = {
. name = " vpu-h1 " ,
} ,
. bits = {
. pxx = IMX8MM_VPUH1_SW_Pxx_REQ ,
. map = IMX8MM_VPUH1_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_VPUH1 ) ,
2021-11-20 13:39:16 -06:00
. keep_clocks = true ,
2021-05-10 12:00:44 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_DISPMIX ] = {
. genpd = {
. name = " dispmix " ,
} ,
. bits = {
. pxx = IMX8MM_DISPMIX_SW_Pxx_REQ ,
. map = IMX8MM_DISPMIX_A53_DOMAIN ,
. hskreq = IMX8MM_DISPMIX_HSK_PWRDNREQN ,
. hskack = IMX8MM_DISPMIX_HSK_PWRDNACKN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_DISPMIX ) ,
2021-10-02 02:59:42 +02:00
. keep_clocks = true ,
2021-05-10 12:00:44 +08:00
} ,
[ IMX8MM_POWER_DOMAIN_MIPI ] = {
. genpd = {
. name = " mipi " ,
} ,
. bits = {
. pxx = IMX8MM_MIPI_SW_Pxx_REQ ,
. map = IMX8MM_MIPI_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MM_PGC_MIPI ) ,
2021-05-10 12:00:44 +08:00
} ,
2021-05-10 12:00:43 +08:00
} ;
static const struct regmap_range imx8mm_yes_ranges [ ] = {
regmap_reg_range ( GPC_LPCR_A_CORE_BSC ,
GPC_PU_PWRHSK ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_MIPI ) ,
GPC_PGC_SR ( IMX8MM_PGC_MIPI ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_PCIE ) ,
GPC_PGC_SR ( IMX8MM_PGC_PCIE ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_OTG1 ) ,
GPC_PGC_SR ( IMX8MM_PGC_OTG1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_OTG2 ) ,
GPC_PGC_SR ( IMX8MM_PGC_OTG2 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_DDR1 ) ,
GPC_PGC_SR ( IMX8MM_PGC_DDR1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_GPU2D ) ,
GPC_PGC_SR ( IMX8MM_PGC_GPU2D ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_GPUMIX ) ,
GPC_PGC_SR ( IMX8MM_PGC_GPUMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_VPUMIX ) ,
GPC_PGC_SR ( IMX8MM_PGC_VPUMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_GPU3D ) ,
GPC_PGC_SR ( IMX8MM_PGC_GPU3D ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_DISPMIX ) ,
GPC_PGC_SR ( IMX8MM_PGC_DISPMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_VPUG1 ) ,
GPC_PGC_SR ( IMX8MM_PGC_VPUG1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_VPUG2 ) ,
GPC_PGC_SR ( IMX8MM_PGC_VPUG2 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MM_PGC_VPUH1 ) ,
GPC_PGC_SR ( IMX8MM_PGC_VPUH1 ) ) ,
} ;
static const struct regmap_access_table imx8mm_access_table = {
. yes_ranges = imx8mm_yes_ranges ,
. n_yes_ranges = ARRAY_SIZE ( imx8mm_yes_ranges ) ,
} ;
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 ,
2022-03-30 12:46:16 +02:00
. pgc_regs = & imx7_pgc_regs ,
2021-05-10 12:00:43 +08:00
} ;
2022-03-30 12:46:18 +02:00
static const struct imx_pgc_domain imx8mp_pgc_domains [ ] = {
[ IMX8MP_POWER_DOMAIN_MIPI_PHY1 ] = {
. genpd = {
. name = " mipi-phy1 " ,
} ,
. bits = {
. pxx = IMX8MP_MIPI_PHY1_SW_Pxx_REQ ,
. map = IMX8MP_MIPI_PHY1_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_MIPI1 ) ,
} ,
[ IMX8MP_POWER_DOMAIN_PCIE_PHY ] = {
. genpd = {
. name = " pcie-phy1 " ,
} ,
. bits = {
. pxx = IMX8MP_PCIE_PHY_SW_Pxx_REQ ,
. map = IMX8MP_PCIE_PHY_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_PCIE ) ,
} ,
[ IMX8MP_POWER_DOMAIN_USB1_PHY ] = {
. genpd = {
. name = " usb-otg1 " ,
} ,
. bits = {
. pxx = IMX8MP_USB1_PHY_Pxx_REQ ,
. map = IMX8MP_USB1_PHY_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_USB1 ) ,
} ,
[ IMX8MP_POWER_DOMAIN_USB2_PHY ] = {
. genpd = {
. name = " usb-otg2 " ,
} ,
. bits = {
. pxx = IMX8MP_USB2_PHY_Pxx_REQ ,
. map = IMX8MP_USB2_PHY_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_USB2 ) ,
} ,
[ IMX8MP_POWER_DOMAIN_MLMIX ] = {
. genpd = {
. name = " mlmix " ,
} ,
. bits = {
. pxx = IMX8MP_MLMIX_Pxx_REQ ,
. map = IMX8MP_MLMIX_A53_DOMAIN ,
. hskreq = IMX8MP_MLMIX_PWRDNREQN ,
. hskack = IMX8MP_MLMIX_PWRDNACKN ,
} ,
. pgc = BIT ( IMX8MP_PGC_MLMIX ) ,
. keep_clocks = true ,
} ,
[ IMX8MP_POWER_DOMAIN_AUDIOMIX ] = {
. genpd = {
. name = " audiomix " ,
} ,
. bits = {
. pxx = IMX8MP_AUDIOMIX_Pxx_REQ ,
. map = IMX8MP_AUDIOMIX_A53_DOMAIN ,
. hskreq = IMX8MP_AUDIOMIX_PWRDNREQN ,
. hskack = IMX8MP_AUDIOMIX_PWRDNACKN ,
} ,
. pgc = BIT ( IMX8MP_PGC_AUDIOMIX ) ,
. keep_clocks = true ,
} ,
[ IMX8MP_POWER_DOMAIN_GPU2D ] = {
. genpd = {
. name = " gpu2d " ,
} ,
. bits = {
. pxx = IMX8MP_GPU_2D_Pxx_REQ ,
. map = IMX8MP_GPU2D_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_GPU2D ) ,
} ,
[ IMX8MP_POWER_DOMAIN_GPUMIX ] = {
. genpd = {
. name = " gpumix " ,
} ,
. bits = {
. pxx = IMX8MP_GPU_SHARE_LOGIC_Pxx_REQ ,
. map = IMX8MP_GPUMIX_A53_DOMAIN ,
. hskreq = IMX8MP_GPUMIX_PWRDNREQN ,
. hskack = IMX8MP_GPUMIX_PWRDNACKN ,
} ,
. pgc = BIT ( IMX8MP_PGC_GPUMIX ) ,
. keep_clocks = true ,
} ,
[ IMX8MP_POWER_DOMAIN_VPUMIX ] = {
. genpd = {
. name = " vpumix " ,
} ,
. bits = {
. pxx = IMX8MP_VPU_MIX_SHARE_LOGIC_Pxx_REQ ,
. map = IMX8MP_VPUMIX_A53_DOMAIN ,
. hskreq = IMX8MP_VPUMIX_PWRDNREQN ,
. hskack = IMX8MP_VPUMIX_PWRDNACKN ,
} ,
. pgc = BIT ( IMX8MP_PGC_VPUMIX ) ,
. keep_clocks = true ,
} ,
[ IMX8MP_POWER_DOMAIN_GPU3D ] = {
. genpd = {
. name = " gpu3d " ,
} ,
. bits = {
. pxx = IMX8MP_GPU_3D_Pxx_REQ ,
. map = IMX8MP_GPU3D_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_GPU3D ) ,
} ,
[ IMX8MP_POWER_DOMAIN_MEDIAMIX ] = {
. genpd = {
. name = " mediamix " ,
} ,
. bits = {
. pxx = IMX8MP_MEDIMIX_Pxx_REQ ,
. map = IMX8MP_MEDIAMIX_A53_DOMAIN ,
. hskreq = IMX8MP_MEDIAMIX_PWRDNREQN ,
. hskack = IMX8MP_MEDIAMIX_PWRDNACKN ,
} ,
. pgc = BIT ( IMX8MP_PGC_MEDIAMIX ) ,
. keep_clocks = true ,
} ,
[ IMX8MP_POWER_DOMAIN_VPU_G1 ] = {
. genpd = {
. name = " vpu-g1 " ,
} ,
. bits = {
. pxx = IMX8MP_VPU_G1_Pxx_REQ ,
. map = IMX8MP_VPU_G1_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_VPU_G1 ) ,
} ,
[ IMX8MP_POWER_DOMAIN_VPU_G2 ] = {
. genpd = {
. name = " vpu-g2 " ,
} ,
. bits = {
. pxx = IMX8MP_VPU_G2_Pxx_REQ ,
. map = IMX8MP_VPU_G2_A53_DOMAIN
} ,
. pgc = BIT ( IMX8MP_PGC_VPU_G2 ) ,
} ,
[ IMX8MP_POWER_DOMAIN_VPU_VC8000E ] = {
. genpd = {
. name = " vpu-h1 " ,
} ,
. bits = {
. pxx = IMX8MP_VPU_VC8K_Pxx_REQ ,
. map = IMX8MP_VPU_VC8000E_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_VPU_VC8000E ) ,
} ,
[ IMX8MP_POWER_DOMAIN_HDMIMIX ] = {
. genpd = {
. name = " hdmimix " ,
} ,
. bits = {
. pxx = IMX8MP_HDMIMIX_Pxx_REQ ,
. map = IMX8MP_HDMIMIX_A53_DOMAIN ,
. hskreq = IMX8MP_HDMIMIX_PWRDNREQN ,
. hskack = IMX8MP_HDMIMIX_PWRDNACKN ,
} ,
. pgc = BIT ( IMX8MP_PGC_HDMIMIX ) ,
. keep_clocks = true ,
} ,
[ IMX8MP_POWER_DOMAIN_HDMI_PHY ] = {
. genpd = {
. name = " hdmi-phy " ,
} ,
. bits = {
. pxx = IMX8MP_HDMI_PHY_Pxx_REQ ,
. map = IMX8MP_HDMI_PHY_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_HDMI ) ,
} ,
[ IMX8MP_POWER_DOMAIN_MIPI_PHY2 ] = {
. genpd = {
. name = " mipi-phy2 " ,
} ,
. bits = {
. pxx = IMX8MP_MIPI_PHY2_Pxx_REQ ,
. map = IMX8MP_MIPI_PHY2_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_MIPI2 ) ,
} ,
[ IMX8MP_POWER_DOMAIN_HSIOMIX ] = {
. genpd = {
. name = " hsiomix " ,
} ,
. bits = {
. pxx = IMX8MP_HSIOMIX_Pxx_REQ ,
. map = IMX8MP_HSIOMIX_A53_DOMAIN ,
. hskreq = IMX8MP_HSIOMIX_PWRDNREQN ,
. hskack = IMX8MP_HSIOMIX_PWRDNACKN ,
} ,
. pgc = BIT ( IMX8MP_PGC_HSIOMIX ) ,
. keep_clocks = true ,
} ,
[ IMX8MP_POWER_DOMAIN_MEDIAMIX_ISPDWP ] = {
. genpd = {
. name = " mediamix-isp-dwp " ,
} ,
. bits = {
. pxx = IMX8MP_MEDIA_ISP_DWP_Pxx_REQ ,
. map = IMX8MP_MEDIA_ISPDWP_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MP_PGC_MEDIA_ISP_DWP ) ,
} ,
} ;
static const struct regmap_range imx8mp_yes_ranges [ ] = {
regmap_reg_range ( GPC_LPCR_A_CORE_BSC ,
IMX8MP_GPC_PGC_CPU_MAPPING ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_NOC ) ,
GPC_PGC_SR ( IMX8MP_PGC_NOC ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_MIPI1 ) ,
GPC_PGC_SR ( IMX8MP_PGC_MIPI1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_PCIE ) ,
GPC_PGC_SR ( IMX8MP_PGC_PCIE ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_USB1 ) ,
GPC_PGC_SR ( IMX8MP_PGC_USB1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_USB2 ) ,
GPC_PGC_SR ( IMX8MP_PGC_USB2 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_MLMIX ) ,
GPC_PGC_SR ( IMX8MP_PGC_MLMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_AUDIOMIX ) ,
GPC_PGC_SR ( IMX8MP_PGC_AUDIOMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_GPU2D ) ,
GPC_PGC_SR ( IMX8MP_PGC_GPU2D ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_GPUMIX ) ,
GPC_PGC_SR ( IMX8MP_PGC_GPUMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_VPUMIX ) ,
GPC_PGC_SR ( IMX8MP_PGC_VPUMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_GPU3D ) ,
GPC_PGC_SR ( IMX8MP_PGC_GPU3D ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_MEDIAMIX ) ,
GPC_PGC_SR ( IMX8MP_PGC_MEDIAMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_VPU_G1 ) ,
GPC_PGC_SR ( IMX8MP_PGC_VPU_G1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_VPU_G2 ) ,
GPC_PGC_SR ( IMX8MP_PGC_VPU_G2 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_VPU_VC8000E ) ,
GPC_PGC_SR ( IMX8MP_PGC_VPU_VC8000E ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_HDMIMIX ) ,
GPC_PGC_SR ( IMX8MP_PGC_HDMIMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_HDMI ) ,
GPC_PGC_SR ( IMX8MP_PGC_HDMI ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_MIPI2 ) ,
GPC_PGC_SR ( IMX8MP_PGC_MIPI2 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_HSIOMIX ) ,
GPC_PGC_SR ( IMX8MP_PGC_HSIOMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_MEDIA_ISP_DWP ) ,
GPC_PGC_SR ( IMX8MP_PGC_MEDIA_ISP_DWP ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MP_PGC_DDRMIX ) ,
GPC_PGC_SR ( IMX8MP_PGC_DDRMIX ) ) ,
} ;
static const struct regmap_access_table imx8mp_access_table = {
. yes_ranges = imx8mp_yes_ranges ,
. n_yes_ranges = ARRAY_SIZE ( imx8mp_yes_ranges ) ,
} ;
static const struct imx_pgc_regs imx8mp_pgc_regs = {
. map = IMX8MP_GPC_PGC_CPU_MAPPING ,
. pup = IMX8MP_GPC_PU_PGC_SW_PUP_REQ ,
. pdn = IMX8MP_GPC_PU_PGC_SW_PDN_REQ ,
. hsk = IMX8MP_GPC_PU_PWRHSK ,
} ;
static const struct imx_pgc_domain_data imx8mp_pgc_domain_data = {
. domains = imx8mp_pgc_domains ,
. domains_num = ARRAY_SIZE ( imx8mp_pgc_domains ) ,
. reg_access_table = & imx8mp_access_table ,
. pgc_regs = & imx8mp_pgc_regs ,
} ;
2021-05-24 20:07:29 -05:00
static const struct imx_pgc_domain imx8mn_pgc_domains [ ] = {
[ IMX8MN_POWER_DOMAIN_HSIOMIX ] = {
. genpd = {
. name = " hsiomix " ,
} ,
. bits = {
. pxx = 0 , /* no power sequence control */
. map = 0 , /* no power sequence control */
. hskreq = IMX8MN_HSIO_HSK_PWRDNREQN ,
. hskack = IMX8MN_HSIO_HSK_PWRDNACKN ,
} ,
2021-10-02 02:59:42 +02:00
. keep_clocks = true ,
2021-05-24 20:07:29 -05:00
} ,
[ IMX8MN_POWER_DOMAIN_OTG1 ] = {
. genpd = {
. name = " usb-otg1 " ,
} ,
. bits = {
. pxx = IMX8MN_OTG1_SW_Pxx_REQ ,
. map = IMX8MN_OTG1_A53_DOMAIN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MN_PGC_OTG1 ) ,
2021-05-24 20:07:29 -05:00
} ,
[ IMX8MN_POWER_DOMAIN_GPUMIX ] = {
. genpd = {
. name = " gpumix " ,
} ,
. bits = {
. pxx = IMX8MN_GPUMIX_SW_Pxx_REQ ,
. map = IMX8MN_GPUMIX_A53_DOMAIN ,
. hskreq = IMX8MN_GPUMIX_HSK_PWRDNREQN ,
. hskack = IMX8MN_GPUMIX_HSK_PWRDNACKN ,
} ,
2021-09-07 04:38:29 +02:00
. pgc = BIT ( IMX8MN_PGC_GPUMIX ) ,
2021-12-14 18:46:18 -06:00
. keep_clocks = true ,
2021-05-24 20:07:29 -05:00
} ,
2021-12-14 18:46:19 -06:00
[ IMX8MN_POWER_DOMAIN_DISPMIX ] = {
. genpd = {
. name = " dispmix " ,
} ,
. bits = {
. pxx = IMX8MN_DISPMIX_SW_Pxx_REQ ,
. map = IMX8MN_DISPMIX_A53_DOMAIN ,
. hskreq = IMX8MN_DISPMIX_HSK_PWRDNREQN ,
. hskack = IMX8MN_DISPMIX_HSK_PWRDNACKN ,
} ,
. pgc = BIT ( IMX8MN_PGC_DISPMIX ) ,
. keep_clocks = true ,
} ,
[ IMX8MN_POWER_DOMAIN_MIPI ] = {
. genpd = {
. name = " mipi " ,
} ,
. bits = {
. pxx = IMX8MN_MIPI_SW_Pxx_REQ ,
. map = IMX8MN_MIPI_A53_DOMAIN ,
} ,
. pgc = BIT ( IMX8MN_PGC_MIPI ) ,
} ,
2021-05-24 20:07:29 -05:00
} ;
static const struct regmap_range imx8mn_yes_ranges [ ] = {
regmap_reg_range ( GPC_LPCR_A_CORE_BSC ,
GPC_PU_PWRHSK ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MN_PGC_MIPI ) ,
GPC_PGC_SR ( IMX8MN_PGC_MIPI ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MN_PGC_OTG1 ) ,
GPC_PGC_SR ( IMX8MN_PGC_OTG1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MN_PGC_DDR1 ) ,
GPC_PGC_SR ( IMX8MN_PGC_DDR1 ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MN_PGC_GPUMIX ) ,
GPC_PGC_SR ( IMX8MN_PGC_GPUMIX ) ) ,
regmap_reg_range ( GPC_PGC_CTRL ( IMX8MN_PGC_DISPMIX ) ,
GPC_PGC_SR ( IMX8MN_PGC_DISPMIX ) ) ,
} ;
static const struct regmap_access_table imx8mn_access_table = {
. yes_ranges = imx8mn_yes_ranges ,
. n_yes_ranges = ARRAY_SIZE ( imx8mn_yes_ranges ) ,
} ;
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 ,
2022-03-30 12:46:16 +02:00
. pgc_regs = & imx7_pgc_regs ,
2021-05-24 20:07:29 -05:00
} ;
2018-08-28 16:36:46 +08:00
static int imx_pgc_domain_probe ( struct platform_device * pdev )
2017-03-28 08:19:45 -07:00
{
2018-08-28 16:36:46 +08:00
struct imx_pgc_domain * domain = pdev - > dev . platform_data ;
2017-03-28 08:19:45 -07:00
int ret ;
domain - > dev = & pdev - > dev ;
domain - > regulator = devm_regulator_get_optional ( domain - > dev , " power " ) ;
if ( IS_ERR ( domain - > regulator ) ) {
2020-08-11 11:04:42 +08:00
if ( PTR_ERR ( domain - > regulator ) ! = - ENODEV )
return dev_err_probe ( domain - > dev , PTR_ERR ( domain - > regulator ) ,
" Failed to get domain's regulator \n " ) ;
2018-11-16 16:49:27 +01:00
} else if ( domain - > voltage ) {
2017-03-28 08:19:45 -07:00
regulator_set_voltage ( domain - > regulator ,
domain - > voltage , domain - > voltage ) ;
}
2021-05-10 12:00:35 +08:00
domain - > num_clks = devm_clk_bulk_get_all ( domain - > dev , & domain - > clks ) ;
if ( domain - > num_clks < 0 )
return dev_err_probe ( domain - > dev , domain - > num_clks ,
" Failed to get domain's clocks \n " ) ;
2018-12-17 16:31:52 +01:00
2021-05-10 12:00:41 +08:00
domain - > reset = devm_reset_control_array_get_optional_exclusive ( domain - > dev ) ;
if ( IS_ERR ( domain - > reset ) )
return dev_err_probe ( domain - > dev , PTR_ERR ( domain - > reset ) ,
" Failed to get domain's resets \n " ) ;
2021-05-10 12:00:38 +08:00
pm_runtime_enable ( domain - > dev ) ;
2021-05-10 12:00:39 +08:00
if ( domain - > bits . map )
2022-03-30 12:46:16 +02:00
regmap_update_bits ( domain - > regmap , domain - > regs - > map ,
2021-05-10 12:00:39 +08:00
domain - > bits . map , domain - > bits . map ) ;
2021-05-10 12:00:34 +08:00
2017-08-02 12:51:29 -07:00
ret = pm_genpd_init ( & domain - > genpd , NULL , true ) ;
if ( ret ) {
dev_err ( domain - > dev , " Failed to init power domain \n " ) ;
2021-05-10 12:00:34 +08:00
goto out_domain_unmap ;
2017-08-02 12:51:29 -07:00
}
2021-10-02 02:59:40 +02:00
if ( IS_ENABLED ( CONFIG_LOCKDEP ) & &
of_property_read_bool ( domain - > dev - > of_node , " power-domains " ) )
lockdep_set_subclass ( & domain - > genpd . mlock , 1 ) ;
2017-03-28 08:19:45 -07:00
ret = of_genpd_add_provider_simple ( domain - > dev - > of_node ,
& domain - > genpd ) ;
if ( ret ) {
dev_err ( domain - > dev , " Failed to add genpd provider \n " ) ;
2021-05-10 12:00:33 +08:00
goto out_genpd_remove ;
2017-03-28 08:19:45 -07:00
}
2021-05-10 12:00:33 +08:00
return 0 ;
out_genpd_remove :
pm_genpd_remove ( & domain - > genpd ) ;
2021-05-10 12:00:34 +08:00
out_domain_unmap :
2021-05-10 12:00:39 +08:00
if ( domain - > bits . map )
2022-03-30 12:46:16 +02:00
regmap_update_bits ( domain - > regmap , domain - > regs - > map ,
2021-05-10 12:00:39 +08:00
domain - > bits . map , 0 ) ;
2021-05-10 12:00:38 +08:00
pm_runtime_disable ( domain - > dev ) ;
2021-05-10 12:00:33 +08:00
2017-03-28 08:19:45 -07:00
return ret ;
}
2018-08-28 16:36:46 +08:00
static int imx_pgc_domain_remove ( struct platform_device * pdev )
2017-03-28 08:19:45 -07:00
{
2018-08-28 16:36:46 +08:00
struct imx_pgc_domain * domain = pdev - > dev . platform_data ;
2017-03-28 08:19:45 -07:00
of_genpd_del_provider ( domain - > dev - > of_node ) ;
pm_genpd_remove ( & domain - > genpd ) ;
2021-05-10 12:00:34 +08:00
2021-05-10 12:00:39 +08:00
if ( domain - > bits . map )
2022-03-30 12:46:16 +02:00
regmap_update_bits ( domain - > regmap , domain - > regs - > map ,
2021-05-10 12:00:39 +08:00
domain - > bits . map , 0 ) ;
2021-05-10 12:00:34 +08:00
2021-05-10 12:00:38 +08:00
pm_runtime_disable ( domain - > dev ) ;
2017-03-28 08:19:45 -07:00
return 0 ;
}
2021-10-02 02:59:43 +02:00
# ifdef CONFIG_PM_SLEEP
static int imx_pgc_domain_suspend ( struct device * dev )
{
int ret ;
/*
* This may look strange , but is done so the generic PM_SLEEP code
* can power down our domain and more importantly power it up again
* after resume , without tripping over our usage of runtime PM to
* power up / down the nested domains .
*/
ret = pm_runtime_get_sync ( dev ) ;
if ( ret < 0 ) {
pm_runtime_put_noidle ( dev ) ;
return ret ;
}
return 0 ;
}
static int imx_pgc_domain_resume ( struct device * dev )
{
return pm_runtime_put ( dev ) ;
}
# endif
static const struct dev_pm_ops imx_pgc_domain_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS ( imx_pgc_domain_suspend , imx_pgc_domain_resume )
} ;
2018-08-28 16:36:46 +08:00
static const struct platform_device_id imx_pgc_domain_id [ ] = {
{ " imx-pgc-domain " , } ,
2017-03-28 08:19:45 -07:00
{ } ,
} ;
2018-08-28 16:36:46 +08:00
static struct platform_driver imx_pgc_domain_driver = {
2017-03-28 08:19:45 -07:00
. driver = {
2018-08-28 16:36:46 +08:00
. name = " imx-pgc " ,
2021-10-02 02:59:43 +02:00
. pm = & imx_pgc_domain_pm_ops ,
2017-03-28 08:19:45 -07:00
} ,
2018-08-28 16:36:46 +08:00
. probe = imx_pgc_domain_probe ,
. remove = imx_pgc_domain_remove ,
. id_table = imx_pgc_domain_id ,
2017-03-28 08:19:45 -07:00
} ;
2018-08-28 16:36:46 +08:00
builtin_platform_driver ( imx_pgc_domain_driver )
2017-03-28 08:19:45 -07:00
static int imx_gpcv2_probe ( struct platform_device * pdev )
{
2018-11-16 16:49:26 +01:00
const struct imx_pgc_domain_data * domain_data =
of_device_get_match_data ( & pdev - > dev ) ;
struct regmap_config regmap_config = {
2017-03-28 08:19:45 -07:00
. reg_bits = 32 ,
. val_bits = 32 ,
. reg_stride = 4 ,
2018-11-16 16:49:26 +01:00
. rd_table = domain_data - > reg_access_table ,
. wr_table = domain_data - > reg_access_table ,
2017-03-28 08:19:45 -07:00
. max_register = SZ_4K ,
} ;
struct device * dev = & pdev - > dev ;
struct device_node * pgc_np , * np ;
struct regmap * regmap ;
void __iomem * base ;
int ret ;
pgc_np = of_get_child_by_name ( dev - > of_node , " pgc " ) ;
if ( ! pgc_np ) {
dev_err ( dev , " No power domains specified in DT \n " ) ;
return - EINVAL ;
}
2019-04-01 06:07:13 +00:00
base = devm_platform_ioremap_resource ( pdev , 0 ) ;
2017-03-28 08:19:45 -07:00
if ( IS_ERR ( base ) )
return PTR_ERR ( base ) ;
regmap = devm_regmap_init_mmio ( dev , base , & regmap_config ) ;
if ( IS_ERR ( regmap ) ) {
ret = PTR_ERR ( regmap ) ;
dev_err ( dev , " failed to init regmap (%d) \n " , ret ) ;
return ret ;
}
for_each_child_of_node ( pgc_np , np ) {
struct platform_device * pd_pdev ;
2018-08-28 16:36:46 +08:00
struct imx_pgc_domain * domain ;
2017-03-28 08:19:45 -07:00
u32 domain_index ;
2021-10-02 14:48:52 +02:00
if ( ! of_device_is_available ( np ) )
continue ;
2017-03-28 08:19:45 -07:00
ret = of_property_read_u32 ( np , " reg " , & domain_index ) ;
if ( ret ) {
dev_err ( dev , " Failed to read 'reg' property \n " ) ;
of_node_put ( np ) ;
return ret ;
}
2018-08-28 16:36:46 +08:00
if ( domain_index > = domain_data - > domains_num ) {
2017-03-28 08:19:45 -07:00
dev_warn ( dev ,
" Domain index %d is out of bounds \n " ,
domain_index ) ;
continue ;
}
2018-08-28 16:36:46 +08:00
pd_pdev = platform_device_alloc ( " imx-pgc-domain " ,
2017-03-28 08:19:45 -07:00
domain_index ) ;
if ( ! pd_pdev ) {
dev_err ( dev , " Failed to allocate platform device \n " ) ;
of_node_put ( np ) ;
return - ENOMEM ;
}
2018-04-10 11:32:09 -07:00
ret = platform_device_add_data ( pd_pdev ,
2018-08-28 16:36:46 +08:00
& domain_data - > domains [ domain_index ] ,
sizeof ( domain_data - > domains [ domain_index ] ) ) ;
2018-04-10 11:32:09 -07:00
if ( ret ) {
platform_device_put ( pd_pdev ) ;
of_node_put ( np ) ;
return ret ;
}
domain = pd_pdev - > dev . platform_data ;
domain - > regmap = regmap ;
2022-03-30 12:46:16 +02:00
domain - > regs = domain_data - > pgc_regs ;
2022-03-30 12:46:18 +02:00
2021-05-10 12:00:36 +08:00
domain - > genpd . power_on = imx_pgc_power_up ;
domain - > genpd . power_off = imx_pgc_power_down ;
2018-04-10 11:32:09 -07:00
2017-03-28 08:19:45 -07:00
pd_pdev - > dev . parent = dev ;
pd_pdev - > dev . of_node = np ;
ret = platform_device_add ( pd_pdev ) ;
if ( ret ) {
platform_device_put ( pd_pdev ) ;
of_node_put ( np ) ;
return ret ;
}
}
return 0 ;
}
static const struct of_device_id imx_gpcv2_dt_ids [ ] = {
2018-08-28 16:36:46 +08:00
{ . compatible = " fsl,imx7d-gpc " , . data = & imx7_pgc_domain_data , } ,
2021-05-10 12:00:43 +08:00
{ . compatible = " fsl,imx8mm-gpc " , . data = & imx8mm_pgc_domain_data , } ,
2021-05-24 20:07:29 -05:00
{ . compatible = " fsl,imx8mn-gpc " , . data = & imx8mn_pgc_domain_data , } ,
2022-03-30 12:46:18 +02:00
{ . compatible = " fsl,imx8mp-gpc " , . data = & imx8mp_pgc_domain_data , } ,
2018-11-16 16:49:27 +01:00
{ . compatible = " fsl,imx8mq-gpc " , . data = & imx8m_pgc_domain_data , } ,
2017-03-28 08:19:45 -07:00
{ }
} ;
static struct platform_driver imx_gpc_driver = {
. driver = {
. name = " imx-gpcv2 " ,
. of_match_table = imx_gpcv2_dt_ids ,
} ,
. probe = imx_gpcv2_probe ,
} ;
builtin_platform_driver ( imx_gpc_driver )