diff options
-rw-r--r-- | arch/arm/mach-s3c2440/mach-gta02.c | 249 | ||||
-rw-r--r-- | drivers/input/misc/lis302dl.c | 442 | ||||
-rw-r--r-- | include/linux/lis302dl.h | 9 |
3 files changed, 333 insertions, 367 deletions
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c index a536638352c..6a77fd1cf08 100644 --- a/arch/arm/mach-s3c2440/mach-gta02.c +++ b/arch/arm/mach-s3c2440/mach-gta02.c @@ -238,7 +238,7 @@ FIQ_HANDLER_ENTRY(64, 64) break; } fiq_ipc.hdq_error = 0; - fiq_ipc.hdq_transaction_ctr++; + fiq_ipc.hdq_transaction_ctr = fiq_ipc.hdq_request_ctr; hdq_state = HDQB_IDLE; /* all tx is done */ /* idle in input mode, it's pulled up by 10K */ s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_INPUT); @@ -256,7 +256,7 @@ FIQ_HANDLER_ENTRY(64, 64) } if (--hdq_ctr == 0) { /* timed out, error */ fiq_ipc.hdq_error = 1; - fiq_ipc.hdq_transaction_ctr++; + fiq_ipc.hdq_transaction_ctr = fiq_ipc.hdq_request_ctr; hdq_state = HDQB_IDLE; /* abort */ } break; @@ -274,7 +274,9 @@ FIQ_HANDLER_ENTRY(64, 64) if (--hdq_bit == 0) { fiq_ipc.hdq_error = 0; - fiq_ipc.hdq_transaction_ctr++; /* done */ + fiq_ipc.hdq_transaction_ctr = + fiq_ipc.hdq_request_ctr; + hdq_state = HDQB_IDLE; } else hdq_state = HDQB_DATA_RX_HIGH; @@ -288,7 +290,7 @@ FIQ_HANDLER_ENTRY(64, 64) break; /* timed out, error */ fiq_ipc.hdq_error = 2; - fiq_ipc.hdq_transaction_ctr++; + fiq_ipc.hdq_transaction_ctr = fiq_ipc.hdq_request_ctr; hdq_state = HDQB_IDLE; /* abort */ break; @@ -305,7 +307,8 @@ FIQ_HANDLER_ENTRY(64, 64) break; /* timed out, error */ fiq_ipc.hdq_error = 3; - fiq_ipc.hdq_transaction_ctr++; + fiq_ipc.hdq_transaction_ctr = fiq_ipc.hdq_request_ctr; + /* we're in input mode already */ hdq_state = HDQB_IDLE; /* abort */ break; @@ -844,8 +847,8 @@ static void gta02_fiq_attach_child_devices(struct device *parent_device) static struct resource sc32440_fiq_resources[] = { [0] = { .flags = IORESOURCE_IRQ, - .start = IRQ_TIMER3, - .end = IRQ_TIMER3, + .start = IRQ_TIMER1, + .end = IRQ_TIMER1, }, }; @@ -1090,17 +1093,22 @@ static struct glamo_spigpio_info glamo_spigpio_cfg = { /* #define DEBUG_SPEW_MS */ #define MG_PER_SAMPLE 18 -struct lis302dl_platform_data lis302_pdata[]; +struct lis302dl_platform_data lis302_pdata_top; +struct lis302dl_platform_data lis302_pdata_bottom; + +/* + * generic SPI RX and TX bitbang + * only call with interrupts off! + */ -void gta02_lis302dl_bitbang_read(struct lis302dl_info *lis) +static void __gta02_lis302dl_bitbang(struct lis302dl_info *lis, u8 *tx, + int tx_bytes, u8 *rx, int rx_bytes) { struct lis302dl_platform_data *pdata = lis->pdata; - u8 shifter = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */ - int n, n1; + u8 shifter = 0; + int n; unsigned long flags; -#ifdef DEBUG_SPEW_MS - s8 x, y, z; -#endif + unsigned long other_cs; local_irq_save(flags); @@ -1110,53 +1118,96 @@ void gta02_lis302dl_bitbang_read(struct lis302dl_info *lis) * 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_top == pdata) + other_cs = lis302_pdata_bottom.pin_chip_select; + else + other_cs = lis302_pdata_top.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 */ + + /* send the register index, r/w and autoinc bits */ + for (n = 0; n < (tx_bytes << 3); n++) { + if (!(n & 7)) + shifter = tx[n >> 3]; s3c2410_gpio_setpin(pdata->pin_clk, 0); s3c2410_gpio_setpin(pdata->pin_mosi, (shifter >> (7 - n)) & 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); - shifter <<= 1; - if (s3c2410_gpio_getpin(pdata->pin_miso)) - shifter |= 1; - s3c2410_gpio_setpin(pdata->pin_clk, 1); - } - switch (n) { - case 0: -#ifdef DEBUG_SPEW_MS - x = shifter; -#endif - input_report_rel(lis->input_dev, REL_X, MG_PER_SAMPLE * (s8)shifter); - break; - case 2: -#ifdef DEBUG_SPEW_MS - y = shifter; -#endif - input_report_rel(lis->input_dev, REL_Y, MG_PER_SAMPLE * (s8)shifter); - break; - case 4: -#ifdef DEBUG_SPEW_MS - z = shifter; -#endif - input_report_rel(lis->input_dev, REL_Z, MG_PER_SAMPLE * (s8)shifter); - break; - } + for (n = 0; n < (rx_bytes << 3); n++) { /* 8 bits each */ + s3c2410_gpio_setpin(pdata->pin_clk, 0); + shifter <<= 1; + if (s3c2410_gpio_getpin(pdata->pin_miso)) + shifter |= 1; + if ((n & 7) == 7) + rx[n >> 3] = shifter; + s3c2410_gpio_setpin(pdata->pin_clk, 1); } s3c2410_gpio_setpin(pdata->pin_chip_select, 1); + s3c2410_gpio_setpin(other_cs, 1); + local_irq_restore(flags); +} + + +static int gta02_lis302dl_bitbang_read_reg(struct lis302dl_info *lis, u8 reg) +{ + u8 data = 0xc0 | reg; /* read, autoincrement */ + unsigned long flags; + + local_irq_save(flags); + + __gta02_lis302dl_bitbang(lis, &data, 1, &data, 1); + + local_irq_restore(flags); + + return data; +} + +static void gta02_lis302dl_bitbang_write_reg(struct lis302dl_info *lis, u8 reg, + u8 val) +{ + u8 data[2] = { 0x00 | reg, val }; /* write, no autoincrement */ + unsigned long flags; + + local_irq_save(flags); + + __gta02_lis302dl_bitbang(lis, &data[0], 2, NULL, 0); + + local_irq_restore(flags); + +} + + +static void gta02_lis302dl_bitbang_sample(struct lis302dl_info *lis) +{ + u8 data = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */ + u8 read[5]; + unsigned long flags; + + local_irq_save(flags); + + __gta02_lis302dl_bitbang(lis, &data, 1, &read[0], 5); + + local_irq_restore(flags); + + input_report_rel(lis->input_dev, REL_X, MG_PER_SAMPLE * (s8)read[0]); + input_report_rel(lis->input_dev, REL_Y, MG_PER_SAMPLE * (s8)read[2]); + input_report_rel(lis->input_dev, REL_Z, MG_PER_SAMPLE * (s8)read[4]); input_sync(lis->input_dev); #ifdef DEBUG_SPEW_MS - printk("%s: %d %d %d\n", pdata->name, x, y, z); + printk(KERN_INFO "%s: %d %d %d\n", pdata->name, read[0], read[2], + read[4]); #endif } @@ -1183,103 +1234,58 @@ void gta02_lis302dl_suspend_io(struct lis302dl_info *lis, int resume) s3c2410_gpio_setpin(pdata->pin_clk, 1); /* misnomer: it is a pullDOWN in 2442 */ s3c2410_gpio_pullup(pdata->pin_miso, 0); + + s3c2410_gpio_cfgpin(pdata->pin_chip_select, S3C2410_GPIO_OUTPUT); + s3c2410_gpio_cfgpin(pdata->pin_clk, S3C2410_GPIO_OUTPUT); + s3c2410_gpio_cfgpin(pdata->pin_mosi, S3C2410_GPIO_OUTPUT); + s3c2410_gpio_cfgpin(pdata->pin_miso, S3C2410_GPIO_INPUT); + } -struct lis302dl_platform_data lis302_pdata[] = { - { + + +struct lis302dl_platform_data lis302_pdata_top = { .name = "lis302-1 (top)", .pin_chip_select= S3C2410_GPD12, .pin_clk = S3C2410_GPG7, .pin_mosi = S3C2410_GPG6, .pin_miso = S3C2410_GPG5, + .interrupt = GTA02_IRQ_GSENSOR_1, .open_drain = 1, /* altered at runtime by PCB rev */ - .lis302dl_bitbang_read = gta02_lis302dl_bitbang_read, + .lis302dl_bitbang_read_sample = gta02_lis302dl_bitbang_sample, + .lis302dl_bitbang_reg_read = gta02_lis302dl_bitbang_read_reg, + .lis302dl_bitbang_reg_write = gta02_lis302dl_bitbang_write_reg, .lis302dl_suspend_io = gta02_lis302dl_suspend_io, - }, { +}; + +struct lis302dl_platform_data lis302_pdata_bottom = { .name = "lis302-2 (bottom)", .pin_chip_select= S3C2410_GPD13, .pin_clk = S3C2410_GPG7, .pin_mosi = S3C2410_GPG6, .pin_miso = S3C2410_GPG5, + .interrupt = GTA02_IRQ_GSENSOR_2, .open_drain = 1, /* altered at runtime by PCB rev */ - .lis302dl_bitbang_read = gta02_lis302dl_bitbang_read, + .lis302dl_bitbang_read_sample = gta02_lis302dl_bitbang_sample, + .lis302dl_bitbang_reg_read = gta02_lis302dl_bitbang_read_reg, + .lis302dl_bitbang_reg_write = gta02_lis302dl_bitbang_write_reg, .lis302dl_suspend_io = gta02_lis302dl_suspend_io, - }, -}; - -static struct spi_board_info gta02_spi_acc_bdinfo[] = { - { - .modalias = "lis302dl", - .platform_data = &lis302_pdata[0], - .irq = GTA02_IRQ_GSENSOR_1, - .max_speed_hz = 10 * 1000 * 1000, - .bus_num = 1, - .chip_select = 0, - .mode = SPI_MODE_3, - }, - { - .modalias = "lis302dl", - .platform_data = &lis302_pdata[1], - .irq = GTA02_IRQ_GSENSOR_2, - .max_speed_hz = 10 * 1000 * 1000, - .bus_num = 1, - .chip_select = 1, - .mode = SPI_MODE_3, - }, }; -static void spi_acc_cs(struct s3c2410_spigpio_info *spigpio_info, - int csid, int cs) -{ - struct lis302dl_platform_data * plat_data = - (struct lis302dl_platform_data *)spigpio_info-> - board_info->platform_data; - switch (cs) { - case BITBANG_CS_ACTIVE: - s3c2410_gpio_setpin(plat_data[csid].pin_chip_select, 0); - break; - case BITBANG_CS_INACTIVE: - s3c2410_gpio_setpin(plat_data[csid].pin_chip_select, 1); - break; - } -} -static struct s3c2410_spigpio_info spi_gpio_cfg = { - .pin_clk = S3C2410_GPG7, - .pin_mosi = S3C2410_GPG6, - .pin_miso = S3C2410_GPG5, - .board_size = ARRAY_SIZE(gta02_spi_acc_bdinfo), - .board_info = gta02_spi_acc_bdinfo, - .chip_select = &spi_acc_cs, - .num_chipselect = 2, -}; - -static struct resource s3c_spi_acc_resource[] = { - [0] = { - .start = S3C2410_GPG3, - .end = S3C2410_GPG3, - }, - [1] = { - .start = S3C2410_GPG5, - .end = S3C2410_GPG5, - }, - [2] = { - .start = S3C2410_GPG6, - .end = S3C2410_GPG6, - }, - [3] = { - .start = S3C2410_GPG7, - .end = S3C2410_GPG7, +static struct platform_device s3c_device_spi_acc1 = { + .name = "lis302dl", + .id = 1, + .dev = { + .platform_data = &lis302_pdata_top, }, }; -static struct platform_device s3c_device_spi_acc = { - .name = "spi_s3c24xx_gpio", - .id = 1, - .num_resources = ARRAY_SIZE(s3c_spi_acc_resource), - .resource = s3c_spi_acc_resource, +static struct platform_device s3c_device_spi_acc2 = { + .name = "lis302dl", + .id = 2, .dev = { - .platform_data = &spi_gpio_cfg, + .platform_data = &lis302_pdata_bottom, }, }; @@ -1591,7 +1597,8 @@ static struct platform_device *gta02_devices_pmu_children[] = { >a02_pm_gsm_dev, >a02_sdio_dev, >a02_pm_usbhost_dev, - &s3c_device_spi_acc, /* input 2 and 3 */ + &s3c_device_spi_acc1, /* input 2 */ + &s3c_device_spi_acc2, /* input 3 */ >a02_button_dev, /* input 4 */ >a02_resume_reason_device, }; @@ -1626,8 +1633,8 @@ static void __init gta02_machine_init(void) switch (system_rev) { case GTA02v6_SYSTEM_REV: /* we need push-pull interrupt from motion sensors */ - lis302_pdata[0].open_drain = 0; - lis302_pdata[1].open_drain = 0; + lis302_pdata_top.open_drain = 0; + lis302_pdata_bottom.open_drain = 0; break; default: break; diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c index 1f1c0ab79bd..489651fe7b0 100644 --- a/drivers/input/misc/lis302dl.c +++ b/drivers/input/misc/lis302dl.c @@ -1,7 +1,9 @@ /* Linux kernel driver for the ST LIS302D 3-axis accelerometer * - * Copyright (C) 2007 by Openmoko, Inc. + * Copyright (C) 2007-2008 by Openmoko, Inc. * Author: Harald Welte <laforge@openmoko.org> + * converted to private bitbang by: + * Andy Green <andy@openmoko.com> * All rights reserved. * * This program is free software; you can redistribute it and/or @@ -39,78 +41,19 @@ #include <linux/lis302dl.h> -/* lowlevel register access functions */ -#define READ_BIT 0x80 -#define READ_BIT_INC_ADS 0xc0 -#define ADDR_MASK 0x3f -static u_int8_t __reg_read(struct lis302dl_info *lis, u_int8_t reg) +static void __reg_set_bit_mask(struct lis302dl_info *lis, u8 reg, u8 mask, + u8 val) { - int rc; - u_int8_t cmd; - - BUG_ON(reg & ~ADDR_MASK); - - cmd = reg | READ_BIT; - - rc = spi_w8r8(lis->spi_dev, cmd); - - return rc; -} - -static u_int8_t reg_read(struct lis302dl_info *lis, u_int8_t reg) -{ - u_int8_t ret; - - mutex_lock(&lis->lock); - ret = __reg_read(lis, reg); - mutex_unlock(&lis->lock); - - return ret; -} - -static int __reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val) -{ - u_int8_t buf[2]; - - BUG_ON(reg & ~ADDR_MASK); - - buf[0] = reg; - buf[1] = val; - - return spi_write(lis->spi_dev, buf, sizeof(buf)); -} - -static int reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val) -{ - int ret; - - mutex_lock(&lis->lock); - ret = __reg_write(lis, reg, val); - mutex_unlock(&lis->lock); - - return ret; -} - -static int reg_set_bit_mask(struct lis302dl_info *lis, - u_int8_t reg, u_int8_t mask, u_int8_t val) -{ - int ret; u_int8_t tmp; val &= mask; - mutex_lock(&lis->lock); - - tmp = __reg_read(lis, reg); + tmp = (lis->pdata->lis302dl_bitbang_reg_read)(lis, reg); tmp &= ~mask; tmp |= val; - ret = __reg_write(lis, reg, tmp); - - mutex_unlock(&lis->lock); - - return ret; + (lis->pdata->lis302dl_bitbang_reg_write)(lis, reg, tmp); } /* interrupt handling related */ @@ -124,17 +67,17 @@ enum lis302dl_intmode { LIS302DL_INTMODE_CLICK = 0x07, }; -static void lis302dl_int_mode(struct spi_device *spi, int int_pin, +static void __lis302dl_int_mode(struct device *dev, int int_pin, enum lis302dl_intmode mode) { - struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); + struct lis302dl_info *lis = dev_get_drvdata(dev); switch (int_pin) { case 1: - reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x07, mode); + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x07, mode); break; case 2: - reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x38, mode << 3); + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x38, mode << 3); break; default: BUG(); @@ -165,7 +108,7 @@ static irqreturn_t lis302dl_interrupt(int irq, void *_lis) { struct lis302dl_info *lis = _lis; - (lis->pdata->lis302dl_bitbang_read)(lis); + (lis->pdata->lis302dl_bitbang_read_sample)(lis); return IRQ_HANDLED; } @@ -175,7 +118,13 @@ static ssize_t show_rate(struct device *dev, struct device_attribute *attr, char *buf) { struct lis302dl_info *lis = dev_get_drvdata(dev); - u_int8_t ctrl1 = reg_read(lis, LIS302DL_REG_CTRL1); + u8 ctrl1; + unsigned long flags; + + local_irq_save(flags); + ctrl1 = (lis->pdata->lis302dl_bitbang_reg_read) + (lis, LIS302DL_REG_CTRL1); + local_irq_restore(flags); return sprintf(buf, "%d\n", ctrl1 & LIS302DL_CTRL1_DR ? 400 : 100); } @@ -184,12 +133,17 @@ static ssize_t set_rate(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct lis302dl_info *lis = dev_get_drvdata(dev); + unsigned long flags; + + local_irq_save(flags); if (!strcmp(buf, "400\n")) - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR, + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR, LIS302DL_CTRL1_DR); else - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR, 0); + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR, + 0); + local_irq_restore(flags); return count; } @@ -200,7 +154,13 @@ static ssize_t show_scale(struct device *dev, struct device_attribute *attr, char *buf) { struct lis302dl_info *lis = dev_get_drvdata(dev); - u_int8_t ctrl1 = reg_read(lis, LIS302DL_REG_CTRL1); + u_int8_t ctrl1; + unsigned long flags; + + local_irq_save(flags); + ctrl1 = (lis->pdata->lis302dl_bitbang_reg_read)(lis, + LIS302DL_REG_CTRL1); + local_irq_restore(flags); return sprintf(buf, "%s\n", ctrl1 & LIS302DL_CTRL1_FS ? "9.2" : "2.3"); } @@ -209,12 +169,18 @@ static ssize_t set_scale(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { struct lis302dl_info *lis = dev_get_drvdata(dev); + unsigned long flags; + + local_irq_save(flags); if (!strcmp(buf, "9.2\n")) - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_FS, + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_FS, LIS302DL_CTRL1_FS); else - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_FS, 0); + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_FS, + 0); + + local_irq_restore(flags); return count; } @@ -222,7 +188,7 @@ static ssize_t set_scale(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(full_scale, S_IRUGO | S_IWUSR, show_scale, set_scale); static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr, - char *buf) + char *buf) { struct lis302dl_info *lis = dev_get_drvdata(dev); int n = 0; @@ -233,7 +199,7 @@ static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr, local_irq_save(flags); for (n = 0; n < sizeof(reg); n++) - reg[n] = reg_read(lis, n); + reg[n] = (lis->pdata->lis302dl_bitbang_reg_read)(lis, n); local_irq_restore(flags); @@ -248,9 +214,9 @@ static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR(dump, S_IRUGO, lis302dl_dump, NULL); -static int freefall_ms_to_duration(struct lis302dl_info *lis, int ms) +static int __freefall_ms_to_duration(struct lis302dl_info *lis, int ms) { - u_int8_t r = reg_read(lis, LIS302DL_REG_CTRL1); + u8 r = (lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_CTRL1); /* If we have 400 ms sampling rate, the stepping is 2.5 ms, * on 100 ms the stepping is 10ms */ @@ -268,9 +234,9 @@ static int freefall_ms_to_duration(struct lis302dl_info *lis, int ms) return ms / 10; } -static int freefall_duration_to_ms(struct lis302dl_info *lis, int duration) +static int __freefall_duration_to_ms(struct lis302dl_info *lis, int duration) { - u_int8_t r = reg_read(lis, LIS302DL_REG_CTRL1); + u8 r = (lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_CTRL1); if (r & LIS302DL_CTRL1_DR) return (duration * 25) / 10; @@ -314,18 +280,18 @@ static ssize_t set_freefall_common(int which, struct device *dev, /* Turn off the interrupt */ local_irq_save(flags); if (lis->flags & LIS302DL_F_IRQ_WAKE) - disable_irq_wake(lis->spi_dev->irq); - lis302dl_int_mode(lis->spi_dev, which, + disable_irq_wake(lis->pdata->interrupt); + __lis302dl_int_mode(lis->dev, which, LIS302DL_INTMODE_DATA_READY); lis->flags &= ~(flag_mask | LIS302DL_F_IRQ_WAKE); - reg_write(lis, r_cfg, 0); - reg_write(lis, r_ths, 0); - reg_write(lis, r_duration, 0); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, r_cfg, 0); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, r_ths, 0); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, r_duration, 0); /* Power off unless the input subsystem is using the device */ if (!(lis->flags & LIS302DL_F_INPUT_OPEN)) - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD, 0); local_irq_restore(flags); @@ -337,7 +303,10 @@ static ssize_t set_freefall_common(int which, struct device *dev, &and_events) != 6) return -EINVAL; - duration = freefall_ms_to_duration(lis, ms); + local_irq_save(flags); + duration = __freefall_ms_to_duration(lis, ms); + local_irq_save(flags); + if (duration < 0) return -ERANGE; @@ -355,23 +324,25 @@ static ssize_t set_freefall_common(int which, struct device *dev, /* Setup the configuration registers */ local_irq_save(flags); - reg_write(lis, r_cfg, 0); /* First zero to get to a known state */ - reg_write(lis, r_cfg, + /* First zero to get to a known state */ + (lis->pdata->lis302dl_bitbang_reg_write)(lis, r_cfg, 0); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, r_cfg, (and_events ? LIS302DL_FFWUCFG_AOI : 0) | x_lo | x_hi | y_lo | y_hi | z_lo | z_hi); - reg_write(lis, r_ths, threshold & ~LIS302DL_FFWUTHS_DCRM); - reg_write(lis, r_duration, duration); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, r_ths, + threshold & ~LIS302DL_FFWUTHS_DCRM); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, r_duration, duration); /* Route the interrupt for wakeup */ - lis302dl_int_mode(lis->spi_dev, which, intmode); + __lis302dl_int_mode(lis->dev, which, intmode); /* Power up the device and note that we want to wake up from * this interrupt */ if (!(lis->flags & LIS302DL_F_IRQ_WAKE)) - enable_irq_wake(lis->spi_dev->irq); + enable_irq_wake(lis->pdata->interrupt); lis->flags |= flag_mask | LIS302DL_F_IRQ_WAKE; - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD, + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD, LIS302DL_CTRL1_PD); local_irq_restore(flags); @@ -403,6 +374,8 @@ static ssize_t show_freefall_common(int which, struct device *dev, int r_duration = LIS302DL_REG_FF_WU_DURATION_1; int r_cfg = LIS302DL_REG_FF_WU_CFG_1; int r_src = LIS302DL_REG_FF_WU_SRC_1; + unsigned long flags; + int ms; /* Configure second freefall/wakeup pin */ if (which == 2) { @@ -411,11 +384,15 @@ static ssize_t show_freefall_common(int which, struct device *dev, r_cfg = LIS302DL_REG_FF_WU_CFG_2; r_src = LIS302DL_REG_FF_WU_SRC_2; } - config = reg_read(lis, r_cfg); - threshold = reg_read(lis, r_ths); - duration = reg_read(lis, r_duration); - r4 = reg_read(lis, r_src); - r5 = reg_read(lis, LIS302DL_REG_CTRL3); + + local_irq_save(flags); + config = (lis->pdata->lis302dl_bitbang_reg_read)(lis, r_cfg); + threshold = (lis->pdata->lis302dl_bitbang_reg_read)(lis, r_ths); + duration = (lis->pdata->lis302dl_bitbang_reg_read)(lis, r_duration); + r4 = (lis->pdata->lis302dl_bitbang_reg_read)(lis, r_src); + r5 = (lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_CTRL3); + ms = __freefall_duration_to_ms(lis, duration); + local_irq_restore(flags); /* All events off? */ if ((config & (LIS302DL_FFWUCFG_XLIE | LIS302DL_FFWUCFG_XHIE | @@ -423,13 +400,14 @@ static ssize_t show_freefall_common(int which, struct device *dev, LIS302DL_FFWUCFG_ZLIE | LIS302DL_FFWUCFG_ZHIE)) == 0) return sprintf(buf, "off\n"); + return sprintf(buf, "%s events, %s interrupt, duration %d, threshold %d, " "enabled: %s %s %s %s %s %s\n", (config & LIS302DL_FFWUCFG_AOI) == 0 ? "or" : "and", (config & LIS302DL_FFWUCFG_LIR) == 0 ? "don't latch" : "latch", - freefall_duration_to_ms(lis, duration), threshold, + ms, threshold, (config & LIS302DL_FFWUCFG_XLIE) == 0 ? "---" : "xlo", (config & LIS302DL_FFWUCFG_XHIE) == 0 ? "---" : "xhi", (config & LIS302DL_FFWUCFG_YLIE) == 0 ? "---" : "ylo", @@ -480,14 +458,11 @@ static int lis302dl_input_open(struct input_dev *inp) local_irq_save(flags); /* make sure we're powered up and generate data ready */ - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1); - local_irq_restore(flags); + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1); lis->flags |= LIS302DL_F_INPUT_OPEN; - /* kick it off -- since we are edge triggered, if we missed the edge - * permanent low interrupt is death for us */ - (lis->pdata->lis302dl_bitbang_read)(lis); + local_irq_restore(flags); return 0; } @@ -504,13 +479,13 @@ static void lis302dl_input_close(struct input_dev *inp) /* since the input core already serializes access and makes sure we * only see close() for the close of the last user, we can safely * disable the data ready events */ - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, 0x00); + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, 0x00); lis->flags &= ~LIS302DL_F_INPUT_OPEN; /* however, don't power down the whole device if still needed */ if (!(lis->flags & LIS302DL_F_WUP_FF || lis->flags & LIS302DL_F_WUP_CLICK)) { - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD, + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD, 0x00); } local_irq_restore(flags); @@ -524,23 +499,23 @@ static int __lis302dl_reset_device(struct lis302dl_info *lis) { int timeout = 10; - reg_write(lis, LIS302DL_REG_CTRL2, LIS302DL_CTRL2_BOOT | - LIS302DL_CTRL2_FDS); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL2, + LIS302DL_CTRL2_BOOT | LIS302DL_CTRL2_FDS); - while ((reg_read(lis, LIS302DL_REG_CTRL2) & LIS302DL_CTRL2_BOOT) && - (timeout--)) + while (((lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_CTRL2) + & LIS302DL_CTRL2_BOOT) && (timeout--)) mdelay(1); return !!(timeout < 0); } -static int __devinit lis302dl_probe(struct spi_device *spi) +static int __devinit lis302dl_probe(struct platform_device *pdev) { int rc; struct lis302dl_info *lis; u_int8_t wai; unsigned long flags; - struct lis302dl_platform_data *pdata; + struct lis302dl_platform_data *pdata = pdev->dev.platform_data; lis = kzalloc(sizeof(*lis), GFP_KERNEL); if (!lis) @@ -548,38 +523,34 @@ static int __devinit lis302dl_probe(struct spi_device *spi) local_irq_save(flags); - mutex_init(&lis->lock); - lis->spi_dev = spi; + lis->dev = &pdev->dev; - spi_set_drvdata(spi, lis); + dev_set_drvdata(lis->dev, lis); - pdata = spi->dev.platform_data; + lis->pdata = pdata; - rc = spi_setup(spi); - if (rc < 0) { - dev_err(&spi->dev, "error during spi_setup\n"); - dev_set_drvdata(&spi->dev, NULL); - goto bail_free_lis; - } + /* Configure our IO */ + (lis->pdata->lis302dl_suspend_io)(lis, 1); - wai = reg_read(lis, LIS302DL_REG_WHO_AM_I); + wai = (lis->pdata->lis302dl_bitbang_reg_read)(lis, + LIS302DL_REG_WHO_AM_I); if (wai != LIS302DL_WHO_AM_I_MAGIC) { - dev_err(&spi->dev, "unknown who_am_i signature 0x%02x\n", wai); - dev_set_drvdata(&spi->dev, NULL); + dev_err(lis->dev, "unknown who_am_i signature 0x%02x\n", wai); + dev_set_drvdata(lis->dev, NULL); rc = -ENODEV; goto bail_free_lis; } - rc = sysfs_create_group(&spi->dev.kobj, &lis302dl_attr_group); + rc = sysfs_create_group(&lis->dev->kobj, &lis302dl_attr_group); if (rc) { - dev_err(&spi->dev, "error creating sysfs group\n"); + dev_err(lis->dev, "error creating sysfs group\n"); goto bail_free_lis; } /* initialize input layer details */ lis->input_dev = input_allocate_device(); if (!lis->input_dev) { - dev_err(&spi->dev, "Unable to allocate input device\n"); + dev_err(lis->dev, "Unable to allocate input device\n"); goto bail_sysfs; } @@ -601,59 +572,67 @@ static int __devinit lis302dl_probe(struct spi_device *spi) rc = input_register_device(lis->input_dev); if (rc) { - dev_err(&spi->dev, "error %d registering input device\n", rc); + dev_err(lis->dev, "error %d registering input device\n", rc); goto bail_inp_dev; } if (__lis302dl_reset_device(lis)) - dev_err(&spi->dev, "device BOOT reload failed\n"); + dev_err(lis->dev, "device BOOT reload failed\n"); /* force us powered */ - reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD | - LIS302DL_CTRL1_Xen | - LIS302DL_CTRL1_Yen | - LIS302DL_CTRL1_Zen); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL1, + LIS302DL_CTRL1_PD | + LIS302DL_CTRL1_Xen | + LIS302DL_CTRL1_Yen | + LIS302DL_CTRL1_Zen); mdelay(1); - reg_write(lis, LIS302DL_REG_CTRL2, 0); - - reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_PP_OD | - LIS302DL_CTRL3_IHL); - reg_write(lis, LIS302DL_REG_FF_WU_THS_1, 0x14); - - reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1, 0x00); - reg_write(lis, LIS302DL_REG_FF_WU_CFG_1, 0x0); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL2, 0); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL3, + LIS302DL_CTRL3_PP_OD | LIS302DL_CTRL3_IHL); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, + LIS302DL_REG_FF_WU_THS_1, 0x14); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, + LIS302DL_REG_FF_WU_DURATION_1, 0x00); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, + LIS302DL_REG_FF_WU_CFG_1, 0x0); /* start off in powered down mode; we power up when someone opens us */ - reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_Xen | - LIS302DL_CTRL1_Yen | - LIS302DL_CTRL1_Zen); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL1, + LIS302DL_CTRL1_Xen | + LIS302DL_CTRL1_Yen | + LIS302DL_CTRL1_Zen); if (pdata->open_drain) /* switch interrupt to open collector, active-low */ - reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_PP_OD | - LIS302DL_CTRL3_IHL); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, + LIS302DL_REG_CTRL3, LIS302DL_CTRL3_PP_OD | + LIS302DL_CTRL3_IHL); else /* push-pull, active-low */ - reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_IHL); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, + LIS302DL_REG_CTRL3, LIS302DL_CTRL3_IHL); - lis302dl_int_mode(spi, 1, LIS302DL_INTMODE_DATA_READY); - lis302dl_int_mode(spi, 2, LIS302DL_INTMODE_DATA_READY); + __lis302dl_int_mode(lis->dev, 1, LIS302DL_INTMODE_DATA_READY); + __lis302dl_int_mode(lis->dev, 2, LIS302DL_INTMODE_DATA_READY); - reg_read(lis, LIS302DL_REG_STATUS); - reg_read(lis, LIS302DL_REG_FF_WU_SRC_1); - reg_read(lis, LIS302DL_REG_FF_WU_SRC_2); - reg_read(lis, LIS302DL_REG_CLICK_SRC); + (lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_STATUS); + (lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_FF_WU_SRC_1); + (lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_FF_WU_SRC_2); + (lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_CLICK_SRC); - dev_info(&spi->dev, "Found %s\n", pdata->name); + dev_info(lis->dev, "Found %s\n", pdata->name); lis->pdata = pdata; - rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt, + set_irq_handler(lis->pdata->interrupt, handle_level_irq); + + rc = request_irq(lis->pdata->interrupt, lis302dl_interrupt, IRQF_TRIGGER_LOW, "lis302dl", lis); + if (rc < 0) { - dev_err(&spi->dev, "error requesting IRQ %d\n", - lis->spi_dev->irq); + dev_err(lis->dev, "error requesting IRQ %d\n", + lis->pdata->interrupt); goto bail_inp_reg; } local_irq_restore(flags); @@ -664,50 +643,71 @@ bail_inp_reg: bail_inp_dev: input_free_device(lis->input_dev); bail_sysfs: - sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group); + sysfs_remove_group(&lis->dev->kobj, &lis302dl_attr_group); bail_free_lis: kfree(lis); local_irq_restore(flags); return rc; } -static int __devexit lis302dl_remove(struct spi_device *spi) +static int __devexit lis302dl_remove(struct platform_device *pdev) { - struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); + struct lis302dl_info *lis = dev_get_drvdata(&pdev->dev); unsigned long flags; /* Reset and power down the device */ local_irq_save(flags); - reg_write(lis, LIS302DL_REG_CTRL3, 0x00); - reg_write(lis, LIS302DL_REG_CTRL2, 0x00); - reg_write(lis, LIS302DL_REG_CTRL1, 0x00); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL3, 0x00); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL2, 0x00); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL1, 0x00); local_irq_restore(flags); /* Cleanup resources */ - free_irq(lis->spi_dev->irq, lis); - sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group); + free_irq(lis->pdata->interrupt, lis); + sysfs_remove_group(&pdev->dev.kobj, &lis302dl_attr_group); input_unregister_device(lis->input_dev); if (lis->input_dev) input_free_device(lis->input_dev); - dev_set_drvdata(&spi->dev, NULL); + dev_set_drvdata(lis->dev, NULL); kfree(lis); return 0; } #ifdef CONFIG_PM -static int lis302dl_suspend(struct spi_device *spi, pm_message_t state) + +static u8 regs_to_save[] = { + LIS302DL_REG_CTRL1, + LIS302DL_REG_CTRL2, + LIS302DL_REG_CTRL3, + LIS302DL_REG_FF_WU_CFG_1, + LIS302DL_REG_FF_WU_THS_1, + LIS302DL_REG_FF_WU_DURATION_1, + LIS302DL_REG_FF_WU_CFG_2, + LIS302DL_REG_FF_WU_THS_2, + LIS302DL_REG_FF_WU_DURATION_2, + LIS302DL_REG_CLICK_CFG, + LIS302DL_REG_CLICK_THSY_X, + LIS302DL_REG_CLICK_THSZ, + LIS302DL_REG_CLICK_TIME_LIMIT, + LIS302DL_REG_CLICK_LATENCY, + LIS302DL_REG_CLICK_WINDOW, + +}; + +static int lis302dl_suspend(struct platform_device *pdev, pm_message_t state) { - struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); + struct lis302dl_info *lis = dev_get_drvdata(&pdev->dev); unsigned long flags; u_int8_t tmp; + int n; /* determine if we want to wake up from the accel. */ if (lis->flags & LIS302DL_F_WUP_FF || lis->flags & LIS302DL_F_WUP_CLICK) return 0; - disable_irq(lis->spi_dev->irq); + disable_irq(lis->pdata->interrupt); local_irq_save(flags); /* @@ -720,38 +720,15 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state) (lis->pdata->lis302dl_suspend_io)(lis, 1); /* save registers */ - lis->regs[LIS302DL_REG_CTRL1] = __reg_read(lis, LIS302DL_REG_CTRL1); - lis->regs[LIS302DL_REG_CTRL2] = __reg_read(lis, LIS302DL_REG_CTRL2); - lis->regs[LIS302DL_REG_CTRL3] = __reg_read(lis, LIS302DL_REG_CTRL3); - lis->regs[LIS302DL_REG_FF_WU_CFG_1] = - __reg_read(lis, LIS302DL_REG_FF_WU_CFG_1); - lis->regs[LIS302DL_REG_FF_WU_THS_1] = - __reg_read(lis, LIS302DL_REG_FF_WU_THS_1); - lis->regs[LIS302DL_REG_FF_WU_DURATION_1] = - __reg_read(lis, LIS302DL_REG_FF_WU_DURATION_1); - lis->regs[LIS302DL_REG_FF_WU_CFG_2] = - __reg_read(lis, LIS302DL_REG_FF_WU_CFG_2); - lis->regs[LIS302DL_REG_FF_WU_THS_2] = - __reg_read(lis, LIS302DL_REG_FF_WU_THS_2); - lis->regs[LIS302DL_REG_FF_WU_DURATION_2] = - __reg_read(lis, LIS302DL_REG_FF_WU_DURATION_2); - lis->regs[LIS302DL_REG_CLICK_CFG] = - __reg_read(lis, LIS302DL_REG_CLICK_CFG); - lis->regs[LIS302DL_REG_CLICK_THSY_X] = - __reg_read(lis, LIS302DL_REG_CLICK_THSY_X); - lis->regs[LIS302DL_REG_CLICK_THSZ] = - __reg_read(lis, LIS302DL_REG_CLICK_THSZ); - lis->regs[LIS302DL_REG_CLICK_TIME_LIMIT] = - __reg_read(lis, LIS302DL_REG_CLICK_TIME_LIMIT); - lis->regs[LIS302DL_REG_CLICK_LATENCY] = - __reg_read(lis, LIS302DL_REG_CLICK_LATENCY); - lis->regs[LIS302DL_REG_CLICK_WINDOW] = - __reg_read(lis, LIS302DL_REG_CLICK_WINDOW); + for (n = 0; n < ARRAY_SIZE(regs_to_save); n++) + lis->regs[regs_to_save[n]] = + (lis->pdata->lis302dl_bitbang_reg_read)(lis, + regs_to_save[n]); /* power down */ - tmp = __reg_read(lis, LIS302DL_REG_CTRL1); + tmp = (lis->pdata->lis302dl_bitbang_reg_read)(lis, LIS302DL_REG_CTRL1); tmp &= ~LIS302DL_CTRL1_PD; - __reg_write(lis, LIS302DL_REG_CTRL1, tmp); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL1, tmp); /* place our IO to the device in sleep-compatible states */ (lis->pdata->lis302dl_suspend_io)(lis, 0); @@ -761,10 +738,11 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state) return 0; } -static int lis302dl_resume(struct spi_device *spi) +static int lis302dl_resume(struct platform_device *pdev) { - struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); + struct lis302dl_info *lis = dev_get_drvdata(&pdev->dev); unsigned long flags; + int n; if (lis->flags & LIS302DL_F_WUP_FF || lis->flags & LIS302DL_F_WUP_CLICK) @@ -776,50 +754,28 @@ static int lis302dl_resume(struct spi_device *spi) (lis->pdata->lis302dl_suspend_io)(lis, 1); /* resume from powerdown first! */ - __reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD | - LIS302DL_CTRL1_Xen | - LIS302DL_CTRL1_Yen | - LIS302DL_CTRL1_Zen); + (lis->pdata->lis302dl_bitbang_reg_write)(lis, LIS302DL_REG_CTRL1, + LIS302DL_CTRL1_PD | + LIS302DL_CTRL1_Xen | + LIS302DL_CTRL1_Yen | + LIS302DL_CTRL1_Zen); mdelay(1); if (__lis302dl_reset_device(lis)) - dev_err(&spi->dev, "device BOOT reload failed\n"); + dev_err(&pdev->dev, "device BOOT reload failed\n"); - /* restore registers after resume */ - __reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1] | - LIS302DL_CTRL1_PD | + lis->regs[LIS302DL_REG_CTRL1] |= LIS302DL_CTRL1_PD | LIS302DL_CTRL1_Xen | LIS302DL_CTRL1_Yen | - LIS302DL_CTRL1_Zen); - __reg_write(lis, LIS302DL_REG_CTRL2, lis->regs[LIS302DL_REG_CTRL2]); - __reg_write(lis, LIS302DL_REG_CTRL3, lis->regs[LIS302DL_REG_CTRL3]); - __reg_write(lis, LIS302DL_REG_FF_WU_CFG_1, - lis->regs[LIS302DL_REG_FF_WU_CFG_1]); - __reg_write(lis, LIS302DL_REG_FF_WU_THS_1, - lis->regs[LIS302DL_REG_FF_WU_THS_1]); - __reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1, - lis->regs[LIS302DL_REG_FF_WU_DURATION_1]); - __reg_write(lis, LIS302DL_REG_FF_WU_CFG_2, - lis->regs[LIS302DL_REG_FF_WU_CFG_2]); - __reg_write(lis, LIS302DL_REG_FF_WU_THS_2, - lis->regs[LIS302DL_REG_FF_WU_THS_2]); - __reg_write(lis, LIS302DL_REG_FF_WU_DURATION_2, - lis->regs[LIS302DL_REG_FF_WU_DURATION_2]); - __reg_write(lis, LIS302DL_REG_CLICK_CFG, - lis->regs[LIS302DL_REG_CLICK_CFG]); - __reg_write(lis, LIS302DL_REG_CLICK_THSY_X, - lis->regs[LIS302DL_REG_CLICK_THSY_X]); - __reg_write(lis, LIS302DL_REG_CLICK_THSZ, - lis->regs[LIS302DL_REG_CLICK_THSZ]); - __reg_write(lis, LIS302DL_REG_CLICK_TIME_LIMIT, - lis->regs[LIS302DL_REG_CLICK_TIME_LIMIT]); - __reg_write(lis, LIS302DL_REG_CLICK_LATENCY, - lis->regs[LIS302DL_REG_CLICK_LATENCY]); - __reg_write(lis, LIS302DL_REG_CLICK_WINDOW, - lis->regs[LIS302DL_REG_CLICK_WINDOW]); + LIS302DL_CTRL1_Zen; + + /* restore registers after resume */ + for (n = 0; n < ARRAY_SIZE(regs_to_save); n++) + (lis->pdata->lis302dl_bitbang_reg_write)(lis, + regs_to_save[n], lis->regs[regs_to_save[n]]); local_irq_restore(flags); - enable_irq(lis->spi_dev->irq); + enable_irq(lis->pdata->interrupt); return 0; } @@ -828,7 +784,7 @@ static int lis302dl_resume(struct spi_device *spi) #define lis302dl_resume NULL #endif -static struct spi_driver lis302dl_driver = { +static struct platform_driver lis302dl_driver = { .driver = { .name = "lis302dl", .owner = THIS_MODULE, @@ -840,14 +796,14 @@ static struct spi_driver lis302dl_driver = { .resume = lis302dl_resume, }; -static int __init lis302dl_init(void) +static int __devinit lis302dl_init(void) { - return spi_register_driver(&lis302dl_driver); + return platform_driver_register(&lis302dl_driver); } static void __exit lis302dl_exit(void) { - spi_unregister_driver(&lis302dl_driver); + platform_driver_unregister(&lis302dl_driver); } MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>"); diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h index 7daa8b39980..4578db4ad6d 100644 --- a/include/linux/lis302dl.h +++ b/include/linux/lis302dl.h @@ -15,15 +15,18 @@ struct lis302dl_platform_data { unsigned long pin_mosi; unsigned long pin_miso; int open_drain; - void (*lis302dl_bitbang_read)(struct lis302dl_info *); + int interrupt; + void (*lis302dl_bitbang_read_sample)(struct lis302dl_info *); void (*lis302dl_suspend_io)(struct lis302dl_info *, int resuming); + int (*lis302dl_bitbang_reg_read)(struct lis302dl_info *, u8 reg); + void (*lis302dl_bitbang_reg_write)(struct lis302dl_info *, u8 reg, + u8 val); }; struct lis302dl_info { struct lis302dl_platform_data *pdata; - struct spi_device *spi_dev; + struct device *dev; struct input_dev *input_dev; - struct mutex lock; unsigned int flags; u_int8_t regs[0x40]; }; |