From e93ec75e2a9c85e5a92af9e1b754fa711bd864b6 Mon Sep 17 00:00:00 2001 From: Andy Green Date: Thu, 15 May 2008 21:47:56 +0100 Subject: [PATCH] fix-motion-sensor-corruption.patch --- arch/arm/mach-s3c2440/mach-gta02.c | 35 ++++++++++++++++++++++++++++++++--- 1 files changed, 32 insertions(+), 3 deletions(-) diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c index e1984a9..9e8fae7 100644 --- a/arch/arm/mach-s3c2440/mach-gta02.c +++ b/arch/arm/mach-s3c2440/mach-gta02.c @@ -905,31 +905,58 @@ static struct platform_device gta02_vibrator_dev = { /* #define DEBUG_SPEW_MS */ #define MG_PER_SAMPLE 18 +struct lis302dl_platform_data lis302_pdata[]; + void gat02_lis302dl_bitbang_read(struct lis302dl_info *lis) { struct lis302dl_platform_data *pdata = lis->pdata; u8 shifter = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */ int n, n1; + unsigned long other_cs; unsigned long flags; #ifdef DEBUG_SPEW_MS s8 x, y, z; #endif - spin_lock_irqsave(&motion_irq_lock, flags); + local_save_flags(flags); + + /* + * Huh.. "quirk"... CS on this device is not really "CS" like you can + * expect. Instead when 1 it selects I2C interface mode. Because we + * have 2 devices on one interface, the "disabled" device when we talk + * to an "enabled" device sees the clocks as I2C clocks, creating + * havoc. + * I2C sees MOSI going LOW while CLK HIGH as a START action, we must + * ensure this is never issued. + */ + + if (&lis302_pdata[0] == pdata) + other_cs = lis302_pdata[1].pin_chip_select; + else + other_cs = lis302_pdata[0].pin_chip_select; + + s3c2410_gpio_setpin(other_cs, 1); + s3c2410_gpio_setpin(pdata->pin_chip_select, 1); + s3c2410_gpio_setpin(pdata->pin_clk, 1); s3c2410_gpio_setpin(pdata->pin_chip_select, 0); for (n = 0; n < 8; n++) { /* write the r/w, inc and address */ s3c2410_gpio_setpin(pdata->pin_clk, 0); s3c2410_gpio_setpin(pdata->pin_mosi, (shifter >> 7) & 1); + s3c2410_gpio_setpin(pdata->pin_clk, 0); + s3c2410_gpio_setpin(pdata->pin_clk, 1); s3c2410_gpio_setpin(pdata->pin_clk, 1); shifter <<= 1; } + for (n = 0; n < 5; n++) { /* 5 consequetive registers */ for (n1 = 0; n1 < 8; n1++) { /* 8 bits each */ s3c2410_gpio_setpin(pdata->pin_clk, 0); - s3c2410_gpio_setpin(pdata->pin_clk, 1); + s3c2410_gpio_setpin(pdata->pin_clk, 0); shifter <<= 1; if (s3c2410_gpio_getpin(pdata->pin_miso)) shifter |= 1; + s3c2410_gpio_setpin(pdata->pin_clk, 1); + s3c2410_gpio_setpin(pdata->pin_clk, 1); } switch (n) { case 0: @@ -953,7 +980,9 @@ void gat02_lis302dl_bitbang_read(struct lis302dl_info *lis) } } s3c2410_gpio_setpin(pdata->pin_chip_select, 1); - spin_unlock_irqrestore(&motion_irq_lock, flags); + s3c2410_gpio_setpin(other_cs, 1); + local_irq_restore(flags); + input_sync(lis->input_dev); #ifdef DEBUG_SPEW_MS printk("%s: %d %d %d\n", pdata->name, x, y, z); -- 1.5.6.5