1 From 54bb0bfc6105dc7842d31ab67bd6afb6de0a6a28 Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Fri, 4 Apr 2008 11:36:01 +0100
4 Subject: [PATCH] gta02-acc.patch
7 arch/arm/mach-s3c2410/mach-gta01.c | 2 +-
8 arch/arm/mach-s3c2410/mach-qt2410.c | 2 +-
9 arch/arm/mach-s3c2440/mach-gta02.c | 181 +++++++++++++++--
10 drivers/input/misc/lis302dl.c | 350 ++++++++++++-------------------
11 drivers/spi/spi_s3c24xx_gpio.c | 13 +-
12 include/asm-arm/arch-s3c2410/spi-gpio.h | 3 +-
13 include/linux/lis302dl.h | 102 +++++++++
14 7 files changed, 415 insertions(+), 238 deletions(-)
16 diff --git a/arch/arm/mach-s3c2410/mach-gta01.c b/arch/arm/mach-s3c2410/mach-gta01.c
17 index 87bb189..0543daa 100644
18 --- a/arch/arm/mach-s3c2410/mach-gta01.c
19 +++ b/arch/arm/mach-s3c2410/mach-gta01.c
20 @@ -510,7 +510,7 @@ static struct spi_board_info gta01_spi_board_info[] = {
24 -static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
25 +static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int csidx, int cs)
28 case BITBANG_CS_ACTIVE:
29 diff --git a/arch/arm/mach-s3c2410/mach-qt2410.c b/arch/arm/mach-s3c2410/mach-qt2410.c
30 index a1caf4b..6f7b56d 100644
31 --- a/arch/arm/mach-s3c2410/mach-qt2410.c
32 +++ b/arch/arm/mach-s3c2410/mach-qt2410.c
33 @@ -214,7 +214,7 @@ static struct platform_device qt2410_led = {
37 -static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
38 +static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int csidx, int cs)
41 case BITBANG_CS_ACTIVE:
42 diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
43 index d11da10..3fbb131 100644
44 --- a/arch/arm/mach-s3c2440/mach-gta02.c
45 +++ b/arch/arm/mach-s3c2440/mach-gta02.c
48 #include <linux/glamofb.h>
50 +/* arbitrates which sensor IRQ owns the shared SPI bus */
51 +static spinlock_t motion_irq_lock;
53 static struct map_desc gta02_iodesc[] __initdata = {
55 .virtual = 0xe0000000,
56 @@ -377,8 +380,6 @@ static struct platform_device *gta02_devices[] __initdata = {
57 &s3c_device_usbgadget,
65 @@ -478,10 +479,12 @@ static struct spi_board_info gta02_spi_board_info[] = {
69 +#if 0 /* currently this is not used and we use gpio spi */
70 static struct glamo_spi_info glamo_spi_cfg = {
71 .board_size = ARRAY_SIZE(gta02_spi_board_info),
72 .board_info = gta02_spi_board_info,
76 static struct glamo_spigpio_info glamo_spigpio_cfg = {
77 .pin_clk = GLAMO_GPIO10_OUTPUT,
78 @@ -507,16 +510,99 @@ static struct platform_device gta01_led_dev = {
80 /* SPI: Accelerometers attached to SPI of s3c244x */
82 -static void gta02_spi_acc_set_cs(struct s3c2410_spi_info *spi, int cs, int pol)
84 + * Situation is that Linux SPI can't work in an interrupt context, so we
85 + * implement our own bitbang here. Arbitration is needed because not only
86 + * can this interrupt happen at any time even if foreground wants to use
87 + * the bitbang API from Linux, but multiple motion sensors can be on the
88 + * same SPI bus, and multiple interrupts can happen.
90 + * Foreground / interrupt arbitration is okay because the interrupts are
91 + * disabled around all the foreground SPI code.
93 + * Interrupt / Interrupt arbitration is evidently needed, otherwise we
94 + * lose edge-triggered service after a while due to the two sensors sharing
95 + * the SPI bus having irqs at the same time eventually.
97 + * Servicing is typ 75 - 100us at 400MHz.
100 +/* #define DEBUG_SPEW_MS */
101 +#define MG_PER_SAMPLE 18
103 +void gat02_lis302dl_bitbang_read(struct lis302dl_info *lis)
105 - s3c2410_gpio_setpin(cs, pol);
106 + struct lis302dl_platform_data *pdata = lis->pdata;
107 + u8 shifter = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */
109 + unsigned long flags;
110 +#ifdef DEBUG_SPEW_MS
114 + spin_lock_irqsave(&motion_irq_lock, flags);
115 + s3c2410_gpio_setpin(pdata->pin_chip_select, 0);
116 + for (n = 0; n < 8; n++) { /* write the r/w, inc and address */
117 + s3c2410_gpio_setpin(pdata->pin_clk, 0);
118 + s3c2410_gpio_setpin(pdata->pin_mosi, (shifter >> 7) & 1);
119 + s3c2410_gpio_setpin(pdata->pin_clk, 1);
122 + for (n = 0; n < 5; n++) { /* 5 consequetive registers */
123 + for (n1 = 0; n1 < 8; n1++) { /* 8 bits each */
124 + s3c2410_gpio_setpin(pdata->pin_clk, 0);
125 + s3c2410_gpio_setpin(pdata->pin_clk, 1);
127 + if (s3c2410_gpio_getpin(pdata->pin_miso))
132 +#ifdef DEBUG_SPEW_MS
135 + input_report_rel(lis->input_dev, REL_X, MG_PER_SAMPLE * (s8)shifter);
138 +#ifdef DEBUG_SPEW_MS
141 + input_report_rel(lis->input_dev, REL_Y, MG_PER_SAMPLE * (s8)shifter);
144 +#ifdef DEBUG_SPEW_MS
147 + input_report_rel(lis->input_dev, REL_Z, MG_PER_SAMPLE * (s8)shifter);
151 + s3c2410_gpio_setpin(pdata->pin_chip_select, 1);
152 + spin_unlock_irqrestore(&motion_irq_lock, flags);
153 + input_sync(lis->input_dev);
154 +#ifdef DEBUG_SPEW_MS
155 + printk("%s: %d %d %d\n", pdata->name, x, y, z);
159 -static const struct lis302dl_platform_data lis302_pdata[] = {
161 +struct lis302dl_platform_data lis302_pdata[] = {
163 - .name = "lis302-1 (top)"
164 + .name = "lis302-1 (top)",
165 + .pin_chip_select= S3C2410_GPD12,
166 + .pin_clk = S3C2410_GPG7,
167 + .pin_mosi = S3C2410_GPG6,
168 + .pin_miso = S3C2410_GPG5,
169 + .open_drain = 1, /* altered at runtime by PCB rev */
170 + .lis302dl_bitbang_read = gat02_lis302dl_bitbang_read,
172 - .name = "lis302-2 (bottom)"
173 + .name = "lis302-2 (bottom)",
174 + .pin_chip_select= S3C2410_GPD13,
175 + .pin_clk = S3C2410_GPG7,
176 + .pin_mosi = S3C2410_GPG6,
177 + .pin_miso = S3C2410_GPG5,
178 + .open_drain = 1, /* altered at runtime by PCB rev */
179 + .lis302dl_bitbang_read = gat02_lis302dl_bitbang_read,
183 @@ -525,26 +611,75 @@ static struct spi_board_info gta02_spi_acc_bdinfo[] = {
184 .modalias = "lis302dl",
185 .platform_data = &lis302_pdata[0],
186 .irq = GTA02_IRQ_GSENSOR_1,
187 - .max_speed_hz = 400 * 1000,
188 + .max_speed_hz = 10 * 1000 * 1000,
190 - .chip_select = S3C2410_GPD12,
195 .modalias = "lis302dl",
196 .platform_data = &lis302_pdata[1],
197 .irq = GTA02_IRQ_GSENSOR_2,
198 - .max_speed_hz = 400 * 1000,
199 + .max_speed_hz = 10 * 1000 * 1000,
201 - .chip_select = S3C2410_GPD13,
207 -static struct s3c2410_spi_info gta02_spi_acc_cfg = {
208 - .set_cs = gta02_spi_acc_set_cs,
209 +static void spi_acc_cs(struct s3c2410_spigpio_info *spigpio_info,
212 + struct lis302dl_platform_data * plat_data =
213 + (struct lis302dl_platform_data *)spigpio_info->
214 + board_info->platform_data;
216 + case BITBANG_CS_ACTIVE:
217 + s3c2410_gpio_setpin(plat_data[csid].pin_chip_select, 0);
219 + case BITBANG_CS_INACTIVE:
220 + s3c2410_gpio_setpin(plat_data[csid].pin_chip_select, 1);
225 +static struct s3c2410_spigpio_info spi_gpio_cfg = {
226 + .pin_clk = S3C2410_GPG7,
227 + .pin_mosi = S3C2410_GPG6,
228 + .pin_miso = S3C2410_GPG5,
229 .board_size = ARRAY_SIZE(gta02_spi_acc_bdinfo),
230 .board_info = gta02_spi_acc_bdinfo,
231 + .chip_select = &spi_acc_cs,
232 + .num_chipselect = 2,
235 +static struct resource s3c_spi_acc_resource[] = {
237 + .start = S3C2410_GPG3,
238 + .end = S3C2410_GPG3,
241 + .start = S3C2410_GPG5,
242 + .end = S3C2410_GPG5,
245 + .start = S3C2410_GPG6,
246 + .end = S3C2410_GPG6,
249 + .start = S3C2410_GPG7,
250 + .end = S3C2410_GPG7,
254 +static struct platform_device s3c_device_spi_acc = {
255 + .name = "spi_s3c24xx_gpio",
257 + .num_resources = ARRAY_SIZE(s3c_spi_acc_resource),
258 + .resource = s3c_spi_acc_resource,
260 + .platform_data = &spi_gpio_cfg,
264 static struct resource gta02_led_resources[] = {
265 @@ -786,10 +921,21 @@ static void __init gta02_machine_init(void)
269 + switch (system_rev) {
270 + case GTA02v6_SYSTEM_REV:
271 + /* we need push-pull interrupt from motion sensors */
272 + lis302_pdata[0].open_drain = 0;
273 + lis302_pdata[1].open_drain = 0;
279 + spin_lock_init(&motion_irq_lock);
281 s3c_device_usb.dev.platform_data = >a02_usb_info;
282 s3c_device_nand.dev.platform_data = >a02_nand_info;
283 s3c_device_sdi.dev.platform_data = >a02_mmc_cfg;
284 - s3c_device_spi1.dev.platform_data = >a02_spi_acc_cfg;
286 /* Only GTA02v1 has a SD_DETECT GPIO. Since the slot is not
287 * hot-pluggable, this is not required anyway */
288 @@ -801,6 +947,12 @@ static void __init gta02_machine_init(void)
292 + /* acc sensor chip selects */
293 + s3c2410_gpio_setpin(S3C2410_GPD12, 1);
294 + s3c2410_gpio_cfgpin(S3C2410_GPD12, S3C2410_GPIO_OUTPUT);
295 + s3c2410_gpio_setpin(S3C2410_GPD13, 1);
296 + s3c2410_gpio_cfgpin(S3C2410_GPD13, S3C2410_GPIO_OUTPUT);
298 INIT_WORK(>a02_udc_vbus_drawer.work, __gta02_udc_vbus_draw);
299 s3c24xx_udc_set_platdata(>a02_udc_cfg);
300 set_s3c2410ts_info(>a02_ts_cfg);
301 @@ -829,6 +981,7 @@ static void __init gta02_machine_init(void)
305 + platform_device_register(&s3c_device_spi_acc);
306 platform_device_register(>a01_button_dev);
307 platform_device_register(>a01_pm_gsm_dev);
309 diff --git a/drivers/input/misc/lis302dl.c b/drivers/input/misc/lis302dl.c
310 index 45c41c8..36bdcf7 100644
311 --- a/drivers/input/misc/lis302dl.c
312 +++ b/drivers/input/misc/lis302dl.c
314 #include <linux/device.h>
315 #include <linux/platform_device.h>
316 #include <linux/delay.h>
317 -#include <linux/input.h>
318 #include <linux/irq.h>
319 #include <linux/interrupt.h>
320 #include <linux/sysfs.h>
322 #include <linux/lis302dl.h>
324 -#include <linux/spi/spi.h>
326 -#define LIS302DL_WHO_AM_I_MAGIC 0x3b
329 - LIS302DL_REG_WHO_AM_I = 0x0f,
330 - LIS302DL_REG_CTRL1 = 0x20,
331 - LIS302DL_REG_CTRL2 = 0x21,
332 - LIS302DL_REG_CTRL3 = 0x22,
333 - LIS302DL_REG_HP_FILTER_RESET = 0x23,
334 - LIS302DL_REG_STATUS = 0x27,
335 - LIS302DL_REG_OUT_X = 0x29,
336 - LIS302DL_REG_OUT_Y = 0x2b,
337 - LIS302DL_REG_OUT_Z = 0x2d,
338 - LIS302DL_REG_FF_WU_CFG_1 = 0x30,
339 - LIS302DL_REG_FF_WU_SRC_1 = 0x31,
340 - LIS302DL_REG_FF_WU_THS_1 = 0x32,
341 - LIS302DL_REG_FF_WU_DURATION_1 = 0x33,
342 - LIS302DL_REG_FF_WU_CFG_2 = 0x34,
343 - LIS302DL_REG_FF_WU_SRC_2 = 0x35,
344 - LIS302DL_REG_FF_WU_THS_2 = 0x36,
345 - LIS302DL_REG_FF_WU_DURATION_2 = 0x37,
346 - LIS302DL_REG_CLICK_CFG = 0x38,
347 - LIS302DL_REG_CLICK_SRC = 0x39,
348 - LIS302DL_REG_CLICK_THSY_X = 0x3b,
349 - LIS302DL_REG_CLICK_THSZ = 0x3c,
350 - LIS302DL_REG_CLICK_TIME_LIMIT = 0x3d,
351 - LIS302DL_REG_CLICK_LATENCY = 0x3e,
352 - LIS302DL_REG_CLICK_WINDOW = 0x3f,
355 -enum lis302dl_reg_ctrl1 {
356 - LIS302DL_CTRL1_Xen = 0x01,
357 - LIS302DL_CTRL1_Yen = 0x02,
358 - LIS302DL_CTRL1_Zen = 0x04,
359 - LIS302DL_CTRL1_STM = 0x08,
360 - LIS302DL_CTRL1_STP = 0x10,
361 - LIS302DL_CTRL1_FS = 0x20,
362 - LIS302DL_CTRL1_PD = 0x40,
363 - LIS302DL_CTRL1_DR = 0x80,
366 -enum lis302dl_reg_ctrl3 {
367 - LIS302DL_CTRL3_PP_OD = 0x40,
370 -enum lis302dl_reg_status {
371 - LIS302DL_STATUS_XDA = 0x01,
372 - LIS302DL_STATUS_YDA = 0x02,
373 - LIS302DL_STATUS_ZDA = 0x04,
374 - LIS302DL_STATUS_XYZDA = 0x08,
375 - LIS302DL_STATUS_XOR = 0x10,
376 - LIS302DL_STATUS_YOR = 0x20,
377 - LIS302DL_STATUS_ZOR = 0x40,
378 - LIS302DL_STATUS_XYZOR = 0x80,
381 -enum lis302dl_reg_ffwusrc1 {
382 - LIS302DL_FFWUSRC1_XL = 0x01,
383 - LIS302DL_FFWUSRC1_XH = 0x02,
384 - LIS302DL_FFWUSRC1_YL = 0x04,
385 - LIS302DL_FFWUSRC1_YH = 0x08,
386 - LIS302DL_FFWUSRC1_ZL = 0x10,
387 - LIS302DL_FFWUSRC1_ZH = 0x20,
388 - LIS302DL_FFWUSRC1_IA = 0x40,
391 -enum lis302dl_reg_cloik_src {
392 - LIS302DL_CLICKSRC_SINGLE_X = 0x01,
393 - LIS302DL_CLICKSRC_DOUBLE_X = 0x02,
394 - LIS302DL_CLICKSRC_SINGLE_Y = 0x04,
395 - LIS302DL_CLICKSRC_DOUBLE_Y = 0x08,
396 - LIS302DL_CLICKSRC_SINGLE_Z = 0x10,
397 - LIS302DL_CLICKSRC_DOUBLE_Z = 0x20,
398 - LIS302DL_CLICKSRC_IA = 0x40,
401 -struct lis302dl_info {
402 - struct spi_device *spi_dev;
403 - struct input_dev *input_dev;
405 - struct work_struct work;
406 - unsigned int flags;
407 - unsigned int working;
408 - u_int8_t regs[0x40];
411 -#define LIS302DL_F_WUP_FF 0x0001 /* wake up from free fall */
412 -#define LIS302DL_F_WUP_CLICK 0x0002
413 -#define LIS302DL_F_POWER 0x0010
414 -#define LIS302DL_F_FS 0x0020 /* ADC full scale */
416 /* lowlevel register access functions */
418 -#define READ_BIT 0x01
420 -#define ADDR_SHIFT 2
421 +#define READ_BIT 0x80
422 +#define READ_BIT_INC_ADS 0xc0
423 +#define ADDR_MASK 0x3f
425 -static inline u_int8_t __reg_read(struct lis302dl_info *lis, u_int8_t reg)
426 +static u_int8_t __reg_read(struct lis302dl_info *lis, u_int8_t reg)
431 - cmd = (reg << ADDR_SHIFT) | READ_BIT;
432 + BUG_ON(reg & ~ADDR_MASK);
434 + cmd = reg | READ_BIT;
436 rc = spi_w8r8(lis->spi_dev, cmd);
438 @@ -161,11 +70,13 @@ static u_int8_t reg_read(struct lis302dl_info *lis, u_int8_t reg)
442 -static inline int __reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val)
443 +static int __reg_write(struct lis302dl_info *lis, u_int8_t reg, u_int8_t val)
447 - buf[0] = (reg << ADDR_SHIFT);
448 + BUG_ON(reg & ~ADDR_MASK);
453 return spi_write(lis->spi_dev, buf, sizeof(buf));
454 @@ -207,10 +118,10 @@ static int reg_set_bit_mask(struct lis302dl_info *lis,
455 enum lis302dl_intmode {
456 LIS302DL_INTMODE_GND = 0x00,
457 LIS302DL_INTMODE_FF_WU_1 = 0x01,
458 - LIX302DL_INTMODE_FF_WU_2 = 0x02,
459 - LIX302DL_INTMODE_FF_WU_12 = 0x03,
460 - LIX302DL_INTMODE_DATA_READY = 0x04,
461 - LIX302DL_INTMODE_CLICK = 0x07,
462 + LIS302DL_INTMODE_FF_WU_2 = 0x02,
463 + LIS302DL_INTMODE_FF_WU_12 = 0x03,
464 + LIS302DL_INTMODE_DATA_READY = 0x04,
465 + LIS302DL_INTMODE_CLICK = 0x07,
468 static void lis302dl_int_mode(struct spi_device *spi, int int_pin,
469 @@ -218,12 +129,18 @@ static void lis302dl_int_mode(struct spi_device *spi, int int_pin,
471 struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
476 reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x07, mode);
477 - else if (int_pin == 2)
480 reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x38, mode << 3);
488 static void _report_btn_single(struct input_dev *inp, int btn)
490 input_report_key(inp, btn, 1);
491 @@ -241,95 +158,14 @@ static void _report_btn_double(struct input_dev *inp, int btn)
493 input_report_key(inp, btn, 0);
497 -static void lis302dl_work(struct work_struct *work)
499 - struct lis302dl_info *lis =
500 - container_of(work, struct lis302dl_info, work);
502 - u_int8_t status, ff_wu_src_1, click_src;
507 - status = reg_read(lis, LIS302DL_REG_STATUS);
508 - ff_wu_src_1 = reg_read(lis, LIS302DL_REG_FF_WU_SRC_1);
509 - click_src = reg_read(lis, LIS302DL_REG_CLICK_SRC);
511 - if (status & LIS302DL_STATUS_XDA) {
512 - val = reg_read(lis, LIS302DL_REG_OUT_X);
513 - if (lis->flags & LIS302DL_F_FS)
515 - input_report_rel(lis->input_dev, REL_X, val);
518 - if (status & LIS302DL_STATUS_YDA) {
519 - val = reg_read(lis, LIS302DL_REG_OUT_Y);
520 - if (lis->flags & LIS302DL_F_FS)
522 - input_report_rel(lis->input_dev, REL_Y, val);
525 - if (status & LIS302DL_STATUS_ZDA) {
526 - val = reg_read(lis, LIS302DL_REG_OUT_Z);
527 - if (lis->flags & LIS302DL_F_FS)
529 - input_report_rel(lis->input_dev, REL_Z, val);
533 - dev_dbg(&lis->spi_dev->dev, "overrun!\n");
535 - /* FIXME: implement overrun statistics */
537 - if (ff_wu_src_1 & LIS302DL_FFWUSRC1_IA) {
538 - /* FIXME: free fall interrupt handling */
541 - if (click_src & LIS302DL_CLICKSRC_IA) {
542 - if (click_src & LIS302DL_CLICKSRC_SINGLE_X)
543 - _report_btn_single(lis->input_dev, BTN_X);
544 - if (click_src & LIS302DL_CLICKSRC_DOUBLE_X)
545 - _report_btn_double(lis->input_dev, BTN_X);
547 - if (click_src & LIS302DL_CLICKSRC_SINGLE_Y)
548 - _report_btn_single(lis->input_dev, BTN_Y);
549 - if (click_src & LIS302DL_CLICKSRC_DOUBLE_Y)
550 - _report_btn_double(lis->input_dev, BTN_Y);
552 - if (click_src & LIS302DL_CLICKSRC_SINGLE_Z)
553 - _report_btn_single(lis->input_dev, BTN_Z);
554 - if (click_src & LIS302DL_CLICKSRC_DOUBLE_Z)
555 - _report_btn_double(lis->input_dev, BTN_Z);
559 - input_sync(lis->input_dev);
560 - put_device(&lis->spi_dev->dev);
562 - enable_irq(lis->spi_dev->irq);
565 -static void lis302dl_schedule_work(struct lis302dl_info *lis)
569 - get_device(&lis->spi_dev->dev);
570 - status = schedule_work(&lis->work);
571 - if (!status && !lis->working)
572 - dev_dbg(&lis->spi_dev->dev, "work item may be lost\n");
575 static irqreturn_t lis302dl_interrupt(int irq, void *_lis)
577 struct lis302dl_info *lis = _lis;
579 - lis302dl_schedule_work(lis);
581 - /* Disable any further interrupts until we have processed
582 - * the current one */
583 - disable_irq(lis->spi_dev->irq);
585 + (lis->pdata->lis302dl_bitbang_read)(lis);
589 @@ -388,6 +224,7 @@ static DEVICE_ATTR(full_scale, S_IRUGO | S_IWUSR, show_scale, set_scale);
590 static struct attribute *lis302dl_sysfs_entries[] = {
591 &dev_attr_sample_rate.attr,
592 &dev_attr_full_scale.attr,
596 static struct attribute_group lis302dl_attr_group = {
597 @@ -402,9 +239,16 @@ static int lis302dl_input_open(struct input_dev *inp)
598 struct lis302dl_info *lis = inp->private;
599 u_int8_t ctrl1 = LIS302DL_CTRL1_PD | LIS302DL_CTRL1_Xen |
600 LIS302DL_CTRL1_Yen | LIS302DL_CTRL1_Zen;
601 + unsigned long flags;
603 + local_save_flags(flags);
604 /* make sure we're powered up and generate data ready */
605 reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1);
606 + local_irq_restore(flags);
608 + /* kick it off -- since we are edge triggered, if we missed the edge
609 + * permanent low interrupt is death for us */
610 + (lis->pdata->lis302dl_bitbang_read)(lis);
614 @@ -414,9 +258,12 @@ static void lis302dl_input_close(struct input_dev *inp)
615 struct lis302dl_info *lis = inp->private;
616 u_int8_t ctrl1 = LIS302DL_CTRL1_Xen | LIS302DL_CTRL1_Yen |
618 + unsigned long flags;
620 + local_save_flags(flags);
622 /* since the input core already serializes access and makes sure we
623 - * only see close() for the close of the lastre user, we can safely
624 + * only see close() for the close of the last user, we can safely
625 * disable the data ready events */
626 reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, 0x00);
628 @@ -426,6 +273,7 @@ static void lis302dl_input_close(struct input_dev *inp)
629 reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD,
632 + local_irq_restore(flags);
635 static int __devinit lis302dl_probe(struct spi_device *spi)
636 @@ -433,84 +281,138 @@ static int __devinit lis302dl_probe(struct spi_device *spi)
638 struct lis302dl_info *lis;
640 + unsigned long flags;
641 + struct lis302dl_platform_data *pdata;
643 lis = kzalloc(sizeof(*lis), GFP_KERNEL);
647 + local_save_flags(flags);
649 mutex_init(&lis->lock);
650 - INIT_WORK(&lis->work, lis302dl_work);
653 spi_set_drvdata(spi, lis);
655 + pdata = spi->dev.platform_data;
659 - printk(KERN_ERR "error durign spi_setup of lis302dl driver\n");
660 + dev_err(&spi->dev, "error during spi_setup\n");
661 dev_set_drvdata(&spi->dev, NULL);
664 + goto bail_free_lis;
667 wai = reg_read(lis, LIS302DL_REG_WHO_AM_I);
668 if (wai != LIS302DL_WHO_AM_I_MAGIC) {
669 - printk(KERN_ERR "unknown who_am_i signature 0x%02x\n", wai);
670 + dev_err(&spi->dev, "unknown who_am_i signature 0x%02x\n", wai);
671 dev_set_drvdata(&spi->dev, NULL);
676 - /* switch interrupt to open collector */
677 - reg_write(lis, LIS302DL_CTRL3_PP_OD, 0x7c);
679 - rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt, IRQF_DISABLED,
682 - dev_err(&spi->dev, "error requesting IRQ %d\n",
683 - lis->spi_dev->irq);
687 + goto bail_free_lis;
690 rc = sysfs_create_group(&spi->dev.kobj, &lis302dl_attr_group);
692 dev_err(&spi->dev, "error creating sysfs group\n");
695 + goto bail_free_lis;
698 /* initialize input layer details */
699 lis->input_dev = input_allocate_device();
700 if (!lis->input_dev) {
701 dev_err(&spi->dev, "Unable to allocate input device\n");
706 set_bit(EV_REL, lis->input_dev->evbit);
707 - set_bit(EV_KEY, lis->input_dev->evbit);
708 + set_bit(REL_X, lis->input_dev->relbit);
709 + set_bit(REL_Y, lis->input_dev->relbit);
710 + set_bit(REL_Z, lis->input_dev->relbit);
711 +/* set_bit(EV_KEY, lis->input_dev->evbit);
712 set_bit(BTN_X, lis->input_dev->keybit);
713 set_bit(BTN_Y, lis->input_dev->keybit);
714 set_bit(BTN_Z, lis->input_dev->keybit);
717 lis->input_dev->private = lis;
718 - lis->input_dev->name = "lis302dl"; /* FIXME: platform data */
719 - lis->input_dev->id.bustype = BUS_I2C; /* FIXME: SPI Bus */
720 + lis->input_dev->name = pdata->name;
721 + /* SPI Bus not defined as a valid bus for input subsystem*/
722 + lis->input_dev->id.bustype = BUS_I2C; /* lie about it */
723 lis->input_dev->open = lis302dl_input_open;
724 lis->input_dev->close = lis302dl_input_close;
726 - input_register_device(lis->input_dev);
727 + rc = input_register_device(lis->input_dev);
729 + dev_err(&spi->dev, "error %d registering input device\n", rc);
733 + reg_write(lis, LIS302DL_REG_CTRL1, 0x47);
734 + reg_write(lis, LIS302DL_REG_CTRL3, 0xc0);
735 + reg_write(lis, LIS302DL_REG_FF_WU_THS_1, 0x14);
736 + reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1, 0x00);
737 + reg_write(lis, LIS302DL_REG_FF_WU_CFG_1, 0x95);
739 + reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_Xen |
740 + LIS302DL_CTRL1_Yen |
741 + LIS302DL_CTRL1_Zen);
743 + if (pdata->open_drain)
744 + /* switch interrupt to open collector, active-low */
745 + reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_PP_OD |
746 + LIS302DL_CTRL3_IHL);
748 + /* push-pull, active-low */
749 + reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_IHL);
751 + lis302dl_int_mode(spi, 1, LIS302DL_INTMODE_DATA_READY);
752 + lis302dl_int_mode(spi, 2, LIS302DL_INTMODE_DATA_READY);
754 + reg_read(lis, LIS302DL_REG_STATUS);
755 + reg_read(lis, LIS302DL_REG_FF_WU_SRC_1);
756 + reg_read(lis, LIS302DL_REG_FF_WU_SRC_2);
757 + reg_read(lis, LIS302DL_REG_CLICK_SRC);
759 + dev_info(&spi->dev, "Found %s\n", pdata->name);
761 + lis->pdata = pdata;
763 + rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt,
764 + IRQF_TRIGGER_FALLING, "lis302dl", lis);
766 + dev_err(&spi->dev, "error requesting IRQ %d\n",
767 + lis->spi_dev->irq);
770 + local_irq_restore(flags);
774 + input_unregister_device(lis->input_dev);
776 + input_free_device(lis->input_dev);
778 + sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group);
781 + local_irq_restore(flags);
785 static int __devexit lis302dl_remove(struct spi_device *spi)
787 struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
788 + unsigned long flags;
790 /* power down the device */
791 + local_save_flags(flags);
792 reg_write(lis, LIS302DL_REG_CTRL1, 0x00);
793 + local_irq_restore(flags);
795 sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group);
796 input_unregister_device(lis->input_dev);
797 + if (lis->input_dev)
798 + input_free_device(lis->input_dev);
799 dev_set_drvdata(&spi->dev, NULL);
802 @@ -521,6 +423,10 @@ static int __devexit lis302dl_remove(struct spi_device *spi)
803 static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
805 struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
806 + unsigned long flags;
808 + disable_irq(lis->spi_dev->irq);
809 + local_save_flags(flags);
812 lis->regs[LIS302DL_REG_CTRL1] = reg_read(lis, LIS302DL_REG_CTRL1);
813 @@ -561,12 +467,17 @@ static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
814 reg_write(lis, LIS302DL_REG_CTRL1, tmp);
817 + local_irq_restore(flags);
822 static int lis302dl_resume(struct spi_device *spi)
824 struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
825 + unsigned long flags;
827 + local_save_flags(flags);
829 /* restore registers after resume */
830 reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1]);
831 @@ -597,6 +508,9 @@ static int lis302dl_resume(struct spi_device *spi)
832 reg_write(lis, LIS302DL_REG_CLICK_WINDOW,
833 lis->regs[LIS302DL_REG_CLICK_WINDOW]);
835 + local_irq_restore(flags);
836 + enable_irq(lis->spi_dev->irq);
841 diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
842 index 109d82c..03b73dd 100644
843 --- a/drivers/spi/spi_s3c24xx_gpio.c
844 +++ b/drivers/spi/spi_s3c24xx_gpio.c
845 @@ -91,7 +91,7 @@ static void s3c2410_spigpio_chipselect(struct spi_device *dev, int value)
846 struct s3c2410_spigpio *sg = spidev_to_sg(dev);
848 if (sg->info && sg->info->chip_select)
849 - (sg->info->chip_select)(sg->info, value);
850 + (sg->info->chip_select)(sg->info, dev->chip_select, value);
853 static int s3c2410_spigpio_probe(struct platform_device *dev)
854 @@ -113,9 +113,11 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
856 platform_set_drvdata(dev, sp);
858 - /* copy in the plkatform data */
859 + /* copy in the platform data */
860 info = sp->info = dev->dev.platform_data;
862 + master->num_chipselect = info->num_chipselect;
864 /* setup spi bitbang adaptor */
865 sp->bitbang.master = spi_master_get(master);
866 sp->bitbang.master->bus_num = info->bus_num;
867 @@ -146,12 +148,17 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
868 /* register the chips to go with the board */
870 for (i = 0; i < sp->info->board_size; i++) {
871 + struct spi_device *spidev;
873 dev_info(&dev->dev, "registering %p: %s\n",
874 &sp->info->board_info[i],
875 sp->info->board_info[i].modalias);
877 sp->info->board_info[i].controller_data = sp;
878 - spi_new_device(master, sp->info->board_info + i);
879 + spidev = spi_new_device(master, sp->info->board_info + i);
881 + spidev->max_speed_hz =
882 + sp->info->board_info[i].max_speed_hz;
886 diff --git a/include/asm-arm/arch-s3c2410/spi-gpio.h b/include/asm-arm/arch-s3c2410/spi-gpio.h
887 index ba1dca8..03dea09 100644
888 --- a/include/asm-arm/arch-s3c2410/spi-gpio.h
889 +++ b/include/asm-arm/arch-s3c2410/spi-gpio.h
890 @@ -22,11 +22,12 @@ struct s3c2410_spigpio_info {
891 unsigned long pin_miso;
894 + int num_chipselect;
896 unsigned long board_size;
897 struct spi_board_info *board_info;
899 - void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
900 + void (*chip_select)(struct s3c2410_spigpio_info *spi, int csid, int cs);
904 diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
905 index d0f31be..2dea813 100644
906 --- a/include/linux/lis302dl.h
907 +++ b/include/linux/lis302dl.h
909 #define _LINUX_LIS302DL_H
911 #include <linux/types.h>
912 +#include <linux/spi/spi.h>
913 +#include <linux/input.h>
916 +struct lis302dl_info;
918 struct lis302dl_platform_data {
920 + unsigned long pin_chip_select;
921 + unsigned long pin_clk;
922 + unsigned long pin_mosi;
923 + unsigned long pin_miso;
925 + void (*lis302dl_bitbang_read)(struct lis302dl_info *);
928 +struct lis302dl_info {
929 + struct lis302dl_platform_data *pdata;
930 + struct spi_device *spi_dev;
931 + struct input_dev *input_dev;
933 + unsigned int flags;
934 + u_int8_t regs[0x40];
938 + LIS302DL_REG_WHO_AM_I = 0x0f,
939 + LIS302DL_REG_CTRL1 = 0x20,
940 + LIS302DL_REG_CTRL2 = 0x21,
941 + LIS302DL_REG_CTRL3 = 0x22,
942 + LIS302DL_REG_HP_FILTER_RESET = 0x23,
943 + LIS302DL_REG_STATUS = 0x27,
944 + LIS302DL_REG_OUT_X = 0x29,
945 + LIS302DL_REG_OUT_Y = 0x2b,
946 + LIS302DL_REG_OUT_Z = 0x2d,
947 + LIS302DL_REG_FF_WU_CFG_1 = 0x30,
948 + LIS302DL_REG_FF_WU_SRC_1 = 0x31,
949 + LIS302DL_REG_FF_WU_THS_1 = 0x32,
950 + LIS302DL_REG_FF_WU_DURATION_1 = 0x33,
951 + LIS302DL_REG_FF_WU_CFG_2 = 0x34,
952 + LIS302DL_REG_FF_WU_SRC_2 = 0x35,
953 + LIS302DL_REG_FF_WU_THS_2 = 0x36,
954 + LIS302DL_REG_FF_WU_DURATION_2 = 0x37,
955 + LIS302DL_REG_CLICK_CFG = 0x38,
956 + LIS302DL_REG_CLICK_SRC = 0x39,
957 + LIS302DL_REG_CLICK_THSY_X = 0x3b,
958 + LIS302DL_REG_CLICK_THSZ = 0x3c,
959 + LIS302DL_REG_CLICK_TIME_LIMIT = 0x3d,
960 + LIS302DL_REG_CLICK_LATENCY = 0x3e,
961 + LIS302DL_REG_CLICK_WINDOW = 0x3f,
964 +enum lis302dl_reg_ctrl1 {
965 + LIS302DL_CTRL1_Xen = 0x01,
966 + LIS302DL_CTRL1_Yen = 0x02,
967 + LIS302DL_CTRL1_Zen = 0x04,
968 + LIS302DL_CTRL1_STM = 0x08,
969 + LIS302DL_CTRL1_STP = 0x10,
970 + LIS302DL_CTRL1_FS = 0x20,
971 + LIS302DL_CTRL1_PD = 0x40,
972 + LIS302DL_CTRL1_DR = 0x80,
975 +enum lis302dl_reg_ctrl3 {
976 + LIS302DL_CTRL3_PP_OD = 0x40,
977 + LIS302DL_CTRL3_IHL = 0x80,
980 +enum lis302dl_reg_status {
981 + LIS302DL_STATUS_XDA = 0x01,
982 + LIS302DL_STATUS_YDA = 0x02,
983 + LIS302DL_STATUS_ZDA = 0x04,
984 + LIS302DL_STATUS_XYZDA = 0x08,
985 + LIS302DL_STATUS_XOR = 0x10,
986 + LIS302DL_STATUS_YOR = 0x20,
987 + LIS302DL_STATUS_ZOR = 0x40,
988 + LIS302DL_STATUS_XYZOR = 0x80,
991 +enum lis302dl_reg_ffwusrc1 {
992 + LIS302DL_FFWUSRC1_XL = 0x01,
993 + LIS302DL_FFWUSRC1_XH = 0x02,
994 + LIS302DL_FFWUSRC1_YL = 0x04,
995 + LIS302DL_FFWUSRC1_YH = 0x08,
996 + LIS302DL_FFWUSRC1_ZL = 0x10,
997 + LIS302DL_FFWUSRC1_ZH = 0x20,
998 + LIS302DL_FFWUSRC1_IA = 0x40,
1001 +enum lis302dl_reg_cloik_src {
1002 + LIS302DL_CLICKSRC_SINGLE_X = 0x01,
1003 + LIS302DL_CLICKSRC_DOUBLE_X = 0x02,
1004 + LIS302DL_CLICKSRC_SINGLE_Y = 0x04,
1005 + LIS302DL_CLICKSRC_DOUBLE_Y = 0x08,
1006 + LIS302DL_CLICKSRC_SINGLE_Z = 0x10,
1007 + LIS302DL_CLICKSRC_DOUBLE_Z = 0x20,
1008 + LIS302DL_CLICKSRC_IA = 0x40,
1011 +#define LIS302DL_WHO_AM_I_MAGIC 0x3b
1013 +#define LIS302DL_F_WUP_FF 0x0001 /* wake up from free fall */
1014 +#define LIS302DL_F_WUP_CLICK 0x0002
1015 +#define LIS302DL_F_POWER 0x0010
1016 +#define LIS302DL_F_FS 0x0020 /* ADC full scale */
1019 #endif /* _LINUX_LIS302DL_H */