summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorYe Li <ye.li@nxp.com>2017-08-01 05:25:19 -0500
committerJason Liu <jason.hui.liu@nxp.com>2017-11-03 02:37:06 +0800
commite1300c3e6b5511d38cd7b027c346471ffb1eb584 (patch)
treed38e69d43ab80a164fa60dfa3dd68122a0b79f91 /arch
parenta4d334e70839021a50dca2ad4ad98ecee16081f9 (diff)
MLK-16118-8 imx8qm/qxp: Enable the power domain driver and update relevant codes
This patch enables the power domain driver for i.MX8QM and QXP boards in defconfig files. The devices with using DM driver will be powered on automatically by DM framework. So we remove the power relevant codes for them. For devices with non-DM drivers, we updates the board/SoC codes to use power domain driver API. So that we can use power domain driver to manage them. The only exceptions are: 1. UART0 at board_early_f, this is very early stage, that power domain is not ready. 2. Power up secondary cores and M4 cores. These resources are not peripherals and are not in power domain tree. Additional, benefiting from power domain driver, We have implemented the function "power_off_pd_devices" to power off all active devices. No need to explicitly power off them in board_quiesce_devices. Reviewed-by: Peng Fan <peng.fan@nxp.com> Signed-off-by: Ye Li <ye.li@nxp.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/cpu/armv8/imx8/clock.c86
-rw-r--r--arch/arm/cpu/armv8/imx8/cpu.c106
-rw-r--r--arch/arm/cpu/armv8/imx8/video_common.c56
-rw-r--r--arch/arm/include/asm/arch-imx8/i2c.h26
-rw-r--r--arch/arm/include/asm/arch-imx8/sys_proto.h2
5 files changed, 156 insertions, 120 deletions
diff --git a/arch/arm/cpu/armv8/imx8/clock.c b/arch/arm/cpu/armv8/imx8/clock.c
index 02b7ac7f0e6..914d7909a56 100644
--- a/arch/arm/cpu/armv8/imx8/clock.c
+++ b/arch/arm/cpu/armv8/imx8/clock.c
@@ -144,27 +144,28 @@ u32 imx_get_i2cclk(unsigned i2c_num)
return clock_rate;
}
-int set_clk_qspi(void)
+void init_clk_fspi(int index)
{
- u32 err;
- u32 rate = 40000000;
- sc_ipc_t ipc;
-
- ipc = gd->arch.ipc_channel_handle;
-
- err = sc_pm_set_clock_rate(ipc, SC_R_QSPI_0, SC_PM_CLK_PER, &rate);
- if (err != SC_ERR_NONE) {
- printf("\nqspi set clock rate (error = %d)\n", err);
- return -EPERM;
+ sc_err_t sciErr = 0;
+ sc_pm_clock_rate_t rate;
+ sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle;
+
+ /* Set FSPI0 clock root to 29 MHz */
+ rate = 29000000;
+ sciErr = sc_pm_set_clock_rate(ipcHndl, SC_R_FSPI_0, SC_PM_CLK_PER, &rate);
+ if (sciErr != SC_ERR_NONE) {
+ puts("FSPI0 setrate failed\n");
+ return;
}
- err = sc_pm_clock_enable(ipc, SC_R_QSPI_0 , SC_PM_CLK_PER, true, false);
- if (err != SC_ERR_NONE) {
- printf("\nqspi enable clock enable (error = %d)\n", err);
- return -EPERM;
+ /* Enable FSPI0 clock root */
+ sciErr = sc_pm_clock_enable(ipcHndl, SC_R_FSPI_0, SC_PM_CLK_PER, true, false);
+ if (sciErr != SC_ERR_NONE) {
+ puts("FSPI0 enable clock failed\n");
+ return;
}
- return 0;
+ return;
}
void enable_usboh3_clk(unsigned char enable)
@@ -191,14 +192,6 @@ void init_clk_usdhc(u32 index)
if (index >= instances)
return;
- /* Power on the usdhc */
- err = sc_pm_set_resource_power_mode(ipc, usdhcs[index],
- SC_PM_PW_MODE_ON);
- if (err != SC_ERR_NONE) {
- printf("SDHC_%d Power on failed! (error = %d)\n", index, err);
- return;
- }
-
err = sc_pm_set_clock_rate(ipc, usdhcs[index], 2, &actual);
if (err != SC_ERR_NONE) {
printf("SDHC_%d set clock failed! (error = %d)\n", index, err);
@@ -214,3 +207,48 @@ void init_clk_usdhc(u32 index)
return;
}
}
+
+void init_clk_fec(int index)
+{
+ sc_err_t err;
+ sc_ipc_t ipc;
+ sc_pm_clock_rate_t rate = 24000000;
+ sc_rsrc_t enet[2] = {SC_R_ENET_0, SC_R_ENET_1};
+
+ if (index > 1)
+ return;
+
+ if (index == -1)
+ index = 0;
+
+ ipc = gd->arch.ipc_channel_handle;
+
+ /* Disable SC_R_ENET_0 clock root */
+ err = sc_pm_clock_enable(ipc, enet[index], 0, false, false);
+ err |= sc_pm_clock_enable(ipc, enet[index], 2, false, false);
+ err |= sc_pm_clock_enable(ipc, enet[index], 4, false, false);
+ if (err != SC_ERR_NONE) {
+ printf("\nSC_R_ENET_0 set clock disable failed! (error = %d)\n", err);
+ return;
+ }
+
+ /* Set SC_R_ENET_0 clock root to 125 MHz */
+ rate = 125000000;
+
+ /* div = 8 clk_source = PLL_1 ss_slice #7 in verfication codes */
+ err = sc_pm_set_clock_rate(ipc, enet[index], 2, &rate);
+ if (err != SC_ERR_NONE) {
+ printf("\nSC_R_ENET_0 set clock ref clock 125M failed! (error = %d)\n", err);
+ return;
+ }
+
+ /* Enable SC_R_ENET_0 clock root */
+ err = sc_pm_clock_enable(ipc, enet[index], 0, true, true);
+ err |= sc_pm_clock_enable(ipc, enet[index], 2, true, true);
+ err |= sc_pm_clock_enable(ipc, enet[index], 4, true, true);
+ if (err != SC_ERR_NONE) {
+ printf("\nSC_R_ENET_0 set clock enable failed! (error = %d)\n", err);
+ return;
+ }
+}
+
diff --git a/arch/arm/cpu/armv8/imx8/cpu.c b/arch/arm/cpu/armv8/imx8/cpu.c
index 075e11b2087..91843318981 100644
--- a/arch/arm/cpu/armv8/imx8/cpu.c
+++ b/arch/arm/cpu/armv8/imx8/cpu.c
@@ -8,9 +8,11 @@
#include <common.h>
#include <errno.h>
#include <asm/io.h>
+#include <power-domain.h>
+#include <dm/device.h>
+#include <dm/uclass-internal.h>
#include <asm/imx-common/sci/sci.h>
#include <asm/imx-common/boot_mode.h>
-#include <asm/arch/i2c.h>
#include <asm/arch/clock.h>
#include <asm/armv8/mmu.h>
#include <elf.h>
@@ -223,53 +225,22 @@ int imx8qxp_wake_secondary_cores(void)
return 0;
}
-int init_i2c_power(unsigned i2c_num)
-{
- sc_ipc_t ipc;
- sc_err_t err;
- u32 i;
-
- if (i2c_num >= ARRAY_SIZE(imx_i2c_desc))
- return -EINVAL;
-
- ipc = gd->arch.ipc_channel_handle;
-
- for (i = 0; i < ARRAY_SIZE(i2c_parent_power_desc); i++) {
- if (i2c_parent_power_desc[i].index == i2c_num) {
- err = sc_pm_set_resource_power_mode(ipc,
- i2c_parent_power_desc[i].rsrc, SC_PM_PW_MODE_ON);
- if (err != SC_ERR_NONE)
- return -EPERM;
- }
- }
-
- /* power up i2c resource */
- err = sc_pm_set_resource_power_mode(ipc,
- imx_i2c_desc[i2c_num].rsrc, SC_PM_PW_MODE_ON);
- if (err != SC_ERR_NONE)
- return -EPERM;
-
- return 0;
-}
-
int init_otg_power(void)
{
- sc_err_t err;
- sc_ipc_t ipc;
+ struct power_domain pd;
int ret = 0;
- ipc = gd->arch.ipc_channel_handle;
-
- err = sc_pm_set_resource_power_mode(ipc, SC_R_USB_0, SC_PM_PW_MODE_ON);
- if (err != SC_ERR_NONE){
- printf("\nSC_R_USB_0 Power up failed! (error = %d)\n", err);
- ret = -EPERM;
+ /* Power on usb */
+ if (!power_domain_lookup_name("conn_usb0", &pd)) {
+ ret = power_domain_on(&pd);
+ if (ret)
+ printf("conn_usb0 Power up failed! (error = %d)\n", ret);
}
- err = sc_pm_set_resource_power_mode(ipc, SC_R_USB_0_PHY, SC_PM_PW_MODE_ON);
- if (err != SC_ERR_NONE){
- printf("\nSC_R_USB_0_PHY Power up failed! (error = %d)\n", err);
- ret = -EPERM;
+ if (!power_domain_lookup_name("conn_usb0_phy", &pd)) {
+ ret = power_domain_on(&pd);
+ if (ret)
+ printf("conn_usb0_phy Power up failed! (error = %d)\n", ret);
}
return ret;
@@ -471,17 +442,25 @@ int arch_auxiliary_core_up(u32 core_id, ulong boot_private_data)
}
if (core_id == 1) {
+ struct power_domain pd;
+
if (sc_pm_clock_enable(ipcHndl, core_rsrc, SC_PM_CLK_PER, true, false) != SC_ERR_NONE) {
printf("Error enable clock\n");
return -EIO;
}
- if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_SAI_0, SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
- printf("Error power on SAI0\n");
- return -EIO;
+
+ if (!power_domain_lookup_name("audio_sai0", &pd)) {
+ if (power_domain_on(&pd)) {
+ printf("Error power on SAI0\n");
+ return -EIO;
+ }
}
- if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_HIFI_RAM, SC_PM_PW_MODE_ON) != SC_ERR_NONE) {
- printf("Error power on HIFI RAM\n");
- return -EIO;
+
+ if (!power_domain_lookup_name("audio_ocram", &pd)) {
+ if (power_domain_on(&pd)) {
+ printf("Error power on HIFI RAM\n");
+ return -EIO;
+ }
}
}
@@ -1090,3 +1069,34 @@ u64 get_page_table_size(void)
return size;
}
#endif
+
+static bool check_device_power_off(struct udevice *dev,
+ const char* permanent_on_devices[], int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++) {
+ if (!strcmp(dev->name, permanent_on_devices[i]))
+ return false;
+ }
+
+ return true;
+}
+
+void power_off_pd_devices(const char* permanent_on_devices[], int size)
+{
+ struct udevice *dev;
+ struct power_domain pd;
+
+ for (uclass_find_first_device(UCLASS_POWER_DOMAIN, &dev); dev;
+ uclass_find_next_device(&dev)) {
+
+ if (device_active(dev)) {
+ /* Power off active pd devices except the permanent power on devices */
+ if (check_device_power_off(dev, permanent_on_devices, size)) {
+ pd.dev = dev;
+ power_domain_off(&pd);
+ }
+ }
+ }
+}
diff --git a/arch/arm/cpu/armv8/imx8/video_common.c b/arch/arm/cpu/armv8/imx8/video_common.c
index 458370b039b..2ef8d4227cf 100644
--- a/arch/arm/cpu/armv8/imx8/video_common.c
+++ b/arch/arm/cpu/armv8/imx8/video_common.c
@@ -21,6 +21,7 @@
#include <video_fb.h>
#include <asm/arch/imx8_mipi_dsi.h>
#include <asm/arch/video_common.h>
+#include <power-domain.h>
DECLARE_GLOBAL_DATA_PTR;
@@ -191,19 +192,36 @@ int lvds_soc_setup(int lvds_id, sc_pm_clock_rate_t pixel_clock)
{
sc_err_t err;
sc_rsrc_t lvds_rsrc, mipi_rsrc;
+ const char *pd_name;
sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle;
+ struct power_domain pd;
+ int ret;
+
if (lvds_id == 0) {
lvds_rsrc = SC_R_LVDS_0;
mipi_rsrc = SC_R_MIPI_0;
+ if (is_imx8qxp())
+ pd_name = "mipi0_dsi_power_domain";
+ else
+ pd_name = "lvds0_power_domain";
} else {
lvds_rsrc = SC_R_LVDS_1;
mipi_rsrc = SC_R_MIPI_1;
+ if (is_imx8qxp())
+ pd_name = "mipi1_dsi_power_domain";
+ else
+ pd_name = "lvds1_power_domain";
}
/* Power up LVDS */
- err = sc_pm_set_resource_power_mode(ipcHndl, lvds_rsrc, SC_PM_PW_MODE_ON);
- if (err != SC_ERR_NONE) {
- printf("LVDS Power up failed! (error = %d)\n", err);
+ if (!power_domain_lookup_name(pd_name, &pd)) {
+ ret = power_domain_on(&pd);
+ if (ret) {
+ printf("%s Power up failed! (error = %d)\n", pd_name, ret);
+ return -EIO;
+ }
+ } else {
+ printf("%s lookup failed!\n", pd_name);
return -EIO;
}
@@ -328,38 +346,34 @@ int display_controller_setup(sc_pm_clock_rate_t pixel_clock)
sc_err_t err;
sc_rsrc_t dc_rsrc, pll0_rsrc, pll1_rsrc;
sc_pm_clock_rate_t pll_clk;
+ const char *dc_pd_name;
sc_ipc_t ipcHndl = gd->arch.ipc_channel_handle;
int dc_id = gdc;
+ struct power_domain pd;
+ int ret;
+
if (dc_id == 0) {
dc_rsrc = SC_R_DC_0;
pll0_rsrc = SC_R_DC_0_PLL_0;
pll1_rsrc = SC_R_DC_0_PLL_1;
+ dc_pd_name = "dc0_power_domain";
} else {
dc_rsrc = SC_R_DC_1;
pll0_rsrc = SC_R_DC_1_PLL_0;
pll1_rsrc = SC_R_DC_1_PLL_1;
+ dc_pd_name = "dc1_power_domain";
}
- /* Power up DC */
- err = sc_pm_set_resource_power_mode(ipcHndl, dc_rsrc, SC_PM_PW_MODE_ON);
- if (err != SC_ERR_NONE) {
- printf("DC Power up failed! (error = %d)\n", err);
- return -EIO;
- }
-
- /* Power up PLL1 (user PLL) */
- err = sc_pm_set_resource_power_mode(ipcHndl, pll0_rsrc, SC_PM_PW_MODE_ON);
- if (err != SC_ERR_NONE) {
- printf("PLL0 Power up failed! (error = %d)\n", err);
- return -EIO;
- }
-
- /* Power up PLL2 */
- err = sc_pm_set_resource_power_mode(ipcHndl, pll1_rsrc, SC_PM_PW_MODE_ON);
- if (err != SC_ERR_NONE) {
- printf("PLL1 Power up failed! (error = %d)\n", err);
+ if (!power_domain_lookup_name(dc_pd_name, &pd)) {
+ ret = power_domain_on(&pd);
+ if (ret) {
+ printf("%s Power up failed! (error = %d)\n", dc_pd_name, ret);
+ return -EIO;
+ }
+ } else {
+ printf("%s lookup failed!\n", dc_pd_name);
return -EIO;
}
diff --git a/arch/arm/include/asm/arch-imx8/i2c.h b/arch/arm/include/asm/arch-imx8/i2c.h
index 4f1375c796d..2de13caea44 100644
--- a/arch/arm/include/asm/arch-imx8/i2c.h
+++ b/arch/arm/include/asm/arch-imx8/i2c.h
@@ -33,30 +33,4 @@ static struct imx_i2c_map imx_i2c_desc[] = {
{15, SC_R_MIPI_1_I2C_0},
{16, SC_R_MIPI_1_I2C_1},
};
-
-/* The power should write in parent order*/
-static __attribute__((unused)) struct imx_i2c_map i2c_parent_power_desc[] = {
- {5, SC_R_DC_0},
- {5, SC_R_LVDS_0},
- {6, SC_R_DC_0},
- {6, SC_R_LVDS_0},
- {7, SC_R_DC_1},
- {7, SC_R_LVDS_1},
- {8, SC_R_DC_1},
- {8, SC_R_LVDS_1},
- {13, SC_R_DC_0},
- {13, SC_R_MIPI_0},
- {14, SC_R_DC_0},
- {14, SC_R_MIPI_0},
-#ifdef CONFIG_IMX8QM
- {15, SC_R_DC_1},
- {15, SC_R_MIPI_1},
-#else
- {15, SC_R_DC_0},
- {15, SC_R_MIPI_1},
-#endif
- {16, SC_R_DC_1},
- {16, SC_R_MIPI_1},
-};
-
#endif /* __ASM_ARCH_IMX8_I2C_H__ */
diff --git a/arch/arm/include/asm/arch-imx8/sys_proto.h b/arch/arm/include/asm/arch-imx8/sys_proto.h
index 9d94cf63684..caf3cdf8325 100644
--- a/arch/arm/include/asm/arch-imx8/sys_proto.h
+++ b/arch/arm/include/asm/arch-imx8/sys_proto.h
@@ -40,4 +40,4 @@ struct rom_sw_info_t {
int print_bootinfo(void);
int init_otg_power(void);
-int init_i2c_power(unsigned i2c_num);
+void power_off_pd_devices(const char* permanent_on_devices[], int size);