diff options
-rw-r--r-- | arch/arm/mach-imx/Makefile | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx.c | 52 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx51.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx53.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx6.c | 4 | ||||
-rw-r--r-- | arch/arm/mach-imx/imx7.c | 19 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/generic.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/reset-reason.h | 37 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/vf610-regs.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-imx/include/mach/vf610.h | 51 | ||||
-rw-r--r-- | arch/arm/mach-imx/vf610.c | 59 | ||||
-rw-r--r-- | common/reset_source.c | 23 | ||||
-rw-r--r-- | include/reset_source.h | 17 |
13 files changed, 276 insertions, 15 deletions
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile index 8ec846ccef..160ed4b084 100644 --- a/arch/arm/mach-imx/Makefile +++ b/arch/arm/mach-imx/Makefile @@ -15,6 +15,7 @@ obj-$(CONFIG_ARCH_IMX6) += imx6.o usb-imx6.o CFLAGS_imx6.o := -march=armv7-a lwl-$(CONFIG_ARCH_IMX6) += imx6-mmdc.o obj-$(CONFIG_ARCH_IMX7) += imx7.o +obj-$(CONFIG_ARCH_VF610) += vf610.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/imx.c b/arch/arm/mach-imx/imx.c index 9400105c66..1b4c1b3df1 100644 --- a/arch/arm/mach-imx/imx.c +++ b/arch/arm/mach-imx/imx.c @@ -14,8 +14,10 @@ #include <common.h> #include <of.h> #include <init.h> +#include <io.h> #include <mach/revision.h> #include <mach/generic.h> +#include <mach/reset-reason.h> static int __imx_silicon_revision = IMX_CHIP_REV_UNKNOWN; @@ -28,7 +30,10 @@ void imx_set_silicon_revision(const char *soc, int revision) { __imx_silicon_revision = revision; - pr_info("detected %s revision %d.%d\n", soc, + if (revision == IMX_CHIP_REV_UNKNOWN) + pr_info("detected %s revision unknown\n", soc); + else + pr_info("detected %s revision %d.%d\n", soc, (revision >> 4) & 0xf, revision & 0xf); } @@ -114,7 +119,7 @@ static int imx_init(void) else if (cpu_is_mx7()) ret = imx7_init(); else if (cpu_is_vf610()) - ret = 0; + ret = vf610_init(); else return -EINVAL; @@ -147,3 +152,46 @@ static int imx_init(void) return ret; } postcore_initcall(imx_init); + +const struct imx_reset_reason imx_reset_reasons[] = { + { IMX_SRC_SRSR_IPP_RESET, RESET_POR, 0 }, + { IMX_SRC_SRSR_WDOG1_RESET, RESET_WDG, 0 }, + { IMX_SRC_SRSR_JTAG_RESET, RESET_JTAG, 0 }, + { IMX_SRC_SRSR_JTAG_SW_RESET, RESET_JTAG, 0 }, + { IMX_SRC_SRSR_WARM_BOOT, RESET_RST, 0 }, + { /* sentinel */ } +}; + +void imx_set_reset_reason(void __iomem *srsr, + const struct imx_reset_reason *reasons) +{ + enum reset_src_type type = RESET_UKWN; + const u32 reg = readl(srsr); + int i, instance = 0; + + /* + * SRSR register captures ALL reset event that occured since + * POR, so we need to clear it to make sure we only caputre + * the latest one. + */ + writel(reg, srsr); + + for (i = 0; reasons[i].mask; i++) { + if (reg & reasons[i].mask) { + type = reasons[i].type; + instance = reasons[i].instance; + break; + } + } + + /* + * Report this with above default priority in order to make + * sure we'll always override info from watchdog driver. + */ + reset_source_set_priority(type, + RESET_SOURCE_DEFAULT_PRIORITY + 1); + reset_source_set_instance(type, instance); + + pr_info("i.MX reset reason %s (SRSR: 0x%08x)\n", + reset_source_name(), reg); +} diff --git a/arch/arm/mach-imx/imx51.c b/arch/arm/mach-imx/imx51.c index ffe6a7c651..ec8cdd868b 100644 --- a/arch/arm/mach-imx/imx51.c +++ b/arch/arm/mach-imx/imx51.c @@ -21,6 +21,7 @@ #include <mach/revision.h> #include <mach/clock-imx51_53.h> #include <mach/generic.h> +#include <mach/reset-reason.h> #define IIM_SREV 0x24 @@ -43,7 +44,7 @@ static int imx51_silicon_revision(void) static void imx51_ipu_mipi_setup(void) { - void __iomem *hsc_addr = (void __iomem *)MX51_MIPI_HSC_BASE_ADDR; + void __iomem *hsc_addr = IOMEM(MX51_MIPI_HSC_BASE_ADDR); u32 val; /* setup MIPI module to legacy mode */ @@ -57,7 +58,10 @@ static void imx51_ipu_mipi_setup(void) int imx51_init(void) { + void __iomem *src = IOMEM(MX51_SRC_BASE_ADDR); + imx_set_silicon_revision("i.MX51", imx51_silicon_revision()); + imx_set_reset_reason(src + IMX_SRC_SRSR, imx_reset_reasons); imx51_boot_save_loc(); add_generic_device("imx51-esdctl", 0, NULL, MX51_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); imx51_ipu_mipi_setup(); @@ -97,7 +101,7 @@ int imx51_devices_init(void) */ static void imx51_setup_pll800_bug(void) { - void __iomem *base = (void *)MX51_PLL1_BASE_ADDR; + void __iomem *base = IOMEM(MX51_PLL1_BASE_ADDR); u32 dp_config; volatile int i; @@ -132,7 +136,7 @@ static void imx51_setup_pll800_bug(void) void imx51_init_lowlevel(unsigned int cpufreq_mhz) { - void __iomem *ccm = (void __iomem *)MX51_CCM_BASE_ADDR; + void __iomem *ccm = IOMEM(MX51_CCM_BASE_ADDR); u32 r; int rev = imx51_silicon_revision(); @@ -167,30 +171,30 @@ void imx51_init_lowlevel(unsigned int cpufreq_mhz) switch (cpufreq_mhz) { case 600: - imx5_setup_pll_600((void __iomem *)MX51_PLL1_BASE_ADDR); + imx5_setup_pll_600(IOMEM(MX51_PLL1_BASE_ADDR)); break; default: /* Default maximum 800MHz */ if (rev <= IMX_CHIP_REV_3_0) imx51_setup_pll800_bug(); else - imx5_setup_pll_800((void __iomem *)MX51_PLL1_BASE_ADDR); + imx5_setup_pll_800(IOMEM(MX51_PLL1_BASE_ADDR)); break; } - imx5_setup_pll_665((void __iomem *)MX51_PLL3_BASE_ADDR); + imx5_setup_pll_665(IOMEM(MX51_PLL3_BASE_ADDR)); /* Switch peripheral to PLL 3 */ writel(0x000010C0, ccm + MX5_CCM_CBCMR); writel(0x13239145, ccm + MX5_CCM_CBCDR); - imx5_setup_pll_665((void __iomem *)MX51_PLL2_BASE_ADDR); + imx5_setup_pll_665(IOMEM(MX51_PLL2_BASE_ADDR)); /* Switch peripheral to PLL2 */ writel(0x19239145, ccm + MX5_CCM_CBCDR); writel(0x000020C0, ccm + MX5_CCM_CBCMR); - imx5_setup_pll_216((void __iomem *)MX51_PLL3_BASE_ADDR); + imx5_setup_pll_216(IOMEM(MX51_PLL3_BASE_ADDR)); /* Set the platform clock dividers */ writel(0x00000125, MX51_ARM_BASE_ADDR + 0x14); diff --git a/arch/arm/mach-imx/imx53.c b/arch/arm/mach-imx/imx53.c index 2758f1bbcf..56f1bda75e 100644 --- a/arch/arm/mach-imx/imx53.c +++ b/arch/arm/mach-imx/imx53.c @@ -21,6 +21,7 @@ #include <mach/revision.h> #include <mach/clock-imx51_53.h> #include <mach/generic.h> +#include <mach/reset-reason.h> #define SI_REV 0x48 @@ -52,7 +53,10 @@ static int imx53_silicon_revision(void) int imx53_init(void) { + void __iomem *src = IOMEM(MX53_SRC_BASE_ADDR); + imx53_silicon_revision(); + imx_set_reset_reason(src + IMX_SRC_SRSR, imx_reset_reasons); imx53_boot_save_loc(); add_generic_device("imx53-esdctl", 0, NULL, MX53_ESDCTL_BASE_ADDR, 0x1000, IORESOURCE_MEM, NULL); diff --git a/arch/arm/mach-imx/imx6.c b/arch/arm/mach-imx/imx6.c index 6c69c3604a..eaf9f2e413 100644 --- a/arch/arm/mach-imx/imx6.c +++ b/arch/arm/mach-imx/imx6.c @@ -20,6 +20,7 @@ #include <mach/imx6.h> #include <mach/generic.h> #include <mach/revision.h> +#include <mach/reset-reason.h> #include <mach/imx6-anadig.h> #include <mach/imx6-regs.h> #include <mach/generic.h> @@ -189,6 +190,7 @@ int imx6_init(void) { const char *cputypestr; u32 mx6_silicon_revision; + void __iomem *src = IOMEM(MX6_SRC_BASE_ADDR); imx6_init_lowlevel(); @@ -233,7 +235,7 @@ int imx6_init(void) } imx_set_silicon_revision(cputypestr, mx6_silicon_revision); - + imx_set_reset_reason(src + IMX_SRC_SRSR, imx_reset_reasons); imx6_setup_ipu_qos(); imx6ul_enet_clk_init(); diff --git a/arch/arm/mach-imx/imx7.c b/arch/arm/mach-imx/imx7.c index 4eef99c872..e49baf6f77 100644 --- a/arch/arm/mach-imx/imx7.c +++ b/arch/arm/mach-imx/imx7.c @@ -19,6 +19,7 @@ #include <mach/imx7.h> #include <mach/generic.h> #include <mach/revision.h> +#include <mach/reset-reason.h> #include <mach/imx7-regs.h> void imx7_init_lowlevel(void) @@ -167,10 +168,21 @@ static struct psci_ops imx7_psci_ops = { .cpu_off = imx7_cpu_off, }; +static const struct imx_reset_reason imx7_reset_reasons[] = { + { IMX_SRC_SRSR_IPP_RESET, RESET_POR, 0 }, + { IMX_SRC_SRSR_WDOG1_RESET, RESET_WDG, 0 }, + { IMX_SRC_SRSR_JTAG_RESET, RESET_JTAG, 0 }, + { IMX_SRC_SRSR_JTAG_SW_RESET, RESET_JTAG, 0 }, + { IMX_SRC_SRSR_WDOG3_RESET, RESET_WDG, 1 }, + { IMX_SRC_SRSR_WDOG4_RESET, RESET_WDG, 2 }, + { IMX_SRC_SRSR_TEMPSENSE_RESET, RESET_THERM, 0 }, + { /* sentinel */ } +}; + int imx7_init(void) { const char *cputypestr; - u32 imx7_silicon_revision; + void __iomem *src = IOMEM(MX7_SRC_BASE_ADDR); imx7_init_lowlevel(); @@ -180,8 +192,6 @@ int imx7_init(void) imx7_boot_save_loc(); - imx7_silicon_revision = imx7_cpu_revision(); - psci_set_ops(&imx7_psci_ops); switch (imx7_cpu_type()) { @@ -196,7 +206,8 @@ int imx7_init(void) break; } - imx_set_silicon_revision(cputypestr, imx7_silicon_revision); + imx_set_silicon_revision(cputypestr, imx7_cpu_revision()); + imx_set_reset_reason(src + IMX7_SRC_SRSR, imx7_reset_reasons); return 0; } diff --git a/arch/arm/mach-imx/include/mach/generic.h b/arch/arm/mach-imx/include/mach/generic.h index dedb4bbf06..ad9d9cb022 100644 --- a/arch/arm/mach-imx/include/mach/generic.h +++ b/arch/arm/mach-imx/include/mach/generic.h @@ -36,6 +36,7 @@ int imx51_init(void); int imx53_init(void); int imx6_init(void); int imx7_init(void); +int vf610_init(void); int imx1_devices_init(void); int imx21_devices_init(void); diff --git a/arch/arm/mach-imx/include/mach/reset-reason.h b/arch/arm/mach-imx/include/mach/reset-reason.h new file mode 100644 index 0000000000..0f644a8c1d --- /dev/null +++ b/arch/arm/mach-imx/include/mach/reset-reason.h @@ -0,0 +1,37 @@ +#ifndef __MACH_RESET_REASON_H__ +#define __MACH_RESET_REASON_H__ + +#include <reset_source.h> + +#define IMX_SRC_SRSR_IPP_RESET BIT(0) +#define IMX_SRC_SRSR_CSU_RESET BIT(2) +#define IMX_SRC_SRSR_IPP_USER_RESET BIT(3) +#define IMX_SRC_SRSR_WDOG1_RESET BIT(4) +#define IMX_SRC_SRSR_JTAG_RESET BIT(5) +#define IMX_SRC_SRSR_JTAG_SW_RESET BIT(6) +#define IMX_SRC_SRSR_WDOG3_RESET BIT(7) +#define IMX_SRC_SRSR_WDOG4_RESET BIT(8) +#define IMX_SRC_SRSR_TEMPSENSE_RESET BIT(9) +#define IMX_SRC_SRSR_WARM_BOOT BIT(16) + +#define IMX_SRC_SRSR 0x008 +#define IMX7_SRC_SRSR 0x05c + +#define VF610_SRC_SRSR_SW_RST BIT(18) +#define VF610_SRC_SRSR_RESETB BIT(7) +#define VF610_SRC_SRSR_JTAG_RST BIT(5) +#define VF610_SRC_SRSR_WDOG_M4 BIT(4) +#define VF610_SRC_SRSR_WDOG_A5 BIT(3) +#define VF610_SRC_SRSR_POR_RST BIT(0) + +struct imx_reset_reason { + uint32_t mask; + enum reset_src_type type; + int instance; +}; + +void imx_set_reset_reason(void __iomem *, const struct imx_reset_reason *); + +extern const struct imx_reset_reason imx_reset_reasons[]; + +#endif /* __MACH_RESET_REASON_H__ */ diff --git a/arch/arm/mach-imx/include/mach/vf610-regs.h b/arch/arm/mach-imx/include/mach/vf610-regs.h index 87772ee76d..416b457aff 100644 --- a/arch/arm/mach-imx/include/mach/vf610-regs.h +++ b/arch/arm/mach-imx/include/mach/vf610-regs.h @@ -109,4 +109,7 @@ #define VF610_MSCM_IRSPRC_CP0_EN 1 #define VF610_MSCM_IRSPRC_NUM 112 +#define VF610_MSCM_CPxCOUNT 0x00c +#define VF610_MSCM_CPxCFG1 0x014 + #endif diff --git a/arch/arm/mach-imx/include/mach/vf610.h b/arch/arm/mach-imx/include/mach/vf610.h new file mode 100644 index 0000000000..6d00d2e457 --- /dev/null +++ b/arch/arm/mach-imx/include/mach/vf610.h @@ -0,0 +1,51 @@ +#ifndef __MACH_VF610_H +#define __MACH_VF610_H + +#include <io.h> +#include <mach/generic.h> +#include <mach/vf610-regs.h> +#include <mach/revision.h> + +#define VF610_CPUTYPE_VFx10 0x010 + +#define VF610_CPUTYPE_VF610 0x610 +#define VF610_CPUTYPE_VF600 0x600 +#define VF610_CPUTYPE_VF510 0x510 +#define VF610_CPUTYPE_VF500 0x500 + +#define VF610_ROM_VERSION_OFFSET 0x80 + +static inline int __vf610_cpu_type(void) +{ + void __iomem *mscm = IOMEM(VF610_MSCM_BASE_ADDR); + const u32 cpxcount = readl(mscm + VF610_MSCM_CPxCOUNT); + const u32 cpxcfg1 = readl(mscm + VF610_MSCM_CPxCFG1); + int cpu_type; + + cpu_type = cpxcount ? VF610_CPUTYPE_VF600 : VF610_CPUTYPE_VF500; + + return cpxcfg1 ? cpu_type | VF610_CPUTYPE_VFx10 : cpu_type; +} + +static inline int vf610_cpu_type(void) +{ + if (!cpu_is_vf610()) + return 0; + + return __vf610_cpu_type(); +} + +static inline int vf610_cpu_revision(void) +{ + if (!cpu_is_vf610()) + return IMX_CHIP_REV_UNKNOWN; + + /* + * There doesn't seem to be a documented way of retreiving + * silicon revision on VFxxx cpus, so we just report Mask ROM + * version instead + */ + return readl(VF610_ROM_VERSION_OFFSET) & 0xff; +} + +#endif diff --git a/arch/arm/mach-imx/vf610.c b/arch/arm/mach-imx/vf610.c new file mode 100644 index 0000000000..c535716c10 --- /dev/null +++ b/arch/arm/mach-imx/vf610.c @@ -0,0 +1,59 @@ +/* + * 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 <mach/generic.h> +#include <mach/revision.h> +#include <mach/vf610.h> +#include <mach/reset-reason.h> + +static const struct imx_reset_reason vf610_reset_reasons[] = { + { VF610_SRC_SRSR_POR_RST, RESET_POR, 0 }, + { VF610_SRC_SRSR_WDOG_A5, RESET_WDG, 0 }, + { VF610_SRC_SRSR_WDOG_M4, RESET_WDG, 1 }, + { VF610_SRC_SRSR_JTAG_RST, RESET_JTAG, 0 }, + { VF610_SRC_SRSR_RESETB, RESET_EXT, 0 }, + { VF610_SRC_SRSR_SW_RST, RESET_RST, 0 }, + { /* sentinel */ } +}; + +int vf610_init(void) +{ + const char *cputypestr; + void __iomem *src = IOMEM(VF610_SRC_BASE_ADDR); + + switch (vf610_cpu_type()) { + case VF610_CPUTYPE_VF610: + cputypestr = "VF610"; + break; + case VF610_CPUTYPE_VF600: + cputypestr = "VF600"; + break; + case VF610_CPUTYPE_VF510: + cputypestr = "VF510"; + break; + case VF610_CPUTYPE_VF500: + cputypestr = "VF500"; + break; + default: + cputypestr = "unknown VFxxx"; + break; + } + + imx_set_silicon_revision(cputypestr, vf610_cpu_revision()); + imx_set_reset_reason(src + IMX_SRC_SRSR, vf610_reset_reasons); + return 0; +} diff --git a/common/reset_source.c b/common/reset_source.c index 06e2ca85f5..338d7b9acb 100644 --- a/common/reset_source.c +++ b/common/reset_source.c @@ -32,6 +32,7 @@ static const char * const reset_src_names[] = { static enum reset_src_type reset_source; static unsigned int reset_source_priority; +static int reset_source_instance; enum reset_src_type reset_source_get(void) { @@ -39,6 +40,12 @@ enum reset_src_type reset_source_get(void) } EXPORT_SYMBOL(reset_source_get); +int reset_source_get_instance(void) +{ + return reset_source_instance; +} +EXPORT_SYMBOL(reset_source_get_instance); + void reset_source_set_priority(enum reset_src_type st, unsigned int priority) { if (priority <= reset_source_priority) @@ -46,17 +53,33 @@ void reset_source_set_priority(enum reset_src_type st, unsigned int priority) reset_source = st; reset_source_priority = priority; + reset_source_instance = 0; pr_debug("Setting reset source to %s with priority %d\n", reset_src_names[reset_source], priority); } EXPORT_SYMBOL(reset_source_set_priority); +const char *reset_source_name(void) +{ + return reset_src_names[reset_source]; +} +EXPORT_SYMBOL(reset_source_name); + +void reset_source_set_instance(enum reset_src_type type, int instance) +{ + if (reset_source == type) + reset_source_instance = instance; +} +EXPORT_SYMBOL(reset_source_set_instance); + static int reset_source_init(void) { globalvar_add_simple_enum("system.reset", (unsigned int *)&reset_source, reset_src_names, ARRAY_SIZE(reset_src_names)); + globalvar_add_simple_int("system.reset_instance", &reset_source_instance, + "%d"); return 0; } diff --git a/include/reset_source.h b/include/reset_source.h index 3ff06b70ad..86e415abcf 100644 --- a/include/reset_source.h +++ b/include/reset_source.h @@ -27,22 +27,39 @@ enum reset_src_type { #ifdef CONFIG_RESET_SOURCE void reset_source_set_priority(enum reset_src_type, unsigned int priority); enum reset_src_type reset_source_get(void); +void reset_source_set_instance(enum reset_src_type type, int instance); +int reset_source_get_instance(void); unsigned int of_get_reset_source_priority(struct device_node *node); +const char *reset_source_name(void); #else static inline void reset_source_set_priority(enum reset_src_type type, unsigned int priority) { } +static inline void reset_source_set_instance(enum reset_src_type type, int instance) +{ +} + static inline enum reset_src_type reset_source_get(void) { return RESET_UKWN; } +static inline int reset_source_get_instance(void) +{ + return 0; +} + static inline unsigned int of_get_reset_source_priority(struct device_node *node) { return 0; } + +static inline const char *reset_source_name(void) +{ + return "unknown"; +} #endif #define RESET_SOURCE_DEFAULT_PRIORITY 100 |