 16642a2e7b
			
		
	
	
	16642a2e7b
	
	
	
		
			
			* Improved system suspend/resume and runtime PM handling for the SH TMU, CMT and MTU2 clock event devices (also used by ARM/shmobile). * Generic PM domains framework extensions related to cpuidle support and domain objects lookup using names. * ARM/shmobile power management updates including improved support for the SH7372's A4S power domain containing the CPU core. * cpufreq changes related to AMD CPUs support from Matthew Garrett, Andre Przywara and Borislav Petkov. * cpu0 cpufreq driver from Shawn Guo. * cpufreq governor fixes related to the relaxing of limit from Michal Pecio. * OMAP cpufreq updates from Axel Lin and Richard Zhao. * cpuidle ladder governor fixes related to the disabling of states from Carsten Emde and me. * Runtime PM core updates related to the interactions with the system suspend core from Alan Stern and Kevin Hilman. * Wakeup sources modification allowing more helper functions to be called from interrupt context from John Stultz and additional diagnostic code from Todd Poynor. * System suspend error code path fix from Feng Hong. -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.18 (GNU/Linux) iQIcBAABAgAGBQJQa1rRAAoJEKhOf7ml8uNsYZ0P/2RZ71sgLWcUCfr0yHaiZeOd 2GxEYSZ+9BZJHADgoAK/bHRTv8crm40Y2RkbaWbxPDRNuE4SutbvNTGTlJSAguSD yHkU/6AFC7u8Jwq+afsWIdGX7eHd78zPpj6EVtVtjHM903WDwbMU2vUz7tQ+fFa+ ZZ7eydq9j0ec0OoH3UeNhet7JSOpT5BSLgjmIkHMBgIvTxNVDbkB31QUxnUxocxn k6S2wQaUSJJWGMLksRRNrhwLq+cGYwTsaOtG/KzRLH1raUyn33B5pcZr0aqhOkjg ClaCks3V8o3vRghSwOPB5aVXzjBKvM3UnSyJNIl+FeCeyWuwSNbkEFdA/e7oPuxG UsW6dcHiuVo6Ir4+zhd9+lN+/AcPTChO5b7lbU8qRF4ce04czWlUY/KzJjaM+YOE CKGq6eX9AHwFjE+h4+VcCXgmzcioiS8Y/CPz13u8N1y0zzwW+ftjb12K+7lVBEG1 fhrePKHgLw3kJ9LqGpR+4vVur7C+rCf6WwCReTY2vXXVYJ+SuKWTRI4zAjTPXtHa i9dpMRASpF+ScRYBcgwIpv789WuHATFKqdBSinZUKBaxQZ5flJ2qIrfqN5VeAejh oQs/zZCdIuAtFKqVycQ0L42YxFNKgPFKQErUCSu3M5OuZLlLVLu7yQvIo2Xmo9qf Hcrpvo5K+w29YkiwGP9e =rbCk -----END PGP SIGNATURE----- Merge tag 'pm-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm Pull power management updates from Rafael J Wysocki: - Improved system suspend/resume and runtime PM handling for the SH TMU, CMT and MTU2 clock event devices (also used by ARM/shmobile). - Generic PM domains framework extensions related to cpuidle support and domain objects lookup using names. - ARM/shmobile power management updates including improved support for the SH7372's A4S power domain containing the CPU core. - cpufreq changes related to AMD CPUs support from Matthew Garrett, Andre Przywara and Borislav Petkov. - cpu0 cpufreq driver from Shawn Guo. - cpufreq governor fixes related to the relaxing of limit from Michal Pecio. - OMAP cpufreq updates from Axel Lin and Richard Zhao. - cpuidle ladder governor fixes related to the disabling of states from Carsten Emde and me. - Runtime PM core updates related to the interactions with the system suspend core from Alan Stern and Kevin Hilman. - Wakeup sources modification allowing more helper functions to be called from interrupt context from John Stultz and additional diagnostic code from Todd Poynor. - System suspend error code path fix from Feng Hong. Fixed up conflicts in cpufreq/powernow-k8 that stemmed from the workqueue fixes conflicting fairly badly with the removal of support for hardware P-state chips. The changes were independent but somewhat intertwined. * tag 'pm-for-3.7-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (76 commits) Revert "PM QoS: Use spinlock in the per-device PM QoS constraints code" PM / Runtime: let rpm_resume() succeed if RPM_ACTIVE, even when disabled, v2 cpuidle: rename function name "__cpuidle_register_driver", v2 cpufreq: OMAP: Check IS_ERR() instead of NULL for omap_device_get_by_hwmod_name cpuidle: remove some empty lines PM: Prevent runtime suspend during system resume PM QoS: Use spinlock in the per-device PM QoS constraints code PM / Sleep: use resume event when call dpm_resume_early cpuidle / ACPI : move cpuidle_device field out of the acpi_processor_power structure ACPI / processor: remove pointless variable initialization ACPI / processor: remove unused function parameter cpufreq: OMAP: remove loops_per_jiffy recalculate for smp sections: fix section conflicts in drivers/cpufreq cpufreq: conservative: update frequency when limits are relaxed cpufreq / ondemand: update frequency when limits are relaxed properly __init-annotate pm_sysrq_init() cpufreq: Add a generic cpufreq-cpu0 driver PM / OPP: Initialize OPP table from device tree ARM: add cpufreq transiton notifier to adjust loops_per_jiffy for smp cpufreq: Remove support for hardware P-state chips from powernow-k8 ...
		
			
				
	
	
		
			186 lines
		
	
	
	
		
			4.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			186 lines
		
	
	
	
		
			4.3 KiB
			
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * rmobile power management support
 | |
