Message ID | 1375167603-16722-1-git-send-email-dongsheng.wang@freescale.com (mailing list archive) |
---|---|
State | Changes Requested, archived |
Headers | show |
On 07/30/2013 09:00 AM, Dongsheng Wang wrote: > From: Wang Dongsheng <dongsheng.wang@freescale.com> > > Add cpuidle support for e500 family, using cpuidle framework to > manage various low power modes. The new implementation will remain > compatible with original idle method. > > Initially, this supports PW10, and subsequent patches will support > PW20/DOZE/NAP. > > Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com> > --- > This patch keep using cpuidle_register_device(), because we need to support cpu > hotplug. I will fix "device" issue in this driver, after > Deepthi Dharwar <deepthi@linux.vnet.ibm.com> add a hotplug handler into cpuidle > freamwork. > > diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h > index 8b48090..cbdbe25 100644 > --- a/arch/powerpc/include/asm/machdep.h > +++ b/arch/powerpc/include/asm/machdep.h > @@ -271,6 +271,16 @@ extern void power7_idle(void); > extern void ppc6xx_idle(void); > extern void book3e_idle(void); > > +/* Wait for Interrupt */ > +static inline void fsl_cpuidle_wait(void) > +{ > +#ifdef CONFIG_PPC64 > + book3e_idle(); > +#else > + e500_idle(); > +#endif > +} > + > /* > * ppc_md contains a copy of the machine description structure for the > * current platform. machine_id contains the initial address where the > diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig > index b3fb81d..7ed114b 100644 > --- a/drivers/cpuidle/Kconfig > +++ b/drivers/cpuidle/Kconfig > @@ -35,6 +35,11 @@ depends on ARM > source "drivers/cpuidle/Kconfig.arm" > endmenu > > +menu "PowerPC CPU Idle Drivers" > +depends on PPC32 || PPC64 > +source "drivers/cpuidle/Kconfig.powerpc" > +endmenu > + > endif > > config ARCH_NEEDS_CPU_IDLE_COUPLED > diff --git a/drivers/cpuidle/Kconfig.powerpc b/drivers/cpuidle/Kconfig.powerpc > new file mode 100644 > index 0000000..9f3f5ef > --- /dev/null > +++ b/drivers/cpuidle/Kconfig.powerpc > @@ -0,0 +1,9 @@ > +# > +# PowerPC CPU Idle drivers > +# > + > +config PPC_E500_CPUIDLE > + bool "CPU Idle Driver for E500 family processors" > + depends on FSL_SOC_BOOKE > + help > + Select this to enable cpuidle on e500 family processors. > diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile > index 0b9d200..0dde3db 100644 > --- a/drivers/cpuidle/Makefile > +++ b/drivers/cpuidle/Makefile > @@ -11,3 +11,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o > obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o > obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o > obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o > + > +################################################################################## > +# PowerPC platform drivers > +obj-$(CONFIG_PPC_E500_CPUIDLE) += cpuidle-e500.o > diff --git a/drivers/cpuidle/cpuidle-e500.c b/drivers/cpuidle/cpuidle-e500.c > new file mode 100644 > index 0000000..1919cea > --- /dev/null > +++ b/drivers/cpuidle/cpuidle-e500.c > @@ -0,0 +1,222 @@ > +/* > + * Copyright 2013 Freescale Semiconductor, Inc. > + * > + * CPU Idle driver for Freescale PowerPC e500 family processors. > + * > + * This program is free software; you can redistribute it and/or modify > + * it under the terms of the GNU General Public License version 2 as > + * published by the Free Software Foundation. > + * > + * Author: Wang Dongsheng <dongsheng.wang@freescale.com> > + */ > + > +#include <linux/cpu.h> > +#include <linux/cpuidle.h> > +#include <linux/init.h> > +#include <linux/kernel.h> > +#include <linux/module.h> > +#include <linux/notifier.h> > + > +#include <asm/machdep.h> > + > +static struct cpuidle_driver e500_idle_driver = { > + .name = "e500_idle", > + .owner = THIS_MODULE, > +}; > + > +static struct cpuidle_device __percpu *e500_cpuidle_devices; > + > +static void e500_cpuidle(void) > +{ > + /* > + * This would call on the cpuidle framework, and the back-end > + * driver to go to idle states. > + */ > + if (cpuidle_idle_call()) { > + /* > + * On error, execute default handler > + * to go into low thread priority and possibly > + * low power mode. > + */ > + HMT_low(); > + HMT_very_low(); > + } > +} Nope, this is not the place to add such function. > +static int pw10_enter(struct cpuidle_device *dev, > + struct cpuidle_driver *drv, int index) > +{ > + fsl_cpuidle_wait(); > + return index; > +} > + > +static struct cpuidle_state fsl_pw_idle_states[] = { > + { > + .name = "pw10", > + .desc = "pw10", > + .flags = CPUIDLE_FLAG_TIME_VALID, > + .exit_latency = 0, > + .target_residency = 0, > + .enter = &pw10_enter > + }, > +}; > + > +static int cpu_hotplug_notify(struct notifier_block *n, > + unsigned long action, void *hcpu) > +{ > + unsigned long hotcpu = (unsigned long)hcpu; > + struct cpuidle_device *dev = > + per_cpu_ptr(e500_cpuidle_devices, hotcpu); > + > + if (dev && cpuidle_get_driver()) { > + switch (action) { > + case CPU_ONLINE: > + case CPU_ONLINE_FROZEN: > + cpuidle_pause_and_lock(); > + cpuidle_enable_device(dev); > + cpuidle_resume_and_unlock(); > + break; > + > + case CPU_DEAD: > + case CPU_DEAD_FROZEN: > + cpuidle_pause_and_lock(); > + cpuidle_disable_device(dev); > + cpuidle_resume_and_unlock(); > + break; > + > + default: > + return NOTIFY_DONE; > + } > + } > + > + return NOTIFY_OK; > +} > + > +static struct notifier_block cpu_hotplug_notifier = { > + .notifier_call = cpu_hotplug_notify, > +}; This should go to the cpuidle framework. > + > +/* > + * e500_idle_devices_init(void) > + * allocate, initialize and register cpuidle device > + */ > +static int e500_idle_devices_init(void) > +{ > + int i; > + struct cpuidle_driver *drv = &e500_idle_driver; > + struct cpuidle_device *dev; > + > + e500_cpuidle_devices = alloc_percpu(struct cpuidle_device); > + if (!e500_cpuidle_devices) > + return -ENOMEM; > + > + for_each_possible_cpu(i) { > + dev = per_cpu_ptr(e500_cpuidle_devices, i); > + dev->state_count = drv->state_count; > + dev->cpu = i; > + > + if (cpuidle_register_device(dev)) { > + pr_err("cpuidle_register_device %d failed!\n", i); > + return -EIO; > + } > + } > + > + return 0; > +} > + > +/* > + * e500_idle_devices_uninit(void) > + * unregister cpuidle devices and de-allocate memory > + */ > +static void e500_idle_devices_uninit(void) > +{ > + int i; > + struct cpuidle_device *dev; > + > + if (!e500_cpuidle_devices) > + return; > + > + for_each_possible_cpu(i) { > + dev = per_cpu_ptr(e500_cpuidle_devices, i); > + cpuidle_unregister_device(dev); > + } > + > + free_percpu(e500_cpuidle_devices); > +} > + > +static void e500_cpuidle_driver_init(unsigned int max_idle_state, > + struct cpuidle_state *cpuidle_state_table) > +{ > + int idle_state; > + struct cpuidle_driver *drv = &e500_idle_driver; > + > + drv->state_count = 0; > + > + for (idle_state = 0; idle_state < max_idle_state; ++idle_state) { > + if (!cpuidle_state_table[idle_state].enter) > + break; > + > + drv->states[drv->state_count] = cpuidle_state_table[idle_state]; > + drv->state_count++; > + } > +} > + > +static int cpu_is_feature(unsigned long feature) > +{ > + return (cur_cpu_spec->cpu_features == feature); > +} > + > +static int __init e500_idle_init(void) > +{ > + struct cpuidle_state *cpuidle_state_table = NULL; > + struct cpuidle_driver *drv = &e500_idle_driver; > + int err; > + unsigned int max_idle_state = 0; > + > + if (cpuidle_disable != IDLE_NO_OVERRIDE) > + return -ENODEV; > + > + if (cpu_is_feature(CPU_FTRS_E500MC) || cpu_is_feature(CPU_FTRS_E5500) || > + cpu_is_feature(CPU_FTRS_E6500)) { > + cpuidle_state_table = fsl_pw_idle_states; > + max_idle_state = ARRAY_SIZE(fsl_pw_idle_states); > + } > + > + if (!cpuidle_state_table || !max_idle_state) > + return -EPERM; Please use different drivers for each and then register the right one instead of state count convolutions. Then use cpuidle_register(&mydriver, NULL) and get rid of the duplicate initialization routine. > + e500_cpuidle_driver_init(max_idle_state, cpuidle_state_table); > + > + if (!drv->state_count) > + return -EPERM; > + > + err = cpuidle_register_driver(drv); > + if (err) { > + pr_err("Register e500 family cpuidle driver failed.\n"); > + > + return err; > + } > + > + err = e500_idle_devices_init(); > + if (err) > + goto out; > + > + err = register_cpu_notifier(&cpu_hotplug_notifier); > + if (err) > + goto out; > + > + ppc_md.power_save = e500_cpuidle; This is not the place. > + > + pr_info("e500_idle_driver registered.\n"); > + > + return 0; > + > +out: > + e500_idle_devices_uninit(); > + cpuidle_unregister_driver(drv); > + > + pr_err("Register e500 family cpuidle driver failed.\n"); > + > + return err; > +} > +device_initcall(e500_idle_init); >
DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogRGFuaWVsIExlemNhbm8g W21haWx0bzpkYW5pZWwubGV6Y2Fub0BsaW5hcm8ub3JnXQ0KPiBTZW50OiBUdWVzZGF5LCBKdWx5 IDMwLCAyMDEzIDU6NTEgUE0NCj4gVG86IFdhbmcgRG9uZ3NoZW5nLUI0MDUzNA0KPiBDYzogV29v ZCBTY290dC1CMDc0MjE7IHJqd0BzaXNrLnBsOyBiZW5oQGtlcm5lbC5jcmFzaGluZy5vcmc7IExp IFlhbmctDQo+IFI1ODQ3MjsgWmhhbyBDaGVuaHVpLUIzNTMzNjsgbGludXgtcG1Admdlci5rZXJu ZWwub3JnOyBsaW51eHBwYy0NCj4gZGV2QGxpc3RzLm96bGFicy5vcmcNCj4gU3ViamVjdDogUmU6 IFtQQVRDSF0gY3B1aWRsZTogYWRkIGZyZWVzY2FsZSBlNTAwIGZhbWlseSBwb3JjZXNzb3JzIGlk bGUNCj4gc3VwcG9ydA0KPiANCj4gT24gMDcvMzAvMjAxMyAwOTowMCBBTSwgRG9uZ3NoZW5nIFdh bmcgd3JvdGU6DQo+ID4gRnJvbTogV2FuZyBEb25nc2hlbmcgPGRvbmdzaGVuZy53YW5nQGZyZWVz Y2FsZS5jb20+DQo+ID4NCj4gPiBBZGQgY3B1aWRsZSBzdXBwb3J0IGZvciBlNTAwIGZhbWlseSwg dXNpbmcgY3B1aWRsZSBmcmFtZXdvcmsgdG8gbWFuYWdlDQo+ID4gdmFyaW91cyBsb3cgcG93ZXIg bW9kZXMuIFRoZSBuZXcgaW1wbGVtZW50YXRpb24gd2lsbCByZW1haW4gY29tcGF0aWJsZQ0KPiA+ IHdpdGggb3JpZ2luYWwgaWRsZSBtZXRob2QuDQo+ID4NCj4gPiBJbml0aWFsbHksIHRoaXMgc3Vw cG9ydHMgUFcxMCwgYW5kIHN1YnNlcXVlbnQgcGF0Y2hlcyB3aWxsIHN1cHBvcnQNCj4gPiBQVzIw L0RPWkUvTkFQLg0KPiA+DQo+ID4gU2lnbmVkLW9mZi1ieTogV2FuZyBEb25nc2hlbmcgPGRvbmdz aGVuZy53YW5nQGZyZWVzY2FsZS5jb20+DQo+ID4gLS0tDQo+ID4gVGhpcyBwYXRjaCBrZWVwIHVz aW5nIGNwdWlkbGVfcmVnaXN0ZXJfZGV2aWNlKCksIGJlY2F1c2Ugd2UgbmVlZCB0bw0KPiA+IHN1 cHBvcnQgY3B1IGhvdHBsdWcuIEkgd2lsbCBmaXggImRldmljZSIgaXNzdWUgaW4gdGhpcyBkcml2 ZXIsIGFmdGVyDQo+ID4gRGVlcHRoaSBEaGFyd2FyIDxkZWVwdGhpQGxpbnV4LnZuZXQuaWJtLmNv bT4gYWRkIGEgaG90cGx1ZyBoYW5kbGVyDQo+ID4gaW50byBjcHVpZGxlIGZyZWFtd29yay4NCj4g Pg0KPiA+IGRpZmYgLS1naXQgYS9hcmNoL3Bvd2VycGMvaW5jbHVkZS9hc20vbWFjaGRlcC5oDQo+ ID4gYi9hcmNoL3Bvd2VycGMvaW5jbHVkZS9hc20vbWFjaGRlcC5oDQo+ID4gaW5kZXggOGI0ODA5 MC4uY2JkYmUyNSAxMDA2NDQNCj4gPiAtLS0gYS9hcmNoL3Bvd2VycGMvaW5jbHVkZS9hc20vbWFj aGRlcC5oDQo+ID4gKysrIGIvYXJjaC9wb3dlcnBjL2luY2x1ZGUvYXNtL21hY2hkZXAuaA0KPiA+ IEBAIC0yNzEsNiArMjcxLDE2IEBAIGV4dGVybiB2b2lkIHBvd2VyN19pZGxlKHZvaWQpOyAgZXh0 ZXJuIHZvaWQNCj4gPiBwcGM2eHhfaWRsZSh2b2lkKTsgIGV4dGVybiB2b2lkIGJvb2szZV9pZGxl KHZvaWQpOw0KPiA+DQo+ID4gKy8qIFdhaXQgZm9yIEludGVycnVwdCAqLw0KPiA+ICtzdGF0aWMg aW5saW5lIHZvaWQgZnNsX2NwdWlkbGVfd2FpdCh2b2lkKSB7ICNpZmRlZiBDT05GSUdfUFBDNjQN Cj4gPiArCWJvb2szZV9pZGxlKCk7DQo+ID4gKyNlbHNlDQo+ID4gKwllNTAwX2lkbGUoKTsNCj4g PiArI2VuZGlmDQo+ID4gK30NCj4gPiArDQo+ID4gIC8qDQo+ID4gICAqIHBwY19tZCBjb250YWlu cyBhIGNvcHkgb2YgdGhlIG1hY2hpbmUgZGVzY3JpcHRpb24gc3RydWN0dXJlIGZvciB0aGUNCj4g PiAgICogY3VycmVudCBwbGF0Zm9ybS4gbWFjaGluZV9pZCBjb250YWlucyB0aGUgaW5pdGlhbCBh ZGRyZXNzIHdoZXJlIHRoZQ0KPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJzL2NwdWlkbGUvS2NvbmZp ZyBiL2RyaXZlcnMvY3B1aWRsZS9LY29uZmlnDQo+ID4gaW5kZXggYjNmYjgxZC4uN2VkMTE0YiAx MDA2NDQNCj4gPiAtLS0gYS9kcml2ZXJzL2NwdWlkbGUvS2NvbmZpZw0KPiA+ICsrKyBiL2RyaXZl cnMvY3B1aWRsZS9LY29uZmlnDQo+ID4gQEAgLTM1LDYgKzM1LDExIEBAIGRlcGVuZHMgb24gQVJN DQo+ID4gIHNvdXJjZSAiZHJpdmVycy9jcHVpZGxlL0tjb25maWcuYXJtIg0KPiA+ICBlbmRtZW51 DQo+ID4NCj4gPiArbWVudSAiUG93ZXJQQyBDUFUgSWRsZSBEcml2ZXJzIg0KPiA+ICtkZXBlbmRz IG9uIFBQQzMyIHx8IFBQQzY0DQo+ID4gK3NvdXJjZSAiZHJpdmVycy9jcHVpZGxlL0tjb25maWcu cG93ZXJwYyINCj4gPiArZW5kbWVudQ0KPiA+ICsNCj4gPiAgZW5kaWYNCj4gPg0KPiA+ICBjb25m aWcgQVJDSF9ORUVEU19DUFVfSURMRV9DT1VQTEVEDQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMv Y3B1aWRsZS9LY29uZmlnLnBvd2VycGMNCj4gYi9kcml2ZXJzL2NwdWlkbGUvS2NvbmZpZy5wb3dl cnBjDQo+ID4gbmV3IGZpbGUgbW9kZSAxMDA2NDQNCj4gPiBpbmRleCAwMDAwMDAwLi45ZjNmNWVm DQo+ID4gLS0tIC9kZXYvbnVsbA0KPiA+ICsrKyBiL2RyaXZlcnMvY3B1aWRsZS9LY29uZmlnLnBv d2VycGMNCj4gPiBAQCAtMCwwICsxLDkgQEANCj4gPiArIw0KPiA+ICsjIFBvd2VyUEMgQ1BVIElk bGUgZHJpdmVycw0KPiA+ICsjDQo+ID4gKw0KPiA+ICtjb25maWcgUFBDX0U1MDBfQ1BVSURMRQ0K PiA+ICsJYm9vbCAiQ1BVIElkbGUgRHJpdmVyIGZvciBFNTAwIGZhbWlseSBwcm9jZXNzb3JzIg0K PiA+ICsJZGVwZW5kcyBvbiBGU0xfU09DX0JPT0tFDQo+ID4gKwloZWxwDQo+ID4gKwkgIFNlbGVj dCB0aGlzIHRvIGVuYWJsZSBjcHVpZGxlIG9uIGU1MDAgZmFtaWx5IHByb2Nlc3NvcnMuDQo+ID4g ZGlmZiAtLWdpdCBhL2RyaXZlcnMvY3B1aWRsZS9NYWtlZmlsZSBiL2RyaXZlcnMvY3B1aWRsZS9N YWtlZmlsZQ0KPiA+IGluZGV4IDBiOWQyMDAuLjBkZGUzZGIgMTAwNjQ0DQo+ID4gLS0tIGEvZHJp dmVycy9jcHVpZGxlL01ha2VmaWxlDQo+ID4gKysrIGIvZHJpdmVycy9jcHVpZGxlL01ha2VmaWxl DQo+ID4gQEAgLTExLDMgKzExLDcgQEAgb2JqLSQoQ09ORklHX0FSTV9ISUdIQkFOS19DUFVJRExF KQkrPSBjcHVpZGxlLQ0KPiBjYWx4ZWRhLm8NCj4gPiAgb2JqLSQoQ09ORklHX0FSTV9LSVJLV09P RF9DUFVJRExFKQkrPSBjcHVpZGxlLWtpcmt3b29kLm8NCj4gPiAgb2JqLSQoQ09ORklHX0FSTV9a WU5RX0NQVUlETEUpCQkrPSBjcHVpZGxlLXp5bnEubw0KPiA+ICBvYmotJChDT05GSUdfQVJNX1U4 NTAwX0NQVUlETEUpICAgICAgICAgKz0gY3B1aWRsZS11eDUwMC5vDQo+ID4gKw0KPiA+DQo+ICsj IyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMj IyMjIyMjIyMjIyMjIyMNCj4gIyMjIyMjIyMjIw0KPiA+ICsjIFBvd2VyUEMgcGxhdGZvcm0gZHJp dmVycw0KPiA+ICtvYmotJChDT05GSUdfUFBDX0U1MDBfQ1BVSURMRSkJCSs9IGNwdWlkbGUtZTUw MC5vDQo+ID4gZGlmZiAtLWdpdCBhL2RyaXZlcnMvY3B1aWRsZS9jcHVpZGxlLWU1MDAuYyBiL2Ry aXZlcnMvY3B1aWRsZS9jcHVpZGxlLQ0KPiBlNTAwLmMNCj4gPiBuZXcgZmlsZSBtb2RlIDEwMDY0 NA0KPiA+IGluZGV4IDAwMDAwMDAuLjE5MTljZWENCj4gPiAtLS0gL2Rldi9udWxsDQo+ID4gKysr IGIvZHJpdmVycy9jcHVpZGxlL2NwdWlkbGUtZTUwMC5jDQo+ID4gQEAgLTAsMCArMSwyMjIgQEAN Cj4gPiArLyoNCj4gPiArICogQ29weXJpZ2h0IDIwMTMgRnJlZXNjYWxlIFNlbWljb25kdWN0b3Is IEluYy4NCj4gPiArICoNCj4gPiArICogQ1BVIElkbGUgZHJpdmVyIGZvciBGcmVlc2NhbGUgUG93 ZXJQQyBlNTAwIGZhbWlseSBwcm9jZXNzb3JzLg0KPiA+ICsgKg0KPiA+ICsgKiBUaGlzIHByb2dy YW0gaXMgZnJlZSBzb2Z0d2FyZTsgeW91IGNhbiByZWRpc3RyaWJ1dGUgaXQgYW5kL29yDQo+IG1v ZGlmeQ0KPiA+ICsgKiBpdCB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEdOVSBHZW5lcmFsIFB1Ymxp YyBMaWNlbnNlIHZlcnNpb24gMiBhcw0KPiA+ICsgKiBwdWJsaXNoZWQgYnkgdGhlIEZyZWUgU29m dHdhcmUgRm91bmRhdGlvbi4NCj4gPiArICoNCj4gPiArICogQXV0aG9yOiBXYW5nIERvbmdzaGVu ZyA8ZG9uZ3NoZW5nLndhbmdAZnJlZXNjYWxlLmNvbT4NCj4gPiArICovDQo+ID4gKw0KPiA+ICsj aW5jbHVkZSA8bGludXgvY3B1Lmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9jcHVpZGxlLmg+DQo+ ID4gKyNpbmNsdWRlIDxsaW51eC9pbml0Lmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9rZXJuZWwu aD4NCj4gPiArI2luY2x1ZGUgPGxpbnV4L21vZHVsZS5oPg0KPiA+ICsjaW5jbHVkZSA8bGludXgv bm90aWZpZXIuaD4NCj4gPiArDQo+ID4gKyNpbmNsdWRlIDxhc20vbWFjaGRlcC5oPg0KPiA+ICsN Cj4gPiArc3RhdGljIHN0cnVjdCBjcHVpZGxlX2RyaXZlciBlNTAwX2lkbGVfZHJpdmVyID0gew0K PiA+ICsJLm5hbWUgPSAiZTUwMF9pZGxlIiwNCj4gPiArCS5vd25lciA9IFRISVNfTU9EVUxFLA0K PiA+ICt9Ow0KPiA+ICsNCj4gPiArc3RhdGljIHN0cnVjdCBjcHVpZGxlX2RldmljZSBfX3BlcmNw dSAqZTUwMF9jcHVpZGxlX2RldmljZXM7DQo+ID4gKw0KPiA+ICtzdGF0aWMgdm9pZCBlNTAwX2Nw dWlkbGUodm9pZCkNCj4gPiArew0KPiA+ICsJLyoNCj4gPiArCSAqIFRoaXMgd291bGQgY2FsbCBv biB0aGUgY3B1aWRsZSBmcmFtZXdvcmssIGFuZCB0aGUgYmFjay1lbmQNCj4gPiArCSAqIGRyaXZl ciB0byBnbyB0byBpZGxlIHN0YXRlcy4NCj4gPiArCSAqLw0KPiA+ICsJaWYgKGNwdWlkbGVfaWRs ZV9jYWxsKCkpIHsNCj4gPiArCQkvKg0KPiA+ICsJCSAqIE9uIGVycm9yLCBleGVjdXRlIGRlZmF1 bHQgaGFuZGxlcg0KPiA+ICsJCSAqIHRvIGdvIGludG8gbG93IHRocmVhZCBwcmlvcml0eSBhbmQg cG9zc2libHkNCj4gPiArCQkgKiBsb3cgcG93ZXIgbW9kZS4NCj4gPiArCQkgKi8NCj4gPiArCQlI TVRfbG93KCk7DQo+ID4gKwkJSE1UX3ZlcnlfbG93KCk7DQo+ID4gKwl9DQo+ID4gK30NCj4gDQo+ IE5vcGUsIHRoaXMgaXMgbm90IHRoZSBwbGFjZSB0byBhZGQgc3VjaCBmdW5jdGlvbi4NCj4gDQpU aGFua3MuDQoNCkJ1dCBXaHkgbm90PyBPbiBwb3dlcnBjIHRoZXJlIGlzIGFscmVhZHkgaGF2ZSBh IGNwdWlkbGUgbWV0aG9kLiBXZSBuZWVkIHRvIGNvbXBhdGlibGUgdGhlbS4NCg0KVW0uLiBhcmNo L3Bvd2VycGMvcGxhdGZvcm1zL3h4eCA/DQoNCj4gPiArc3RhdGljIGludCBwdzEwX2VudGVyKHN0 cnVjdCBjcHVpZGxlX2RldmljZSAqZGV2LA0KPiA+ICsJCQlzdHJ1Y3QgY3B1aWRsZV9kcml2ZXIg KmRydiwgaW50IGluZGV4KQ0KPiA+ICt7DQo+ID4gKwlmc2xfY3B1aWRsZV93YWl0KCk7DQo+ID4g KwlyZXR1cm4gaW5kZXg7DQo+ID4gK30NCj4gPiArDQo+ID4gK3N0YXRpYyBzdHJ1Y3QgY3B1aWRs ZV9zdGF0ZSBmc2xfcHdfaWRsZV9zdGF0ZXNbXSA9IHsNCj4gPiArCXsNCj4gPiArCQkubmFtZSA9 ICJwdzEwIiwNCj4gPiArCQkuZGVzYyA9ICJwdzEwIiwNCj4gPiArCQkuZmxhZ3MgPSBDUFVJRExF X0ZMQUdfVElNRV9WQUxJRCwNCj4gPiArCQkuZXhpdF9sYXRlbmN5ID0gMCwNCj4gPiArCQkudGFy Z2V0X3Jlc2lkZW5jeSA9IDAsDQo+ID4gKwkJLmVudGVyID0gJnB3MTBfZW50ZXINCj4gPiArCX0s DQo+ID4gK307DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGNwdV9ob3RwbHVnX25vdGlmeShzdHJ1 Y3Qgbm90aWZpZXJfYmxvY2sgKm4sDQo+ID4gKwkJCXVuc2lnbmVkIGxvbmcgYWN0aW9uLCB2b2lk ICpoY3B1KQ0KPiA+ICt7DQo+ID4gKwl1bnNpZ25lZCBsb25nIGhvdGNwdSA9ICh1bnNpZ25lZCBs b25nKWhjcHU7DQo+ID4gKwlzdHJ1Y3QgY3B1aWRsZV9kZXZpY2UgKmRldiA9DQo+ID4gKwkJCXBl cl9jcHVfcHRyKGU1MDBfY3B1aWRsZV9kZXZpY2VzLCBob3RjcHUpOw0KPiA+ICsNCj4gPiArCWlm IChkZXYgJiYgY3B1aWRsZV9nZXRfZHJpdmVyKCkpIHsNCj4gPiArCQlzd2l0Y2ggKGFjdGlvbikg ew0KPiA+ICsJCWNhc2UgQ1BVX09OTElORToNCj4gPiArCQljYXNlIENQVV9PTkxJTkVfRlJPWkVO Og0KPiA+ICsJCQljcHVpZGxlX3BhdXNlX2FuZF9sb2NrKCk7DQo+ID4gKwkJCWNwdWlkbGVfZW5h YmxlX2RldmljZShkZXYpOw0KPiA+ICsJCQljcHVpZGxlX3Jlc3VtZV9hbmRfdW5sb2NrKCk7DQo+ ID4gKwkJCWJyZWFrOw0KPiA+ICsNCj4gPiArCQljYXNlIENQVV9ERUFEOg0KPiA+ICsJCWNhc2Ug Q1BVX0RFQURfRlJPWkVOOg0KPiA+ICsJCQljcHVpZGxlX3BhdXNlX2FuZF9sb2NrKCk7DQo+ID4g KwkJCWNwdWlkbGVfZGlzYWJsZV9kZXZpY2UoZGV2KTsNCj4gPiArCQkJY3B1aWRsZV9yZXN1bWVf YW5kX3VubG9jaygpOw0KPiA+ICsJCQlicmVhazsNCj4gPiArDQo+ID4gKwkJZGVmYXVsdDoNCj4g PiArCQkJcmV0dXJuIE5PVElGWV9ET05FOw0KPiA+ICsJCX0NCj4gPiArCX0NCj4gPiArDQo+ID4g KwlyZXR1cm4gTk9USUZZX09LOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgc3RydWN0IG5v dGlmaWVyX2Jsb2NrIGNwdV9ob3RwbHVnX25vdGlmaWVyID0gew0KPiA+ICsJLm5vdGlmaWVyX2Nh bGwgPSBjcHVfaG90cGx1Z19ub3RpZnksDQo+ID4gK307DQo+IA0KPiBUaGlzIHNob3VsZCBnbyB0 byB0aGUgY3B1aWRsZSBmcmFtZXdvcmsuDQo+IA0KWWVzLCBJIHNlZSwgRGVlcHRoaSB3aWxsIHBv c3QgaXQuLi4NCjooLCBUaGlzIHBhdGNoIGlzIHJlbHlpbmcgb24gZm9yIERlZXB0aGkncyBwYXRj aCBhYm91dCAiaG90cGx1ZyBub3RpZmllciIuDQoNCj4gPiArDQo+ID4gKy8qDQo+ID4gKyAqIGU1 MDBfaWRsZV9kZXZpY2VzX2luaXQodm9pZCkNCj4gPiArICogYWxsb2NhdGUsIGluaXRpYWxpemUg YW5kIHJlZ2lzdGVyIGNwdWlkbGUgZGV2aWNlDQo+ID4gKyAqLw0KPiA+ICtzdGF0aWMgaW50IGU1 MDBfaWRsZV9kZXZpY2VzX2luaXQodm9pZCkNCj4gPiArew0KPiA+ICsJaW50IGk7DQo+ID4gKwlz dHJ1Y3QgY3B1aWRsZV9kcml2ZXIgKmRydiA9ICZlNTAwX2lkbGVfZHJpdmVyOw0KPiA+ICsJc3Ry dWN0IGNwdWlkbGVfZGV2aWNlICpkZXY7DQo+ID4gKw0KPiA+ICsJZTUwMF9jcHVpZGxlX2Rldmlj ZXMgPSBhbGxvY19wZXJjcHUoc3RydWN0IGNwdWlkbGVfZGV2aWNlKTsNCj4gPiArCWlmICghZTUw MF9jcHVpZGxlX2RldmljZXMpDQo+ID4gKwkJcmV0dXJuIC1FTk9NRU07DQo+ID4gKw0KPiA+ICsJ Zm9yX2VhY2hfcG9zc2libGVfY3B1KGkpIHsNCj4gPiArCQlkZXYgPSBwZXJfY3B1X3B0cihlNTAw X2NwdWlkbGVfZGV2aWNlcywgaSk7DQo+ID4gKwkJZGV2LT5zdGF0ZV9jb3VudCA9IGRydi0+c3Rh dGVfY291bnQ7DQo+ID4gKwkJZGV2LT5jcHUgPSBpOw0KPiA+ICsNCj4gPiArCQlpZiAoY3B1aWRs ZV9yZWdpc3Rlcl9kZXZpY2UoZGV2KSkgew0KPiA+ICsJCQlwcl9lcnIoImNwdWlkbGVfcmVnaXN0 ZXJfZGV2aWNlICVkIGZhaWxlZCFcbiIsIGkpOw0KPiA+ICsJCQlyZXR1cm4gLUVJTzsNCj4gPiAr CQl9DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcmV0dXJuIDA7DQo+ID4gK30NCj4gPiArDQo+ID4g Ky8qDQo+ID4gKyAqIGU1MDBfaWRsZV9kZXZpY2VzX3VuaW5pdCh2b2lkKQ0KPiA+ICsgKiB1bnJl Z2lzdGVyIGNwdWlkbGUgZGV2aWNlcyBhbmQgZGUtYWxsb2NhdGUgbWVtb3J5DQo+ID4gKyAqLw0K PiA+ICtzdGF0aWMgdm9pZCBlNTAwX2lkbGVfZGV2aWNlc191bmluaXQodm9pZCkNCj4gPiArew0K PiA+ICsJaW50IGk7DQo+ID4gKwlzdHJ1Y3QgY3B1aWRsZV9kZXZpY2UgKmRldjsNCj4gPiArDQo+ ID4gKwlpZiAoIWU1MDBfY3B1aWRsZV9kZXZpY2VzKQ0KPiA+ICsJCXJldHVybjsNCj4gPiArDQo+ ID4gKwlmb3JfZWFjaF9wb3NzaWJsZV9jcHUoaSkgew0KPiA+ICsJCWRldiA9IHBlcl9jcHVfcHRy KGU1MDBfY3B1aWRsZV9kZXZpY2VzLCBpKTsNCj4gPiArCQljcHVpZGxlX3VucmVnaXN0ZXJfZGV2 aWNlKGRldik7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJZnJlZV9wZXJjcHUoZTUwMF9jcHVpZGxl X2RldmljZXMpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgdm9pZCBlNTAwX2NwdWlkbGVf ZHJpdmVyX2luaXQodW5zaWduZWQgaW50IG1heF9pZGxlX3N0YXRlLA0KPiA+ICsJCXN0cnVjdCBj cHVpZGxlX3N0YXRlICpjcHVpZGxlX3N0YXRlX3RhYmxlKQ0KPiA+ICt7DQo+ID4gKwlpbnQgaWRs ZV9zdGF0ZTsNCj4gPiArCXN0cnVjdCBjcHVpZGxlX2RyaXZlciAqZHJ2ID0gJmU1MDBfaWRsZV9k cml2ZXI7DQo+ID4gKw0KPiA+ICsJZHJ2LT5zdGF0ZV9jb3VudCA9IDA7DQo+ID4gKw0KPiA+ICsJ Zm9yIChpZGxlX3N0YXRlID0gMDsgaWRsZV9zdGF0ZSA8IG1heF9pZGxlX3N0YXRlOyArK2lkbGVf c3RhdGUpIHsNCj4gPiArCQlpZiAoIWNwdWlkbGVfc3RhdGVfdGFibGVbaWRsZV9zdGF0ZV0uZW50 ZXIpDQo+ID4gKwkJCWJyZWFrOw0KPiA+ICsNCj4gPiArCQlkcnYtPnN0YXRlc1tkcnYtPnN0YXRl X2NvdW50XSA9DQo+IGNwdWlkbGVfc3RhdGVfdGFibGVbaWRsZV9zdGF0ZV07DQo+ID4gKwkJZHJ2 LT5zdGF0ZV9jb3VudCsrOw0KPiA+ICsJfQ0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50 IGNwdV9pc19mZWF0dXJlKHVuc2lnbmVkIGxvbmcgZmVhdHVyZSkNCj4gPiArew0KPiA+ICsJcmV0 dXJuIChjdXJfY3B1X3NwZWMtPmNwdV9mZWF0dXJlcyA9PSBmZWF0dXJlKTsNCj4gPiArfQ0KPiA+ ICsNCj4gPiArc3RhdGljIGludCBfX2luaXQgZTUwMF9pZGxlX2luaXQodm9pZCkNCj4gPiArew0K PiA+ICsJc3RydWN0IGNwdWlkbGVfc3RhdGUgKmNwdWlkbGVfc3RhdGVfdGFibGUgPSBOVUxMOw0K PiA+ICsJc3RydWN0IGNwdWlkbGVfZHJpdmVyICpkcnYgPSAmZTUwMF9pZGxlX2RyaXZlcjsNCj4g PiArCWludCBlcnI7DQo+ID4gKwl1bnNpZ25lZCBpbnQgbWF4X2lkbGVfc3RhdGUgPSAwOw0KPiA+ ICsNCj4gPiArCWlmIChjcHVpZGxlX2Rpc2FibGUgIT0gSURMRV9OT19PVkVSUklERSkNCj4gPiAr CQlyZXR1cm4gLUVOT0RFVjsNCj4gPiArDQo+ID4gKwlpZiAoY3B1X2lzX2ZlYXR1cmUoQ1BVX0ZU UlNfRTUwME1DKSB8fA0KPiBjcHVfaXNfZmVhdHVyZShDUFVfRlRSU19FNTUwMCkgfHwNCj4gPiAr CQkJY3B1X2lzX2ZlYXR1cmUoQ1BVX0ZUUlNfRTY1MDApKSB7DQo+ID4gKwkJY3B1aWRsZV9zdGF0 ZV90YWJsZSA9IGZzbF9wd19pZGxlX3N0YXRlczsNCj4gPiArCQltYXhfaWRsZV9zdGF0ZSA9IEFS UkFZX1NJWkUoZnNsX3B3X2lkbGVfc3RhdGVzKTsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlpZiAo IWNwdWlkbGVfc3RhdGVfdGFibGUgfHwgIW1heF9pZGxlX3N0YXRlKQ0KPiA+ICsJCXJldHVybiAt RVBFUk07DQo+IA0KPiBQbGVhc2UgdXNlIGRpZmZlcmVudCBkcml2ZXJzIGZvciBlYWNoIGFuZCB0 aGVuIHJlZ2lzdGVyIHRoZSByaWdodCBvbmUNCj4gaW5zdGVhZCBvZiBzdGF0ZSBjb3VudCBjb252 b2x1dGlvbnMuDQo+IA0KPiBUaGVuIHVzZSBjcHVpZGxlX3JlZ2lzdGVyKCZteWRyaXZlciwgTlVM TCkgYW5kIGdldCByaWQgb2YgdGhlIGR1cGxpY2F0ZQ0KPiBpbml0aWFsaXphdGlvbiByb3V0aW5l Lg0KPiANClllcywgVGhhbmtzLCBUaGlzIHBhdGNoIGtlZXAgdXNpbmcgY3B1aWRsZV9yZWdpc3Rl cl9kZXZpY2UoKSwgYmVjYXVzZSB3ZSBuZWVkIHRvDQpzdXBwb3J0IGNwdSBob3RwbHVnLiBJIHdp bGwgZml4ICJkZXZpY2UiIGlzc3VlIGluIHRoaXMgZHJpdmVyLCBhZnRlcg0KRGVlcHRoaSBEaGFy d2FyIDxkZWVwdGhpQGxpbnV4LnZuZXQuaWJtLmNvbT4gYWRkIGEgaG90cGx1ZyBoYW5kbGVyDQpp bnRvIGNwdWlkbGUgZnJlYW13b3JrLg0KDQo+IA0KPiA+ICsJZTUwMF9jcHVpZGxlX2RyaXZlcl9p bml0KG1heF9pZGxlX3N0YXRlLCBjcHVpZGxlX3N0YXRlX3RhYmxlKTsNCj4gPiArDQo+ID4gKwlp ZiAoIWRydi0+c3RhdGVfY291bnQpDQo+ID4gKwkJcmV0dXJuIC1FUEVSTTsNCj4gPiArDQo+ID4g KwllcnIgPSBjcHVpZGxlX3JlZ2lzdGVyX2RyaXZlcihkcnYpOw0KPiA+ICsJaWYgKGVycikgew0K PiA+ICsJCXByX2VycigiUmVnaXN0ZXIgZTUwMCBmYW1pbHkgY3B1aWRsZSBkcml2ZXIgZmFpbGVk LlxuIik7DQo+ID4gKw0KPiA+ICsJCXJldHVybiBlcnI7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJ ZXJyID0gZTUwMF9pZGxlX2RldmljZXNfaW5pdCgpOw0KPiA+ICsJaWYgKGVycikNCj4gPiArCQln b3RvIG91dDsNCj4gPiArDQo+ID4gKwllcnIgPSByZWdpc3Rlcl9jcHVfbm90aWZpZXIoJmNwdV9o b3RwbHVnX25vdGlmaWVyKTsNCj4gPiArCWlmIChlcnIpDQo+ID4gKwkJZ290byBvdXQ7DQo+ID4g Kw0KPiA+ICsJcHBjX21kLnBvd2VyX3NhdmUgPSBlNTAwX2NwdWlkbGU7DQo+IA0KPiBUaGlzIGlz IG5vdCB0aGUgcGxhY2UuDQo+IA0KPiA+ICsNCj4gPiArCXByX2luZm8oImU1MDBfaWRsZV9kcml2 ZXIgcmVnaXN0ZXJlZC5cbiIpOw0KPiA+ICsNCj4gPiArCXJldHVybiAwOw0KPiA+ICsNCj4gPiAr b3V0Og0KPiA+ICsJZTUwMF9pZGxlX2RldmljZXNfdW5pbml0KCk7DQo+ID4gKwljcHVpZGxlX3Vu cmVnaXN0ZXJfZHJpdmVyKGRydik7DQo+ID4gKw0KPiA+ICsJcHJfZXJyKCJSZWdpc3RlciBlNTAw IGZhbWlseSBjcHVpZGxlIGRyaXZlciBmYWlsZWQuXG4iKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4g ZXJyOw0KPiA+ICt9DQo+ID4gK2RldmljZV9pbml0Y2FsbChlNTAwX2lkbGVfaW5pdCk7DQo+ID4N Cj4gDQo+IA0KPiAtLQ0KPiAgPGh0dHA6Ly93d3cubGluYXJvLm9yZy8+IExpbmFyby5vcmcg4pSC IE9wZW4gc291cmNlIHNvZnR3YXJlIGZvciBBUk0gU29Dcw0KPiANCj4gRm9sbG93IExpbmFybzog IDxodHRwOi8vd3d3LmZhY2Vib29rLmNvbS9wYWdlcy9MaW5hcm8+IEZhY2Vib29rIHwNCj4gPGh0 dHA6Ly90d2l0dGVyLmNvbS8jIS9saW5hcm9vcmc+IFR3aXR0ZXIgfA0KPiA8aHR0cDovL3d3dy5s aW5hcm8ub3JnL2xpbmFyby1ibG9nLz4gQmxvZw0KPiANCg0K -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
On 07/30/2013 04:32 PM, Wang Dongsheng-B40534 wrote: Hi Dongsheng, I have posted out a generic powerpc idle backend driver ccing you. Please take a look at it and integrate your platform idle states into it. Right now, cpu hotplug notifier is common for all powerpc. This shouldn't hinder you. This will reduce code duplication and would make it easier to plug into the framework. All you need is platform specific idle states table and config changes. Regards, Deepthi > >> -----Original Message----- >> From: Daniel Lezcano [mailto:daniel.lezcano@linaro.org] >> Sent: Tuesday, July 30, 2013 5:51 PM >> To: Wang Dongsheng-B40534 >> Cc: Wood Scott-B07421; rjw@sisk.pl; benh@kernel.crashing.org; Li Yang- >> R58472; Zhao Chenhui-B35336; linux-pm@vger.kernel.org; linuxppc- >> dev@lists.ozlabs.org >> Subject: Re: [PATCH] cpuidle: add freescale e500 family porcessors idle >> support >> >> On 07/30/2013 09:00 AM, Dongsheng Wang wrote: >>> From: Wang Dongsheng <dongsheng.wang@freescale.com> >>> >>> Add cpuidle support for e500 family, using cpuidle framework to manage >>> various low power modes. The new implementation will remain compatible >>> with original idle method. >>> >>> Initially, this supports PW10, and subsequent patches will support >>> PW20/DOZE/NAP. >>> >>> Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com> >>> --- >>> This patch keep using cpuidle_register_device(), because we need to >>> support cpu hotplug. I will fix "device" issue in this driver, after >>> Deepthi Dharwar <deepthi@linux.vnet.ibm.com> add a hotplug handler >>> into cpuidle freamwork. >>> >>> diff --git a/arch/powerpc/include/asm/machdep.h >>> b/arch/powerpc/include/asm/machdep.h >>> index 8b48090..cbdbe25 100644 >>> --- a/arch/powerpc/include/asm/machdep.h >>> +++ b/arch/powerpc/include/asm/machdep.h >>> @@ -271,6 +271,16 @@ extern void power7_idle(void); extern void >>> ppc6xx_idle(void); extern void book3e_idle(void); >>> >>> +/* Wait for Interrupt */ >>> +static inline void fsl_cpuidle_wait(void) { #ifdef CONFIG_PPC64 >>> + book3e_idle(); >>> +#else >>> + e500_idle(); >>> +#endif >>> +} >>> + >>> /* >>> * ppc_md contains a copy of the machine description structure for the >>> * current platform. machine_id contains the initial address where the >>> diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig >>> index b3fb81d..7ed114b 100644 >>> --- a/drivers/cpuidle/Kconfig >>> +++ b/drivers/cpuidle/Kconfig >>> @@ -35,6 +35,11 @@ depends on ARM >>> source "drivers/cpuidle/Kconfig.arm" >>> endmenu >>> >>> +menu "PowerPC CPU Idle Drivers" >>> +depends on PPC32 || PPC64 >>> +source "drivers/cpuidle/Kconfig.powerpc" >>> +endmenu >>> + >>> endif >>> >>> config ARCH_NEEDS_CPU_IDLE_COUPLED >>> diff --git a/drivers/cpuidle/Kconfig.powerpc >> b/drivers/cpuidle/Kconfig.powerpc >>> new file mode 100644 >>> index 0000000..9f3f5ef >>> --- /dev/null >>> +++ b/drivers/cpuidle/Kconfig.powerpc >>> @@ -0,0 +1,9 @@ >>> +# >>> +# PowerPC CPU Idle drivers >>> +# >>> + >>> +config PPC_E500_CPUIDLE >>> + bool "CPU Idle Driver for E500 family processors" >>> + depends on FSL_SOC_BOOKE >>> + help >>> + Select this to enable cpuidle on e500 family processors. >>> diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile >>> index 0b9d200..0dde3db 100644 >>> --- a/drivers/cpuidle/Makefile >>> +++ b/drivers/cpuidle/Makefile >>> @@ -11,3 +11,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle- >> calxeda.o >>> obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o >>> obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o >>> obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o >>> + >>> >> +######################################################################## >> ########## >>> +# PowerPC platform drivers >>> +obj-$(CONFIG_PPC_E500_CPUIDLE) += cpuidle-e500.o >>> diff --git a/drivers/cpuidle/cpuidle-e500.c b/drivers/cpuidle/cpuidle- >> e500.c >>> new file mode 100644 >>> index 0000000..1919cea >>> --- /dev/null >>> +++ b/drivers/cpuidle/cpuidle-e500.c >>> @@ -0,0 +1,222 @@ >>> +/* >>> + * Copyright 2013 Freescale Semiconductor, Inc. >>> + * >>> + * CPU Idle driver for Freescale PowerPC e500 family processors. >>> + * >>> + * This program is free software; you can redistribute it and/or >> modify >>> + * it under the terms of the GNU General Public License version 2 as >>> + * published by the Free Software Foundation. >>> + * >>> + * Author: Wang Dongsheng <dongsheng.wang@freescale.com> >>> + */ >>> + >>> +#include <linux/cpu.h> >>> +#include <linux/cpuidle.h> >>> +#include <linux/init.h> >>> +#include <linux/kernel.h> >>> +#include <linux/module.h> >>> +#include <linux/notifier.h> >>> + >>> +#include <asm/machdep.h> >>> + >>> +static struct cpuidle_driver e500_idle_driver = { >>> + .name = "e500_idle", >>> + .owner = THIS_MODULE, >>> +}; >>> + >>> +static struct cpuidle_device __percpu *e500_cpuidle_devices; >>> + >>> +static void e500_cpuidle(void) >>> +{ >>> + /* >>> + * This would call on the cpuidle framework, and the back-end >>> + * driver to go to idle states. >>> + */ >>> + if (cpuidle_idle_call()) { >>> + /* >>> + * On error, execute default handler >>> + * to go into low thread priority and possibly >>> + * low power mode. >>> + */ >>> + HMT_low(); >>> + HMT_very_low(); >>> + } >>> +} >> >> Nope, this is not the place to add such function. >> > Thanks. > > But Why not? On powerpc there is already have a cpuidle method. We need to compatible them. > > Um.. arch/powerpc/platforms/xxx ? > >>> +static int pw10_enter(struct cpuidle_device *dev, >>> + struct cpuidle_driver *drv, int index) >>> +{ >>> + fsl_cpuidle_wait(); >>> + return index; >>> +} >>> + >>> +static struct cpuidle_state fsl_pw_idle_states[] = { >>> + { >>> + .name = "pw10", >>> + .desc = "pw10", >>> + .flags = CPUIDLE_FLAG_TIME_VALID, >>> + .exit_latency = 0, >>> + .target_residency = 0, >>> + .enter = &pw10_enter >>> + }, >>> +}; >>> + >>> +static int cpu_hotplug_notify(struct notifier_block *n, >>> + unsigned long action, void *hcpu) >>> +{ >>> + unsigned long hotcpu = (unsigned long)hcpu; >>> + struct cpuidle_device *dev = >>> + per_cpu_ptr(e500_cpuidle_devices, hotcpu); >>> + >>> + if (dev && cpuidle_get_driver()) { >>> + switch (action) { >>> + case CPU_ONLINE: >>> + case CPU_ONLINE_FROZEN: >>> + cpuidle_pause_and_lock(); >>> + cpuidle_enable_device(dev); >>> + cpuidle_resume_and_unlock(); >>> + break; >>> + >>> + case CPU_DEAD: >>> + case CPU_DEAD_FROZEN: >>> + cpuidle_pause_and_lock(); >>> + cpuidle_disable_device(dev); >>> + cpuidle_resume_and_unlock(); >>> + break; >>> + >>> + default: >>> + return NOTIFY_DONE; >>> + } >>> + } >>> + >>> + return NOTIFY_OK; >>> +} >>> + >>> +static struct notifier_block cpu_hotplug_notifier = { >>> + .notifier_call = cpu_hotplug_notify, >>> +}; >> >> This should go to the cpuidle framework. >> > Yes, I see, Deepthi will post it... > :(, This patch is relying on for Deepthi's patch about "hotplug notifier". > >>> + >>> +/* >>> + * e500_idle_devices_init(void) >>> + * allocate, initialize and register cpuidle device >>> + */ >>> +static int e500_idle_devices_init(void) >>> +{ >>> + int i; >>> + struct cpuidle_driver *drv = &e500_idle_driver; >>> + struct cpuidle_device *dev; >>> + >>> + e500_cpuidle_devices = alloc_percpu(struct cpuidle_device); >>> + if (!e500_cpuidle_devices) >>> + return -ENOMEM; >>> + >>> + for_each_possible_cpu(i) { >>> + dev = per_cpu_ptr(e500_cpuidle_devices, i); >>> + dev->state_count = drv->state_count; >>> + dev->cpu = i; >>> + >>> + if (cpuidle_register_device(dev)) { >>> + pr_err("cpuidle_register_device %d failed!\n", i); >>> + return -EIO; >>> + } >>> + } >>> + >>> + return 0; >>> +} >>> + >>> +/* >>> + * e500_idle_devices_uninit(void) >>> + * unregister cpuidle devices and de-allocate memory >>> + */ >>> +static void e500_idle_devices_uninit(void) >>> +{ >>> + int i; >>> + struct cpuidle_device *dev; >>> + >>> + if (!e500_cpuidle_devices) >>> + return; >>> + >>> + for_each_possible_cpu(i) { >>> + dev = per_cpu_ptr(e500_cpuidle_devices, i); >>> + cpuidle_unregister_device(dev); >>> + } >>> + >>> + free_percpu(e500_cpuidle_devices); >>> +} >>> + >>> +static void e500_cpuidle_driver_init(unsigned int max_idle_state, >>> + struct cpuidle_state *cpuidle_state_table) >>> +{ >>> + int idle_state; >>> + struct cpuidle_driver *drv = &e500_idle_driver; >>> + >>> + drv->state_count = 0; >>> + >>> + for (idle_state = 0; idle_state < max_idle_state; ++idle_state) { >>> + if (!cpuidle_state_table[idle_state].enter) >>> + break; >>> + >>> + drv->states[drv->state_count] = >> cpuidle_state_table[idle_state]; >>> + drv->state_count++; >>> + } >>> +} >>> + >>> +static int cpu_is_feature(unsigned long feature) >>> +{ >>> + return (cur_cpu_spec->cpu_features == feature); >>> +} >>> + >>> +static int __init e500_idle_init(void) >>> +{ >>> + struct cpuidle_state *cpuidle_state_table = NULL; >>> + struct cpuidle_driver *drv = &e500_idle_driver; >>> + int err; >>> + unsigned int max_idle_state = 0; >>> + >>> + if (cpuidle_disable != IDLE_NO_OVERRIDE) >>> + return -ENODEV; >>> + >>> + if (cpu_is_feature(CPU_FTRS_E500MC) || >> cpu_is_feature(CPU_FTRS_E5500) || >>> + cpu_is_feature(CPU_FTRS_E6500)) { >>> + cpuidle_state_table = fsl_pw_idle_states; >>> + max_idle_state = ARRAY_SIZE(fsl_pw_idle_states); >>> + } >>> + >>> + if (!cpuidle_state_table || !max_idle_state) >>> + return -EPERM; >> >> Please use different drivers for each and then register the right one >> instead of state count convolutions. >> >> Then use cpuidle_register(&mydriver, NULL) and get rid of the duplicate >> initialization routine. >> > Yes, Thanks, This patch keep using cpuidle_register_device(), because we need to > support cpu hotplug. I will fix "device" issue in this driver, after > Deepthi Dharwar <deepthi@linux.vnet.ibm.com> add a hotplug handler > into cpuidle freamwork. > >> >>> + e500_cpuidle_driver_init(max_idle_state, cpuidle_state_table); >>> + >>> + if (!drv->state_count) >>> + return -EPERM; >>> + >>> + err = cpuidle_register_driver(drv); >>> + if (err) { >>> + pr_err("Register e500 family cpuidle driver failed.\n"); >>> + >>> + return err; >>> + } >>> + >>> + err = e500_idle_devices_init(); >>> + if (err) >>> + goto out; >>> + >>> + err = register_cpu_notifier(&cpu_hotplug_notifier); >>> + if (err) >>> + goto out; >>> + >>> + ppc_md.power_save = e500_cpuidle; >> >> This is not the place. >> >>> + >>> + pr_info("e500_idle_driver registered.\n"); >>> + >>> + return 0; >>> + >>> +out: >>> + e500_idle_devices_uninit(); >>> + cpuidle_unregister_driver(drv); >>> + >>> + pr_err("Register e500 family cpuidle driver failed.\n"); >>> + >>> + return err; >>> +} >>> +device_initcall(e500_idle_init); >>> >> >> >> -- >> <http://www.linaro.org/> Linaro.org ? Open source software for ARM SoCs >> >> Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook | >> <http://twitter.com/#!/linaroorg> Twitter | >> <http://www.linaro.org/linaro-blog/> Blog >> > > _______________________________________________ > Linuxppc-dev mailing list > Linuxppc-dev@lists.ozlabs.org > https://lists.ozlabs.org/listinfo/linuxppc-dev > -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
> -----Original Message----- > From: Wood Scott-B07421 > Sent: Wednesday, July 31, 2013 3:38 AM > To: Wang Dongsheng-B40534 > Cc: rjw@sisk.pl; daniel.lezcano@linaro.org; benh@kernel.crashing.org; Li > Yang-R58472; Zhao Chenhui-B35336; linux-pm@vger.kernel.org; linuxppc- > dev@lists.ozlabs.org > Subject: Re: [PATCH] cpuidle: add freescale e500 family porcessors idle > support > > On 07/30/2013 02:00:03 AM, Dongsheng Wang wrote: > > From: Wang Dongsheng <dongsheng.wang@freescale.com> > > > > Add cpuidle support for e500 family, using cpuidle framework to > > manage various low power modes. The new implementation will remain > > compatible with original idle method. > > > > Initially, this supports PW10, and subsequent patches will support > > PW20/DOZE/NAP. > > Could you explain what the cpuidle framework does for us that the > current idle code doesn't? > The current idle code, Only a state of low power can make the core idle. The core can't get into more low power state. > In particular, what scenario do you see where we would require a > software > governor to choose between idle states, and how much power is saved > compared to a simpler approach? There is timer that can be used to > automatically enter PW20 after a certain amount of time in PW10. Yes, the hardware can automatically enter PW20 state. But this is hardware feature, we need to software to manage it. Only for PW20 state, we can drop this cpuidle and using the hardware to control it. But if we need to support PH10/PH15/PH20/PH30, the current idle code cannot support them. > How much better results do you get from a software governor? Do we even > have the right data to characterize each state so that a software governor > could make good decisions? Is cpuidle capable of governing the interval > of such a timer, rather than directly governing states? > From now on we did not benchmark these data, because we only have PW10 state. I can do support doze/nap for e6500. To get some data to show you. > As for doze/nap, why would we want to use those on newer cores? Do you > have numbers for how much power each mode saves? > The PH state is plan to support, if the core can make into more low power state, why not to do this. PH10(doze)/PH15(nap)/PH20/PH30, These states can save more CPU power. > Active governors may be useful on older cores that only have doze/nap, > to > select between them, but if that's the use case then why start with > pw10? Pw10 is supported on E500MC/E5500/E6500. And we plan to support PW20 for E65OO core. I will take doze/nap up a bit later. > And I'd want to see numbers for how much power nap saves versus doze. > > > Signed-off-by: Wang Dongsheng <dongsheng.wang@freescale.com> > > --- > > This patch keep using cpuidle_register_device(), because we need to > > support cpu > > hotplug. I will fix "device" issue in this driver, after > > Deepthi Dharwar <deepthi@linux.vnet.ibm.com> add a hotplug handler > > into cpuidle > > freamwork. > > Where's the diffstat? > See, http://patchwork.ozlabs.org/patch/260997/ > > @@ -0,0 +1,222 @@ > > +/* > > + * Copyright 2013 Freescale Semiconductor, Inc. > > + * > > + * CPU Idle driver for Freescale PowerPC e500 family processors. > > + * > > + * This program is free software; you can redistribute it and/or > > modify > > + * it under the terms of the GNU General Public License version 2 as > > + * published by the Free Software Foundation. > > + * > > + * Author: Wang Dongsheng <dongsheng.wang@freescale.com> > > + */ > > Is this derived from some other file? It looks like it... Where's the > attribution? > The copyright is from drivers/cpufreq/ppc-corenet-cpufreq.c > > +#include <linux/cpu.h> > > +#include <linux/cpuidle.h> > > +#include <linux/init.h> > > +#include <linux/kernel.h> > > +#include <linux/module.h> > > +#include <linux/notifier.h> > > + > > +#include <asm/machdep.h> > > + > > +static struct cpuidle_driver e500_idle_driver = { > > + .name = "e500_idle", > > + .owner = THIS_MODULE, > > +}; > > + > > +static struct cpuidle_device __percpu *e500_cpuidle_devices; > > + > > +static void e500_cpuidle(void) > > +{ > > + /* > > + * This would call on the cpuidle framework, and the back-end > > + * driver to go to idle states. > > + */ > > + if (cpuidle_idle_call()) { > > + /* > > + * On error, execute default handler > > + * to go into low thread priority and possibly > > + * low power mode. > > + */ > > + HMT_low(); > > + HMT_very_low(); > > This HMT stuff doesn't do anything on e500 derivatives AFAIK. > Yes, there should do nothing, let arch_cpu_idle to do the failed. > > +static struct cpuidle_state fsl_pw_idle_states[] = { > > + { > > + .name = "pw10", > > + .desc = "pw10", > > + .flags = CPUIDLE_FLAG_TIME_VALID, > > + .exit_latency = 0, > > + .target_residency = 0, > > + .enter = &pw10_enter > > Where is pw10_enter defined? > In this patch.. > > +static int cpu_is_feature(unsigned long feature) > > +{ > > + return (cur_cpu_spec->cpu_features == feature); > > +} > > + > > +static int __init e500_idle_init(void) > > +{ > > + struct cpuidle_state *cpuidle_state_table = NULL; > > + struct cpuidle_driver *drv = &e500_idle_driver; > > + int err; > > + unsigned int max_idle_state = 0; > > + > > + if (cpuidle_disable != IDLE_NO_OVERRIDE) > > + return -ENODEV; > > + > > + if (cpu_is_feature(CPU_FTRS_E500MC) || > > cpu_is_feature(CPU_FTRS_E5500) || > > + cpu_is_feature(CPU_FTRS_E6500)) { > > There's no guarantee that a CPU with the same set of features is the > exact same CPU. > > What specific feature are you looking for here? > Here is the type of the core. E500MC,E5500,E6500 do wait. > > + cpuidle_state_table = fsl_pw_idle_states; > > + max_idle_state = ARRAY_SIZE(fsl_pw_idle_states); > > + } > > + > > + if (!cpuidle_state_table || !max_idle_state) > > + return -EPERM; > > ENODEV? > Looks better than EPERM. -dongsheng -- To unsubscribe from this list: send the line "unsubscribe linux-pm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h index 8b48090..cbdbe25 100644 --- a/arch/powerpc/include/asm/machdep.h +++ b/arch/powerpc/include/asm/machdep.h @@ -271,6 +271,16 @@ extern void power7_idle(void); extern void ppc6xx_idle(void); extern void book3e_idle(void); +/* Wait for Interrupt */ +static inline void fsl_cpuidle_wait(void) +{ +#ifdef CONFIG_PPC64 + book3e_idle(); +#else + e500_idle(); +#endif +} + /* * ppc_md contains a copy of the machine description structure for the * current platform. machine_id contains the initial address where the diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig index b3fb81d..7ed114b 100644 --- a/drivers/cpuidle/Kconfig +++ b/drivers/cpuidle/Kconfig @@ -35,6 +35,11 @@ depends on ARM source "drivers/cpuidle/Kconfig.arm" endmenu +menu "PowerPC CPU Idle Drivers" +depends on PPC32 || PPC64 +source "drivers/cpuidle/Kconfig.powerpc" +endmenu + endif config ARCH_NEEDS_CPU_IDLE_COUPLED diff --git a/drivers/cpuidle/Kconfig.powerpc b/drivers/cpuidle/Kconfig.powerpc new file mode 100644 index 0000000..9f3f5ef --- /dev/null +++ b/drivers/cpuidle/Kconfig.powerpc @@ -0,0 +1,9 @@ +# +# PowerPC CPU Idle drivers +# + +config PPC_E500_CPUIDLE + bool "CPU Idle Driver for E500 family processors" + depends on FSL_SOC_BOOKE + help + Select this to enable cpuidle on e500 family processors. diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile index 0b9d200..0dde3db 100644 --- a/drivers/cpuidle/Makefile +++ b/drivers/cpuidle/Makefile @@ -11,3 +11,7 @@ obj-$(CONFIG_ARM_HIGHBANK_CPUIDLE) += cpuidle-calxeda.o obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o + +################################################################################## +# PowerPC platform drivers +obj-$(CONFIG_PPC_E500_CPUIDLE) += cpuidle-e500.o diff --git a/drivers/cpuidle/cpuidle-e500.c b/drivers/cpuidle/cpuidle-e500.c new file mode 100644 index 0000000..1919cea --- /dev/null +++ b/drivers/cpuidle/cpuidle-e500.c @@ -0,0 +1,222 @@ +/* + * Copyright 2013 Freescale Semiconductor, Inc. + * + * CPU Idle driver for Freescale PowerPC e500 family processors. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * Author: Wang Dongsheng <dongsheng.wang@freescale.com> + */ + +#include <linux/cpu.h> +#include <linux/cpuidle.h> +#include <linux/init.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/notifier.h> + +#include <asm/machdep.h> + +static struct cpuidle_driver e500_idle_driver = { + .name = "e500_idle", + .owner = THIS_MODULE, +}; + +static struct cpuidle_device __percpu *e500_cpuidle_devices; + +static void e500_cpuidle(void) +{ + /* + * This would call on the cpuidle framework, and the back-end + * driver to go to idle states. + */ + if (cpuidle_idle_call()) { + /* + * On error, execute default handler + * to go into low thread priority and possibly + * low power mode. + */ + HMT_low(); + HMT_very_low(); + } +} + +static int pw10_enter(struct cpuidle_device *dev, + struct cpuidle_driver *drv, int index) +{ + fsl_cpuidle_wait(); + return index; +} + +static struct cpuidle_state fsl_pw_idle_states[] = { + { + .name = "pw10", + .desc = "pw10", + .flags = CPUIDLE_FLAG_TIME_VALID, + .exit_latency = 0, + .target_residency = 0, + .enter = &pw10_enter + }, +}; + +static int cpu_hotplug_notify(struct notifier_block *n, + unsigned long action, void *hcpu) +{ + unsigned long hotcpu = (unsigned long)hcpu; + struct cpuidle_device *dev = + per_cpu_ptr(e500_cpuidle_devices, hotcpu); + + if (dev && cpuidle_get_driver()) { + switch (action) { + case CPU_ONLINE: + case CPU_ONLINE_FROZEN: + cpuidle_pause_and_lock(); + cpuidle_enable_device(dev); + cpuidle_resume_and_unlock(); + break; + + case CPU_DEAD: + case CPU_DEAD_FROZEN: + cpuidle_pause_and_lock(); + cpuidle_disable_device(dev); + cpuidle_resume_and_unlock(); + break; + + default: + return NOTIFY_DONE; + } + } + + return NOTIFY_OK; +} + +static struct notifier_block cpu_hotplug_notifier = { + .notifier_call = cpu_hotplug_notify, +}; + +/* + * e500_idle_devices_init(void) + * allocate, initialize and register cpuidle device + */ +static int e500_idle_devices_init(void) +{ + int i; + struct cpuidle_driver *drv = &e500_idle_driver; + struct cpuidle_device *dev; + + e500_cpuidle_devices = alloc_percpu(struct cpuidle_device); + if (!e500_cpuidle_devices) + return -ENOMEM; + + for_each_possible_cpu(i) { + dev = per_cpu_ptr(e500_cpuidle_devices, i); + dev->state_count = drv->state_count; + dev->cpu = i; + + if (cpuidle_register_device(dev)) { + pr_err("cpuidle_register_device %d failed!\n", i); + return -EIO; + } + } + + return 0; +} + +/* + * e500_idle_devices_uninit(void) + * unregister cpuidle devices and de-allocate memory + */ +static void e500_idle_devices_uninit(void) +{ + int i; + struct cpuidle_device *dev; + + if (!e500_cpuidle_devices) + return; + + for_each_possible_cpu(i) { + dev = per_cpu_ptr(e500_cpuidle_devices, i); + cpuidle_unregister_device(dev); + } + + free_percpu(e500_cpuidle_devices); +} + +static void e500_cpuidle_driver_init(unsigned int max_idle_state, + struct cpuidle_state *cpuidle_state_table) +{ + int idle_state; + struct cpuidle_driver *drv = &e500_idle_driver; + + drv->state_count = 0; + + for (idle_state = 0; idle_state < max_idle_state; ++idle_state) { + if (!cpuidle_state_table[idle_state].enter) + break; + + drv->states[drv->state_count] = cpuidle_state_table[idle_state]; + drv->state_count++; + } +} + +static int cpu_is_feature(unsigned long feature) +{ + return (cur_cpu_spec->cpu_features == feature); +} + +static int __init e500_idle_init(void) +{ + struct cpuidle_state *cpuidle_state_table = NULL; + struct cpuidle_driver *drv = &e500_idle_driver; + int err; + unsigned int max_idle_state = 0; + + if (cpuidle_disable != IDLE_NO_OVERRIDE) + return -ENODEV; + + if (cpu_is_feature(CPU_FTRS_E500MC) || cpu_is_feature(CPU_FTRS_E5500) || + cpu_is_feature(CPU_FTRS_E6500)) { + cpuidle_state_table = fsl_pw_idle_states; + max_idle_state = ARRAY_SIZE(fsl_pw_idle_states); + } + + if (!cpuidle_state_table || !max_idle_state) + return -EPERM; + + e500_cpuidle_driver_init(max_idle_state, cpuidle_state_table); + + if (!drv->state_count) + return -EPERM; + + err = cpuidle_register_driver(drv); + if (err) { + pr_err("Register e500 family cpuidle driver failed.\n"); + + return err; + } + + err = e500_idle_devices_init(); + if (err) + goto out; + + err = register_cpu_notifier(&cpu_hotplug_notifier); + if (err) + goto out; + + ppc_md.power_save = e500_cpuidle; + + pr_info("e500_idle_driver registered.\n"); + + return 0; + +out: + e500_idle_devices_uninit(); + cpuidle_unregister_driver(drv); + + pr_err("Register e500 family cpuidle driver failed.\n"); + + return err; +} +device_initcall(e500_idle_init);