r1055 - trunk/src/target/kernel/patches

laforge at sita.openmoko.org laforge at sita.openmoko.org
Tue Feb 20 19:51:15 CET 2007


Author: laforge
Date: 2007-02-20 19:51:14 +0100 (Tue, 20 Feb 2007)
New Revision: 1055

Modified:
   trunk/src/target/kernel/patches/gta01-pcf50606.patch
Log:
Implement suspend/resume for those registers of the PMU that don't survive
STANDBY mode.  This might be bogus, since we can't switch the PMU to standby
in Power_off CPU mode anyway.  Anyway, it doesn't make things worse to have it ;)


Modified: trunk/src/target/kernel/patches/gta01-pcf50606.patch
===================================================================
--- trunk/src/target/kernel/patches/gta01-pcf50606.patch	2007-02-20 18:49:55 UTC (rev 1054)
+++ trunk/src/target/kernel/patches/gta01-pcf50606.patch	2007-02-20 18:51:14 UTC (rev 1055)
@@ -3,8 +3,8 @@
 Index: linux-2.6.20/drivers/i2c/chips/pcf50606.c
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20/drivers/i2c/chips/pcf50606.c	2007-02-18 17:18:58.000000000 +0100
-@@ -0,0 +1,1497 @@
++++ linux-2.6.20/drivers/i2c/chips/pcf50606.c	2007-02-20 16:46:19.000000000 +0100
+@@ -0,0 +1,1596 @@
 +/* Philips PCF50606 Power Management Unit (PMU) driver
 + *
 + * (C) 2006 by OpenMoko, Inc.
@@ -101,6 +101,21 @@
 +	struct input_dev *input_dev;
 +	int allow_close;
 +	int onkey_seconds;
++#ifdef CONFIG_PM
++	struct {
++		u_int8_t dcdc1, dcdc2;
++		u_int8_t dcdec1;
++		u_int8_t dcudc1;
++		u_int8_t ioregc;
++		u_int8_t d1regc1;
++		u_int8_t d2regc1;
++		u_int8_t d3regc1;
++		u_int8_t lpregc1;
++		u_int8_t adcc1, adcc2;
++		u_int8_t pwmc1;
++		u_int8_t int1m, int2m, int3m;
++	} standby_regs;
++#endif
 +};
 +
 +struct pcf50606_data *pcf50606_global;
@@ -529,7 +544,7 @@
 +
 +static void pcf50606_work(struct work_struct *work)
 +{
-+	struct pcf50606_data *pcf = 
++	struct pcf50606_data *pcf =
 +			container_of(work, struct pcf50606_data, work);
 +	u_int8_t int1, int2, int3;
 +
@@ -1391,6 +1406,10 @@
 +	if (err < 0)
 +		goto exit_detach;
 +
++	if (enable_irq_wake(GTA01_IRQ_PCF50606) < 0)
++		printk(KERN_ERR "PCF50606: IRQ %u cannot be enabled as wake-up"
++		       "source in this hardware revision!");
++
 +	data->rtc = rtc_device_register("pcf50606", &new_client->dev,
 +					&pcf50606_rtc_ops, THIS_MODULE);
 +	if (IS_ERR(data->rtc)) {
@@ -1476,9 +1495,89 @@
 +	return 0;
 +}
 +
++#ifdef CONFIG_PM
++#define INT1M_RESUMERS	(PCF50606_INT1_ALARM|PCF50606_INT1_ONKEYF|PCF50606_INT1_EXTONR)
++#define INT2M_RESUMERS	(PCF50606_INT2_CHGWD10S|PCF50606_INT2_CHGPROT|PCF50606_INT2_CHGERR)
++#define INT3M_RESUMERS	(PCF50606_INT3_LOWBAT|PCF50606_INT3_HIGHTMP)
++static int pcf50606_suspend(struct device *dev, pm_message_t state)
++{
++	struct i2c_client *client = to_i2c_client(dev);
++	struct pcf50606_data *pcf = i2c_get_clientdata(client);
++
++	/* The general idea is to power down all unused power supplies,
++	 * and then mask all PCF50606 interrup sources but EXTONR, ONKEYF
++	 * and ALARM */
++
++	mutex_lock(&pcf->lock);
++
++	/* Save all registers that don't "survive" standby state */
++	pcf->standby_regs.dcdc1 = __reg_read(pcf, PCF50606_REG_DCDC1);
++	pcf->standby_regs.dcdc2 = __reg_read(pcf, PCF50606_REG_DCDC2);
++	pcf->standby_regs.dcdec1 = __reg_read(pcf, PCF50606_REG_DCDEC1);
++	pcf->standby_regs.dcudc1 = __reg_read(pcf, PCF50606_REG_DCUDC1);
++	pcf->standby_regs.ioregc = __reg_read(pcf, PCF50606_REG_IOREGC);
++	pcf->standby_regs.d1regc1 = __reg_read(pcf, PCF50606_REG_D1REGC1);
++	pcf->standby_regs.d2regc1 = __reg_read(pcf, PCF50606_REG_D2REGC1);
++	pcf->standby_regs.d3regc1 = __reg_read(pcf, PCF50606_REG_D3REGC1);
++	pcf->standby_regs.lpregc1 = __reg_read(pcf, PCF50606_REG_LPREGC1);
++	pcf->standby_regs.adcc1 = __reg_read(pcf, PCF50606_REG_ADCC1);
++	pcf->standby_regs.adcc2 = __reg_read(pcf, PCF50606_REG_ADCC2);
++	pcf->standby_regs.pwmc1 = __reg_read(pcf, PCF50606_REG_PWMC1);
++
++
++	/* FIXME: switch off unneeded power supplies */
++
++	pcf->standby_regs.int1m = __reg_read(pcf, PCF50606_REG_INT1M);
++	pcf->standby_regs.int2m = __reg_read(pcf, PCF50606_REG_INT2M);
++	pcf->standby_regs.int3m = __reg_read(pcf, PCF50606_REG_INT3M);
++	__reg_write(pcf, PCF50606_REG_INT1M, ~INT1M_RESUMERS & 0xff);
++	__reg_write(pcf, PCF50606_REG_INT2M, ~INT2M_RESUMERS & 0xff);
++	__reg_write(pcf, PCF50606_REG_INT3M, ~INT3M_RESUMERS & 0xff);
++
++	mutex_unlock(&pcf->lock);
++
++	return 0;
++}
++
++static int pcf50606_resume(struct device *dev)
++{
++	struct i2c_client *client = to_i2c_client(dev);
++	struct pcf50606_data *pcf = i2c_get_clientdata(client);
++
++	mutex_lock(&pcf->lock);
++
++	/* Resume all saved registers that don't "survive" standby state */
++	__reg_write(pcf, PCF50606_REG_INT1M, pcf->standby_regs.int1m);
++	__reg_write(pcf, PCF50606_REG_INT2M, pcf->standby_regs.int2m);
++	__reg_write(pcf, PCF50606_REG_INT3M, pcf->standby_regs.int3m);
++
++	__reg_write(pcf, PCF50606_REG_DCDC1, pcf->standby_regs.dcdc1);
++	__reg_write(pcf, PCF50606_REG_DCDC2, pcf->standby_regs.dcdc2);
++	__reg_write(pcf, PCF50606_REG_DCDEC1, pcf->standby_regs.dcdec1);
++	__reg_write(pcf, PCF50606_REG_DCUDC1, pcf->standby_regs.dcudc1);
++	__reg_write(pcf, PCF50606_REG_IOREGC, pcf->standby_regs.ioregc);
++	__reg_write(pcf, PCF50606_REG_D1REGC1, pcf->standby_regs.d1regc1);
++	__reg_write(pcf, PCF50606_REG_D2REGC1, pcf->standby_regs.d2regc1);
++	__reg_write(pcf, PCF50606_REG_D3REGC1, pcf->standby_regs.d3regc1);
++	__reg_write(pcf, PCF50606_REG_LPREGC1, pcf->standby_regs.lpregc1);
++	__reg_write(pcf, PCF50606_REG_ADCC1, pcf->standby_regs.adcc1);
++	__reg_write(pcf, PCF50606_REG_ADCC2, pcf->standby_regs.adcc2);
++	__reg_write(pcf, PCF50606_REG_PWMC1, pcf->standby_regs.pwmc1);
++
++	mutex_unlock(&pcf->lock);
++
++	return 0;
++}
++#else
++#define pcf50606_suspend NULL
++#define pcf50606_resume NULL
++#endif
++
 +static struct i2c_driver pcf50606_driver = {
 +	.driver = {
 +		.name	= "pcf50606",
++		.suspend= &pcf50606_suspend,
++		.resume	= &pcf50606_resume,
 +	},
 +	.id		= I2C_DRIVERID_PCF50606,
 +	.attach_adapter	= &pcf50606_attach_adapter,





More information about the commitlog mailing list