|  *
 | |
|  * Copyright (C) 2012  Renesas Solutions Corp.
 | |
|  * Copyright (C) 2012  Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
 | |
|  *
 | |
|  * based on pm-sh7372.c
 | |
|  *  Copyright (C) 2011 Magnus Damm
 | |
|  *
 | |
|  * This file is subject to the terms and conditions of the GNU General Public
 | |
|  * License.  See the file "COPYING" in the main directory of this archive
 | |
|  * for more details.
 | |
|  */
 | |
| #include <linux/console.h>
 | |
| #include <linux/delay.h>
 | |
| #include <linux/platform_device.h>
 | |
| #include <linux/pm.h>
 | |
| #include <linux/pm_clock.h>
 | |
| #include <asm/io.h>
 | |
| #include <mach/pm-rmobile.h>
 | |
| 
 | |
| /* SYSC */
 | |
| #define SPDCR		IOMEM(0xe6180008)
 | |
| #define SWUCR		IOMEM(0xe6180014)
 | |
| #define PSTR		IOMEM(0xe6180080)
 | |
| 
 | |
| #define PSTR_RETRIES	100
 | |
| #define PSTR_DELAY_US	10
 | |
| 
 | |
| #ifdef CONFIG_PM
 | |
| static int rmobile_pd_power_down(struct generic_pm_domain *genpd)
 | |
