This experimental patch enables offline charging. It was tested on a C-1000 and it applies to 3.2.0. Basically, i reintroduced the old way of reading the MAX1111 chip, as it was done in older kernels (older than 2.6.34 i think). This is by no means an ideal solution. The real problem was detailed earlier in this post:
http://lists.linuxtogo.org/pipermail/zaurus-devel/2010-July/000346.html Sharpsl_pm debug output after suspend: sharpsl-pm sharpsl-pm: SharpSL suspending for first time. sharpsl-pm sharpsl-pm: Time is: 000009ed sharpsl-pm sharpsl-pm: Offline Charge Activate = 16 sharpsl-pm sharpsl-pm: Activating Offline Charger... sharpsl-pm sharpsl-pm: Charge Mode: 0 sharpsl-pm sharpsl-pm: Offline Charger: Step 1 sharpsl-pm sharpsl-pm: Average: 130 from values: 130, 131, 131, 130, 130 sharpsl-pm sharpsl-pm: AC Voltage: 130 sharpsl-pm sharpsl-pm: Average: 122 from values: 122, 122, 122, 123, 123 sharpsl-pm sharpsl-pm: Temperature: 122 sharpsl-pm sharpsl-pm: Charge LED On sharpsl-pm sharpsl-pm: Charging alarm at: 00000c45 sharpsl-pm sharpsl-pm: Corgi woken up from suspend: 00000001 sharpsl-pm sharpsl-pm: SharpSL resuming... So the output suggests that offline charging is active, yet both leds are turned off during suspend. So i discharged the battery as much as i could and i left it to charge during suspend for two hours. The battery went from ~4.8V to ~5.3V in that period. At least that's what my multimeter claims. I'm not skilled in electronics, someone else should test this further. Here's the patch: diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c index 32318ba..ece52e2 100644 --- a/arch/arm/mach-pxa/sharpsl_pm.c +++ b/arch/arm/mach-pxa/sharpsl_pm.c @@ -12,7 +12,7 @@ * */ -#undef DEBUG +#define DEBUG #include <linux/module.h> #include <linux/kernel.h> @@ -24,12 +24,14 @@ #include <linux/leds.h> #include <linux/suspend.h> #include <linux/gpio.h> - +#include <linux/pxa2xx_ssp.h> #include <asm/mach-types.h> #include <mach/pm.h> #include <mach/pxa2xx-regs.h> #include <mach/regs-rtc.h> #include <mach/sharpsl_pm.h> +#include <mach/gpio-pxa.h> +#include <mach/spitz.h> /* * Prototypes @@ -154,18 +156,139 @@ struct battery_thresh sharpsl_battery_levels_noac[] = { /* * Read MAX1111 ADC */ + +#define SSP2_REGS_START 0x41700000 +#define SSP2_REG_SIZE 64 +#define TIMEOUT 100000 +#define SSCR0_SerClkDiv(x) (((x) - 1) << 8) + +static void __iomem *ssp2_reg_base; +static volatile unsigned int sscr0, sscr1; +struct mutex ssp_lock; + +static void init_ssp2() { + ssp2_reg_base = ioremap(SSP2_REGS_START, SSP2_REG_SIZE); +} + +static void ssp_enable() +{ + *((u32 *)ssp2_reg_base + SSCR0) |= SSCR0_SSE; +} + +static void ssp_disable() +{ + *((u32 *)ssp2_reg_base + SSCR0) &= ~SSCR0_SSE; +} + +static int ssp_read_word(u32 *data) { + + int timeout = TIMEOUT; + + while (!(__raw_readl(ssp2_reg_base + SSSR) & SSSR_RNE)) { + if (!--timeout) + return -ETIMEDOUT; + cpu_relax(); + } + + *data = __raw_readl(ssp2_reg_base + SSDR); + return 0; +} + +static int ssp_write_word(u32 data) { + int timeout = TIMEOUT; + + while (!(__raw_readl(ssp2_reg_base + SSSR) & SSSR_TNF)) { + if (!--timeout) + return -ETIMEDOUT; + cpu_relax(); + } + + __raw_writel(data, ssp2_reg_base + SSDR); + + return 0; +} + +static void save_sscr() { + sscr0 = *((u32 *)ssp2_reg_base + SSCR0); + sscr1 = *((u32 *)ssp2_reg_base + SSCR1); +} + +static void restore_sscr () { + *((u32 *)ssp2_reg_base + SSCR0) = sscr0; + *((u32 *)ssp2_reg_base + SSCR1) = sscr1; +} + +static void ssp_config () { + *((u32 *)ssp2_reg_base + SSCR0) = (SSCR0_Motorola | (SSCR0_DSS & 0x07) | SSCR0_SerClkDiv(56)); + *((u32 *)ssp2_reg_base + SSCR1) = 0x0; +} + +static int max1111_raw_read(int channel) { + + + CKEN |= (1 << 3); + long voltage = 0, voltage1 = 0, voltage2 = 0; + + save_sscr(); + ssp_disable(); + ssp_config(); + mdelay(1); + ssp_enable(); + + int max1111_cmd = (channel << MAXCTRL_SEL_SH) | MAXCTRL_PD0 | MAXCTRL_PD1 + | MAXCTRL_SGL | MAXCTRL_UNI | MAXCTRL_STR; + + gpio_set_value(SPITZ_GPIO_MAX1111_CS, 0); /*pull CS low */ + /* TB1/RB1 */ + ssp_write_word(max1111_cmd); + ssp_read_word((u32*)&voltage1); /* null read */ + + /* TB12/RB2 */ + ssp_write_word(0); + ssp_read_word((u32*)&voltage1); + + /* TB13/RB3*/ + ssp_write_word(0); + ssp_read_word((u32*)&voltage2); + + gpio_set_value(SPITZ_GPIO_MAX1111_CS, 1); + + ssp_disable(); + restore_sscr(); + ssp_enable(); + + CKEN &= ~(1 << 3); + + if ((voltage1 & 0xc0) || (voltage2 & 0x3f)) + voltage = -1; + else + voltage = ((voltage1 << 2) & 0xfc) | ((voltage2 >> 6) & 0x03); + + if (voltage <= 0) + printk (KERN_ALERT "voltage raw %d\n", voltage); + + return voltage; +} + int sharpsl_pm_pxa_read_max1111(int channel) { + /* Ugly, better move this function into another module */ if (machine_is_tosa()) return 0; + int ret; extern int max1111_read_channel(int); - /* max1111 accepts channels from 0-3, however, * it is encoded from 0-7 here in the code. */ - return max1111_read_channel(channel >> 1); + ret = max1111_read_channel(channel >> 1); + + if (ret <= 0) + return max1111_raw_read(channel); + else + return ret; + } static int get_percentage(int voltage) @@ -926,6 +1049,8 @@ static int __devinit sharpsl_pm_probe(struct platform_device *pdev) suspend_set_ops(&sharpsl_pm_ops); #endif + init_ssp2(); + mod_timer(&sharpsl_pm.ac_timer, jiffies + msecs_to_jiffies(250)); return 0; @@ -959,6 +1084,8 @@ static int sharpsl_pm_remove(struct platform_device *pdev) del_timer_sync(&sharpsl_pm.chrg_full_timer); del_timer_sync(&sharpsl_pm.ac_timer); + iounmap(ssp2_reg_base); + return 0; }
_______________________________________________ Zaurus-devel mailing list Zaurus-devel@lists.linuxtogo.org http://lists.linuxtogo.org/cgi-bin/mailman/listinfo/zaurus-devel