diff options
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.24/1187-fix-pcf50633-use-i2c-bulk-autoincrement.patch.patch')
-rw-r--r-- | target/linux/s3c24xx/patches-2.6.24/1187-fix-pcf50633-use-i2c-bulk-autoincrement.patch.patch | 222 |
1 files changed, 222 insertions, 0 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.24/1187-fix-pcf50633-use-i2c-bulk-autoincrement.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1187-fix-pcf50633-use-i2c-bulk-autoincrement.patch.patch new file mode 100644 index 0000000..b04e60d --- /dev/null +++ b/target/linux/s3c24xx/patches-2.6.24/1187-fix-pcf50633-use-i2c-bulk-autoincrement.patch.patch @@ -0,0 +1,222 @@ +From 8a2d04c222684e3278dd28d11f57a05fe0865183 Mon Sep 17 00:00:00 2001 +From: Andy Green <andy@openmoko.com> +Date: Wed, 2 Jul 2008 22:40:12 +0100 +Subject: [PATCH] fix-pcf50633-use-i2c-bulk-autoincrement.patch + +Simplify and speed up bulk sequential I2C actions in pcf50633 +the time savings are pretty considerable and so is the simplification + +Signed-off-by: Andy Green <andy@openmoko.com> +--- + drivers/i2c/chips/pcf50633.c | 117 +++++++++++++++++++++++++----------------- + 1 files changed, 70 insertions(+), 47 deletions(-) + +diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c +index 1f88c32..96857a3 100644 +--- a/drivers/i2c/chips/pcf50633.c ++++ b/drivers/i2c/chips/pcf50633.c +@@ -156,14 +156,14 @@ struct pcf50633_data { + + #ifdef CONFIG_PM + struct { +- u_int8_t int1m, int2m, int3m, int4m, int5m; + u_int8_t ooctim2; +- u_int8_t autoout, autoena, automxc; +- u_int8_t down1out, down1mxc; +- u_int8_t down2out, down2ena; +- u_int8_t memldoout, memldoena; +- u_int8_t ledout, ledena, leddim; +- u_int8_t ldo[__NUM_PCF50633_REGS][2]; ++ /* enables are always [1] below ++ * I2C has limit of 32 sequential regs, so done in two lumps ++ * because it covers 33 register extent otherwise ++ */ ++ u_int8_t misc[PCF50633_REG_LEDDIM - PCF50633_REG_AUTOOUT + 1]; ++ /* skip 1 reserved reg here */ ++ u_int8_t ldo[PCF50633_REG_HCLDOENA - PCF50633_REG_LDO1OUT + 1]; + } standby_regs; + + struct resume_dependency resume_dependency; +@@ -1737,6 +1737,8 @@ static int pcf50633bl_set_intensity(struct backlight_device *bd) + int old_intensity = reg_read(pcf, PCF50633_REG_LEDOUT); + int ret; + ++ dev_info(&pcf->client.dev, "pcf50633bl_set_intensity\n"); ++ + if (!(reg_read(pcf, PCF50633_REG_LEDENA) & 1)) + old_intensity = 0; + +@@ -2221,6 +2223,9 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state) + int i; + int ret; + u_int8_t tmp; ++ u_int8_t res[5]; ++ ++ dev_err(dev, "pcf50633_suspend\n"); + + /* we suspend once (!) as late as possible in the suspend sequencing */ + +@@ -2228,30 +2233,26 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state) + return 0; + + /* The general idea is to power down all unused power supplies, +- * and then mask all PCF50606 interrup sources but EXTONR, ONKEYF ++ * and then mask all PCF50633 interrupt sources but EXTONR, ONKEYF + * and ALARM */ + + mutex_lock(&pcf->lock); + + /* Save all registers that don't "survive" standby state */ + pcf->standby_regs.ooctim2 = __reg_read(pcf, PCF50633_REG_OOCTIM2); +- pcf->standby_regs.autoout = __reg_read(pcf, PCF50633_REG_AUTOOUT); +- pcf->standby_regs.autoena = __reg_read(pcf, PCF50633_REG_AUTOENA); +- pcf->standby_regs.automxc = __reg_read(pcf, PCF50633_REG_AUTOMXC); +- pcf->standby_regs.down1out = __reg_read(pcf, PCF50633_REG_DOWN1OUT); +- pcf->standby_regs.down1mxc = __reg_read(pcf, PCF50633_REG_DOWN1MXC); +- pcf->standby_regs.down2out = __reg_read(pcf, PCF50633_REG_DOWN2OUT); +- pcf->standby_regs.down2ena = __reg_read(pcf, PCF50633_REG_DOWN2ENA); +- pcf->standby_regs.memldoout = __reg_read(pcf, PCF50633_REG_MEMLDOOUT); +- pcf->standby_regs.memldoena = __reg_read(pcf, PCF50633_REG_MEMLDOENA); +- pcf->standby_regs.ledout = __reg_read(pcf, PCF50633_REG_LEDOUT); +- pcf->standby_regs.ledena = __reg_read(pcf, PCF50633_REG_LEDENA); +- pcf->standby_regs.leddim = __reg_read(pcf, PCF50633_REG_LEDDIM); ++ ++ ret = i2c_smbus_read_i2c_block_data(&pcf->client, ++ PCF50633_REG_AUTOOUT, ++ sizeof(pcf->standby_regs.misc), ++ &pcf->standby_regs.misc[0]); ++ if (ret != 18) ++ dev_err(dev, "Failed to save misc levels and enables :-(\n"); + + /* regulator voltages and enable states */ + ret = i2c_smbus_read_i2c_block_data(&pcf->client, +- PCF50633_REG_LDO1OUT, 14, +- &pcf->standby_regs.ldo[0][0]); ++ PCF50633_REG_LDO1OUT, ++ sizeof(pcf->standby_regs.ldo), ++ &pcf->standby_regs.ldo[0]); + if (ret != 14) + dev_err(dev, "Failed to save LDO levels and enables :-(\n"); + +@@ -2261,11 +2262,16 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state) + continue; + + dev_dbg(dev, "disabling regulator %u\n", i); +- /* we cannot use pcf50633_onoff_set() because we're +- * already under the mutex */ +- tmp = __reg_read(pcf, regulator_registers[i]+1); +- tmp &= 0xfe; +- __reg_write(pcf, regulator_registers[i]+1, tmp); ++ ++ /* we can save ourselves the read part of a read-modify-write ++ * here because we captured all these already ++ */ ++ if (i < 4) ++ tmp = pcf->standby_regs.misc[i * 4 + 1]; ++ else ++ tmp = pcf->standby_regs.ldo[(i - 4) * 2 + 1]; ++ ++ __reg_write(pcf, regulator_registers[i] + 1, tmp & 0xfe); + } + + /* turn off the backlight */ +@@ -2276,11 +2282,14 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state) + /* set interrupt masks so only those sources we want to wake + * us are able to + */ +- __reg_write(pcf, PCF50633_REG_INT1M, ~pcf->pdata->resumers[0]); +- __reg_write(pcf, PCF50633_REG_INT2M, ~pcf->pdata->resumers[1]); +- __reg_write(pcf, PCF50633_REG_INT3M, ~pcf->pdata->resumers[2]); +- __reg_write(pcf, PCF50633_REG_INT4M, ~pcf->pdata->resumers[3]); +- __reg_write(pcf, PCF50633_REG_INT5M, ~pcf->pdata->resumers[4]); ++ for (i = 0; i < 5; i++) ++ res[i] = ~pcf->pdata->resumers[i]; ++ ++ ret = i2c_smbus_write_i2c_block_data(&pcf->client, ++ PCF50633_REG_INT1M, ++ 5, &res[0]); ++ if (ret) ++ dev_err(dev, "Failed to set wake masks :-( %d\n", ret); + + pcf->have_been_suspended = 1; + +@@ -2312,9 +2321,12 @@ EXPORT_SYMBOL_GPL(pcf50633_ready); + void pcf50633_backlight_resume(struct pcf50633_data *pcf) + { + /* we force the backlight on in fact */ +- __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.ledout); +- __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.ledena | 0x01); +- __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.leddim); ++ __reg_write(pcf, PCF50633_REG_LEDOUT, pcf->standby_regs.misc[ ++ PCF50633_REG_LEDOUT - PCF50633_REG_AUTOOUT]); ++ __reg_write(pcf, PCF50633_REG_LEDENA, pcf->standby_regs.misc[ ++ PCF50633_REG_LEDENA - PCF50633_REG_AUTOOUT] | 1); ++ __reg_write(pcf, PCF50633_REG_LEDDIM, pcf->standby_regs.misc[ ++ PCF50633_REG_LEDDIM - PCF50633_REG_AUTOOUT]); + } + EXPORT_SYMBOL_GPL(pcf50633_backlight_resume); + +@@ -2324,7 +2336,10 @@ static int pcf50633_resume(struct device *dev) + struct i2c_client *client = to_i2c_client(dev); + struct pcf50633_data *pcf = i2c_get_clientdata(client); + int ret; ++ u8 res[5]; + ++ dev_info(dev, "pcf50633_resume suspended on entry = %d\n", ++ pcf->have_been_suspended); + mutex_lock(&pcf->lock); + + pcf->have_been_suspended = 2; /* resuming */ +@@ -2332,14 +2347,14 @@ static int pcf50633_resume(struct device *dev) + /* these guys get reset while pcf50633 is suspend state, refresh */ + + __reg_write(pcf, PCF50633_REG_OOCTIM2, pcf->standby_regs.ooctim2); +- __reg_write(pcf, PCF50633_REG_AUTOOUT, pcf->standby_regs.autoout); +- __reg_write(pcf, PCF50633_REG_AUTOMXC, pcf->standby_regs.automxc); +- __reg_write(pcf, PCF50633_REG_DOWN1OUT, pcf->standby_regs.down1out); +- __reg_write(pcf, PCF50633_REG_DOWN1MXC, pcf->standby_regs.down1mxc); +- __reg_write(pcf, PCF50633_REG_DOWN2OUT, pcf->standby_regs.down2out); +- __reg_write(pcf, PCF50633_REG_DOWN2ENA, pcf->standby_regs.down2ena); +- __reg_write(pcf, PCF50633_REG_MEMLDOOUT, pcf->standby_regs.memldoout); +- __reg_write(pcf, PCF50633_REG_MEMLDOENA, pcf->standby_regs.memldoena); ++ ++ /* regulator voltages and enable states */ ++ ret = i2c_smbus_write_i2c_block_data(&pcf->client, ++ PCF50633_REG_AUTOOUT, ++ sizeof(pcf->standby_regs.misc) - 4, ++ &pcf->standby_regs.misc[0]); ++ if (ret) ++ dev_err(dev, "Failed to restore misc :-( %d\n", ret); + + /* platform can choose to defer backlight bringup */ + if (!pcf->pdata->defer_resume_backlight) +@@ -2347,14 +2362,22 @@ static int pcf50633_resume(struct device *dev) + + /* regulator voltages and enable states */ + ret = i2c_smbus_write_i2c_block_data(&pcf->client, +- PCF50633_REG_LDO1OUT, 14, +- &pcf->standby_regs.ldo[0][0]); ++ PCF50633_REG_LDO1OUT, ++ sizeof(pcf->standby_regs.ldo), ++ &pcf->standby_regs.ldo[0]); + if (ret) + dev_err(dev, "Failed to restore LDOs :-( %d\n", ret); + +- mutex_unlock(&pcf->lock); ++ memset(res, 0, sizeof(res)); ++ ret = i2c_smbus_write_i2c_block_data(&pcf->client, ++ PCF50633_REG_INT1M, ++ 5, &res[0]); ++ if (ret) ++ dev_err(dev, "Failed to set int masks :-( %d\n", ret); + +- pcf50633_irq(pcf->irq, pcf); ++ pcf->have_been_suspended = 3; /* resume completed */ ++ ++ mutex_unlock(&pcf->lock); + + callback_all_resume_dependencies(&pcf->resume_dependency); + +-- +1.5.6.5 + |