diff options
Diffstat (limited to 'target/linux/s3c24xx/patches-2.6.24/1040-gta02-acc.patch.patch')
-rw-r--r-- | target/linux/s3c24xx/patches-2.6.24/1040-gta02-acc.patch.patch | 1023 |
1 files changed, 0 insertions, 1023 deletions
diff --git a/target/linux/s3c24xx/patches-2.6.24/1040-gta02-acc.patch.patch b/target/linux/s3c24xx/patches-2.6.24/1040-gta02-acc.patch.patch deleted file mode 100644 index fdf024f..0000000 --- a/target/linux/s3c24xx/patches-2.6.24/1040-gta02-acc.patch.patch +++ /dev/null @@ -1,1023 +0,0 @@ -From 54bb0bfc6105dc7842d31ab67bd6afb6de0a6a28 Mon Sep 17 00:00:00 2001 -From: mokopatches <mokopatches@openmoko.org> -Date: Fri, 4 Apr 2008 11:36:01 +0100 -Subject: [PATCH] gta02-acc.patch - ---- - arch/arm/mach-s3c2410/mach-gta01.c | 2 +- - arch/arm/mach-s3c2410/mach-qt2410.c | 2 +- - arch/arm/mach-s3c2440/mach-gta02.c | 181 +++++++++++++++-- - drivers/input/misc/lis302dl.c | 350 ++++++++++++------------------- - drivers/spi/spi_s3c24xx_gpio.c | 13 +- - include/asm-arm/arch-s3c2410/spi-gpio.h | 3 +- - include/linux/lis302dl.h | 102 +++++++++ - 7 files changed, 415 insertions(+), 238 deletions(-) - -diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c -index 87bb189..0543daa 100644 ---- a/arch/arm/mach-s3c2410/mach-gta01.c -+++ b/arch/arm/mach-s3c2410/mach-gta01.c -@@ -510,7 +510,7 @@ static struct spi_board_info gta01_spi_board_info[] = { - }, - }; - --static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs) -+static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int csidx, int cs) - { - switch (cs) { - case BITBANG_CS_ACTIVE: -diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c -index a1caf4b..6f7b56d 100644 ---- a/arch/arm/mach-s3c2410/mach-qt2410.c -+++ b/arch/arm/mach-s3c2410/mach-qt2410.c -@@ -214,7 +214,7 @@ static struct platform_device qt2410_led = { - - /* SPI */ - --static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs) -+static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int csidx, int cs) - { - switch (cs) { - case BITBANG_CS_ACTIVE: -diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c -index d11da10..3fbb131 100644 ---- a/arch/arm/mach-s3c2440/mach-gta02.c -+++ b/arch/arm/mach-s3c2440/mach-gta02.c -@@ -78,6 +78,9 @@ - - #include <linux/glamofb.h> - -+/* arbitrates which sensor IRQ owns the shared SPI bus */ -+static spinlock_t motion_irq_lock; -+ - static struct map_desc gta02_iodesc[] __initdata = { - { - .virtual = 0xe0000000, -@@ -377,8 +380,6 @@ static struct platform_device *gta02_devices[] __initdata = { - &s3c_device_usbgadget, - &s3c_device_nand, - &s3c_device_ts, -- &s3c_device_spi0, -- &s3c_device_spi1, - >a02_nor_flash, - }; - -@@ -478,10 +479,12 @@ static struct spi_board_info gta02_spi_board_info[] = { - }, - }; - -+#if 0 /* currently this is not used and we use gpio spi */ - static struct glamo_spi_info glamo_spi_cfg = { - .board_size = ARRAY_SIZE(gta02_spi_board_info), - .board_info = gta02_spi_board_info, - }; -+#endif /* 0 */ - - static struct glamo_spigpio_info glamo_spigpio_cfg = { - .pin_clk = GLAMO_GPIO10_OUTPUT, -@@ -507,16 +510,99 @@ static struct platform_device gta01_led_dev = { - - /* SPI: Accelerometers attached to SPI of s3c244x */ - --static void gta02_spi_acc_set_cs(struct s3c2410_spi_info *spi, int cs, int pol) -+/* -+ * Situation is that Linux SPI can't work in an interrupt context, so we -+ * implement our own bitbang here. Arbitration is needed because not only -+ * can this interrupt happen at any time even if foreground wants to use -+ * the bitbang API from Linux, but multiple motion sensors can be on the -+ * same SPI bus, and multiple interrupts can happen. -+ * -+ * Foreground / interrupt arbitration is okay because the interrupts are -+ * disabled around all the foreground SPI code. -+ * -+ * Interrupt / Interrupt arbitration is evidently needed, otherwise we -+ * lose edge-triggered service after a while due to the two sensors sharing -+ * the SPI bus having irqs at the same time eventually. -+ * -+ * Servicing is typ 75 - 100us at 400MHz. -+ */ -+ -+/* #define DEBUG_SPEW_MS */ -+#define MG_PER_SAMPLE 18 -+ -+void gat02_lis302dl_bitbang_read(struct lis302dl_info *lis) - { -- s3c2410_gpio_setpin(cs, pol); -+ struct lis302dl_platform_data *pdata = lis->pdata; -+ u8 shifter = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */ -+ int n, n1; -+ unsigned long flags; -+#ifdef DEBUG_SPEW_MS -+ s8 x, y, z; -+#endif -+ -+ spin_lock_irqsave(&motion_irq_lock, flags); -+ 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, 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); -+ shifter <<= 1; -+ if (s3c2410_gpio_getpin(pdata->pin_miso)) -+ shifter |= 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; -+ } -+ } -+ s3c2410_gpio_setpin(pdata->pin_chip_select, 1); -+ spin_unlock_irqrestore(&motion_irq_lock, flags); -+ input_sync(lis->input_dev); -+#ifdef DEBUG_SPEW_MS -+ printk("%s: %d %d %d\n", pdata->name, x, y, z); -+#endif - } - --static const struct lis302dl_platform_data lis302_pdata[] = { -+ -+struct lis302dl_platform_data lis302_pdata[] = { - { -- .name = "lis302-1 (top)" -+ .name = "lis302-1 (top)", -+ .pin_chip_select= S3C2410_GPD12, -+ .pin_clk = S3C2410_GPG7, -+ .pin_mosi = S3C2410_GPG6, -+ .pin_miso = S3C2410_GPG5, -+ .open_drain = 1, /* altered at runtime by PCB rev */ -+ .lis302dl_bitbang_read = gat02_lis302dl_bitbang_read, - }, { -- .name = "lis302-2 (bottom)" -+ .name = "lis302-2 (bottom)", -+ .pin_chip_select= S3C2410_GPD13, -+ .pin_clk = S3C2410_GPG7, -+ .pin_mosi = S3C2410_GPG6, -+ .pin_miso = S3C2410_GPG5, -+ .open_drain = 1, /* altered at runtime by PCB rev */ -+ .lis302dl_bitbang_read = gat02_lis302dl_bitbang_read, - }, - }; - -@@ -525,26 +611,75 @@ static struct spi_board_info gta02_spi_acc_bdinfo[] = { - .modalias = "lis302dl", - .platform_data = &lis302_pdata[0], - .irq = GTA02_IRQ_GSENSOR_1, -- .max_speed_hz = 400 * 1000, -+ .max_speed_hz = 10 * 1000 * 1000, - .bus_num = 1, -- .chip_select = S3C2410_GPD12, -+ .chip_select = 0, - .mode = SPI_MODE_3, - }, - { - .modalias = "lis302dl", - .platform_data = &lis302_pdata[1], - .irq = GTA02_IRQ_GSENSOR_2, -- .max_speed_hz = 400 * 1000, -+ .max_speed_hz = 10 * 1000 * 1000, - .bus_num = 1, -- .chip_select = S3C2410_GPD13, -+ .chip_select = 1, - .mode = SPI_MODE_3, - }, - }; - --static struct s3c2410_spi_info gta02_spi_acc_cfg = { -- .set_cs = gta02_spi_acc_set_cs, -+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_acc = { -+ .name = "spi_s3c24xx_gpio", -+ .id = 1, -+ .num_resources = ARRAY_SIZE(s3c_spi_acc_resource), -+ .resource = s3c_spi_acc_resource, -+ .dev = { -+ .platform_data = &spi_gpio_cfg, -+ }, - }; - - static struct resource gta02_led_resources[] = { -@@ -786,10 +921,21 @@ static void __init gta02_machine_init(void) - { - int rc; - -+ 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; -+ break; -+ default: -+ break; -+ } -+ -+ spin_lock_init(&motion_irq_lock); -+ - s3c_device_usb.dev.platform_data = >a02_usb_info; - s3c_device_nand.dev.platform_data = >a02_nand_info; - s3c_device_sdi.dev.platform_data = >a02_mmc_cfg; -- s3c_device_spi1.dev.platform_data = >a02_spi_acc_cfg; - - /* Only GTA02v1 has a SD_DETECT GPIO. Since the slot is not - * hot-pluggable, this is not required anyway */ -@@ -801,6 +947,12 @@ static void __init gta02_machine_init(void) - break; - } - -+ /* acc sensor chip selects */ -+ s3c2410_gpio_setpin(S3C2410_GPD12, 1); -+ s3c2410_gpio_cfgpin(S3C2410_GPD12, S3C2410_GPIO_OUTPUT); -+ s3c2410_gpio_setpin(S3C2410_GPD13, 1); -+ s3c2410_gpio_cfgpin(S3C2410_GPD13, S3C2410_GPIO_OUTPUT); -+ - INIT_WORK(>a02_udc_vbus_drawer.work, __gta02_udc_vbus_draw); - s3c24xx_udc_set_platdata(>a02_udc_cfg); - set_s3c2410ts_info(>a02_ts_cfg); -@@ -829,6 +981,7 @@ static void __init gta02_machine_init(void) - break; - } - -+ platform_device_register(&s3c_device_spi_acc); - platform_device_register(>a01_button_dev); - platform_device_register(>a01_pm_gsm_dev); - -diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c -index 45c41c8..36bdcf7 100644 ---- a/drivers/input/misc/lis302dl.c -+++ b/drivers/input/misc/lis302dl.c -@@ -33,117 +33,26 @@ - #include <linux/device.h> - #include <linux/platform_device.h> - #include <linux/delay.h> --#include <linux/input.h> - #include <linux/irq.h> - #include <linux/interrupt.h> - #include <linux/sysfs.h> - - #include <linux/lis302dl.h> - --#include <linux/spi/spi.h> -- --#define LIS302DL_WHO_AM_I_MAGIC 0x3b -- --enum lis302dl_reg { -- LIS302DL_REG_WHO_AM_I = 0x0f, -- LIS302DL_REG_CTRL1 = 0x20, -- LIS302DL_REG_CTRL2 = 0x21, -- LIS302DL_REG_CTRL3 = 0x22, -- LIS302DL_REG_HP_FILTER_RESET = 0x23, -- LIS302DL_REG_STATUS = 0x27, -- LIS302DL_REG_OUT_X = 0x29, -- LIS302DL_REG_OUT_Y = 0x2b, -- LIS302DL_REG_OUT_Z = 0x2d, -- LIS302DL_REG_FF_WU_CFG_1 = 0x30, -- LIS302DL_REG_FF_WU_SRC_1 = 0x31, -- LIS302DL_REG_FF_WU_THS_1 = 0x32, -- LIS302DL_REG_FF_WU_DURATION_1 = 0x33, -- LIS302DL_REG_FF_WU_CFG_2 = 0x34, -- LIS302DL_REG_FF_WU_SRC_2 = 0x35, -- LIS302DL_REG_FF_WU_THS_2 = 0x36, -- LIS302DL_REG_FF_WU_DURATION_2 = 0x37, -- LIS302DL_REG_CLICK_CFG = 0x38, -- LIS302DL_REG_CLICK_SRC = 0x39, -- LIS302DL_REG_CLICK_THSY_X = 0x3b, -- LIS302DL_REG_CLICK_THSZ = 0x3c, -- LIS302DL_REG_CLICK_TIME_LIMIT = 0x3d, -- LIS302DL_REG_CLICK_LATENCY = 0x3e, -- LIS302DL_REG_CLICK_WINDOW = 0x3f, --}; -- --enum lis302dl_reg_ctrl1 { -- LIS302DL_CTRL1_Xen = 0x01, -- LIS302DL_CTRL1_Yen = 0x02, -- LIS302DL_CTRL1_Zen = 0x04, -- LIS302DL_CTRL1_STM = 0x08, -- LIS302DL_CTRL1_STP = 0x10, -- LIS302DL_CTRL1_FS = 0x20, -- LIS302DL_CTRL1_PD = 0x40, -- LIS302DL_CTRL1_DR = 0x80, --}; -- --enum lis302dl_reg_ctrl3 { -- LIS302DL_CTRL3_PP_OD = 0x40, --}; -- --enum lis302dl_reg_status { -- LIS302DL_STATUS_XDA = 0x01, -- LIS302DL_STATUS_YDA = 0x02, -- LIS302DL_STATUS_ZDA = 0x04, -- LIS302DL_STATUS_XYZDA = 0x08, -- LIS302DL_STATUS_XOR = 0x10, -- LIS302DL_STATUS_YOR = 0x20, -- LIS302DL_STATUS_ZOR = 0x40, -- LIS302DL_STATUS_XYZOR = 0x80, --}; -- --enum lis302dl_reg_ffwusrc1 { -- LIS302DL_FFWUSRC1_XL = 0x01, -- LIS302DL_FFWUSRC1_XH = 0x02, -- LIS302DL_FFWUSRC1_YL = 0x04, -- LIS302DL_FFWUSRC1_YH = 0x08, -- LIS302DL_FFWUSRC1_ZL = 0x10, -- LIS302DL_FFWUSRC1_ZH = 0x20, -- LIS302DL_FFWUSRC1_IA = 0x40, --}; -- --enum lis302dl_reg_cloik_src { -- LIS302DL_CLICKSRC_SINGLE_X = 0x01, -- LIS302DL_CLICKSRC_DOUBLE_X = 0x02, -- LIS302DL_CLICKSRC_SINGLE_Y = 0x04, -- LIS302DL_CLICKSRC_DOUBLE_Y = 0x08, -- LIS302DL_CLICKSRC_SINGLE_Z = 0x10, -- LIS302DL_CLICKSRC_DOUBLE_Z = 0x20, -- LIS302DL_CLICKSRC_IA = 0x40, --}; -- --struct lis302dl_info { -- struct spi_device *spi_dev; -- struct input_dev *input_dev; -- struct mutex lock; -- struct work_struct work; -- unsigned int flags; -- unsigned int working; -- u_int8_t regs[0x40]; --}; -- --#define LIS302DL_F_WUP_FF 0x0001 /* wake up from free fall */ --#define LIS302DL_F_WUP_CLICK 0x0002 --#define LIS302DL_F_POWER 0x0010 --#define LIS302DL_F_FS 0x0020 /* ADC full scale */ -- - /* lowlevel register access functions */ - --#define READ_BIT 0x01 --#define MS_BIT 0x02 --#define ADDR_SHIFT 2 -+#define READ_BIT 0x80 -+#define READ_BIT_INC_ADS 0xc0 -+#define ADDR_MASK 0x3f - --static inline u_int8_t __reg_read(struct lis302dl_info *lis, u_int8_t reg) -+static u_int8_t __reg_read(struct lis302dl_info *lis, u_int8_t reg) - { - int rc; - u_int8_t cmd; - -- cmd = (reg << ADDR_SHIFT) | READ_BIT; -+ BUG_ON(reg & ~ADDR_MASK); -+ -+ cmd = reg | READ_BIT; - - rc = spi_w8r8(lis->spi_dev, cmd); - -@@ -161,11 +70,13 @@ static u_int8_t reg_read(struct lis302dl_info *lis, u_int8_t reg) - return ret; - } - --static inline int __reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val) -+static int __reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val) - { - u_int8_t buf[2]; - -- buf[0] = (reg << ADDR_SHIFT); -+ BUG_ON(reg & ~ADDR_MASK); -+ -+ buf[0] = reg; - buf[1] = val; - - return spi_write(lis->spi_dev, buf, sizeof(buf)); -@@ -207,10 +118,10 @@ static int reg_set_bit_mask(struct lis302dl_info *lis, - enum lis302dl_intmode { - LIS302DL_INTMODE_GND = 0x00, - LIS302DL_INTMODE_FF_WU_1 = 0x01, -- LIX302DL_INTMODE_FF_WU_2 = 0x02, -- LIX302DL_INTMODE_FF_WU_12 = 0x03, -- LIX302DL_INTMODE_DATA_READY = 0x04, -- LIX302DL_INTMODE_CLICK = 0x07, -+ LIS302DL_INTMODE_FF_WU_2 = 0x02, -+ LIS302DL_INTMODE_FF_WU_12 = 0x03, -+ LIS302DL_INTMODE_DATA_READY = 0x04, -+ LIS302DL_INTMODE_CLICK = 0x07, - }; - - static void lis302dl_int_mode(struct spi_device *spi, int int_pin, -@@ -218,12 +129,18 @@ static void lis302dl_int_mode(struct spi_device *spi, int int_pin, - { - struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); - -- if (int_pin == 1) -+ switch (int_pin) { -+ case 1: - reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x07, mode); -- else if (int_pin == 2) -+ break; -+ case 2: - reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x38, mode << 3); -+ break; -+ default: -+ BUG(); -+ } - } -- -+#if 0 - static void _report_btn_single(struct input_dev *inp, int btn) - { - input_report_key(inp, btn, 1); -@@ -241,95 +158,14 @@ static void _report_btn_double(struct input_dev *inp, int btn) - input_sync(inp); - input_report_key(inp, btn, 0); - } -+#endif - --static void lis302dl_work(struct work_struct *work) --{ -- struct lis302dl_info *lis = -- container_of(work, struct lis302dl_info, work); -- -- u_int8_t status, ff_wu_src_1, click_src; -- u_int8_t val; -- -- lis->working = 1; -- -- status = reg_read(lis, LIS302DL_REG_STATUS); -- ff_wu_src_1 = reg_read(lis, LIS302DL_REG_FF_WU_SRC_1); -- click_src = reg_read(lis, LIS302DL_REG_CLICK_SRC); -- -- if (status & LIS302DL_STATUS_XDA) { -- val = reg_read(lis, LIS302DL_REG_OUT_X); -- if (lis->flags & LIS302DL_F_FS) -- val = val << 2; -- input_report_rel(lis->input_dev, REL_X, val); -- } -- -- if (status & LIS302DL_STATUS_YDA) { -- val = reg_read(lis, LIS302DL_REG_OUT_Y); -- if (lis->flags & LIS302DL_F_FS) -- val = val << 2; -- input_report_rel(lis->input_dev, REL_Y, val); -- } -- -- if (status & LIS302DL_STATUS_ZDA) { -- val = reg_read(lis, LIS302DL_REG_OUT_Z); -- if (lis->flags & LIS302DL_F_FS) -- val = val << 2; -- input_report_rel(lis->input_dev, REL_Z, val); -- } -- -- if (status & 0xf0) -- dev_dbg(&lis->spi_dev->dev, "overrun!\n"); -- -- /* FIXME: implement overrun statistics */ -- -- if (ff_wu_src_1 & LIS302DL_FFWUSRC1_IA) { -- /* FIXME: free fall interrupt handling */ -- } -- -- if (click_src & LIS302DL_CLICKSRC_IA) { -- if (click_src & LIS302DL_CLICKSRC_SINGLE_X) -- _report_btn_single(lis->input_dev, BTN_X); -- if (click_src & LIS302DL_CLICKSRC_DOUBLE_X) -- _report_btn_double(lis->input_dev, BTN_X); -- -- if (click_src & LIS302DL_CLICKSRC_SINGLE_Y) -- _report_btn_single(lis->input_dev, BTN_Y); -- if (click_src & LIS302DL_CLICKSRC_DOUBLE_Y) -- _report_btn_double(lis->input_dev, BTN_Y); -- -- if (click_src & LIS302DL_CLICKSRC_SINGLE_Z) -- _report_btn_single(lis->input_dev, BTN_Z); -- if (click_src & LIS302DL_CLICKSRC_DOUBLE_Z) -- _report_btn_double(lis->input_dev, BTN_Z); -- } -- -- lis->working = 0; -- input_sync(lis->input_dev); -- put_device(&lis->spi_dev->dev); -- -- enable_irq(lis->spi_dev->irq); --} -- --static void lis302dl_schedule_work(struct lis302dl_info *lis) --{ -- int status; -- -- get_device(&lis->spi_dev->dev); -- status = schedule_work(&lis->work); -- if (!status && !lis->working) -- dev_dbg(&lis->spi_dev->dev, "work item may be lost\n"); --} - - static irqreturn_t lis302dl_interrupt(int irq, void *_lis) - { - struct lis302dl_info *lis = _lis; - -- lis302dl_schedule_work(lis); -- -- /* Disable any further interrupts until we have processed -- * the current one */ -- disable_irq(lis->spi_dev->irq); -- -+ (lis->pdata->lis302dl_bitbang_read)(lis); - return IRQ_HANDLED; - } - -@@ -388,6 +224,7 @@ static DEVICE_ATTR(full_scale, S_IRUGO | S_IWUSR, show_scale, set_scale); - static struct attribute *lis302dl_sysfs_entries[] = { - &dev_attr_sample_rate.attr, - &dev_attr_full_scale.attr, -+ NULL - }; - - static struct attribute_group lis302dl_attr_group = { -@@ -402,9 +239,16 @@ static int lis302dl_input_open(struct input_dev *inp) - struct lis302dl_info *lis = inp->private; - u_int8_t ctrl1 = LIS302DL_CTRL1_PD | LIS302DL_CTRL1_Xen | - LIS302DL_CTRL1_Yen | LIS302DL_CTRL1_Zen; -+ unsigned long flags; - -+ local_save_flags(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); -+ -+ /* 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); - - return 0; - } -@@ -414,9 +258,12 @@ static void lis302dl_input_close(struct input_dev *inp) - struct lis302dl_info *lis = inp->private; - u_int8_t ctrl1 = LIS302DL_CTRL1_Xen | LIS302DL_CTRL1_Yen | - LIS302DL_CTRL1_Zen; -+ unsigned long flags; -+ -+ local_save_flags(flags); - - /* since the input core already serializes access and makes sure we -- * only see close() for the close of the lastre user, we can safely -+ * 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); - -@@ -426,6 +273,7 @@ static void lis302dl_input_close(struct input_dev *inp) - reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD, - 0x00); - } -+ local_irq_restore(flags); - } - - static int __devinit lis302dl_probe(struct spi_device *spi) -@@ -433,84 +281,138 @@ static int __devinit lis302dl_probe(struct spi_device *spi) - int rc; - struct lis302dl_info *lis; - u_int8_t wai; -+ unsigned long flags; -+ struct lis302dl_platform_data *pdata; - - lis = kzalloc(sizeof(*lis), GFP_KERNEL); - if (!lis) - return -ENOMEM; - -+ local_save_flags(flags); -+ - mutex_init(&lis->lock); -- INIT_WORK(&lis->work, lis302dl_work); - lis->spi_dev = spi; - - spi_set_drvdata(spi, lis); - -+ pdata = spi->dev.platform_data; -+ - rc = spi_setup(spi); - if (rc < 0) { -- printk(KERN_ERR "error durign spi_setup of lis302dl driver\n"); -+ dev_err(&spi->dev, "error during spi_setup\n"); - dev_set_drvdata(&spi->dev, NULL); -- kfree(lis); -- return rc; -+ goto bail_free_lis; - } - - wai = reg_read(lis, LIS302DL_REG_WHO_AM_I); - if (wai != LIS302DL_WHO_AM_I_MAGIC) { -- printk(KERN_ERR "unknown who_am_i signature 0x%02x\n", wai); -+ dev_err(&spi->dev, "unknown who_am_i signature 0x%02x\n", wai); - dev_set_drvdata(&spi->dev, NULL); -- kfree(lis); -- return -ENODEV; -- } -- -- /* switch interrupt to open collector */ -- reg_write(lis, LIS302DL_CTRL3_PP_OD, 0x7c); -- -- rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt, IRQF_DISABLED, -- "lis302dl", NULL); -- if (rc < 0) { -- dev_err(&spi->dev, "error requesting IRQ %d\n", -- lis->spi_dev->irq); -- /* FIXME */ -- return rc; -+ rc = -ENODEV; -+ goto bail_free_lis; - } - - rc = sysfs_create_group(&spi->dev.kobj, &lis302dl_attr_group); - if (rc) { - dev_err(&spi->dev, "error creating sysfs group\n"); -- /* FIXME */ -- return rc; -+ 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"); -- /* FIXME */ -+ goto bail_sysfs; - } - - set_bit(EV_REL, lis->input_dev->evbit); -- set_bit(EV_KEY, lis->input_dev->evbit); -+ set_bit(REL_X, lis->input_dev->relbit); -+ set_bit(REL_Y, lis->input_dev->relbit); -+ set_bit(REL_Z, lis->input_dev->relbit); -+/* set_bit(EV_KEY, lis->input_dev->evbit); - set_bit(BTN_X, lis->input_dev->keybit); - set_bit(BTN_Y, lis->input_dev->keybit); - set_bit(BTN_Z, lis->input_dev->keybit); -- -+*/ - lis->input_dev->private = lis; -- lis->input_dev->name = "lis302dl"; /* FIXME: platform data */ -- lis->input_dev->id.bustype = BUS_I2C; /* FIXME: SPI Bus */ -+ lis->input_dev->name = pdata->name; -+ /* SPI Bus not defined as a valid bus for input subsystem*/ -+ lis->input_dev->id.bustype = BUS_I2C; /* lie about it */ - lis->input_dev->open = lis302dl_input_open; - lis->input_dev->close = lis302dl_input_close; - -- input_register_device(lis->input_dev); -+ rc = input_register_device(lis->input_dev); -+ if (rc) { -+ dev_err(&spi->dev, "error %d registering input device\n", rc); -+ goto bail_inp_dev; -+ } -+ -+ reg_write(lis, LIS302DL_REG_CTRL1, 0x47); -+ reg_write(lis, LIS302DL_REG_CTRL3, 0xc0); -+ 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, 0x95); -+ -+ 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); -+ else -+ /* push-pull, active-low */ -+ 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); -+ -+ 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); - -+ dev_info(&spi->dev, "Found %s\n", pdata->name); -+ -+ lis->pdata = pdata; -+ -+ rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt, -+ IRQF_TRIGGER_FALLING, "lis302dl", lis); -+ if (rc < 0) { -+ dev_err(&spi->dev, "error requesting IRQ %d\n", -+ lis->spi_dev->irq); -+ goto bail_inp_reg; -+ } -+ local_irq_restore(flags); - return 0; -+ -+bail_inp_reg: -+ input_unregister_device(lis->input_dev); -+bail_inp_dev: -+ input_free_device(lis->input_dev); -+bail_sysfs: -+ sysfs_remove_group(&spi->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) - { - struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); -+ unsigned long flags; - - /* power down the device */ -+ local_save_flags(flags); - reg_write(lis, LIS302DL_REG_CTRL1, 0x00); -+ local_irq_restore(flags); -+ - sysfs_remove_group(&spi->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); - kfree(lis); - -@@ -521,6 +423,10 @@ static int __devexit lis302dl_remove(struct spi_device *spi) - static int lis302dl_suspend(struct spi_device *spi, pm_message_t state) - { - struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); -+ unsigned long flags; -+ -+ disable_irq(lis->spi_dev->irq); -+ local_save_flags(flags); - - /* save registers */ - lis->regs[LIS302DL_REG_CTRL1] = reg_read(lis, LIS302DL_REG_CTRL1); -@@ -561,12 +467,17 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state) - reg_write(lis, LIS302DL_REG_CTRL1, tmp); - } - -+ local_irq_restore(flags); -+ - return 0; - } - - static int lis302dl_resume(struct spi_device *spi) - { - struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); -+ unsigned long flags; -+ -+ local_save_flags(flags); - - /* restore registers after resume */ - reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1]); -@@ -597,6 +508,9 @@ static int lis302dl_resume(struct spi_device *spi) - reg_write(lis, LIS302DL_REG_CLICK_WINDOW, - lis->regs[LIS302DL_REG_CLICK_WINDOW]); - -+ local_irq_restore(flags); -+ enable_irq(lis->spi_dev->irq); -+ - return 0; - } - #else -diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c -index 109d82c..03b73dd 100644 ---- a/drivers/spi/spi_s3c24xx_gpio.c -+++ b/drivers/spi/spi_s3c24xx_gpio.c -@@ -91,7 +91,7 @@ static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value) - struct s3c2410_spigpio *sg = spidev_to_sg(dev); - - if (sg->info && sg->info->chip_select) -- (sg->info->chip_select)(sg->info, value); -+ (sg->info->chip_select)(sg->info, dev->chip_select, value); - } - - static int s3c2410_spigpio_probe(struct platform_device *dev) -@@ -113,9 +113,11 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) - - platform_set_drvdata(dev, sp); - -- /* copy in the plkatform data */ -+ /* copy in the platform data */ - info = sp->info = dev->dev.platform_data; - -+ master->num_chipselect = info->num_chipselect; -+ - /* setup spi bitbang adaptor */ - sp->bitbang.master = spi_master_get(master); - sp->bitbang.master->bus_num = info->bus_num; -@@ -146,12 +148,17 @@ static int s3c2410_spigpio_probe(struct platform_device *dev) - /* register the chips to go with the board */ - - for (i = 0; i < sp->info->board_size; i++) { -+ struct spi_device *spidev; -+ - dev_info(&dev->dev, "registering %p: %s\n", - &sp->info->board_info[i], - sp->info->board_info[i].modalias); - - sp->info->board_info[i].controller_data = sp; -- spi_new_device(master, sp->info->board_info + i); -+ spidev = spi_new_device(master, sp->info->board_info + i); -+ if (spidev) -+ spidev->max_speed_hz = -+ sp->info->board_info[i].max_speed_hz; - } - - return 0; -diff --git a/include/asm-arm/arch-s3c2410/spi-gpio.h b/include/asm-arm/arch-s3c2410/spi-gpio.h -index ba1dca8..03dea09 100644 ---- a/include/asm-arm/arch-s3c2410/spi-gpio.h -+++ b/include/asm-arm/arch-s3c2410/spi-gpio.h -@@ -22,11 +22,12 @@ struct s3c2410_spigpio_info { - unsigned long pin_miso; - - int bus_num; -+ int num_chipselect; - - unsigned long board_size; - struct spi_board_info *board_info; - -- void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs); -+ void (*chip_select)(struct s3c2410_spigpio_info *spi, int csid, int cs); - }; - - -diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h -index d0f31be..2dea813 100644 ---- a/include/linux/lis302dl.h -+++ b/include/linux/lis302dl.h -@@ -2,10 +2,112 @@ - #define _LINUX_LIS302DL_H - - #include <linux/types.h> -+#include <linux/spi/spi.h> -+#include <linux/input.h> -+ -+ -+struct lis302dl_info; - - struct lis302dl_platform_data { - char *name; -+ unsigned long pin_chip_select; -+ unsigned long pin_clk; -+ unsigned long pin_mosi; -+ unsigned long pin_miso; -+ int open_drain; -+ void (*lis302dl_bitbang_read)(struct lis302dl_info *); -+}; -+ -+struct lis302dl_info { -+ struct lis302dl_platform_data *pdata; -+ struct spi_device *spi_dev; -+ struct input_dev *input_dev; -+ struct mutex lock; -+ unsigned int flags; -+ u_int8_t regs[0x40]; -+}; -+ -+enum lis302dl_reg { -+ LIS302DL_REG_WHO_AM_I = 0x0f, -+ LIS302DL_REG_CTRL1 = 0x20, -+ LIS302DL_REG_CTRL2 = 0x21, -+ LIS302DL_REG_CTRL3 = 0x22, -+ LIS302DL_REG_HP_FILTER_RESET = 0x23, -+ LIS302DL_REG_STATUS = 0x27, -+ LIS302DL_REG_OUT_X = 0x29, -+ LIS302DL_REG_OUT_Y = 0x2b, -+ LIS302DL_REG_OUT_Z = 0x2d, -+ LIS302DL_REG_FF_WU_CFG_1 = 0x30, -+ LIS302DL_REG_FF_WU_SRC_1 = 0x31, -+ LIS302DL_REG_FF_WU_THS_1 = 0x32, -+ LIS302DL_REG_FF_WU_DURATION_1 = 0x33, -+ LIS302DL_REG_FF_WU_CFG_2 = 0x34, -+ LIS302DL_REG_FF_WU_SRC_2 = 0x35, -+ LIS302DL_REG_FF_WU_THS_2 = 0x36, -+ LIS302DL_REG_FF_WU_DURATION_2 = 0x37, -+ LIS302DL_REG_CLICK_CFG = 0x38, -+ LIS302DL_REG_CLICK_SRC = 0x39, -+ LIS302DL_REG_CLICK_THSY_X = 0x3b, -+ LIS302DL_REG_CLICK_THSZ = 0x3c, -+ LIS302DL_REG_CLICK_TIME_LIMIT = 0x3d, -+ LIS302DL_REG_CLICK_LATENCY = 0x3e, -+ LIS302DL_REG_CLICK_WINDOW = 0x3f, -+}; -+ -+enum lis302dl_reg_ctrl1 { -+ LIS302DL_CTRL1_Xen = 0x01, -+ LIS302DL_CTRL1_Yen = 0x02, -+ LIS302DL_CTRL1_Zen = 0x04, -+ LIS302DL_CTRL1_STM = 0x08, -+ LIS302DL_CTRL1_STP = 0x10, -+ LIS302DL_CTRL1_FS = 0x20, -+ LIS302DL_CTRL1_PD = 0x40, -+ LIS302DL_CTRL1_DR = 0x80, -+}; -+ -+enum lis302dl_reg_ctrl3 { -+ LIS302DL_CTRL3_PP_OD = 0x40, -+ LIS302DL_CTRL3_IHL = 0x80, - }; - -+enum lis302dl_reg_status { -+ LIS302DL_STATUS_XDA = 0x01, -+ LIS302DL_STATUS_YDA = 0x02, -+ LIS302DL_STATUS_ZDA = 0x04, -+ LIS302DL_STATUS_XYZDA = 0x08, -+ LIS302DL_STATUS_XOR = 0x10, -+ LIS302DL_STATUS_YOR = 0x20, -+ LIS302DL_STATUS_ZOR = 0x40, -+ LIS302DL_STATUS_XYZOR = 0x80, -+}; -+ -+enum lis302dl_reg_ffwusrc1 { -+ LIS302DL_FFWUSRC1_XL = 0x01, -+ LIS302DL_FFWUSRC1_XH = 0x02, -+ LIS302DL_FFWUSRC1_YL = 0x04, -+ LIS302DL_FFWUSRC1_YH = 0x08, -+ LIS302DL_FFWUSRC1_ZL = 0x10, -+ LIS302DL_FFWUSRC1_ZH = 0x20, -+ LIS302DL_FFWUSRC1_IA = 0x40, -+}; -+ -+enum lis302dl_reg_cloik_src { -+ LIS302DL_CLICKSRC_SINGLE_X = 0x01, -+ LIS302DL_CLICKSRC_DOUBLE_X = 0x02, -+ LIS302DL_CLICKSRC_SINGLE_Y = 0x04, -+ LIS302DL_CLICKSRC_DOUBLE_Y = 0x08, -+ LIS302DL_CLICKSRC_SINGLE_Z = 0x10, -+ LIS302DL_CLICKSRC_DOUBLE_Z = 0x20, -+ LIS302DL_CLICKSRC_IA = 0x40, -+}; -+ -+#define LIS302DL_WHO_AM_I_MAGIC 0x3b -+ -+#define LIS302DL_F_WUP_FF 0x0001 /* wake up from free fall */ -+#define LIS302DL_F_WUP_CLICK 0x0002 -+#define LIS302DL_F_POWER 0x0010 -+#define LIS302DL_F_FS 0x0020 /* ADC full scale */ -+ -+ - #endif /* _LINUX_LIS302DL_H */ - --- -1.5.6.5 - |