diff options
author | Tony Lindgren <tony@atomide.com> | 2014-09-08 15:20:15 -0700 |
---|---|---|
committer | Tony Lindgren <tony@atomide.com> | 2014-09-08 15:20:15 -0700 |
commit | 887782e04f8ada770e24cfb190d2ceed3b2c4974 (patch) | |
tree | acb6a9ee8b1993d1ca15392897da60512a094dba /arch | |
parent | d7eb67f7fef9c046f27a975118da2324de65a90c (diff) | |
parent | 628ed4717000789bff827c5799d1aac4c1008541 (diff) | |
download | linux-887782e04f8ada770e24cfb190d2ceed3b2c4974.tar.gz linux-887782e04f8ada770e24cfb190d2ceed3b2c4974.tar.bz2 linux-887782e04f8ada770e24cfb190d2ceed3b2c4974.zip |
Merge branch 'pull/v3.18/for-omap-soc' of https://github.com/nmenon/linux-2.6-playground into omap-for-v3.18/soc
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/mach-omap2/common.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/io.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-mpuss-lowpower.c | 102 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-secure.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-wakeupgen.c | 20 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-wakeupgen.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pdata-quirks.c | 10 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.h | 1 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm44xx.c | 48 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm3xxx.c | 18 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prm44xx.c | 90 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prminst44xx.c | 40 | ||||
-rw-r--r-- | arch/arm/mach-omap2/prminst44xx.h | 3 |
13 files changed, 275 insertions, 64 deletions
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h index dc571f1d3b8a..5bb15920f73a 100644 --- a/arch/arm/mach-omap2/common.h +++ b/arch/arm/mach-omap2/common.h @@ -60,7 +60,7 @@ static inline int omap3_pm_init(void) } #endif -#if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_PM) && (defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5)) int omap4_pm_init(void); int omap4_pm_init_early(void); #else diff --git a/arch/arm/mach-omap2/io.c b/arch/arm/mach-omap2/io.c index 5d0667c119f6..2890c2df09f6 100644 --- a/arch/arm/mach-omap2/io.c +++ b/arch/arm/mach-omap2/io.c @@ -667,6 +667,7 @@ void __init omap5_init_early(void) omap2_set_globals_cm(OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_AON_BASE), OMAP2_L4_IO_ADDRESS(OMAP54XX_CM_CORE_BASE)); omap2_set_globals_prcm_mpu(OMAP2_L4_IO_ADDRESS(OMAP54XX_PRCM_MPU_BASE)); + omap4_pm_init_early(); omap_prm_base_init(); omap_cm_base_init(); omap44xx_prm_init(); @@ -682,6 +683,8 @@ void __init omap5_init_early(void) void __init omap5_init_late(void) { omap_common_late_init(); + omap4_pm_init(); + omap2_clk_enable_autoidle_all(); } #endif diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c index e9cdacfe1923..6944ae3674e8 100644 --- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c +++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c @@ -56,6 +56,7 @@ #include "omap4-sar-layout.h" #include "pm.h" #include "prcm_mpu44xx.h" +#include "prcm_mpu54xx.h" #include "prminst44xx.h" #include "prcm44xx.h" #include "prm44xx.h" @@ -68,7 +69,6 @@ struct omap4_cpu_pm_info { void __iomem *scu_sar_addr; void __iomem *wkup_sar_addr; void __iomem *l2x0_sar_addr; - void (*secondary_startup)(void); }; /** @@ -76,6 +76,7 @@ struct omap4_cpu_pm_info { * @finish_suspend: CPU suspend finisher function pointer * @resume: CPU resume function pointer * @scu_prepare: CPU Snoop Control program function pointer + * @hotplug_restart: CPU restart function pointer * * Structure holds functions pointer for CPU low power operations like * suspend, resume and scu programming. @@ -84,11 +85,13 @@ struct cpu_pm_ops { int (*finish_suspend)(unsigned long cpu_state); void (*resume)(void); void (*scu_prepare)(unsigned int cpu_id, unsigned int cpu_state); + void (*hotplug_restart)(void); }; static DEFINE_PER_CPU(struct omap4_cpu_pm_info, omap4_pm_info); static struct powerdomain *mpuss_pd; static void __iomem *sar_base; +static u32 cpu_context_offset; static int default_finish_suspend(unsigned long cpu_state) { @@ -106,6 +109,7 @@ struct cpu_pm_ops omap_pm_ops = { .finish_suspend = default_finish_suspend, .resume = dummy_cpu_resume, .scu_prepare = dummy_scu_prepare, + .hotplug_restart = dummy_cpu_resume, }; /* @@ -116,7 +120,8 @@ static inline void set_cpu_wakeup_addr(unsigned int cpu_id, u32 addr) { struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); - writel_relaxed(addr, pm_info->wkup_sar_addr); + if (pm_info->wkup_sar_addr) + writel_relaxed(addr, pm_info->wkup_sar_addr); } /* @@ -141,7 +146,8 @@ static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state) break; } - writel_relaxed(scu_pwr_st, pm_info->scu_sar_addr); + if (pm_info->scu_sar_addr) + writel_relaxed(scu_pwr_st, pm_info->scu_sar_addr); } /* Helper functions for MPUSS OSWR */ @@ -161,14 +167,14 @@ static inline void cpu_clear_prev_logic_pwrst(unsigned int cpu_id) if (cpu_id) { reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU1_INST, - OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET); + cpu_context_offset); omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU1_INST, - OMAP4_RM_CPU1_CPU1_CONTEXT_OFFSET); + cpu_context_offset); } else { reg = omap4_prcm_mpu_read_inst_reg(OMAP4430_PRCM_MPU_CPU0_INST, - OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET); + cpu_context_offset); omap4_prcm_mpu_write_inst_reg(reg, OMAP4430_PRCM_MPU_CPU0_INST, - OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET); + cpu_context_offset); } } @@ -179,7 +185,8 @@ static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state) { struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id); - writel_relaxed(save_state, pm_info->l2x0_sar_addr); + if (pm_info->l2x0_sar_addr) + writel_relaxed(save_state, pm_info->l2x0_sar_addr); } /* @@ -189,10 +196,14 @@ static void l2x0_pwrst_prepare(unsigned int cpu_id, unsigned int save_state) #ifdef CONFIG_CACHE_L2X0 static void __init save_l2x0_context(void) { - writel_relaxed(l2x0_saved_regs.aux_ctrl, - sar_base + L2X0_AUXCTRL_OFFSET); - writel_relaxed(l2x0_saved_regs.prefetch_ctrl, - sar_base + L2X0_PREFETCH_CTRL_OFFSET); + void __iomem *l2x0_base = omap4_get_l2cache_base(); + + if (l2x0_base && sar_base) { + writel_relaxed(l2x0_saved_regs.aux_ctrl, + sar_base + L2X0_AUXCTRL_OFFSET); + writel_relaxed(l2x0_saved_regs.prefetch_ctrl, + sar_base + L2X0_PREFETCH_CTRL_OFFSET); + } } #else static void __init save_l2x0_context(void) @@ -231,6 +242,10 @@ int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state) save_state = 1; break; case PWRDM_POWER_RET: + if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) { + save_state = 0; + break; + } default: /* * CPUx CSWR is invalid hardware state. Also CPUx OSWR @@ -307,7 +322,7 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) pwrdm_clear_all_prev_pwrst(pm_info->pwrdm); pwrdm_set_next_pwrst(pm_info->pwrdm, power_state); - set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup)); + set_cpu_wakeup_addr(cpu, virt_to_phys(omap_pm_ops.hotplug_restart)); omap_pm_ops.scu_prepare(cpu, power_state); /* @@ -323,6 +338,21 @@ int omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state) /* + * Enable Mercury Fast HG retention mode by default. + */ +static void enable_mercury_retention_mode(void) +{ + u32 reg; + + reg = omap4_prcm_mpu_read_inst_reg(OMAP54XX_PRCM_MPU_DEVICE_INST, + OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET); + /* Enable HG_EN, HG_RAMPUP = fast mode */ + reg |= BIT(24) | BIT(25); + omap4_prcm_mpu_write_inst_reg(reg, OMAP54XX_PRCM_MPU_DEVICE_INST, + OMAP54XX_PRCM_MPU_PRM_PSCON_COUNT_OFFSET); +} + +/* * Initialise OMAP4 MPUSS */ int __init omap4_mpuss_init(void) @@ -334,13 +364,17 @@ int __init omap4_mpuss_init(void) return -ENODEV; } - sar_base = omap4_get_sar_ram_base(); + if (cpu_is_omap44xx()) + sar_base = omap4_get_sar_ram_base(); /* Initilaise per CPU PM information */ pm_info = &per_cpu(omap4_pm_info, 0x0); - pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; - pm_info->wkup_sar_addr = sar_base + CPU0_WAKEUP_NS_PA_ADDR_OFFSET; - pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0; + if (sar_base) { + pm_info->scu_sar_addr = sar_base + SCU_OFFSET0; + pm_info->wkup_sar_addr = sar_base + + CPU0_WAKEUP_NS_PA_ADDR_OFFSET; + pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET0; + } pm_info->pwrdm = pwrdm_lookup("cpu0_pwrdm"); if (!pm_info->pwrdm) { pr_err("Lookup failed for CPU0 pwrdm\n"); @@ -355,13 +389,12 @@ int __init omap4_mpuss_init(void) pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON); pm_info = &per_cpu(omap4_pm_info, 0x1); - pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; - pm_info->wkup_sar_addr = sar_base + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; - pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; - if (cpu_is_omap446x()) - pm_info->secondary_startup = omap4460_secondary_startup; - else - pm_info->secondary_startup = omap4_secondary_startup; + if (sar_base) { + pm_info->scu_sar_addr = sar_base + SCU_OFFSET1; + pm_info->wkup_sar_addr = sar_base + + CPU1_WAKEUP_NS_PA_ADDR_OFFSET; + pm_info->l2x0_sar_addr = sar_base + L2X0_SAVE_OFFSET1; + } pm_info->pwrdm = pwrdm_lookup("cpu1_pwrdm"); if (!pm_info->pwrdm) { @@ -384,20 +417,27 @@ int __init omap4_mpuss_init(void) pwrdm_clear_all_prev_pwrst(mpuss_pd); mpuss_clear_prev_logic_pwrst(); - /* Save device type on scratchpad for low level code to use */ - if (omap_type() != OMAP2_DEVICE_TYPE_GP) - writel_relaxed(1, sar_base + OMAP_TYPE_OFFSET); - else - writel_relaxed(0, sar_base + OMAP_TYPE_OFFSET); - - save_l2x0_context(); + if (sar_base) { + /* Save device type on scratchpad for low level code to use */ + writel_relaxed((omap_type() != OMAP2_DEVICE_TYPE_GP) ? 1 : 0, + sar_base + OMAP_TYPE_OFFSET); + save_l2x0_context(); + } if (cpu_is_omap44xx()) { omap_pm_ops.finish_suspend = omap4_finish_suspend; omap_pm_ops.resume = omap4_cpu_resume; omap_pm_ops.scu_prepare = scu_pwrst_prepare; + omap_pm_ops.hotplug_restart = omap4_secondary_startup; + cpu_context_offset = OMAP4_RM_CPU0_CPU0_CONTEXT_OFFSET; + } else if (soc_is_omap54xx() || soc_is_dra7xx()) { + cpu_context_offset = OMAP54XX_RM_CPU0_CPU0_CONTEXT_OFFSET; + enable_mercury_retention_mode(); } + if (cpu_is_omap446x()) + omap_pm_ops.hotplug_restart = omap4460_secondary_startup; + return 0; } diff --git a/arch/arm/mach-omap2/omap-secure.h b/arch/arm/mach-omap2/omap-secure.h index 3e97c6c8ecf1..dec2b05d184b 100644 --- a/arch/arm/mach-omap2/omap-secure.h +++ b/arch/arm/mach-omap2/omap-secure.h @@ -45,6 +45,7 @@ #define OMAP4_MON_L2X0_PREFETCH_INDEX 0x113 #define OMAP5_DRA7_MON_SET_CNTFRQ_INDEX 0x109 +#define OMAP5_MON_AMBA_IF_INDEX 0x108 /* Secure PPA(Primary Protected Application) APIs */ #define OMAP4_PPA_L2_POR_INDEX 0x23 diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 37843a7d3639..f961c46453b9 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -32,6 +32,7 @@ #include "soc.h" #include "omap4-sar-layout.h" #include "common.h" +#include "pm.h" #define AM43XX_NR_REG_BANKS 7 #define AM43XX_IRQS 224 @@ -381,7 +382,7 @@ static struct notifier_block irq_notifier_block = { static void __init irq_pm_init(void) { /* FIXME: Remove this when MPU OSWR support is added */ - if (!soc_is_omap54xx()) + if (!IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) cpu_pm_register_notifier(&irq_notifier_block); } #else @@ -406,6 +407,7 @@ int __init omap_wakeupgen_init(void) { int i; unsigned int boot_cpu = smp_processor_id(); + u32 val; /* Not supported on OMAP4 ES1.0 silicon */ if (omap_rev() == OMAP4430_REV_ES1_0) { @@ -451,6 +453,22 @@ int __init omap_wakeupgen_init(void) for (i = 0; i < max_irqs; i++) irq_target_cpu[i] = boot_cpu; + /* + * Enables OMAP5 ES2 PM Mode using ES2_PM_MODE in AMBA_IF_MODE + * 0x0: ES1 behavior, CPU cores would enter and exit OFF mode together. + * 0x1: ES2 behavior, CPU cores are allowed to enter/exit OFF mode + * independently. + * This needs to be set one time thanks to always ON domain. + * + * We do not support ES1 behavior anymore. OMAP5 is assumed to be + * ES2.0, and the same is applicable for DRA7. + */ + if (soc_is_omap54xx() || soc_is_dra7xx()) { + val = __raw_readl(wakeupgen_base + OMAP_AMBA_IF_MODE); + val |= BIT(5); + omap_smc1(OMAP5_MON_AMBA_IF_INDEX, val); + } + irq_hotplug_init(); irq_pm_init(); diff --git a/arch/arm/mach-omap2/omap-wakeupgen.h b/arch/arm/mach-omap2/omap-wakeupgen.h index b0fd16f5c391..b3c8eccfae79 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.h +++ b/arch/arm/mach-omap2/omap-wakeupgen.h @@ -27,6 +27,7 @@ #define OMAP_WKG_ENB_E_1 0x420 #define OMAP_AUX_CORE_BOOT_0 0x800 #define OMAP_AUX_CORE_BOOT_1 0x804 +#define OMAP_AMBA_IF_MODE 0x80c #define OMAP_PTMSYNCREQ_MASK 0xc00 #define OMAP_PTMSYNCREQ_EN 0xc04 #define OMAP_TIMESTAMPCYCLELO 0xc08 diff --git a/arch/arm/mach-omap2/pdata-quirks.c b/arch/arm/mach-omap2/pdata-quirks.c index 90c88d498485..5fea34edb607 100644 --- a/arch/arm/mach-omap2/pdata-quirks.c +++ b/arch/arm/mach-omap2/pdata-quirks.c @@ -352,6 +352,16 @@ struct of_dev_auxdata omap_auxdata_lookup[] __initdata = { OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a100040, "4a100040.pinmux", &pcs_pdata), OF_DEV_AUXDATA("ti,omap4-padconf", 0x4a31e040, "4a31e040.pinmux", &pcs_pdata), #endif +#ifdef CONFIG_SOC_OMAP5 + OF_DEV_AUXDATA("ti,omap5-padconf", 0x4a002840, "4a002840.pinmux", &pcs_pdata), + OF_DEV_AUXDATA("ti,omap5-padconf", 0x4ae0c840, "4ae0c840.pinmux", &pcs_pdata), +#endif +#ifdef CONFIG_SOC_DRA7XX + OF_DEV_AUXDATA("ti,dra7-padconf", 0x4a003400, "4a003400.pinmux", &pcs_pdata), +#endif +#ifdef CONFIG_SOC_AM43XX + OF_DEV_AUXDATA("ti,am437-padconf", 0x44e10800, "44e10800.pinmux", &pcs_pdata), +#endif #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) OF_DEV_AUXDATA("ti,omap4-iommu", 0x4a066000, "4a066000.mmu", &omap4_iommu_pdata), diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h index e150102d6c06..425bfcd67db6 100644 --- a/arch/arm/mach-omap2/pm.h +++ b/arch/arm/mach-omap2/pm.h @@ -101,6 +101,7 @@ static inline void enable_omap3630_toggle_l2_on_restore(void) { } #endif /* defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP3) */ #define PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD (1 << 0) +#define PM_OMAP4_CPU_OSWR_DISABLE (1 << 1) #if defined(CONFIG_PM) && defined(CONFIG_ARCH_OMAP4) extern u16 pm44xx_errata; diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c index 0bfce38a744a..503097c72b82 100644 --- a/arch/arm/mach-omap2/pm44xx.c +++ b/arch/arm/mach-omap2/pm44xx.c @@ -37,6 +37,8 @@ struct power_state { struct list_head node; }; +static u32 cpu_suspend_state = PWRDM_POWER_OFF; + static LIST_HEAD(pwrst_list); #ifdef CONFIG_SUSPEND @@ -67,7 +69,7 @@ static int omap4_pm_suspend(void) * domain CSWR is not supported by hardware. * More details can be found in OMAP4430 TRM section 4.3.4.2. */ - omap4_enter_lowpower(cpu_id, PWRDM_POWER_OFF); + omap4_enter_lowpower(cpu_id, cpu_suspend_state); /* Restore next powerdomain state */ list_for_each_entry(pwrst, &pwrst_list, node) { @@ -113,8 +115,11 @@ static int __init pwrdms_setup(struct powerdomain *pwrdm, void *unused) * through hotplug path and CPU0 explicitly programmed * further down in the code path */ - if (!strncmp(pwrdm->name, "cpu", 3)) + if (!strncmp(pwrdm->name, "cpu", 3)) { + if (IS_PM44XX_ERRATUM(PM_OMAP4_CPU_OSWR_DISABLE)) + cpu_suspend_state = PWRDM_POWER_RET; return 0; + } pwrst = kmalloc(sizeof(struct power_state), GFP_ATOMIC); if (!pwrst) @@ -208,6 +213,32 @@ static inline int omap4_init_static_deps(void) } /** + * omap5_dra7_init_static_deps - Init static clkdm dependencies on OMAP5 and + * DRA7 + * + * The dynamic dependency between MPUSS -> EMIF is broken and has + * not worked as expected. The hardware recommendation is to + * enable static dependencies for these to avoid system + * lock ups or random crashes. + */ +static inline int omap5_dra7_init_static_deps(void) +{ + struct clockdomain *mpuss_clkdm, *emif_clkdm; + int ret; + + mpuss_clkdm = clkdm_lookup("mpu_clkdm"); + emif_clkdm = clkdm_lookup("emif_clkdm"); + if (!mpuss_clkdm || !emif_clkdm) + return -EINVAL; + + ret = clkdm_add_wkdep(mpuss_clkdm, emif_clkdm); + if (ret) + pr_err("Failed to add MPUSS -> EMIF wakeup dependency\n"); + + return ret; +} + +/** * omap4_pm_init_early - Does early initialization necessary for OMAP4+ devices * * Initializes basic stuff for power management functionality. @@ -217,6 +248,9 @@ int __init omap4_pm_init_early(void) if (cpu_is_omap446x()) pm44xx_errata |= PM_OMAP4_ROM_SMP_BOOT_ERRATUM_GICD; + if (soc_is_omap54xx() || soc_is_dra7xx()) + pm44xx_errata |= PM_OMAP4_CPU_OSWR_DISABLE; + return 0; } @@ -244,10 +278,14 @@ int __init omap4_pm_init(void) goto err2; } - if (cpu_is_omap44xx()) { + if (cpu_is_omap44xx()) ret = omap4_init_static_deps(); - if (ret) - goto err2; + else if (soc_is_omap54xx() || soc_is_dra7xx()) + ret = omap5_dra7_init_static_deps(); + + if (ret) { + pr_err("Failed to initialise static dependencies.\n"); + goto err2; } ret = omap4_mpuss_init(); diff --git a/arch/arm/mach-omap2/prm3xxx.c b/arch/arm/mach-omap2/prm3xxx.c index 2458be6fc67b..e0088e0508f8 100644 --- a/arch/arm/mach-omap2/prm3xxx.c +++ b/arch/arm/mach-omap2/prm3xxx.c @@ -17,6 +17,7 @@ #include <linux/err.h> #include <linux/io.h> #include <linux/irq.h> +#include <linux/of_irq.h> #include "soc.h" #include "common.h" @@ -649,6 +650,11 @@ int __init omap3xxx_prm_init(void) return prm_register(&omap3xxx_prm_ll_data); } +static struct of_device_id omap3_prm_dt_match_table[] = { + { .compatible = "ti,omap3-prm" }, + { } +}; + static int omap3xxx_prm_late_init(void) { int ret; @@ -656,6 +662,18 @@ static int omap3xxx_prm_late_init(void) if (!(prm_features & PRM_HAS_IO_WAKEUP)) return 0; + if (of_have_populated_dt()) { + struct device_node *np; + int irq_num; + + np = of_find_matching_node(NULL, omap3_prm_dt_match_table); + if (np) { + irq_num = of_irq_get(np, 0); + if (irq_num >= 0) + omap3_prcm_irq_setup.irq = irq_num; + } + } + omap3xxx_prm_enable_io_wakeup(); ret = omap_prcm_register_chain_handler(&omap3_prcm_irq_setup); if (!ret) diff --git a/arch/arm/mach-omap2/prm44xx.c b/arch/arm/mach-omap2/prm44xx.c index a7f6ea27180a..0958d070d3db 100644 --- a/arch/arm/mach-omap2/prm44xx.c +++ b/arch/arm/mach-omap2/prm44xx.c @@ -17,6 +17,7 @@ #include <linux/errno.h> #include <linux/err.h> #include <linux/io.h> +#include <linux/of_irq.h> #include "soc.h" @@ -32,7 +33,6 @@ /* Static data */ static const struct omap_prcm_irq omap4_prcm_irqs[] = { - OMAP_PRCM_IRQ("wkup", 0, 0), OMAP_PRCM_IRQ("io", 9, 1), }; @@ -154,21 +154,36 @@ void omap4_prm_vp_clear_txdone(u8 vp_id) u32 omap4_prm_vcvp_read(u8 offset) { + s32 inst = omap4_prmst_get_prm_dev_inst(); + + if (inst == PRM_INSTANCE_UNKNOWN) + return 0; + return omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, - OMAP4430_PRM_DEVICE_INST, offset); + inst, offset); } void omap4_prm_vcvp_write(u32 val, u8 offset) { + s32 inst = omap4_prmst_get_prm_dev_inst(); + + if (inst == PRM_INSTANCE_UNKNOWN) + return; + omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, - OMAP4430_PRM_DEVICE_INST, offset); + inst, offset); } u32 omap4_prm_vcvp_rmw(u32 mask, u32 bits, u8 offset) { + s32 inst = omap4_prmst_get_prm_dev_inst(); + + if (inst == PRM_INSTANCE_UNKNOWN) + return 0; + return omap4_prminst_rmw_inst_reg_bits(mask, bits, OMAP4430_PRM_PARTITION, - OMAP4430_PRM_DEVICE_INST, + inst, offset); } @@ -275,14 +290,18 @@ void omap44xx_prm_restore_irqen(u32 *saved_mask) void omap44xx_prm_reconfigure_io_chain(void) { int i = 0; + s32 inst = omap4_prmst_get_prm_dev_inst(); + + if (inst == PRM_INSTANCE_UNKNOWN) + return; /* Trigger WUCLKIN enable */ omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, OMAP4430_WUCLK_CTRL_MASK, - OMAP4430_PRM_DEVICE_INST, + inst, OMAP4_PRM_IO_PMCTRL_OFFSET); omap_test_timeout( - (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + (((omap4_prm_read_inst_reg(inst, OMAP4_PRM_IO_PMCTRL_OFFSET) & OMAP4430_WUCLK_STATUS_MASK) >> OMAP4430_WUCLK_STATUS_SHIFT) == 1), @@ -292,10 +311,10 @@ void omap44xx_prm_reconfigure_io_chain(void) /* Trigger WUCLKIN disable */ omap4_prm_rmw_inst_reg_bits(OMAP4430_WUCLK_CTRL_MASK, 0x0, - OMAP4430_PRM_DEVICE_INST, + inst, OMAP4_PRM_IO_PMCTRL_OFFSET); omap_test_timeout( - (((omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + (((omap4_prm_read_inst_reg(inst, OMAP4_PRM_IO_PMCTRL_OFFSET) & OMAP4430_WUCLK_STATUS_MASK) >> OMAP4430_WUCLK_STATUS_SHIFT) == 0), @@ -316,9 +335,14 @@ void omap44xx_prm_reconfigure_io_chain(void) */ static void __init omap44xx_prm_enable_io_wakeup(void) { + s32 inst = omap4_prmst_get_prm_dev_inst(); + + if (inst == PRM_INSTANCE_UNKNOWN) + return; + omap4_prm_rmw_inst_reg_bits(OMAP4430_GLOBAL_WUEN_MASK, OMAP4430_GLOBAL_WUEN_MASK, - OMAP4430_PRM_DEVICE_INST, + inst, OMAP4_PRM_IO_PMCTRL_OFFSET); } @@ -333,8 +357,13 @@ static u32 omap44xx_prm_read_reset_sources(void) struct prm_reset_src_map *p; u32 r = 0; u32 v; + s32 inst = omap4_prmst_get_prm_dev_inst(); - v = omap4_prm_read_inst_reg(OMAP4430_PRM_DEVICE_INST, + if (inst == PRM_INSTANCE_UNKNOWN) + return 0; + + + v = omap4_prm_read_inst_reg(inst, OMAP4_RM_RSTST); p = omap44xx_prm_reset_src_map; @@ -664,17 +693,56 @@ static struct prm_ll_data omap44xx_prm_ll_data = { int __init omap44xx_prm_init(void) { - if (cpu_is_omap44xx()) + if (cpu_is_omap44xx() || soc_is_omap54xx() || soc_is_dra7xx()) prm_features |= PRM_HAS_IO_WAKEUP; return prm_register(&omap44xx_prm_ll_data); } +static struct of_device_id omap_prm_dt_match_table[] = { + { .compatible = "ti,omap4-prm" }, + { .compatible = "ti,omap5-prm" }, + { .compatible = "ti,dra7-prm" }, + { } +}; + static int omap44xx_prm_late_init(void) { + struct device_node *np; + int irq_num; + if (!(prm_features & PRM_HAS_IO_WAKEUP)) return 0; + /* OMAP4+ is DT only now */ + if (!of_have_populated_dt()) + return 0; + + np = of_find_matching_node(NULL, omap_prm_dt_match_table); + + if (!np) { + /* Default loaded up with OMAP4 values */ + if (!cpu_is_omap44xx()) + return 0; + } else { + irq_num = of_irq_get(np, 0); + /* + * Already have OMAP4 IRQ num. For all other platforms, we need + * IRQ numbers from DT + */ + if (irq_num < 0 && !cpu_is_omap44xx()) { + if (irq_num == -EPROBE_DEFER) + return irq_num; + + /* Have nothing to do */ + return 0; + } + + /* Once OMAP4 DT is filled as well */ + if (irq_num >= 0) + omap4_prcm_irq_setup.irq = irq_num; + } + omap44xx_prm_enable_io_wakeup(); return omap_prcm_register_chain_handler(&omap4_prcm_irq_setup); diff --git a/arch/arm/mach-omap2/prminst44xx.c b/arch/arm/mach-omap2/prminst44xx.c index 69f0dd08629c..225e0258d76d 100644 --- a/arch/arm/mach-omap2/prminst44xx.c +++ b/arch/arm/mach-omap2/prminst44xx.c @@ -31,6 +31,8 @@ static void __iomem *_prm_bases[OMAP4_MAX_PRCM_PARTITIONS]; +static s32 prm_dev_inst = PRM_INSTANCE_UNKNOWN; + /** * omap_prm_base_init - Populates the prm partitions * @@ -43,6 +45,24 @@ void omap_prm_base_init(void) _prm_bases[OMAP4430_PRCM_MPU_PARTITION] = prcm_mpu_base; } +s32 omap4_prmst_get_prm_dev_inst(void) +{ + if (prm_dev_inst != PRM_INSTANCE_UNKNOWN) + return prm_dev_inst; + + /* This cannot be done way early at boot.. as things are not setup */ + if (cpu_is_omap44xx()) + prm_dev_inst = OMAP4430_PRM_DEVICE_INST; + else if (soc_is_omap54xx()) + prm_dev_inst = OMAP54XX_PRM_DEVICE_INST; + else if (soc_is_dra7xx()) + prm_dev_inst = DRA7XX_PRM_DEVICE_INST; + else if (soc_is_am43xx()) + prm_dev_inst = AM43XX_PRM_DEVICE_INST; + + return prm_dev_inst; +} + /* Read a register in a PRM instance */ u32 omap4_prminst_read_inst_reg(u8 part, s16 inst, u16 idx) { @@ -169,28 +189,18 @@ int omap4_prminst_deassert_hardreset(u8 shift, u8 part, s16 inst, void omap4_prminst_global_warm_sw_reset(void) { u32 v; - s16 dev_inst; + s32 inst = omap4_prmst_get_prm_dev_inst(); - if (cpu_is_omap44xx()) - dev_inst = OMAP4430_PRM_DEVICE_INST; - else if (soc_is_omap54xx()) - dev_inst = OMAP54XX_PRM_DEVICE_INST; - else if (soc_is_dra7xx()) - dev_inst = DRA7XX_PRM_DEVICE_INST; - else if (soc_is_am43xx()) - dev_inst = AM43XX_PRM_DEVICE_INST; - else + if (inst == PRM_INSTANCE_UNKNOWN) return; - v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, dev_inst, + v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, inst, OMAP4_PRM_RSTCTRL_OFFSET); v |= OMAP4430_RST_GLOBAL_WARM_SW_MASK; omap4_prminst_write_inst_reg(v, OMAP4430_PRM_PARTITION, - dev_inst, - OMAP4_PRM_RSTCTRL_OFFSET); + inst, OMAP4_PRM_RSTCTRL_OFFSET); /* OCP barrier */ v = omap4_prminst_read_inst_reg(OMAP4430_PRM_PARTITION, - dev_inst, - OMAP4_PRM_RSTCTRL_OFFSET); + inst, OMAP4_PRM_RSTCTRL_OFFSET); } diff --git a/arch/arm/mach-omap2/prminst44xx.h b/arch/arm/mach-omap2/prminst44xx.h index a2ede2d65481..583aa3774571 100644 --- a/arch/arm/mach-omap2/prminst44xx.h +++ b/arch/arm/mach-omap2/prminst44xx.h @@ -12,6 +12,9 @@ #ifndef __ARCH_ASM_MACH_OMAP2_PRMINST44XX_H #define __ARCH_ASM_MACH_OMAP2_PRMINST44XX_H +#define PRM_INSTANCE_UNKNOWN -1 +extern s32 omap4_prmst_get_prm_dev_inst(void); + /* * In an ideal world, we would not export these low-level functions, * but this will probably take some time to fix properly |