diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2017-02-13 09:26:04 +0100 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2017-02-13 09:26:04 +0100 |
commit | 30139163b75970fcd58df6b6b987883e36571046 (patch) | |
tree | 00bd354cefa617f8474cc73994b1a72c11e770a0 /arch/arm/mach-imx | |
parent | bb1a6a2fd3cc41be6db1a1362f311456019317b1 (diff) | |
parent | 19df384cec181be4407f82377ffbb3059b1ed748 (diff) | |
download | barebox-30139163b75970fcd58df6b6b987883e36571046.tar.gz barebox-30139163b75970fcd58df6b6b987883e36571046.tar.xz |
Merge branch 'for-next/imx'
Diffstat (limited to 'arch/arm/mach-imx')
22 files changed, 771 insertions, 86 deletions
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig index 9dbe31c4b6..f83aedc0b9 100644 --- a/arch/arm/mach-imx/Kconfig +++ b/arch/arm/mach-imx/Kconfig @@ -39,6 +39,7 @@ config ARCH_TEXT_BASE default 0x4fc00000 if MACH_UDOO default 0x4fc00000 if MACH_VARISCITE_MX6 default 0x4fc00000 if MACH_PHYTEC_SOM_IMX6 + default 0x9fc00000 if MACH_WARP7 config ARCH_IMX_IMXIMAGE bool @@ -147,6 +148,10 @@ config ARCH_IMX6 select COMMON_CLK_OF_PROVIDER select HW_HAS_PCI +config ARCH_IMX6SL + bool + select ARCH_IMX6 + config ARCH_IMX6SX bool select ARCH_IMX6 @@ -157,6 +162,12 @@ config ARCH_IMX6UL bool select ARCH_IMX6 +config ARCH_IMX7 + bool + select CPU_V7 + select OFTREE + select COMMON_CLK_OF_PROVIDER + config ARCH_VF610 bool select ARCH_HAS_L2X0 @@ -166,6 +177,7 @@ config ARCH_VF610 select OFTREE select COMMON_CLK select COMMON_CLK_OF_PROVIDER + select IMX_OCOTP # Needed for clock adjustement config IMX_MULTI_BOARDS bool "Allow multiple boards to be selected" @@ -346,10 +358,23 @@ config MACH_CM_FX6 bool "CM FX6" select ARCH_IMX6 +config MACH_WARP7 + bool "NXP i.MX7: element 14 WaRP7 Board" + select ARCH_IMX7 + config MACH_VF610_TWR bool "Freescale VF610 Tower Board" select ARCH_VF610 +config MACH_ZII_RDU2 + bool "ZII i.MX6Q(+) RDU2" + select ARCH_IMX6 + +config MACH_ZII_VF610_DEV + bool "Zodiac VF610 Dev Family" + select ARCH_VF610 + select CLKDEV_LOOKUP + endif # ---------------------------------------------------------- diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index d0fe7abc00..fc5305f051 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -13,6 +13,7 @@ obj-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o esdctl-v4.o pbl-$(CONFIG_ARCH_IMX53) += imx53.o imx5.o esdctl-v4.o obj-$(CONFIG_ARCH_IMX6) += imx6.o usb-imx6.o lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o +obj-$(CONFIG_ARCH_IMX7) += imx7.o obj-$(CONFIG_ARCH_IMX_XLOAD) += xload.o obj-$(CONFIG_IMX_IIM) += iim.o obj-$(CONFIG_IMX_OCOTP) += ocotp.o diff --git a/arch/arm/mach-imx/boot.c b/arch/arm/mach-imx/boot.c index 489306072f..72597f5e2d 100644 --- a/arch/arm/mach-imx/boot.c +++ b/arch/arm/mach-imx/boot.c @@ -25,6 +25,7 @@ #include <mach/imx51-regs.h> #include <mach/imx53-regs.h> #include <mach/imx6-regs.h> +#include <mach/imx7-regs.h> /* [CTRL][TYPE] */ static const enum bootsource locations[4][4] = { @@ -346,3 +347,72 @@ void imx6_boot_save_loc(void) bootsource_set(src); bootsource_set_instance(instance); } + +#define IMX7_SRC_SBMR1 0x58 +#define IMX7_SRC_SBMR2 0x70 + +void imx7_get_boot_source(enum bootsource *src, int *instance) +{ + void __iomem *src_base = IOMEM(MX7_SRC_BASE_ADDR); + uint32_t sbmr1 = readl(src_base + IMX7_SRC_SBMR1); + uint32_t sbmr2 = readl(src_base + IMX7_SRC_SBMR2); + int boot_mode; + + /* BMOD[1:0] */ + boot_mode = (sbmr2 >> 24) & 0x3; + + switch (boot_mode) { + case 0: /* Fuses, fall through */ + case 2: /* internal boot */ + goto internal_boot; + case 1: /* Serial Downloader */ + *src = BOOTSOURCE_SERIAL; + break; + case 3: /* reserved */ + break; + }; + + return; + +internal_boot: + + switch ((sbmr1 >> 12) & 0xf) { + case 1: + case 2: + *src = BOOTSOURCE_MMC; + *instance = (sbmr1 >> 10 & 0x3); + break; + case 3: + *src = BOOTSOURCE_NAND; + break; + case 4: + *src = BOOTSOURCE_SPI_NOR, + *instance = (sbmr1 >> 9 & 0x7); + break; + case 6: + *src = BOOTSOURCE_SPI; /* Really: qspi */ + break; + case 5: + *src = BOOTSOURCE_NOR; + break; + default: + break; + } + + /* BOOT_CFG1[7:0] */ + if (sbmr1 & (1 << 7)) + *src = BOOTSOURCE_NAND; + + return; +} + +void imx7_boot_save_loc(void) +{ + enum bootsource src = BOOTSOURCE_UNKNOWN; + int instance = BOOTSOURCE_INSTANCE_UNKNOWN; + + imx7_get_boot_source(&src, &instance); + + bootsource_set(src); + bootsource_set_instance(instance); +} diff --git a/arch/arm/mach-imx/clocksource.c b/arch/arm/mach-imx/clocksource.c index 8d00bbb3f0..8482abd691 100644 --- a/arch/arm/mach-imx/clocksource.c +++ b/arch/arm/mach-imx/clocksource.c @@ -155,6 +155,9 @@ static __maybe_unused struct of_device_id imx_gpt_dt_ids[] = { .compatible = "fsl,imx6ul-gpt", .data = ®s_imx31, }, { + .compatible = "fsl,imx7d-gpt", + .data = ®s_imx31, + }, { /* sentinel */ } }; diff --git a/arch/arm/mach-imx/cpu_init.c b/arch/arm/mach-imx/cpu_init.c index 6971d89d9e..2b388cad8c 100644 --- a/arch/arm/mach-imx/cpu_init.c +++ b/arch/arm/mach-imx/cpu_init.c @@ -34,6 +34,11 @@ void imx6_cpu_lowlevel_init(void) enable_arm_errata_845369_war(); } +void imx7_cpu_lowlevel_init(void) +{ + arm_cpu_lowlevel_init(); +} + void vf610_cpu_lowlevel_init(void) { arm_cpu_lowlevel_init(); diff --git a/arch/arm/mach-imx/esdctl.c b/arch/arm/mach-imx/esdctl.c index ffe708f385..1eebc77b63 100644 --- a/arch/arm/mach-imx/esdctl.c +++ b/arch/arm/mach-imx/esdctl.c @@ -432,6 +432,9 @@ static struct platform_device_id imx_esdctl_ids[] = { static __maybe_unused struct of_device_id imx_esdctl_dt_ids[] = { { + .compatible = "fsl,imx6sl-mmdc", + .data = &imx6ul_data + }, { .compatible = "fsl,imx6ul-mmdc", .data = &imx6ul_data }, { diff --git a/arch/arm/mach-imx/imx.c b/arch/arm/mach-imx/imx.c index 952db007d9..19907397f9 100644 --- a/arch/arm/mach-imx/imx.c +++ b/arch/arm/mach-imx/imx.c @@ -61,10 +61,16 @@ static int imx_soc_from_dt(void) return IMX_CPU_IMX6; if (of_machine_is_compatible("fsl,imx6sx")) return IMX_CPU_IMX6; + if (of_machine_is_compatible("fsl,imx6sl")) + return IMX_CPU_IMX6; if (of_machine_is_compatible("fsl,imx6qp")) return IMX_CPU_IMX6; if (of_machine_is_compatible("fsl,imx6ul")) return IMX_CPU_IMX6; + if (of_machine_is_compatible("fsl,imx7s")) + return IMX_CPU_IMX7; + if (of_machine_is_compatible("fsl,imx7d")) + return IMX_CPU_IMX7; if (of_machine_is_compatible("fsl,vf610")) return IMX_CPU_VF610; @@ -103,6 +109,8 @@ static int imx_init(void) ret = imx53_init(); else if (cpu_is_mx6()) ret = imx6_init(); + else if (cpu_is_mx7()) + ret = imx7_init(); else if (cpu_is_vf610()) ret = 0; else diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index b2979b049e..44a8dbefd0 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -151,6 +151,9 @@ int imx6_init(void) case IMX6_CPUTYPE_IMX6S: cputypestr = "i.MX6 Solo"; break; + case IMX6_CPUTYPE_IMX6SL: + cputypestr = "i.MX6 SoloLite"; + break; case IMX6_CPUTYPE_IMX6SX: cputypestr = "i.MX6 SoloX"; break; diff --git a/arch/arm/mach-imx/imx7.c b/arch/arm/mach-imx/imx7.c new file mode 100644 index 0000000000..4eef99c872 --- /dev/null +++ b/arch/arm/mach-imx/imx7.c @@ -0,0 +1,202 @@ +/* + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of + * the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include <init.h> +#include <common.h> +#include <io.h> +#include <linux/sizes.h> +#include <asm/psci.h> +#include <mach/imx7.h> +#include <mach/generic.h> +#include <mach/revision.h> +#include <mach/imx7-regs.h> + +void imx7_init_lowlevel(void) +{ + void __iomem *aips1 = IOMEM(MX7_AIPS1_CONFIG_BASE_ADDR); + void __iomem *aips2 = IOMEM(MX7_AIPS2_CONFIG_BASE_ADDR); + + /* + * Set all MPROTx to be non-bufferable, trusted for R/W, + * not forced to user-mode. + */ + writel(0x77777777, aips1); + writel(0x77777777, aips1 + 0x4); + writel(0, aips1 + 0x40); + writel(0, aips1 + 0x44); + writel(0, aips1 + 0x48); + writel(0, aips1 + 0x4c); + writel(0, aips1 + 0x50); + + writel(0x77777777, aips2); + writel(0x77777777, aips2 + 0x4); + writel(0, aips2 + 0x40); + writel(0, aips2 + 0x44); + writel(0, aips2 + 0x48); + writel(0, aips2 + 0x4c); + writel(0, aips2 + 0x50); +} + +#define SC_CNTCR 0x0 +#define SC_CNTSR 0x4 +#define SC_CNTCV1 0x8 +#define SC_CNTCV2 0xc +#define SC_CNTFID0 0x20 +#define SC_CNTFID1 0x24 +#define SC_CNTFID2 0x28 +#define SC_counterid 0xfcc + +#define SC_CNTCR_ENABLE (1 << 0) +#define SC_CNTCR_HDBG (1 << 1) +#define SC_CNTCR_FREQ0 (1 << 8) +#define SC_CNTCR_FREQ1 (1 << 9) + +static int imx7_timer_init(void) +{ + void __iomem *sctr = IOMEM(MX7_SYSCNT_CTRL_BASE_ADDR); + unsigned long val, freq; + + freq = 8000000; + asm("mcr p15, 0, %0, c14, c0, 0" : : "r" (freq)); + + writel(freq, sctr + SC_CNTFID0); + + /* Enable system counter */ + val = readl(sctr + SC_CNTCR); + val &= ~(SC_CNTCR_FREQ0 | SC_CNTCR_FREQ1); + val |= SC_CNTCR_FREQ0 | SC_CNTCR_ENABLE | SC_CNTCR_HDBG; + writel(val, sctr + SC_CNTCR); + + return 0; +} + +#define CSU_NUM_REGS 64 +#define CSU_INIT_SEC_LEVEL0 0x00FF00FF + +static void imx7_init_csu(void) +{ + void __iomem *csu = IOMEM(MX7_CSU_BASE_ADDR); + int i = 0; + + for (i = 0; i < CSU_NUM_REGS; i++) + writel(CSU_INIT_SEC_LEVEL0, csu + i * 4); +} + +#define GPC_CPU_PGC_SW_PDN_REQ 0xfc +#define GPC_CPU_PGC_SW_PUP_REQ 0xf0 +#define GPC_PGC_C1 0x840 +#define GPC_PGC(n) (0x800 + (n) * 0x40) + +#define BM_CPU_PGC_SW_PDN_PUP_REQ_CORE1_A7 0x2 + +#define PGC_CTRL 0x0 + +/* below is for i.MX7D */ +#define SRC_GPR1_MX7D 0x074 +#define SRC_A7RCR1 0x008 + +static void imx_gpcv2_set_core_power(int core, bool pdn) +{ + void __iomem *gpc = IOMEM(MX7_GPC_BASE_ADDR); + void __iomem *pgc = gpc + GPC_PGC(core); + + u32 reg = pdn ? GPC_CPU_PGC_SW_PUP_REQ : GPC_CPU_PGC_SW_PDN_REQ; + u32 val; + + writel(1, pgc + PGC_CTRL); + + val = readl(gpc + reg); + val |= 1 << core; + writel(val, gpc + reg); + + while (readl(gpc + reg) & (1 << core)); + + writel(0, pgc + PGC_CTRL); +} + +static int imx7_cpu_on(u32 cpu_id) +{ + void __iomem *src = IOMEM(MX7_SRC_BASE_ADDR); + u32 val; + + writel(psci_cpu_entry, src + cpu_id * 8 + SRC_GPR1_MX7D); + imx_gpcv2_set_core_power(cpu_id, true); + + val = readl(src + SRC_A7RCR1); + val |= 1 << cpu_id; + writel(val, src + SRC_A7RCR1); + + return 0; +} + +static int imx7_cpu_off(void) +{ + void __iomem *src = IOMEM(MX7_SRC_BASE_ADDR); + u32 val; + int cpu_id = psci_get_cpu_id(); + + val = readl(src + SRC_A7RCR1); + val &= ~(1 << cpu_id); + writel(val, src + SRC_A7RCR1); + + /* + * FIXME: This reads nice and symmetrically to cpu_on above, + * but of course this will never be reached as we have just + * put the CPU we are currently running on into reset. + */ + + imx_gpcv2_set_core_power(cpu_id, false); + + while (1); + + return 0; +} + +static struct psci_ops imx7_psci_ops = { + .cpu_on = imx7_cpu_on, + .cpu_off = imx7_cpu_off, +}; + +int imx7_init(void) +{ + const char *cputypestr; + u32 imx7_silicon_revision; + + imx7_init_lowlevel(); + + imx7_init_csu(); + + imx7_timer_init(); + + imx7_boot_save_loc(); + + imx7_silicon_revision = imx7_cpu_revision(); + + psci_set_ops(&imx7_psci_ops); + + switch (imx7_cpu_type()) { + case IMX7_CPUTYPE_IMX7D: + cputypestr = "i.MX7d"; + break; + case IMX7_CPUTYPE_IMX7S: + cputypestr = "i.MX7s"; + break; + default: + cputypestr = "unknown i.MX7"; + break; + } + + imx_set_silicon_revision(cputypestr, imx7_silicon_revision); + + return 0; +} diff --git a/arch/arm/mach-imx/include/mach/debug_ll.h b/arch/arm/mach-imx/include/mach/debug_ll.h index a132f3c163..39d710f7d8 100644 --- a/arch/arm/mach-imx/include/mach/debug_ll.h +++ b/arch/arm/mach-imx/include/mach/debug_ll.h @@ -14,6 +14,7 @@ #include <mach/imx51-regs.h> #include <mach/imx53-regs.h> #include <mach/imx6-regs.h> +#include <mach/imx7-regs.h> #include <mach/vf610-regs.h> #include <serial/imx-uart.h> @@ -44,6 +45,8 @@ #define IMX_DEBUG_SOC MX53 #elif defined CONFIG_DEBUG_IMX6Q_UART #define IMX_DEBUG_SOC MX6 +#elif defined CONFIG_DEBUG_IMX7D_UART +#define IMX_DEBUG_SOC MX7 #elif defined CONFIG_DEBUG_VF610_UART #define IMX_DEBUG_SOC VF610 #else diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h index 34194509e8..73be9ceb55 100644 --- a/arch/arm/mach-imx/include/mach/generic.h +++ b/arch/arm/mach-imx/include/mach/generic.h @@ -14,12 +14,14 @@ void imx27_boot_save_loc(void); void imx51_boot_save_loc(void); void imx53_boot_save_loc(void); void imx6_boot_save_loc(void); +void imx7_boot_save_loc(void); void imx25_get_boot_source(enum bootsource *src, int *instance); void imx35_get_boot_source(enum bootsource *src, int *instance); void imx51_get_boot_source(enum bootsource *src, int *instance); void imx53_get_boot_source(enum bootsource *src, int *instance); void imx6_get_boot_source(enum bootsource *src, int *instance); +void imx7_get_boot_source(enum bootsource *src, int *instance); int imx1_init(void); int imx21_init(void); @@ -31,6 +33,7 @@ int imx50_init(void); int imx51_init(void); int imx53_init(void); int imx6_init(void); +int imx7_init(void); int imx1_devices_init(void); int imx21_devices_init(void); @@ -45,6 +48,7 @@ int imx6_devices_init(void); void imx5_cpu_lowlevel_init(void); void imx6_cpu_lowlevel_init(void); +void imx7_cpu_lowlevel_init(void); void vf610_cpu_lowlevel_init(void); /* There's a off-by-one betweem the gpio bank number and the gpiochip */ @@ -174,6 +178,18 @@ extern unsigned int __imx_cpu_type; # define cpu_is_mx6() (0) #endif +#ifdef CONFIG_ARCH_IMX7 +# ifdef imx_cpu_type +# undef imx_cpu_type +# define imx_cpu_type __imx_cpu_type +# else +# define imx_cpu_type IMX_CPU_IMX7 +# endif +# define cpu_is_mx7() (imx_cpu_type == IMX_CPU_IMX7) +#else +# define cpu_is_mx7() (0) +#endif + #ifdef CONFIG_ARCH_VF610 # ifdef imx_cpu_type # undef imx_cpu_type diff --git a/arch/arm/mach-imx/include/mach/imx6-fusemap.h b/arch/arm/mach-imx/include/mach/imx6-fusemap.h index 5fdd904fb7..e14044e98a 100644 --- a/arch/arm/mach-imx/include/mach/imx6-fusemap.h +++ b/arch/arm/mach-imx/include/mach/imx6-fusemap.h @@ -1,62 +1,22 @@ #ifndef __MACH_IMX_IMX6_OCOTP_H #define __MACH_IMX_IMX6_OCOTP_H -#include <mach/ocotp.h> +#include <mach/ocotp-fusemap.h> -#define IMX6_OCOTP_TESTER_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(0) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_BOOT_CFG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(2) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_MEM_TRIM_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(4) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_SJC_RESP_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(6) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_MAC_ADDR_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(8) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_GP1_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(10) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_GP2_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(12) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_SRK_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(14) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_ANALOG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(18) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_MISC_CONF_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(22) | OCOTP_WIDTH(1)) - -/* 0 <= n <= 1 */ -#define IMX6_OCOTP_UNIQUE_ID(n) (OCOTP_WORD(0x410 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) #define IMX6_OCOTP_SI_REV (OCOTP_WORD(0x430) | OCOTP_BIT(16) | OCOTP_WIDTH(4)) -#define IMX6_OCOTP_NUM_CORES (OCOTP_WORD(0x430) | OCOTP_BIT(20) | OCOTP_WIDTH(2)) #define IMX6_OCOTP_SATA_RST_SRC (OCOTP_WORD(0x430) | OCOTP_BIT(24) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_MLB_DISABLE (OCOTP_WORD(0x430) | OCOTP_BIT(26) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_VPU_DISABLE (OCOTP_WORD(0x440) | OCOTP_BIT(15) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_SPEED_GRADING (OCOTP_WORD(0x440) | OCOTP_BIT(16) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_BOOT_CFG1 (OCOTP_WORD(0x450) | OCOTP_BIT(0) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_BOOT_CFG2 (OCOTP_WORD(0x450) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_BOOT_CFG3 (OCOTP_WORD(0x450) | OCOTP_BIT(16) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_BOOT_CFG4 (OCOTP_WORD(0x450) | OCOTP_BIT(24) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_SEC_CONFIG (OCOTP_WORD(0x460) | OCOTP_BIT(1) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_DIR_BT_DIS (OCOTP_WORD(0x460) | OCOTP_BIT(3) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_BT_FUSE_SEL (OCOTP_WORD(0x460) | OCOTP_BIT(4) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_DDR3_CONFIG (OCOTP_WORD(0x460) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) #define IMX6_OCOTP_HDCP (OCOTP_WORD(0x460) | OCOTP_BIT(16) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_SJC_DISABLE (OCOTP_WORD(0x460) | OCOTP_BIT(20) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_WDOG_ENABLE (OCOTP_WORD(0x460) | OCOTP_BIT(21) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_JTAG_SMODE (OCOTP_WORD(0x460) | OCOTP_BIT(22) | OCOTP_WIDTH(2)) -#define IMX6_OCOTP_KTE (OCOTP_WORD(0x460) | OCOTP_BIT(26) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_JTAG_HEO (OCOTP_WORD(0x460) | OCOTP_BIT(27) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_TZASC_ENABLE (OCOTP_WORD(0x460) | OCOTP_BIT(28) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_SDMMC_HYS_EN (OCOTP_WORD(0x460) | OCOTP_BIT(29) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_eMMC_RESET_EN (OCOTP_WORD(0x460) | OCOTP_BIT(30) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_NAND_READ_CMD_CODE1 (OCOTP_WORD(0x470) | OCOTP_BIT(0) | OCOTP_WIDTH(8)) -#define IMX6_OCOTP_NAND_READ_CMD_CODE2 (OCOTP_WORD(0x470) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) #define IMX6_OCOTP_BT_LPB_POLARITY (OCOTP_WORD(0x470) | OCOTP_BIT(20) | OCOTP_WIDTH(1)) #define IMX6_OCOTP_LPB_BOOT (OCOTP_WORD(0x470) | OCOTP_BIT(21) | OCOTP_WIDTH(2)) #define IMX6_OCOTP_MMC_DLL_DLY (OCOTP_WORD(0x470) | OCOTP_BIT(24) | OCOTP_WIDTH(7)) #define IMX6_OCOTP_TEMPERATURE_GRADE (OCOTP_WORD(0x480) | OCOTP_BIT(6) | OCOTP_WIDTH(2)) #define IMX6_OCOTP_POWER_GATE_CORES (OCOTP_WORD(0x4d0) | OCOTP_BIT(31) | OCOTP_WIDTH(1)) -#define IMX6_OCOTP_USB_VID (OCOTP_WORD(0x4f0) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) -#define IMX6_OCOTP_USB_PID (OCOTP_WORD(0x4f0) | OCOTP_BIT(16) | OCOTP_WIDTH(16)) -/* 0 <= n <= 7 */ -#define IMX6_OCOTP_SRK_HASH(n) (OCOTP_WORD(0x580 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_SJC_RESP_31_0 (OCOTP_WORD(0x600) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_SJC_RESP_55_32 (OCOTP_WORD(0x610) | OCOTP_BIT(0) | OCOTP_WIDTH(24)) -#define IMX6_OCOTP_MAC_ADDR_31_0 (OCOTP_WORD(0x620) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_MAC_ADDR_47_32 (OCOTP_WORD(0x630) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) -#define IMX6_OCOTP_GP1 (OCOTP_WORD(0x660) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_GP2 (OCOTP_WORD(0x670) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) -#define IMX6_OCOTP_PAD_SETTINGS (OCOTP_WORD(0x6d0) | OCOTP_BIT(0) | OCOTP_WIDTH(6)) #define IMX6DQ_OCOTP_TEST_PORT_DISABLE (OCOTP_WORD(0x6e0) | OCOTP_BIT(1) | OCOTP_WIDTH(1)) #define IMX6SDL_OCOTP_FIELD_RETURN (OCOTP_WORD(0x6e0) | OCOTP_BIT(0) | OCOTP_WIDTH(1)) diff --git a/arch/arm/mach-imx/include/mach/imx6.h b/arch/arm/mach-imx/include/mach/imx6.h index 8c169f15d6..327676bc69 100644 --- a/arch/arm/mach-imx/include/mach/imx6.h +++ b/arch/arm/mach-imx/include/mach/imx6.h @@ -9,7 +9,9 @@ void imx6_init_lowlevel(void); #define IMX6_ANATOP_SI_REV 0x260 +#define IMX6SL_ANATOP_SI_REV 0x280 +#define IMX6_CPUTYPE_IMX6SL 0x160 #define IMX6_CPUTYPE_IMX6S 0x161 #define IMX6_CPUTYPE_IMX6DL 0x261 #define IMX6_CPUTYPE_IMX6SX 0x462 @@ -36,6 +38,16 @@ static inline int __imx6_cpu_type(void) val = readl(MX6_ANATOP_BASE_ADDR + IMX6_ANATOP_SI_REV); val = (val >> 16) & 0xff; + /* non-MX6-standard SI_REV reg offset for MX6SL */ + if (IS_ENABLED(CONFIG_ARCH_IMX6SL) && + val < (IMX6_CPUTYPE_IMX6S & 0xff)) { + uint32_t tmp; + tmp = readl(MX6_ANATOP_BASE_ADDR + IMX6SL_ANATOP_SI_REV); + tmp = (tmp >> 16) & 0xff; + if ((IMX6_CPUTYPE_IMX6SL & 0xff) == tmp) + /* intentionally skip scu_get_core_count() for MX6SL */ + return IMX6_CPUTYPE_IMX6SL; + } val |= scu_get_core_count() << 8; @@ -50,12 +62,37 @@ static inline int imx6_cpu_type(void) return __imx6_cpu_type(); } +#define DEFINE_MX6_CPU_TYPE(str, type) \ + static inline int cpu_mx6_is_##str(void) \ + { \ + return __imx6_cpu_type() == type; \ + } \ + \ + static inline int cpu_is_##str(void) \ + { \ + if (!cpu_is_mx6()) \ + return 0; \ + return cpu_mx6_is_##str(); \ + } + +DEFINE_MX6_CPU_TYPE(mx6s, IMX6_CPUTYPE_IMX6S); +DEFINE_MX6_CPU_TYPE(mx6dl, IMX6_CPUTYPE_IMX6DL); +DEFINE_MX6_CPU_TYPE(mx6q, IMX6_CPUTYPE_IMX6Q); +DEFINE_MX6_CPU_TYPE(mx6d, IMX6_CPUTYPE_IMX6D); +DEFINE_MX6_CPU_TYPE(mx6sx, IMX6_CPUTYPE_IMX6SX); +DEFINE_MX6_CPU_TYPE(mx6sl, IMX6_CPUTYPE_IMX6SL); +DEFINE_MX6_CPU_TYPE(mx6ul, IMX6_CPUTYPE_IMX6UL); + static inline int __imx6_cpu_revision(void) { uint32_t rev; + uint32_t si_rev_offset = IMX6_ANATOP_SI_REV; - rev = readl(MX6_ANATOP_BASE_ADDR + IMX6_ANATOP_SI_REV); + if (IS_ENABLED(CONFIG_ARCH_IMX6SL) && cpu_mx6_is_mx6sl()) + si_rev_offset = IMX6SL_ANATOP_SI_REV; + + rev = readl(MX6_ANATOP_BASE_ADDR + si_rev_offset); switch (rev & 0xfff) { case 0x00: @@ -85,24 +122,4 @@ static inline int imx6_cpu_revision(void) return __imx6_cpu_revision(); } -#define DEFINE_MX6_CPU_TYPE(str, type) \ - static inline int cpu_mx6_is_##str(void) \ - { \ - return __imx6_cpu_type() == type; \ - } \ - \ - static inline int cpu_is_##str(void) \ - { \ - if (!cpu_is_mx6()) \ - return 0; \ - return cpu_mx6_is_##str(); \ - } - -DEFINE_MX6_CPU_TYPE(mx6s, IMX6_CPUTYPE_IMX6S); -DEFINE_MX6_CPU_TYPE(mx6dl, IMX6_CPUTYPE_IMX6DL); -DEFINE_MX6_CPU_TYPE(mx6q, IMX6_CPUTYPE_IMX6Q); -DEFINE_MX6_CPU_TYPE(mx6d, IMX6_CPUTYPE_IMX6D); -DEFINE_MX6_CPU_TYPE(mx6sx, IMX6_CPUTYPE_IMX6SX); -DEFINE_MX6_CPU_TYPE(mx6ul, IMX6_CPUTYPE_IMX6UL); - #endif /* __MACH_IMX6_H */ diff --git a/arch/arm/mach-imx/include/mach/imx7-regs.h b/arch/arm/mach-imx/include/mach/imx7-regs.h new file mode 100644 index 0000000000..8774c32d73 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/imx7-regs.h @@ -0,0 +1,119 @@ +#ifndef __MACH_IMX7_REGS_H +#define __MACH_IMX7_REGS_H + +/* Defines for Blocks connected via AIPS */ +#define MX7_AIPS1_BASE_ADDR 0x30000000 +#define MX7_AIPS2_BASE_ADDR 0x30400000 +#define MX7_AIPS3_BASE_ADDR 0x30800000 + +/* ATZ#1- On Platform */ +#define MX7_DAP_BASE_ADDR (MX7_AIPS1_BASE_ADDR) +#define MX7_AIPS1_CONFIG_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x1F0000) + +/* ATZ#1- Off Platform */ +#define MX7_GPIO1_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x200000) +#define MX7_GPIO2_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x210000) +#define MX7_GPIO3_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x220000) +#define MX7_GPIO4_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x230000) +#define MX7_GPIO5_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x240000) +#define MX7_GPIO6_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x250000) +#define MX7_GPIO7_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x260000) +#define MX7_IOMUXC_LPSR_GPR_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x270000) +#define MX7_WDOG1_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x280000) +#define MX7_WDOG2_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x290000) +#define MX7_WDOG3_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2A0000) +#define MX7_WDOG4_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2B0000) +#define MX7_IOMUXC_LPSR_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2C0000) +#define MX7_GPT1_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2D0000) +#define MX7_GPT2_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2E0000) +#define MX7_GPT3_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x2F0000) +#define MX7_GPT4_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x300000) +#define MX7_ROMCP_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x310000) +#define MX7_KPP_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x320000) +#define MX7_IOMUXC_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x330000) +#define MX7_IOMUXC_GPR_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x340000) +#define MX7_OCOTP_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x350000) +#define MX7_ANATOP_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x360000) +#define MX7_SNVS_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x370000) +#define MX7_CCM_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x380000) +#define MX7_SRC_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x390000) +#define MX7_GPC_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3A0000) +#define MX7_SEMAPHORE1_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3B0000) +#define MX7_SEMAPHORE2_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3C0000) +#define MX7_RDC_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3D0000) +#define MX7_CSU_BASE_ADDR (MX7_AIPS1_BASE_ADDR + 0x3E0000) + +/* ATZ#2- On Platform */ +#define MX7_AIPS2_CONFIG_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x1F0000) + +/* ATZ#2- Off Platform */ +#define MX7_ADC1_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x230000) +#define MX7_ADC2_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x230000) +#define MX7_ECSPI4_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x230000) +#define MX7_FTM1_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x240000) +#define MX7_FTM2_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x250000) +#define MX7_PWM1_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x260000) +#define MX7_PWM2_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x270000) +#define MX7_PWM3_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x280000) +#define MX7_PWM4_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x290000) +#define MX7_SYSCNT_RD_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2A0000) +#define MX7_SYSCNT_CMP_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2B0000) +#define MX7_SYSCNT_CTRL_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2C0000) +#define MX7_PCIE_PHY_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2D0000) +#define MX7_EPDC_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x2F0000) +#define MX7_PXP_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x300000) +#define MX7_CSI_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x310000) +#define MX7_LCDIF_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x330000) +#define MX7_MIPI_CSI_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x350000) +#define MX7_MIPI_DSI_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x360000) +#define MX7_TZASC_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x380000) +#define MX7_DDRPHY_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x390000) +#define MX7_DDRC_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x3A0000) +#define MX7_IP2APB_PERFMON1_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x3C0000) +#define MX7_IP2APB_PERFMON2_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x3D0000) +#define MX7_AXI_DEBUG_MON_BASE_ADDR (MX7_AIPS2_BASE_ADDR + 0x3E0000) + +/* ATZ#3- On Platform */ +#define MX7_ECSPI1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x20000) +#define MX7_ECSPI2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x30000) +#define MX7_ECSPI3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x40000) +#define MX7_UART1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x60000) +#define MX7_UART2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x70000) +#define MX7_UART3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x80000) +#define MX7_SAI1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0xA0000) +#define MX7_SAI2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0xB0000) +#define MX7_SAI3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0xC0000) +#define MX7_SPBA_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x90000) +#define MX7_CAAM_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x100000) +#define MX7_AIPS3_CONFIG_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x1F0000) + +/* ATZ#3- Off Platform */ +#define MX7_CAN1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x200000) +#define MX7_CAN2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x210000) +#define MX7_I2C1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x220000) +#define MX7_I2C2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x230000) +#define MX7_I2C3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x240000) +#define MX7_I2C4_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x250000) +#define MX7_UART4_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x260000) +#define MX7_UART5_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x270000) +#define MX7_UART6_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x280000) +#define MX7_UART7_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x290000) +#define MX7_MU_A_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x2A0000) +#define MX7_MU_B_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x2B0000) +#define MX7_SEM_HS_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x2C0000) +#define MX7_USBOH2_PL301_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x2D0000) +#define MX7_OTG1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x310000) +#define MX7_OTG2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x320000) +#define MX7_USBOH3_USB_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x330000) +#define MX7_USDHC1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x340000) +#define MX7_USDHC2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x350000) +#define MX7_USDHC3_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x360000) +#define MX7_SIM1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x390000) +#define MX7_SIM2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3A0000) +#define MX7_QSPI_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3B0000) +#define MX7_WEIM_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3C0000) +#define MX7_SDMA_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3D0000) +#define MX7_ENET1_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3E0000) +#define MX7_ENET2_BASE_ADDR (MX7_AIPS3_BASE_ADDR + 0x3F0000) + +#endif /* __MACH_IMX7_REGS_H */ diff --git a/arch/arm/mach-imx/include/mach/imx7.h b/arch/arm/mach-imx/include/mach/imx7.h new file mode 100644 index 0000000000..8518935468 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/imx7.h @@ -0,0 +1,59 @@ +#ifndef __MACH_IMX7_H +#define __MACH_IMX7_H + +#include <io.h> +#include <mach/generic.h> +#include <mach/imx7-regs.h> +#include <mach/revision.h> + +void imx7_init_lowlevel(void); + +#define ANADIG_DIGPROG_IMX7 0x800 + +#define IMX7_CPUTYPE_IMX7S 0x71 +#define IMX7_CPUTYPE_IMX7D 0x72 + +static inline int __imx7_cpu_type(void) +{ + void __iomem *ocotp = IOMEM(MX7_OCOTP_BASE_ADDR); + + if (readl(ocotp + 0x450) & 1) + return IMX7_CPUTYPE_IMX7S; + else + return IMX7_CPUTYPE_IMX7D; +} + +static inline int imx7_cpu_type(void) +{ + if (!cpu_is_mx7()) + return 0; + + return __imx7_cpu_type(); +} + +static inline int imx7_cpu_revision(void) +{ + if (!cpu_is_mx7()) + return IMX_CHIP_REV_UNKNOWN; + + /* register value has the format of the IMX_CHIP_REV_* macros */ + return readl(MX7_ANATOP_BASE_ADDR + ANADIG_DIGPROG_IMX7) & 0xff; +} + +#define DEFINE_MX7_CPU_TYPE(str, type) \ + static inline int cpu_mx7_is_##str(void) \ + { \ + return __imx7_cpu_type() == type; \ + } \ + \ + static inline int cpu_is_##str(void) \ + { \ + if (!cpu_is_mx7()) \ + return 0; \ + return cpu_mx7_is_##str(); \ + } + +DEFINE_MX7_CPU_TYPE(mx7s, IMX7_CPUTYPE_IMX7S); +DEFINE_MX7_CPU_TYPE(mx7d, IMX7_CPUTYPE_IMX7D); + +#endif /* __MACH_IMX7_H */
\ No newline at end of file diff --git a/arch/arm/mach-imx/include/mach/imx_cpu_types.h b/arch/arm/mach-imx/include/mach/imx_cpu_types.h index 50be0b6b5e..f95ef6f135 100644 --- a/arch/arm/mach-imx/include/mach/imx_cpu_types.h +++ b/arch/arm/mach-imx/include/mach/imx_cpu_types.h @@ -11,6 +11,7 @@ #define IMX_CPU_IMX51 51 #define IMX_CPU_IMX53 53 #define IMX_CPU_IMX6 6 +#define IMX_CPU_IMX7 7 #define IMX_CPU_VF610 610 #endif /* __MACH_IMX_CPU_TYPES_H */ diff --git a/arch/arm/mach-imx/include/mach/iomux-v3.h b/arch/arm/mach-imx/include/mach/iomux-v3.h index b8cc9af68a..271fe94a00 100644 --- a/arch/arm/mach-imx/include/mach/iomux-v3.h +++ b/arch/arm/mach-imx/include/mach/iomux-v3.h @@ -16,6 +16,8 @@ #ifndef __MACH_IOMUX_V3_H__ #define __MACH_IOMUX_V3_H__ +#include <io.h> + /* * build IOMUX_PAD structure * @@ -76,6 +78,14 @@ typedef u64 iomux_v3_cfg_t; ((iomux_v3_cfg_t)(_sel_input_ofs) << MUX_SEL_INPUT_OFS_SHIFT) | \ ((iomux_v3_cfg_t)(_sel_input) << MUX_SEL_INPUT_SHIFT)) +#define IOMUX_PAD_FIELD(name, pad) (((pad) & name##_MASK) >> name##_SHIFT) +#define IOMUX_CTRL_OFS(pad) IOMUX_PAD_FIELD(MUX_CTRL_OFS, pad) +#define IOMUX_MODE(pad) IOMUX_PAD_FIELD(MUX_MODE, pad) +#define IOMUX_SEL_INPUT_OFS(pad) IOMUX_PAD_FIELD(MUX_SEL_INPUT_OFS, pad) +#define IOMUX_SEL_INPUT(pad) IOMUX_PAD_FIELD(MUX_SEL_INPUT, pad) +#define IOMUX_PAD_CTRL_OFS(pad) IOMUX_PAD_FIELD(MUX_PAD_CTRL_OFS, pad) +#define IOMUX_PAD_CTRL(pad) IOMUX_PAD_FIELD(MUX_PAD_CTRL, pad) + #define NEW_PAD_CTRL(cfg, pad) (((cfg) & ~MUX_PAD_CTRL_MASK) | MUX_PAD_CTRL(pad)) /* * Use to set PAD control @@ -104,6 +114,57 @@ typedef u64 iomux_v3_cfg_t; #define IOMUX_CONFIG_SION (0x1 << 4) +#define SHARE_MUX_CONF_REG 0x1 +#define ZERO_OFFSET_VALID 0x2 +#define IMX7_PINMUX_LPSR 0x4 + +static inline void iomux_v3_setup_pad(void __iomem *iomux, unsigned int flags, + u32 mux_reg, u32 conf_reg, u32 input_reg, + u32 mux_val, u32 conf_val, u32 input_val) +{ + const bool mux_ok = !!mux_reg || (flags & ZERO_OFFSET_VALID); + const bool conf_ok = !!conf_reg; + const bool input_ok = !!input_reg; + + /* + * The sel_input registers for the LPSR controller pins are in the regular pinmux + * controller, so bend the register offset over to the other controller. + */ + if (flags & IMX7_PINMUX_LPSR) + input_reg += 0x70000; + + if (flags & SHARE_MUX_CONF_REG) { + mux_val |= conf_val; + } else { + if (conf_ok) + writel(conf_val, iomux + conf_reg); + } + + if (mux_ok) + writel(mux_val, iomux + mux_reg); + + if (input_ok) + writel(input_val, iomux + input_reg); +} + +static inline void imx_setup_pad(void __iomem *iomux, iomux_v3_cfg_t pad) +{ + uint32_t pad_ctrl; + + pad_ctrl = IOMUX_PAD_CTRL(pad); + pad_ctrl = (pad_ctrl & NO_PAD_CTRL) ? 0 : pad_ctrl, + + iomux_v3_setup_pad(iomux, 0, + IOMUX_CTRL_OFS(pad), + IOMUX_PAD_CTRL_OFS(pad), + IOMUX_SEL_INPUT_OFS(pad), + IOMUX_MODE(pad), + pad_ctrl, + IOMUX_SEL_INPUT(pad)); +} + + + /* * setups a single pad in the iomuxer */ diff --git a/arch/arm/mach-imx/include/mach/iomux-vf610.h b/arch/arm/mach-imx/include/mach/iomux-vf610.h index 15356282f2..b9e509b396 100644 --- a/arch/arm/mach-imx/include/mach/iomux-vf610.h +++ b/arch/arm/mach-imx/include/mach/iomux-vf610.h @@ -163,9 +163,13 @@ enum { VF610_PAD_PTD22__NF_IO6 = IOMUX_PAD(0x0120, 0x0120, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), VF610_PAD_PTD21__NF_IO5 = IOMUX_PAD(0x0124, 0x0124, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), VF610_PAD_PTD20__NF_IO4 = IOMUX_PAD(0x0128, 0x0128, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), + VF610_PAD_PTD19__GPIO_75 = IOMUX_PAD(0x012C, 0x012C, 0, __NA_, 0, VF610_GPIO_PAD_CTRL), VF610_PAD_PTD19__NF_IO3 = IOMUX_PAD(0x012c, 0x012c, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), + VF610_PAD_PTD18__GPIO_76 = IOMUX_PAD(0x0120, 0x0130, 0, __NA_, 0, VF610_GPIO_PAD_CTRL), VF610_PAD_PTD18__NF_IO2 = IOMUX_PAD(0x0130, 0x0130, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), + VF610_PAD_PTD17__GPIO_77 = IOMUX_PAD(0x0134, 0x0134, 0, __NA_, 0, VF610_GPIO_PAD_CTRL), VF610_PAD_PTD17__NF_IO1 = IOMUX_PAD(0x0134, 0x0134, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), + VF610_PAD_PTD16__GPIO_78 = IOMUX_PAD(0x0138, 0x0138, 0, __NA_, 0, VF610_GPIO_PAD_CTRL), VF610_PAD_PTD16__NF_IO0 = IOMUX_PAD(0x0138, 0x0138, 2, __NA_, 0, VF610_NFC_IO_PAD_CTRL), VF610_PAD_PTB24__NF_WE_B = IOMUX_PAD(0x0178, 0x0178, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL), VF610_PAD_PTB25__NF_CE0_B = IOMUX_PAD(0x017c, 0x017c, 5, __NA_, 0, VF610_NFC_CN_PAD_CTRL), @@ -223,4 +227,19 @@ enum { VF610_PAD_DDR_ODT0__DDR_ODT_1 = IOMUX_PAD(0x02d8, 0x02d8, 0, __NA_, 0, VF610_DDR_PAD_CTRL), }; +#define PINCTRL_VF610_MUX_SHIFT 20 + + +static inline void vf610_setup_pad(void __iomem *iomux, iomux_v3_cfg_t pad) +{ + iomux_v3_setup_pad(iomux, SHARE_MUX_CONF_REG | ZERO_OFFSET_VALID, + IOMUX_CTRL_OFS(pad), + IOMUX_PAD_CTRL_OFS(pad), + IOMUX_SEL_INPUT_OFS(pad), + IOMUX_MODE(pad) << PINCTRL_VF610_MUX_SHIFT, + IOMUX_PAD_CTRL(pad), + IOMUX_SEL_INPUT(pad)); +} + + #endif /* __IOMUX_VF610_H__ */ diff --git a/arch/arm/mach-imx/include/mach/ocotp-fusemap.h b/arch/arm/mach-imx/include/mach/ocotp-fusemap.h new file mode 100644 index 0000000000..44b58ca6e8 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/ocotp-fusemap.h @@ -0,0 +1,49 @@ +#ifndef __MACH_IMX_OCOTP_FUSEMAP_H +#define __MACH_IMX_OCOTP_FUSEMAP_H + +#include <mach/ocotp.h> + +#define OCOTP_TESTER_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(0) | OCOTP_WIDTH(2)) +#define OCOTP_BOOT_CFG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(2) | OCOTP_WIDTH(2)) +#define OCOTP_MEM_TRIM_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(4) | OCOTP_WIDTH(2)) +#define OCOTP_SJC_RESP_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(6) | OCOTP_WIDTH(1)) +#define OCOTP_MAC_ADDR_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(8) | OCOTP_WIDTH(2)) +#define OCOTP_GP1_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(10) | OCOTP_WIDTH(2)) +#define OCOTP_GP2_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(12) | OCOTP_WIDTH(2)) +#define OCOTP_SRK_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(14) | OCOTP_WIDTH(1)) +#define OCOTP_ANALOG_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(18) | OCOTP_WIDTH(2)) +#define OCOTP_MISC_CONF_LOCK (OCOTP_WORD(0x400) | OCOTP_BIT(22) | OCOTP_WIDTH(1)) + +/* 0 <= n <= 1 */ +#define OCOTP_UNIQUE_ID(n) (OCOTP_WORD(0x410 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_NUM_CORES (OCOTP_WORD(0x430) | OCOTP_BIT(20) | OCOTP_WIDTH(2)) +#define OCOTP_MLB_DISABLE (OCOTP_WORD(0x430) | OCOTP_BIT(26) | OCOTP_WIDTH(1)) + +#define OCOTP_BOOT_CFG1 (OCOTP_WORD(0x450) | OCOTP_BIT(0) | OCOTP_WIDTH(8)) +#define OCOTP_BOOT_CFG2 (OCOTP_WORD(0x450) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) +#define OCOTP_BOOT_CFG3 (OCOTP_WORD(0x450) | OCOTP_BIT(16) | OCOTP_WIDTH(8)) +#define OCOTP_BOOT_CFG4 (OCOTP_WORD(0x450) | OCOTP_BIT(24) | OCOTP_WIDTH(8)) +#define OCOTP_SEC_CONFIG_1 (OCOTP_WORD(0x460) | OCOTP_BIT(1) | OCOTP_WIDTH(1)) +#define OCOTP_DIR_BT_DIS (OCOTP_WORD(0x460) | OCOTP_BIT(3) | OCOTP_WIDTH(1)) +#define OCOTP_BT_FUSE_SEL (OCOTP_WORD(0x460) | OCOTP_BIT(4) | OCOTP_WIDTH(1)) +#define OCOTP_SJC_DISABLE (OCOTP_WORD(0x460) | OCOTP_BIT(20) | OCOTP_WIDTH(1)) +#define OCOTP_WDOG_ENABLE (OCOTP_WORD(0x460) | OCOTP_BIT(21) | OCOTP_WIDTH(1)) +#define OCOTP_JTAG_SMODE (OCOTP_WORD(0x460) | OCOTP_BIT(22) | OCOTP_WIDTH(2)) +#define OCOTP_KTE (OCOTP_WORD(0x460) | OCOTP_BIT(26) | OCOTP_WIDTH(1)) +#define OCOTP_JTAG_HEO (OCOTP_WORD(0x460) | OCOTP_BIT(27) | OCOTP_WIDTH(1)) +#define OCOTP_NAND_READ_CMD_CODE1 (OCOTP_WORD(0x470) | OCOTP_BIT(0) | OCOTP_WIDTH(8)) +#define OCOTP_NAND_READ_CMD_CODE2 (OCOTP_WORD(0x470) | OCOTP_BIT(8) | OCOTP_WIDTH(8)) +#define OCOTP_TEMP_SENSE (OCOTP_WORD(0x4e0) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_USB_VID (OCOTP_WORD(0x4f0) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) +#define OCOTP_USB_PID (OCOTP_WORD(0x4f0) | OCOTP_BIT(16) | OCOTP_WIDTH(16)) +/* 0 <= n <= 7 */ +#define OCOTP_SRK_HASH(n) (OCOTP_WORD(0x580 + 0x10 * (n)) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_SJC_RESP_31_0 (OCOTP_WORD(0x600) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_SJC_RESP_55_32 (OCOTP_WORD(0x610) | OCOTP_BIT(0) | OCOTP_WIDTH(24)) +#define OCOTP_MAC_ADDR_31_0 (OCOTP_WORD(0x620) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_MAC_ADDR_47_32 (OCOTP_WORD(0x630) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) +#define OCOTP_GP1 (OCOTP_WORD(0x660) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_GP2 (OCOTP_WORD(0x670) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define OCOTP_PAD_SETTINGS (OCOTP_WORD(0x6d0) | OCOTP_BIT(0) | OCOTP_WIDTH(6)) + +#endif /* __MACH_IMX_OCOTP_FUSEMAP_H */ diff --git a/arch/arm/mach-imx/include/mach/ocotp.h b/arch/arm/mach-imx/include/mach/ocotp.h index 430bc756be..5474c27ede 100644 --- a/arch/arm/mach-imx/include/mach/ocotp.h +++ b/arch/arm/mach-imx/include/mach/ocotp.h @@ -16,5 +16,6 @@ int imx_ocotp_read_field(uint32_t field, unsigned *value); int imx_ocotp_write_field(uint32_t field, unsigned value); int imx_ocotp_permanent_write(int enable); +bool imx_ocotp_sense_enable(bool enable); #endif /* __MACH_IMX_OCOTP_H */ diff --git a/arch/arm/mach-imx/include/mach/vf610-fusemap.h b/arch/arm/mach-imx/include/mach/vf610-fusemap.h new file mode 100644 index 0000000000..a56faf10cc --- /dev/null +++ b/arch/arm/mach-imx/include/mach/vf610-fusemap.h @@ -0,0 +1,15 @@ +#ifndef __MACH_VF610_OCOTP_H +#define __MACH_VF610_OCOTP_H + +#include <mach/ocotp-fusemap.h> + +#define VF610_OCOTP_CPU_BUS_FRQ OCOTP_WORD(0x430) | OCOTP_BIT(22) | OCOTP_WIDTH(1) +#define VF610_OCOTP_OVG_DISABLE OCOTP_WORD(0x430) | OCOTP_BIT(30) | OCOTP_WIDTH(1) +#define VF610_OCOTP_SEC_CONFIG_0 OCOTP_WORD(0x440) | OCOTP_BIT(1) | OCOTP_WIDTH(1) +#define VF610_OCOTP_SPEED_GRADING OCOTP_WORD(0x440) | OCOTP_BIT(18) | OCOTP_WIDTH(4) +#define VF610_OCOTP_MAC_ADDR0_31_0 OCOTP_MAC_ADDR_31_0 +#define VF610_OCOTP_MAC_ADDR0_47_32 OCOTP_MAC_ADDR_47_32 +#define VF610_OCOTP_MAC_ADDR1_31_0 (OCOTP_WORD(0x640) | OCOTP_BIT(0) | OCOTP_WIDTH(32)) +#define VF610_OCOTP_MAC_ADDR1_47_32 (OCOTP_WORD(0x650) | OCOTP_BIT(0) | OCOTP_WIDTH(16)) + +#endif diff --git a/arch/arm/mach-imx/ocotp.c b/arch/arm/mach-imx/ocotp.c index 68ff0ce28b..99b365aad8 100644 --- a/arch/arm/mach-imx/ocotp.c +++ b/arch/arm/mach-imx/ocotp.c @@ -69,12 +69,22 @@ /* Other definitions */ #define IMX6_OTP_DATA_ERROR_VAL 0xBADABADA #define DEF_RELAX 20 -#define MAC_OFFSET (0x22 * 4) +#define MAC_OFFSET_0 (0x22 * 4) +#define MAC_OFFSET_1 (0x24 * 4) +#define MAX_MAC_OFFSETS 2 #define MAC_BYTES 8 struct imx_ocotp_data { int num_regs; u32 (*addr_to_offset)(u32 addr); + u8 mac_offsets[MAX_MAC_OFFSETS]; + u8 mac_offsets_num; +}; + +struct ocotp_priv_ethaddr { + char value[MAC_BYTES]; + struct regmap *map; + u8 offset; }; struct ocotp_priv { @@ -84,9 +94,10 @@ struct ocotp_priv { struct device_d dev; int permanent_write_enable; int sense_enable; - char ethaddr[6]; + struct ocotp_priv_ethaddr ethaddr[MAX_MAC_OFFSETS]; struct regmap_config map_config; const struct imx_ocotp_data *data; + int mac_offset_idx; }; static struct ocotp_priv *imx_ocotp; @@ -348,6 +359,13 @@ int imx_ocotp_permanent_write(int enable) return 0; } +bool imx_ocotp_sense_enable(bool enable) +{ + const bool old_value = imx_ocotp->sense_enable; + imx_ocotp->sense_enable = enable; + return old_value; +} + static uint32_t inc_offset(uint32_t offset) { if ((offset & 0x3) == 0x3) @@ -397,37 +415,39 @@ static void imx_ocotp_init_dt(struct device_d *dev, void __iomem *base) } } +static void memreverse(void *dest, const void *src, size_t n) +{ + char *destp = dest; + const char *srcp = src + n - 1; + + while(n--) + *destp++ = *srcp--; +} + static int imx_ocotp_get_mac(struct param_d *param, void *priv) { - struct ocotp_priv *ocotp_priv = priv; - char buf[8]; - int i, ret; + char buf[MAC_BYTES]; + int ret; + struct ocotp_priv_ethaddr *ethaddr = priv; - ret = regmap_bulk_read(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES); + ret = regmap_bulk_read(ethaddr->map, ethaddr->offset, + buf, MAC_BYTES); if (ret < 0) return ret; - for (i = 0; i < 6; i++) - ocotp_priv->ethaddr[i] = buf[5 - i]; - + memreverse(ethaddr->value, buf, 6); return 0; } static int imx_ocotp_set_mac(struct param_d *param, void *priv) { - struct ocotp_priv *ocotp_priv = priv; - char buf[8]; - int i, ret; - - for (i = 0; i < 6; i++) - buf[5 - i] = ocotp_priv->ethaddr[i]; - buf[6] = 0; buf[7] = 0; + char buf[MAC_BYTES]; + struct ocotp_priv_ethaddr *ethaddr = priv; - ret = regmap_bulk_write(ocotp_priv->map, MAC_OFFSET, buf, MAC_BYTES); - if (ret < 0) - return ret; + memreverse(buf, ethaddr->value, 6); - return 0; + return regmap_bulk_write(ethaddr->map, ethaddr->offset, + buf, MAC_BYTES); } static struct regmap_bus imx_ocotp_regmap_bus = { @@ -486,9 +506,28 @@ static int imx_ocotp_probe(struct device_d *dev) NULL, NULL, &priv->permanent_write_enable, NULL); } - if (IS_ENABLED(CONFIG_NET)) - dev_add_param_mac(&(priv->dev), "mac_addr", imx_ocotp_set_mac, - imx_ocotp_get_mac, priv->ethaddr, priv); + if (IS_ENABLED(CONFIG_NET)) { + int i; + struct ocotp_priv_ethaddr *ethaddr; + + for (i = 0; i < priv->data->mac_offsets_num; i++) { + ethaddr = &priv->ethaddr[i]; + ethaddr->map = priv->map; + ethaddr->offset = priv->data->mac_offsets[i]; + + dev_add_param_mac(&priv->dev, xasprintf("mac_addr%d", i), + imx_ocotp_set_mac, imx_ocotp_get_mac, + ethaddr->value, ethaddr); + } + + /* + * Alias to mac_addr0 for backwards compatibility + */ + ethaddr = &priv->ethaddr[0]; + dev_add_param_mac(&priv->dev, "mac_addr", + imx_ocotp_set_mac, imx_ocotp_get_mac, + ethaddr->value, ethaddr); + } dev_add_param_bool(&(priv->dev), "sense_enable", NULL, NULL, &priv->sense_enable, priv); @@ -527,16 +566,22 @@ static u32 vf610_addr_to_offset(u32 addr) static struct imx_ocotp_data imx6q_ocotp_data = { .num_regs = 512, .addr_to_offset = imx6q_addr_to_offset, + .mac_offsets_num = 1, + .mac_offsets = { MAC_OFFSET_0 }, }; static struct imx_ocotp_data imx6sl_ocotp_data = { .num_regs = 256, .addr_to_offset = imx6sl_addr_to_offset, + .mac_offsets_num = 1, + .mac_offsets = { MAC_OFFSET_0 }, }; static struct imx_ocotp_data vf610_ocotp_data = { .num_regs = 512, .addr_to_offset = vf610_addr_to_offset, + .mac_offsets_num = 2, + .mac_offsets = { MAC_OFFSET_0, MAC_OFFSET_1 }, }; static __maybe_unused struct of_device_id imx_ocotp_dt_ids[] = { @@ -572,4 +617,4 @@ static int imx_ocotp_init(void) return 0; } -coredevice_initcall(imx_ocotp_init); +postcore_initcall(imx_ocotp_init); |