| {
 | |
| 	struct rmobile_pm_domain *rmobile_pd = to_rmobile_pd(genpd);
 | |
| 	unsigned int mask = 1 << rmobile_pd->bit_shift;
 | |
| 
 | |
| 	if (rmobile_pd->suspend) {
 | |
| 		int ret = rmobile_pd->suspend();
 | |
| 
 | |
| 		if (ret)
 | |
| 			return ret;
 | |
| 	}
 | |
| 
 | |
| 	if (__raw_readl(PSTR) & mask) {
 | |
| 		unsigned int retry_count;
 | |
| 		__raw_writel(mask, SPDCR);
 | |
| 
 | |
| 		for (retry_count = PSTR_RETRIES; retry_count; retry_count--) {
 | |
| 			if (!(__raw_readl(SPDCR) & mask))
 | |
| 				break;
 | |
| 			cpu_relax();
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	if (!rmobile_pd->no_debug)
 | |
| 		pr_debug("%s: Power off, 0x%08x -> PSTR = 0x%08x\n",
 | |
| 			 genpd->name, mask, __raw_readl(PSTR));
 | |
| 
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| static int __rmobile_pd_power_up(struct rmobile_pm_domain *rmobile_pd,
 | |
| 				 bool do_resume)
 | |
| {
 | |
| 	unsigned int mask = 1 << rmobile_pd->bit_shift;
 | |
| 	unsigned int retry_count;
 | |
| 	int ret = 0;
 | |
| 
 | |
| 	if (__raw_readl(PSTR) & mask)
 | |
| 		goto out;
 | |
| 
 | |
| 	__raw_writel(mask, SWUCR);
 | |
| 
 | |
| 	for (retry_count = 2 * PSTR_RETRIES; retry_count; retry_count--) {
 | |
| 		if (!(__raw_readl(SWUCR) & mask))
 | |
| 			break;
 | |
| 		if (retry_count > PSTR_RETRIES)
 | |
| 			udelay(PSTR_DELAY_US);
 | |
| 		else
 | |
| 			cpu_relax();
 | |
| 	}
 | |
| 	if (!retry_count)
 | |
| 		ret = -EIO;
 | |
| 
 | |
| 	if (!rmobile_pd->no_debug)
 | |
| 		pr_debug("%s: Power on, 0x%08x -> PSTR = 0x%08x\n",
 | |
| 			 rmobile_pd->genpd.name, mask, __raw_readl(PSTR));
 | |
| 
 | |
| out:
 | |
| 	if (ret == 0 && rmobile_pd->resume && do_resume)
 | |
| 		rmobile_pd->resume();
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static int rmobile_pd_power_up(struct generic_pm_domain *genpd)
 | |
| {
 | |
| 	return __rmobile_pd_power_up(to_rmobile_pd(genpd), true);
 | |
| }
 | |
| 
 | |
| static bool rmobile_pd_active_wakeup(struct device *dev)
 | |
| {
 | |
| 	bool (*active_wakeup)(struct device *dev);
 | |
| 
 | |
| 	active_wakeup = dev_gpd_data(dev)->ops.active_wakeup;
 | |
| 	return active_wakeup ? active_wakeup(dev) : true;
 | |
| }
 | |
| 
 | |
| static int rmobile_pd_stop_dev(struct device *dev)
 | |
| {
 | |
| 	int (*stop)(struct device *dev);
 | |
| 
 | |
| 	stop = dev_gpd_data(dev)->ops.stop;
 | |
| 	if (stop) {
 | |
| 		int ret = stop(dev);
 | |
| 		if (ret)
 | |
| 			return ret;
 | |
| 	}
 | |
| 	return pm_clk_suspend(dev);
 | |
| }
 | |
| 
 | |
| static int rmobile_pd_start_dev(struct device *dev)
 | |
| {
 | |
| 	int (*start)(struct device *dev);
 | |
| 	int ret;
 | |
| 
 | |
| 	ret = pm_clk_resume(dev);
 | |
| 	if (ret)
 | |
| 		return ret;
 | |
| 
 | |
| 	start = dev_gpd_data(dev)->ops.start;
 | |
| 	if (start)
 | |
| 		ret = start(dev);
 | |
| 
 | |
| 	return ret;
 | |
| }
 | |
| 
 | |
| static void rmobile_init_pm_domain(struct rmobile_pm_domain *rmobile_pd)
 | |
| {
 | |
| 	struct generic_pm_domain *genpd = &rmobile_pd->genpd;
 | |
| 	struct dev_power_governor *gov = rmobile_pd->gov;
 | |
| 
 | |
| 	pm_genpd_init(genpd, gov ? : &simple_qos_governor, false);
 | |
| 	genpd->dev_ops.stop		= rmobile_pd_stop_dev;
 | |
| 	genpd->dev_ops.start		= rmobile_pd_start_dev;
 | |
| 	genpd->dev_ops.active_wakeup	= rmobile_pd_active_wakeup;
 | |
| 	genpd->dev_irq_safe		= true;
 | |
| 	genpd->power_off		= rmobile_pd_power_down;
 | |
| 	genpd->power_on			= rmobile_pd_power_up;
 | |
| 	__rmobile_pd_power_up(rmobile_pd, false);
 | |
| }
 | |
| 
 | |
| void rmobile_init_domains(struct rmobile_pm_domain domains[], int num)
 | |
| {
 | |
| 	int j;
 | |
| 
 | |
| 	for (j = 0; j < num; j++)
 | |
| 		rmobile_init_pm_domain(&domains[j]);
 | |
| }
 | |
| 
 | |
| void rmobile_add_device_to_domain_td(const char *domain_name,
 | |
| 				     struct platform_device *pdev,
 | |
| 				     struct gpd_timing_data *td)
 | |
| {
 | |
| 	struct device *dev = &pdev->dev;
 | |
| 
 | |
| 	__pm_genpd_name_add_device(domain_name, dev, td);
 | |
| 	if (pm_clk_no_clocks(dev))
 | |
| 		pm_clk_add(dev, NULL);
 | |
| }
 | |
| 
 | |
| void rmobile_add_devices_to_domains(struct pm_domain_device data[],
 | |
| 				    int size)
 | |
| {
 | |
| 	struct gpd_timing_data latencies = {
 | |
| 		.stop_latency_ns = DEFAULT_DEV_LATENCY_NS,
 | |
| 		.start_latency_ns = DEFAULT_DEV_LATENCY_NS,
 | |
| 		.save_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
 | |
| 		.restore_state_latency_ns = DEFAULT_DEV_LATENCY_NS,
 | |
| 	};
 | |
| 	int j;
 | |
| 
 | |
| 	for (j = 0; j < size; j++)
 | |
| 		rmobile_add_device_to_domain_td(data[j].domain_name,
 | |
| 						data[j].pdev, &latencies);
 | |
| }
 | |
| #endif /* CONFIG_PM */
 |