aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-s3c2440/mach-gta02.c249
-rw-r--r--drivers/input/misc/lis302dl.c442
-rw-r--r--include/linux/lis302dl.h9
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[] = {
&gta02_pm_gsm_dev,
&gta02_sdio_dev,
&gta02_pm_usbhost_dev,
- &s3c_device_spi_acc, /* input 2 and 3 */
+ &s3c_device_spi_acc1, /* input 2 */
+ &s3c_device_spi_acc2, /* input 3 */
&gta02_button_dev, /* input 4 */
&gta02_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];
};