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);  } | 
