Add cpu, power, and clocks functions for support i.MX8QM and i.MX8QXP SoCs.
Signed-off-by: Ranjani Vaidyanathan <Ranjani.Vaidyanathan@nxp.com>
Signed-off-by: Nitin Garg <nitin.garg@nxp.com>
Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Signed-off-by: Adrian Alonso <adrian.alonso@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Fugang Duan <fugang.duan@nxp.com>
Signed-off-by: Ye Li <ye.li@nxp.com>
# SPDX-License-Identifier: GPL-2.0+
#
+obj-y += cpu.o
+obj-y += clock.o
obj-y += fsl_mu_hal.o
--- /dev/null
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/errno.h>
+#include <asm/arch/clock.h>
+#include <asm/imx-common/sci/sci.h>
+#include <asm/arch/imx8-pins.h>
+#include <asm/arch/i2c.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+u32 get_lpuart_clk(void)
+{
+ return mxc_get_clock(MXC_UART_CLK);
+}
+
+static u32 get_arm_main_clk(void)
+{
+ sc_err_t err;
+ sc_pm_clock_rate_t clkrate;
+
+ err = sc_pm_get_clock_rate((sc_ipc_t)gd->arch.ipc_channel_handle,
+ SC_R_A53, SC_PM_CLK_CPU, &clkrate);
+ if (err != SC_ERR_NONE) {
+ printf("sc get ARM A53 clk failed! err=%d\n", err);
+ return 0;
+ }
+ return clkrate;
+}
+
+unsigned int mxc_get_clock(enum mxc_clock clk)
+{
+ sc_err_t err;
+ sc_pm_clock_rate_t clkrate;
+
+ switch (clk) {
+ case MXC_UART_CLK:
+ err = sc_pm_get_clock_rate((sc_ipc_t)gd->arch.ipc_channel_handle,
+ SC_R_UART_0, 2, &clkrate);
+ if (err != SC_ERR_NONE) {
+ printf("sc get UART clk failed! err=%d\n", err);
+ return 0;
+ }
+ return clkrate;
+ case MXC_ESDHC_CLK:
+ err = sc_pm_get_clock_rate((sc_ipc_t)gd->arch.ipc_channel_handle,
+ SC_R_SDHC_0, 2, &clkrate);
+ if (err != SC_ERR_NONE) {
+ printf("sc get uSDHC1 clk failed! err=%d\n", err);
+ return 0;
+ }
+ return clkrate;
+ case MXC_ESDHC2_CLK:
+ err = sc_pm_get_clock_rate((sc_ipc_t)gd->arch.ipc_channel_handle,
+ SC_R_SDHC_1, 2, &clkrate);
+ if (err != SC_ERR_NONE) {
+ printf("sc get uSDHC2 clk failed! err=%d\n", err);
+ return 0;
+ }
+ return clkrate;
+ case MXC_ESDHC3_CLK:
+ err = sc_pm_get_clock_rate((sc_ipc_t)gd->arch.ipc_channel_handle,
+ SC_R_SDHC_2, 2, &clkrate);
+ if (err != SC_ERR_NONE) {
+ printf("sc get uSDHC3 clk failed! err=%d\n", err);
+ return 0;
+ }
+ return clkrate;
+ case MXC_FEC_CLK:
+ err = sc_pm_get_clock_rate((sc_ipc_t)gd->arch.ipc_channel_handle,
+ SC_R_ENET_0, 2, &clkrate);
+ if (err != SC_ERR_NONE) {
+ printf("sc get ENET clk failed! err=%d\n", err);
+ return 0;
+ }
+ return clkrate;
+ case MXC_ARM_CLK:
+ return get_arm_main_clk();
+ default:
+ printf("Unsupported mxc_clock %d\n", clk);
+ break;
+ }
+
+ return 0;
+}
+
+u32 imx_get_fecclk(void)
+{
+ return mxc_get_clock(MXC_FEC_CLK);
+}
+
+int enable_i2c_clk(unsigned char enable, unsigned i2c_num)
+{
+ sc_ipc_t ipc;
+ sc_err_t err;
+
+ if (i2c_num >= ARRAY_SIZE(imx_i2c_desc))
+ return -EINVAL;
+
+ ipc = gd->arch.ipc_channel_handle;
+
+ if (enable)
+ err = sc_pm_clock_enable(ipc,
+ imx_i2c_desc[i2c_num].rsrc, 2, true, false);
+ else
+ err = sc_pm_clock_enable(ipc,
+ imx_i2c_desc[i2c_num].rsrc, 2, false, false);
+
+ if (err != SC_ERR_NONE) {
+ printf("i2c clock error %d\n", err);
+ return -EPERM;
+ }
+
+ return 0;
+}
+
+u32 imx_get_i2cclk(unsigned i2c_num)
+{
+ sc_err_t err;
+ sc_ipc_t ipc;
+ u32 clock_rate;
+
+ if (i2c_num >= ARRAY_SIZE(imx_i2c_desc))
+ return 0;
+
+ ipc = gd->arch.ipc_channel_handle;
+ err = sc_pm_get_clock_rate(ipc, imx_i2c_desc[i2c_num].rsrc, 2,
+ &clock_rate);
+ if (err != SC_ERR_NONE)
+ return 0;
+
+ return clock_rate;
+}
+
+int set_clk_qspi(void)
+{
+ 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;
+ }
+
+ 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;
+ }
+
+ return 0;
+}
+
+void enable_usboh3_clk(unsigned char enable)
+{
+ sc_err_t err;
+ sc_ipc_t ipc;
+ sc_rsrc_t usbs[] = {SC_R_USB_0, SC_R_USB_1, SC_R_USB_2};
+
+ int i;
+
+ ipc = gd->arch.ipc_channel_handle;
+ if (enable) {
+ for (i = 0; i < 2; i++) {
+ /* The 24Mhz OTG PHY clock is pd linked, so it has been power up when pd is on */
+ err = sc_pm_clock_enable(ipc, usbs[i], SC_PM_CLK_PHY, true, false);
+ if (err != SC_ERR_NONE)
+ printf("\nSC_R_USB_%d enable clock enable failed! (error = %d)\n", i, err);
+ }
+ } else {
+ for (i = 0; i < 2; i++) {
+ err = sc_pm_clock_enable(ipc, usbs[i], SC_PM_CLK_PHY, false, false);
+ if (err != SC_ERR_NONE)
+ printf("\nSC_R_USB_%d enable clock disable failed! (error = %d)\n", i, err);
+ }
+ }
+
+ return;
+}
+
+void init_clk_usdhc(u32 index)
+{
+#ifdef CONFIG_IMX8QM
+ sc_rsrc_t usdhcs[] = {SC_R_SDHC_0, SC_R_SDHC_1, SC_R_SDHC_2};
+ u32 instances = 3;
+#else
+ sc_rsrc_t usdhcs[] = {SC_R_SDHC_0, SC_R_SDHC_1};
+ u32 instances = 2;
+#endif
+
+ sc_err_t err;
+ sc_ipc_t ipc;
+ sc_pm_clock_rate_t actual = 200000000;
+
+ ipc = gd->arch.ipc_channel_handle;
+
+ 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);
+ return;
+ }
+
+ if (actual != 200000000)
+ debug("Actual rate for SDHC_%d is %d\n", index, actual);
+
+ err = sc_pm_clock_enable(ipc, usdhcs[index], SC_PM_CLK_PER, true, false);
+ if (err != SC_ERR_NONE) {
+ printf("SDHC_%d per clk enable failed!\n", index);
+ return;
+ }
+}
--- /dev/null
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ */
+
+#include <common.h>
+#include <errno.h>
+#include <asm/io.h>
+#include <asm/imx-common/sci/sci.h>
+#include <asm/arch/i2c.h>
+#include <asm/arch/clock.h>
+#include <asm/armv8/mmu.h>
+#include <elf.h>
+#include <asm/arch-imx/cpu.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+static struct mm_region imx8_mem_map[] = {
+ {
+ .virt = 0x0UL,
+ .phys = 0x0UL,
+ .size = 0x2000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_OUTER_SHARE
+ }, {
+ .virt = 0x2000000UL,
+ .phys = 0x2000000UL,
+ .size = 0x7E000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ .virt = 0x80000000UL,
+ .phys = 0x80000000UL,
+ .size = 0x80000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_OUTER_SHARE
+ }, {
+ .virt = 0x100000000UL,
+ .phys = 0x100000000UL,
+ .size = 0x700000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_DEVICE_NGNRNE) |
+ PTE_BLOCK_NON_SHARE |
+ PTE_BLOCK_PXN | PTE_BLOCK_UXN
+ }, {
+ .virt = 0x880000000UL,
+ .phys = 0x880000000UL,
+ .size = 0x780000000UL,
+ .attrs = PTE_BLOCK_MEMTYPE(MT_NORMAL) |
+ PTE_BLOCK_OUTER_SHARE
+ }, {
+ /* List terminator */
+ 0,
+ }
+};
+struct mm_region *mem_map = imx8_mem_map;
+
+u32 get_cpu_rev(void)
+{
+ sc_ipc_t ipcHndl;
+ uint32_t id = 0, rev = 0;
+ sc_err_t err;
+
+ ipcHndl = gd->arch.ipc_channel_handle;
+
+ err = sc_misc_get_control(ipcHndl, SC_R_SC_PID0, SC_C_ID, &id);
+ if (err != SC_ERR_NONE)
+ return 0;
+
+ rev = (id >> 5) & 0xf;
+ id = (id & 0x1f) + MXC_SOC_IMX8; /* Dummy ID for chip */
+
+ return (id << 12) | rev;
+}
+
+#ifdef CONFIG_DISPLAY_CPUINFO
+const char *get_imx8_type(u32 imxtype)
+{
+ switch (imxtype) {
+ case MXC_CPU_IMX8QM:
+ return "8QM"; /* i.MX8 Quad MAX */
+ case MXC_CPU_IMX8QXP:
+ return "8QXP"; /* i.MX8 Quad XP */
+ case MXC_CPU_IMX8DX:
+ return "8DX"; /* i.MX8 Dual X */
+ default:
+ return "??";
+ }
+}
+
+const char *get_imx8_rev(u32 rev)
+{
+ switch (rev) {
+ case CHIP_REV_A:
+ return "A";
+ case CHIP_REV_B:
+ return "B";
+ default:
+ return "?";
+ }
+}
+
+int print_cpuinfo(void)
+{
+ u32 cpurev;
+ cpurev = get_cpu_rev();
+
+ printf("CPU: Freescale i.MX%s rev%s at %d MHz\n",
+ get_imx8_type((cpurev & 0xFF000) >> 12),
+ get_imx8_rev((cpurev & 0xFFF)),
+ mxc_get_clock(MXC_ARM_CLK) / 1000000);
+
+ return 0;
+}
+#endif
+
+int arch_cpu_init(void)
+{
+ sc_ipc_t ipcHndl = 0;
+ sc_err_t sciErr = 0;
+ gd->arch.ipc_channel_handle = 0;
+
+ /* Open IPC channel */
+ sciErr = sc_ipc_open(&ipcHndl, SC_IPC_CH);
+ if (sciErr != SC_ERR_NONE)
+ return -EPERM;
+
+ gd->arch.ipc_channel_handle = ipcHndl;
+
+ return 0;
+}
+
+u32 cpu_mask(void)
+{
+#ifdef CONFIG_IMX8QM
+ return 0x3f;
+#else
+ return 0xf; /*For IMX8QXP*/
+#endif
+}
+
+#define CCI400_DVM_MESSAGE_REQ_EN 0x00000002
+#define CCI400_SNOOP_REQ_EN 0x00000001
+#define CHANGE_PENDING_BIT (1 << 0)
+int imx8qm_wake_seconday_cores(void)
+{
+#ifdef CONFIG_ARMV8_MULTIENTRY
+ sc_ipc_t ipcHndl;
+ u64 *table = get_spin_tbl_addr();
+
+ /* Clear spin table so that secondary processors
+ * observe the correct value after waking up from wfe.
+ */
+ memset(table, 0, CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE);
+ flush_dcache_range((unsigned long)table,
+ (unsigned long)table +
+ (CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE));
+
+ /* Open IPC channel */
+ if (sc_ipc_open(&ipcHndl, SC_IPC_CH) != SC_ERR_NONE)
+ return -EIO;
+
+ __raw_writel(0xc, 0x52090000);
+ __raw_writel(1, 0x52090008);
+
+ /* IPC to pwr up and boot other cores */
+ if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_A53_1, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+ return -EIO;
+ if (sc_pm_cpu_start(ipcHndl, SC_R_A53_1, true, 0x80000000) != SC_ERR_NONE)
+ return -EIO;
+
+ if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_A53_2, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+ return -EIO;
+ if (sc_pm_cpu_start(ipcHndl, SC_R_A53_2, true, 0x80000000) != SC_ERR_NONE)
+ return -EIO;
+
+ if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_A53_3, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+ return -EIO;
+ if (sc_pm_cpu_start(ipcHndl, SC_R_A53_3, true, 0x80000000) != SC_ERR_NONE)
+ return -EIO;
+
+ /* Enable snoop and dvm msg requests for a53 port on CCI slave interface 3 */
+ __raw_writel(CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN, 0x52094000);
+
+ while (__raw_readl(0x5209000c) & CHANGE_PENDING_BIT)
+ ;
+
+ /* Pwr up cluster 1 and boot core 0*/
+ if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_A72, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+ return -EIO;
+
+ if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_A72_0, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+ return -EIO;
+ if (sc_pm_cpu_start(ipcHndl, SC_R_A72_0, true, 0x80000000) != SC_ERR_NONE)
+ return -EIO;
+
+ /* IPC to pwr up and boot core 1 */
+ if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_A72_1, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+ return -EIO;
+ if (sc_pm_cpu_start(ipcHndl, SC_R_A72_1, true, 0x80000000) != SC_ERR_NONE)
+ return -EIO;
+
+ /* Enable snoop and dvm msg requests for a72 port on CCI slave interface 4 */
+ __raw_writel(CCI400_DVM_MESSAGE_REQ_EN | CCI400_SNOOP_REQ_EN, 0x52095000);
+
+ while (__raw_readl(0x5209000c) & CHANGE_PENDING_BIT)
+ ;
+#endif
+ return 0;
+}
+
+int imx8qxp_wake_secondary_cores(void)
+{
+#ifdef CONFIG_ARMV8_MULTIENTRY
+ sc_ipc_t ipcHndl;
+ u64 *table = get_spin_tbl_addr();
+
+ /* Clear spin table so that secondary processors
+ * observe the correct value after waking up from wfe.
+ */
+ memset(table, 0, CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE);
+ flush_dcache_range((unsigned long)table,
+ (unsigned long)table +
+ (CONFIG_MAX_CPUS*SPIN_TABLE_ELEM_SIZE));
+
+ /* Open IPC channel */
+ if (sc_ipc_open(&ipcHndl, SC_IPC_CH) != SC_ERR_NONE)
+ return -EIO;
+
+ /* IPC to pwr up and boot other cores */
+ if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_A35_1, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+ return -EIO;
+ if (sc_pm_cpu_start(ipcHndl, SC_R_A35_1, true, 0x80000000) != SC_ERR_NONE)
+ return -EIO;
+
+ if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_A35_2, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+ return -EIO;
+ if (sc_pm_cpu_start(ipcHndl, SC_R_A35_2, true, 0x80000000) != SC_ERR_NONE)
+ return -EIO;
+
+ if (sc_pm_set_resource_power_mode(ipcHndl, SC_R_A35_3, SC_PM_PW_MODE_ON) != SC_ERR_NONE)
+ return -EIO;
+ if (sc_pm_cpu_start(ipcHndl, SC_R_A35_3, true, 0x80000000) != SC_ERR_NONE)
+ return -EIO;
+
+#endif
+ 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;
+}
+
+#define FUSE_MAC0_WORD0 452
+#define FUSE_MAC0_WORD1 453
+#define FUSE_MAC1_WORD0 454
+#define FUSE_MAC1_WORD1 455
+void imx_get_mac_from_fuse(int dev_id, unsigned char *mac)
+{
+ sc_err_t err;
+ sc_ipc_t ipc;
+ uint32_t val1 = 0, val2 = 0;
+ uint32_t word1, word2;
+
+ ipc = gd->arch.ipc_channel_handle;
+
+ if (dev_id == 0) {
+ word1 = FUSE_MAC0_WORD0;
+ word2 = FUSE_MAC0_WORD1;
+ } else {
+ word1 = FUSE_MAC1_WORD0;
+ word2 = FUSE_MAC1_WORD1;
+ }
+
+ err = sc_misc_otp_fuse_read(ipc, word1, &val1);
+ if (err != SC_ERR_NONE) {
+ printf("%s fuse %d read error: %d\n", __func__, word1, err);
+ return;
+ }
+
+ err = sc_misc_otp_fuse_read(ipc, word2, &val2);
+ if (err != SC_ERR_NONE) {
+ printf("%s fuse %d read error: %d\n", __func__, word2, err);
+ return;
+ }
+
+ mac[0] = val1;
+ mac[1] = val1 >> 8;
+ mac[2] = val1 >> 16;
+ mac[3] = val1 >> 24;
+ mac[4] = val2;
+ mac[5] = val2 >> 8;
+}
#define MXC_CPU_MX7S 0x71 /* dummy ID */
#define MXC_CPU_MX7D 0x72
#define MXC_CPU_MX7ULP 0x81 /* Temporally hard code */
+#define MXC_CPU_IMX8QM 0x91 /* dummy ID */
+#define MXC_CPU_IMX8QXP 0x92 /* dummy ID */
+#define MXC_CPU_IMX8DX 0x93 /* dummy ID */
#define MXC_CPU_VF610 0xF6 /* dummy ID */
#define MXC_SOC_MX6 0x60
#define MXC_SOC_MX7 0x70
#define MXC_SOC_MX7ULP 0x80 /* dummy */
+#define MXC_SOC_IMX8 0x90 /* dummy */
#define CHIP_REV_1_0 0x10
#define CHIP_REV_1_1 0x11
#define CHIP_REV_2_5 0x25
#define CHIP_REV_3_0 0x30
+#define CHIP_REV_A 0x0
+#define CHIP_REV_B 0x1
+
#define BOARD_REV_1_0 0x0
#define BOARD_REV_2_0 0x1
#define BOARD_VER_OFFSET 0x8
--- /dev/null
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ */
+
+#ifndef __ASM_ARCH_CLOCK_H__
+#define __ASM_ARCH_CLOCK_H__
+
+/* Mainly for compatible to imx common code. */
+enum mxc_clock {
+ MXC_ARM_CLK = 0,
+ MXC_AHB_CLK,
+ MXC_IPG_CLK,
+ MXC_UART_CLK,
+ MXC_CSPI_CLK,
+ MXC_AXI_CLK,
+ MXC_DDR_CLK,
+ MXC_ESDHC_CLK,
+ MXC_ESDHC2_CLK,
+ MXC_ESDHC3_CLK,
+ MXC_I2C_CLK,
+ MXC_FEC_CLK,
+};
+
+u32 mxc_get_clock(enum mxc_clock clk);
+u32 get_lpuart_clk(void);
+int enable_i2c_clk(unsigned char enable, unsigned i2c_num);
+u32 imx_get_i2cclk(unsigned i2c_num);
+void enable_usboh3_clk(unsigned char enable);
+int set_clk_qspi(void);
+u32 imx_get_fecclk(void);
+void init_clk_usdhc(u32 index);
+
+#endif /* __ASM_ARCH_CLOCK_H__ */
--- /dev/null
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+u32 cpu_mask(void);
--- /dev/null
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ */
+#ifndef __ASM_ARCH_IMX8_I2C_H__
+#define __ASM_ARCH_IMX8_I2C_H__
+
+#include <asm/imx-common/sci/sci.h>
+
+struct imx_i2c_map {
+ int index;
+ sc_rsrc_t rsrc;
+};
+
+static struct imx_i2c_map imx_i2c_desc[] = {
+ {0, SC_R_I2C_0},
+ {1, SC_R_I2C_1},
+ {2, SC_R_I2C_2},
+ {3, SC_R_I2C_3},
+ {4, SC_R_I2C_4},
+ {5, SC_R_LVDS_0_I2C_0}, /* lvds0 i2c0 */
+ {6, SC_R_LVDS_0_I2C_0}, /* lvds0 i2c1 */
+ {7, SC_R_LVDS_1_I2C_0}, /* lvds1 i2c0 */
+ {8, SC_R_LVDS_1_I2C_0}, /* lvds1 i2c1 */
+ {9, SC_R_CSI_0_I2C_0},
+ {10, SC_R_CSI_1_I2C_0},
+ {11, SC_R_HDMI_I2C_0},
+ {12, SC_R_HDMI_RX_I2C_0},
+ {13, SC_R_MIPI_0_I2C_0},
+ {14, SC_R_MIPI_0_I2C_1},
+ {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},
+ {15, SC_R_DC_1},
+ {15, SC_R_MIPI_1},
+ {16, SC_R_DC_1},
+ {16, SC_R_MIPI_1},
+};
+
+#endif /* __ASM_ARCH_IMX8_I2C_H__ */
--- /dev/null
+/*
+ * Copyright 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ *
+ */
+
+#ifndef __ASM_ARCH_IMX_REGS_H__
+#define __ASM_ARCH_IMX_REGS_H__
+
+#define MU_BASE_ADDR(id) ((0x5D1B0000UL + (id*0x10000)))
+
+#define LPUART_BASE 0x5A060000
+
+#define GPT1_BASE_ADDR 0x5D140000
+#define SCU_LPUART_BASE 0x33220000
+#define GPIO1_BASE_ADDR 0x5D080000
+#define GPIO2_BASE_ADDR 0x5D090000
+#define GPIO3_BASE_ADDR 0x5D0A0000
+#define GPIO4_BASE_ADDR 0x5D0B0000
+#define GPIO5_BASE_ADDR 0x5D0C0000
+#define GPIO6_BASE_ADDR 0x5D0D0000
+#define GPIO7_BASE_ADDR 0x5D0E0000
+#define GPIO8_BASE_ADDR 0x5D0F0000
+#define LPI2C1_BASE_ADDR 0x5A800000
+#define LPI2C2_BASE_ADDR 0x5A810000
+#define LPI2C3_BASE_ADDR 0x5A820000
+#define LPI2C4_BASE_ADDR 0x5A830000
+#define LPI2C5_BASE_ADDR 0x5A840000
+
+#ifdef CONFIG_LPUART
+#define LPUART_BASE SCU_LPUART_BASE
+#endif
+
+#endif /* __ASM_ARCH_IMX_REGS_H__ */
--- /dev/null
+/*
+ * Copyright (C) 2017 NXP
+ *
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <asm/imx-common/sys_proto.h>
+
+int init_qspi_power(void);
+int init_usb_power(void);
+int init_i2c_power(unsigned i2c_num);
#define is_mx6() (is_soc_type(MXC_SOC_MX6))
#define is_mx7() (is_soc_type(MXC_SOC_MX7))
+#define is_imx8() (is_soc_type(MXC_SOC_IMX8))
#define is_mx6dqp() (is_cpu_type(MXC_CPU_MX6QP) || is_cpu_type(MXC_CPU_MX6DP))
#define is_mx6dq() (is_cpu_type(MXC_CPU_MX6Q) || is_cpu_type(MXC_CPU_MX6D))
#define is_mx7ulp() (is_cpu_type(MXC_CPU_MX7ULP))
+#define is_imx8qm() (is_cpu_type(MXC_CPU_IMX8QM))
+#define is_imx8qxp() (is_cpu_type(MXC_CPU_IMX8QXP))
+#define is_imx8dx() (is_cpu_type(MXC_CPU_IMX8DX))
+
u32 get_nr_cpus(void);
u32 get_cpu_rev(void);
u32 get_cpu_speed_grade_hz(void);