diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-omap2/hsmmc.c | 5 | ||||
-rw-r--r-- | arch/arm/mach-omap2/omap-wakeupgen.c | 68 | ||||
-rw-r--r-- | arch/arm/mach-omap2/pm.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-omap2/sr_device.c | 15 | ||||
-rw-r--r-- | arch/arm/mach-omap2/timer.c | 28 |
5 files changed, 96 insertions, 22 deletions
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c index cb754c46747e..be517b048762 100644 --- a/arch/arm/mach-omap2/hsmmc.c +++ b/arch/arm/mach-omap2/hsmmc.c @@ -153,7 +153,6 @@ static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c, hc_name = kzalloc(sizeof(char) * (HSMMC_NAME_LEN + 1), GFP_KERNEL); if (!hc_name) { - pr_err("Cannot allocate memory for controller slot name\n"); kfree(hc_name); return -ENOMEM; } @@ -315,10 +314,8 @@ static void __init omap_hsmmc_init_one(struct omap2_hsmmc_info *hsmmcinfo, int res; mmc_data = kzalloc(sizeof(*mmc_data), GFP_KERNEL); - if (!mmc_data) { - pr_err("Cannot allocate memory for mmc device!\n"); + if (!mmc_data) return; - } res = omap_hsmmc_pdata_init(hsmmcinfo, mmc_data); if (res < 0) diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c index 369f95a703ac..33ed5d53fa45 100644 --- a/arch/arm/mach-omap2/omap-wakeupgen.c +++ b/arch/arm/mach-omap2/omap-wakeupgen.c @@ -58,6 +58,17 @@ static unsigned int irq_banks = DEFAULT_NR_REG_BANKS; static unsigned int max_irqs = DEFAULT_IRQS; static unsigned int omap_secure_apis; +#ifdef CONFIG_CPU_PM +static unsigned int wakeupgen_context[MAX_NR_REG_BANKS]; +#endif + +struct omap_wakeupgen_ops { + void (*save_context)(void); + void (*restore_context)(void); +}; + +static struct omap_wakeupgen_ops *wakeupgen_ops; + /* * Static helper functions. */ @@ -264,6 +275,16 @@ static inline void omap5_irq_save_context(void) } +static inline void am43xx_irq_save_context(void) +{ + u32 i; + + for (i = 0; i < irq_banks; i++) { + wakeupgen_context[i] = wakeupgen_readl(i, 0); + wakeupgen_writel(0, i, CPU0_ID); + } +} + /* * Save WakeupGen interrupt context in SAR BANK3. Restore is done by * ROM code. WakeupGen IP is integrated along with GIC to manage the @@ -280,11 +301,8 @@ static void irq_save_context(void) if (!sar_base) sar_base = omap4_get_sar_ram_base(); - - if (soc_is_omap54xx()) - omap5_irq_save_context(); - else - omap4_irq_save_context(); + if (wakeupgen_ops && wakeupgen_ops->save_context) + wakeupgen_ops->save_context(); } /* @@ -306,6 +324,20 @@ static void irq_sar_clear(void) writel_relaxed(val, sar_base + offset); } +static void am43xx_irq_restore_context(void) +{ + u32 i; + + for (i = 0; i < irq_banks; i++) + wakeupgen_writel(wakeupgen_context[i], i, CPU0_ID); +} + +static void irq_restore_context(void) +{ + if (wakeupgen_ops && wakeupgen_ops->restore_context) + wakeupgen_ops->restore_context(); +} + /* * Save GIC and Wakeupgen interrupt context using secure API * for HS/EMU devices. @@ -319,6 +351,26 @@ static void irq_save_secure_context(void) if (ret != API_HAL_RET_VALUE_OK) pr_err("GIC and Wakeupgen context save failed\n"); } + +/* Define ops for context save and restore for each SoC */ +static struct omap_wakeupgen_ops omap4_wakeupgen_ops = { + .save_context = omap4_irq_save_context, + .restore_context = irq_sar_clear, +}; + +static struct omap_wakeupgen_ops omap5_wakeupgen_ops = { + .save_context = omap5_irq_save_context, + .restore_context = irq_sar_clear, +}; + +static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = { + .save_context = am43xx_irq_save_context, + .restore_context = am43xx_irq_restore_context, +}; +#else +static struct omap_wakeupgen_ops omap4_wakeupgen_ops = {}; +static struct omap_wakeupgen_ops omap5_wakeupgen_ops = {}; +static struct omap_wakeupgen_ops am43xx_wakeupgen_ops = {}; #endif #ifdef CONFIG_HOTPLUG_CPU @@ -359,7 +411,7 @@ static int irq_notifier(struct notifier_block *self, unsigned long cmd, void *v) break; case CPU_CLUSTER_PM_EXIT: if (omap_type() == OMAP2_DEVICE_TYPE_GP) - irq_sar_clear(); + irq_restore_context(); break; } return NOTIFY_OK; @@ -494,9 +546,13 @@ static int __init wakeupgen_init(struct device_node *node, irq_banks = OMAP4_NR_BANKS; max_irqs = OMAP4_NR_IRQS; omap_secure_apis = 1; + wakeupgen_ops = &omap4_wakeupgen_ops; + } else if (soc_is_omap54xx()) { + wakeupgen_ops = &omap5_wakeupgen_ops; } else if (soc_is_am43xx()) { irq_banks = AM43XX_NR_REG_BANKS; max_irqs = AM43XX_IRQS; + wakeupgen_ops = &am43xx_wakeupgen_ops; } domain = irq_domain_add_hierarchy(parent_domain, 0, max_irqs, diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c index 63027e60cc20..366158a54fcd 100644 --- a/arch/arm/mach-omap2/pm.c +++ b/arch/arm/mach-omap2/pm.c @@ -71,7 +71,7 @@ void omap_pm_get_oscillator(u32 *tstart, u32 *tshut) } #endif -int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) +int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused) { clkdm_allow_idle(clkdm); return 0; diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index d7cff2632d1e..eef6935e0403 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -44,13 +44,9 @@ static void __init sr_set_nvalues(struct omap_volt_data *volt_data, while (volt_data[count].volt_nominal) count++; - nvalue_table = kzalloc(sizeof(struct omap_sr_nvalue_table)*count, - GFP_KERNEL); - - if (!nvalue_table) { - pr_err("OMAP: SmartReflex: cannot allocate memory for n-value table\n"); + nvalue_table = kcalloc(count, sizeof(*nvalue_table), GFP_KERNEL); + if (!nvalue_table) return; - } for (i = 0, j = 0; i < count; i++) { u32 v; @@ -102,12 +98,9 @@ static int __init sr_dev_init(struct omap_hwmod *oh, void *user) char *name = "smartreflex"; static int i; - sr_data = kzalloc(sizeof(struct omap_sr_data), GFP_KERNEL); - if (!sr_data) { - pr_err("%s: Unable to allocate memory for %s sr_data\n", - __func__, oh->name); + sr_data = kzalloc(sizeof(*sr_data), GFP_KERNEL); + if (!sr_data) return -ENOMEM; - } sr_dev_attr = (struct omap_smartreflex_dev_attr *)oh->dev_attr; if (!sr_dev_attr || !sr_dev_attr->sensor_voltdm_name) { diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c index e4be76016939..ce982d193046 100644 --- a/arch/arm/mach-omap2/timer.c +++ b/arch/arm/mach-omap2/timer.c @@ -68,6 +68,9 @@ static struct omap_dm_timer clkev; static struct clock_event_device clockevent_gpt; +/* Clockevent hwmod for am335x and am437x suspend */ +static struct omap_hwmod *clockevent_gpt_hwmod; + #ifdef CONFIG_SOC_HAS_REALTIME_COUNTER static unsigned long arch_timer_freq; @@ -125,6 +128,23 @@ static int omap2_gp_timer_set_periodic(struct clock_event_device *evt) return 0; } +static void omap_clkevt_idle(struct clock_event_device *unused) +{ + if (!clockevent_gpt_hwmod) + return; + + omap_hwmod_idle(clockevent_gpt_hwmod); +} + +static void omap_clkevt_unidle(struct clock_event_device *unused) +{ + if (!clockevent_gpt_hwmod) + return; + + omap_hwmod_enable(clockevent_gpt_hwmod); + __omap_dm_timer_int_enable(&clkev, OMAP_TIMER_INT_OVERFLOW); +} + static struct clock_event_device clockevent_gpt = { .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT, @@ -332,6 +352,14 @@ static void __init omap2_gp_clockevent_init(int gptimer_id, 3, /* Timer internal resynch latency */ 0xffffffff); + if (soc_is_am33xx() || soc_is_am43xx()) { + clockevent_gpt.suspend = omap_clkevt_idle; + clockevent_gpt.resume = omap_clkevt_unidle; + + clockevent_gpt_hwmod = + omap_hwmod_lookup(clockevent_gpt.name); + } + pr_info("OMAP clockevent source: %s at %lu Hz\n", clockevent_gpt.name, clkev.rate); } |