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

Reply via email to