Changeset 3971


Ignore:
Timestamp:
01/29/08 10:10:44 (5 years ago)
Author:
werner
Message:

motion-sensors-irq-spi.patch

From: Andy Green <andy@…>

This patch removes the workqueue method originally implemented for
motion sensor service and replaces with with a platform-defined
callback which is used in the ISR.

An implementation for the callback is also provided which performs
IRQ-safe SPI bitbang at high speed to service the motion sensor
and insert the x y z data into the input queue.

Interrupts are changed to edge trigger from level removing the
sluggish behaviour.

Interrupts are serviced in typ 75 - 100us without involving the
scheduler now.

The input event interface was broken, this also fixes it.

# cat /proc/bus/input/devices
...
I: Bus=0018 Vendor=0000 Product=0000 Version=0000
N: Name="lis302-1 (top)"
P: Phys=
S: Sysfs=/devices/virtual/input/input2
U: Uniq=
H: Handlers=event2
B: EV=5
B: REL=7

I: Bus=0018 Vendor=0000 Product=0000 Version=0000
N: Name="lis302-2 (bottom)"
P: Phys=
S: Sysfs=/devices/virtual/input/input3
U: Uniq=
H: Handlers=event3
B: EV=5
B: REL=7

Data is scaled to be report in mG, so 1000 = 1G.

Data should be reported at 100 sps per axis.
You can sample the X Y Z data easily through hexdump.
Hexdump on a serial terminal can't keep up with the
data, so it is not shown in order.

# hexdump /dev/input/event2
...
00009c0 55d7 478e 70bd 000d 0002 0000 ffdc ffff
00009d0 55d7 478e 712d 000d 0002 0002 03de 0000
00009e0 55d7 478e 714b 000d 0000 0000 0000 0000
00009f0 55d7 478e 976b 000d 0002 0000 ffee ffff
0000a00 55d7 478e 97c9 000d 0002 0001 0012 0000
0000a10 55d7 478e 97f2 000d 0002 0002 03de 0000
0000a20 55d7 478e 980f 000d 0000 0000 0000 0000

The first 8 bytes are timestamp info.
The next 16-bit word is EV_REL to show it is relative
coordinate data.
The next word is 0000=X, 0001=Y, 0002=Z
The last 32 bits on each line is the sample data, in
signed milli-G.

You can single out just one coordinate for rough testing
like this

# hexdump /dev/input/event3 | grep ".* .* .* .* .* 0002 0002 .* .*$" | cut -d' ' -f8
03a8
03ba
03a8
03a8
03ba
03a8
03a8
03a8
03ba
...

Due to tolerances 1G is reported as ~0x3ba milli-G == 954mG
on the sensor I looked at. Or it could be the alien space
drive I mounted on my roof.

Signed-off-by: Andy Green <andy@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/src/target/kernel/2.6.24.x/patches/gta02-acc.patch

    r3970 r3971  
    2525 static struct glamo_spigpio_info glamo_spigpio_cfg = { 
    2626        .pin_clk        = GLAMO_GPIO10_OUTPUT, 
    27 @@ -504,16 +504,13 @@ 
     27@@ -504,16 +504,93 @@ 
    2828  
    2929 /* SPI: Accelerometers attached to SPI of s3c244x */ 
    3030  
    3131-static void gta02_spi_acc_set_cs(struct s3c2410_spi_info *spi, int cs, int pol) 
    32 -{ 
     32+/* 
     33+ * Situation is that Linux SPI can't work in an interrupt context, so we 
     34+ * implement our own bitbang here.  Arbitration is needed because not only 
     35+ * can this interrupt happen at any time even if foreground wants to use 
     36+ * the bitbang API from Linux, but multiple motion sensors can be on the 
     37+ * same SPI bus, and multiple interrupts can happen. 
     38+ * 
     39+ * Foreground / interrupt arbitration is okay because the interrupts are 
     40+ * disabled around all the foreground SPI code. 
     41+ * 
     42+ * Interrupt / Interrupt arbitration is okay because the interrupts are 
     43+ * at the same priority (I think) 
     44+ * 
     45+ * Servicing is typ 75 - 100us at 400MHz. 
     46+ */ 
     47+ 
     48+/* #define DEBUG_SPEW_MS */ 
     49+#define MG_PER_SAMPLE 18 
     50+ 
     51+void gat02_lis302dl_bitbang_read(struct lis302dl_info *lis) 
     52 { 
    3353-       s3c2410_gpio_setpin(cs, pol); 
    34 -} 
    35 - 
    36  static const struct lis302dl_platform_data lis302_pdata[] = { 
     54+       struct lis302dl_platform_data *pdata = lis->pdata; 
     55+       u8 shifter = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */ 
     56+       int n, n1; 
     57+#ifdef DEBUG_SPEW_MS 
     58+       s8 x, y, z; 
     59+#endif 
     60+ 
     61+       s3c2410_gpio_setpin(pdata->pin_chip_select, 0); 
     62+       for (n = 0; n < 8; n++) { /* write the r/w, inc and address */ 
     63+               s3c2410_gpio_setpin(pdata->pin_clk, 0); 
     64+               s3c2410_gpio_setpin(pdata->pin_mosi, (shifter >> 7) & 1); 
     65+               s3c2410_gpio_setpin(pdata->pin_clk, 1); 
     66+               shifter <<= 1; 
     67+       } 
     68+       for (n = 0; n < 5; n++) { /* 5 consequetive registers */ 
     69+               for (n1 = 0; n1 < 8; n1++) { /* 8 bits each */ 
     70+                       s3c2410_gpio_setpin(pdata->pin_clk, 0); 
     71+                       s3c2410_gpio_setpin(pdata->pin_clk, 1); 
     72+                       shifter <<= 1; 
     73+                       if (s3c2410_gpio_getpin(pdata->pin_miso)) 
     74+                               shifter |= 1; 
     75+               } 
     76+               switch (n) { 
     77+               case 0: 
     78+#ifdef DEBUG_SPEW_MS 
     79+                       x = shifter; 
     80+#endif 
     81+                       input_report_rel(lis->input_dev, REL_X, MG_PER_SAMPLE * (s8)shifter); 
     82+                       break; 
     83+               case 2: 
     84+#ifdef DEBUG_SPEW_MS 
     85+                       y = shifter; 
     86+#endif 
     87+                       input_report_rel(lis->input_dev, REL_Y, MG_PER_SAMPLE * (s8)shifter); 
     88+                       break; 
     89+               case 4: 
     90+#ifdef DEBUG_SPEW_MS 
     91+                       z = shifter; 
     92+#endif 
     93+                       input_report_rel(lis->input_dev, REL_Z, MG_PER_SAMPLE * (s8)shifter); 
     94+                       break; 
     95+               } 
     96+       } 
     97+       s3c2410_gpio_setpin(pdata->pin_chip_select, 1); 
     98+       input_sync(lis->input_dev); 
     99+#ifdef DEBUG_SPEW_MS 
     100+       printk("%s: %d %d %d\n", pdata->name, x, y, z); 
     101+#endif 
     102 } 
     103  
     104-static const struct lis302dl_platform_data lis302_pdata[] = { 
     105+ 
     106+const struct lis302dl_platform_data lis302_pdata[] = { 
    37107        { 
    38108-               .name           = "lis302-1 (top)" 
    39109+               .name           = "lis302-1 (top)", 
    40110+               .pin_chip_select= S3C2410_GPD12, 
     111+               .pin_clk        = S3C2410_GPG7, 
     112+               .pin_mosi       = S3C2410_GPG6, 
     113+               .pin_miso       = S3C2410_GPG5, 
     114+               .lis302dl_bitbang_read = gat02_lis302dl_bitbang_read, 
    41115        }, { 
    42116-               .name           = "lis302-2 (bottom)" 
    43117+               .name           = "lis302-2 (bottom)", 
    44118+               .pin_chip_select= S3C2410_GPD13, 
     119+               .pin_clk        = S3C2410_GPG7, 
     120+               .pin_mosi       = S3C2410_GPG6, 
     121+               .pin_miso       = S3C2410_GPG5, 
     122+               .lis302dl_bitbang_read = gat02_lis302dl_bitbang_read, 
    45123        }, 
    46124 }; 
    47125  
    48 @@ -522,26 +519,75 @@ 
     126@@ -522,26 +599,75 @@ 
    49127                .modalias       = "lis302dl", 
    50128                .platform_data  = &lis302_pdata[0], 
     
    128206  
    129207 static struct resource gta02_led_resources[] = { 
    130 @@ -784,7 +830,6 @@ 
     208@@ -784,7 +910,6 @@ 
    131209        s3c_device_usb.dev.platform_data = &gta02_usb_info; 
    132210        s3c_device_nand.dev.platform_data = &gta02_nand_info; 
     
    136214        /* Only GTA02v1 has a SD_DETECT GPIO.  Since the slot is not 
    137215         * hot-pluggable, this is not required anyway */ 
    138 @@ -796,6 +841,12 @@ 
     216@@ -796,6 +921,12 @@ 
    139217                break; 
    140218        } 
     
    149227        s3c24xx_udc_set_platdata(&gta02_udc_cfg); 
    150228        set_s3c2410ts_info(&gta02_ts_cfg); 
    151 @@ -824,6 +875,7 @@ 
     229@@ -824,6 +955,7 @@ 
    152230                break; 
    153231        } 
     
    161239--- linux-2.6.24.orig/drivers/input/misc/lis302dl.c 
    162240+++ linux-2.6.24/drivers/input/misc/lis302dl.c 
    163 @@ -84,6 +84,7 @@ 
    164   
    165  enum lis302dl_reg_ctrl3 { 
    166         LIS302DL_CTRL3_PP_OD            = 0x40, 
    167 +       LIS302DL_CTRL3_IHL              = 0x80, 
    168  }; 
    169   
    170  enum lis302dl_reg_status { 
    171 @@ -134,16 +135,17 @@ 
    172   
     241@@ -33,117 +33,26 @@ 
     242 #include <linux/device.h> 
     243 #include <linux/platform_device.h> 
     244 #include <linux/delay.h> 
     245-#include <linux/input.h> 
     246 #include <linux/irq.h> 
     247 #include <linux/interrupt.h> 
     248 #include <linux/sysfs.h> 
     249  
     250 #include <linux/lis302dl.h> 
     251  
     252-#include <linux/spi/spi.h> 
     253- 
     254-#define LIS302DL_WHO_AM_I_MAGIC                0x3b 
     255- 
     256-enum lis302dl_reg { 
     257-       LIS302DL_REG_WHO_AM_I           = 0x0f, 
     258-       LIS302DL_REG_CTRL1              = 0x20, 
     259-       LIS302DL_REG_CTRL2              = 0x21, 
     260-       LIS302DL_REG_CTRL3              = 0x22, 
     261-       LIS302DL_REG_HP_FILTER_RESET    = 0x23, 
     262-       LIS302DL_REG_STATUS             = 0x27, 
     263-       LIS302DL_REG_OUT_X              = 0x29, 
     264-       LIS302DL_REG_OUT_Y              = 0x2b, 
     265-       LIS302DL_REG_OUT_Z              = 0x2d, 
     266-       LIS302DL_REG_FF_WU_CFG_1        = 0x30, 
     267-       LIS302DL_REG_FF_WU_SRC_1        = 0x31, 
     268-       LIS302DL_REG_FF_WU_THS_1        = 0x32, 
     269-       LIS302DL_REG_FF_WU_DURATION_1   = 0x33, 
     270-       LIS302DL_REG_FF_WU_CFG_2        = 0x34, 
     271-       LIS302DL_REG_FF_WU_SRC_2        = 0x35, 
     272-       LIS302DL_REG_FF_WU_THS_2        = 0x36, 
     273-       LIS302DL_REG_FF_WU_DURATION_2   = 0x37, 
     274-       LIS302DL_REG_CLICK_CFG          = 0x38, 
     275-       LIS302DL_REG_CLICK_SRC          = 0x39, 
     276-       LIS302DL_REG_CLICK_THSY_X       = 0x3b, 
     277-       LIS302DL_REG_CLICK_THSZ         = 0x3c, 
     278-       LIS302DL_REG_CLICK_TIME_LIMIT   = 0x3d, 
     279-       LIS302DL_REG_CLICK_LATENCY      = 0x3e, 
     280-       LIS302DL_REG_CLICK_WINDOW       = 0x3f, 
     281-}; 
     282- 
     283-enum lis302dl_reg_ctrl1 { 
     284-       LIS302DL_CTRL1_Xen              = 0x01, 
     285-       LIS302DL_CTRL1_Yen              = 0x02, 
     286-       LIS302DL_CTRL1_Zen              = 0x04, 
     287-       LIS302DL_CTRL1_STM              = 0x08, 
     288-       LIS302DL_CTRL1_STP              = 0x10, 
     289-       LIS302DL_CTRL1_FS               = 0x20, 
     290-       LIS302DL_CTRL1_PD               = 0x40, 
     291-       LIS302DL_CTRL1_DR               = 0x80, 
     292-}; 
     293- 
     294-enum lis302dl_reg_ctrl3 { 
     295-       LIS302DL_CTRL3_PP_OD            = 0x40, 
     296-}; 
     297- 
     298-enum lis302dl_reg_status { 
     299-       LIS302DL_STATUS_XDA             = 0x01, 
     300-       LIS302DL_STATUS_YDA             = 0x02, 
     301-       LIS302DL_STATUS_ZDA             = 0x04, 
     302-       LIS302DL_STATUS_XYZDA           = 0x08, 
     303-       LIS302DL_STATUS_XOR             = 0x10, 
     304-       LIS302DL_STATUS_YOR             = 0x20, 
     305-       LIS302DL_STATUS_ZOR             = 0x40, 
     306-       LIS302DL_STATUS_XYZOR           = 0x80, 
     307-}; 
     308- 
     309-enum lis302dl_reg_ffwusrc1 { 
     310-       LIS302DL_FFWUSRC1_XL            = 0x01, 
     311-       LIS302DL_FFWUSRC1_XH            = 0x02, 
     312-       LIS302DL_FFWUSRC1_YL            = 0x04, 
     313-       LIS302DL_FFWUSRC1_YH            = 0x08, 
     314-       LIS302DL_FFWUSRC1_ZL            = 0x10, 
     315-       LIS302DL_FFWUSRC1_ZH            = 0x20, 
     316-       LIS302DL_FFWUSRC1_IA            = 0x40, 
     317-}; 
     318- 
     319-enum lis302dl_reg_cloik_src { 
     320-       LIS302DL_CLICKSRC_SINGLE_X      = 0x01, 
     321-       LIS302DL_CLICKSRC_DOUBLE_X      = 0x02, 
     322-       LIS302DL_CLICKSRC_SINGLE_Y      = 0x04, 
     323-       LIS302DL_CLICKSRC_DOUBLE_Y      = 0x08, 
     324-       LIS302DL_CLICKSRC_SINGLE_Z      = 0x10, 
     325-       LIS302DL_CLICKSRC_DOUBLE_Z      = 0x20, 
     326-       LIS302DL_CLICKSRC_IA            = 0x40, 
     327-}; 
     328- 
     329-struct lis302dl_info { 
     330-       struct spi_device *spi_dev; 
     331-       struct input_dev *input_dev; 
     332-       struct mutex lock; 
     333-       struct work_struct work; 
     334-       unsigned int flags; 
     335-       unsigned int working; 
     336-       u_int8_t regs[0x40]; 
     337-}; 
     338- 
     339-#define LIS302DL_F_WUP_FF              0x0001  /* wake up from free fall */ 
     340-#define LIS302DL_F_WUP_CLICK           0x0002 
     341-#define LIS302DL_F_POWER               0x0010 
     342-#define LIS302DL_F_FS                  0x0020  /* ADC full scale */ 
     343- 
    173344 /* lowlevel register access functions */ 
    174345  
     
    176347-#define MS_BIT         0x02 
    177348-#define ADDR_SHIFT     2 
    178 +#define READ_BIT       0x80 
    179 +#define        ADDR_MASK       0x3f 
     349+#define READ_BIT               0x80 
     350+#define READ_BIT_INC_ADS       0xc0 
     351+#define        ADDR_MASK               0x3f 
    180352  
    181353-static inline u_int8_t __reg_read(struct lis302dl_info *lis, u_int8_t reg) 
     
    192364        rc = spi_w8r8(lis->spi_dev, cmd); 
    193365  
    194 @@ -161,11 +163,13 @@ 
     366@@ -161,11 +70,13 @@ 
    195367        return ret; 
    196368 } 
     
    208380  
    209381        return spi_write(lis->spi_dev, buf, sizeof(buf)); 
    210 @@ -207,10 +211,10 @@ 
     382@@ -207,10 +118,10 @@ 
    211383 enum lis302dl_intmode { 
    212384        LIS302DL_INTMODE_GND            = 0x00, 
     
    223395  
    224396 static void lis302dl_int_mode(struct spi_device *spi, int int_pin, 
    225 @@ -218,10 +222,16 @@ 
     397@@ -218,12 +129,18 @@ 
    226398 { 
    227399        struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); 
     
    240412+       } 
    241413 } 
    242   
     414- 
     415+#if 0 
    243416 static void _report_btn_single(struct input_dev *inp, int btn) 
    244 @@ -247,34 +257,30 @@ 
    245         struct lis302dl_info *lis = 
    246                         container_of(work, struct lis302dl_info, work); 
    247   
     417 { 
     418        input_report_key(inp, btn, 1); 
     419@@ -241,95 +158,14 @@ 
     420        input_sync(inp); 
     421        input_report_key(inp, btn, 0); 
     422 } 
     423+#endif 
     424  
     425-static void lis302dl_work(struct work_struct *work) 
     426-{ 
     427-       struct lis302dl_info *lis = 
     428-                       container_of(work, struct lis302dl_info, work); 
     429- 
    248430-       u_int8_t status, ff_wu_src_1, click_src; 
    249431-       u_int8_t val; 
    250 +       u_int8_t status, ff_wu_src_1, ff_wu_src_2, click_src; 
    251 +       u_int8_t val_x, val_y, val_z; 
    252   
    253         lis->working = 1; 
    254   
    255         status = reg_read(lis, LIS302DL_REG_STATUS); 
    256         ff_wu_src_1 = reg_read(lis, LIS302DL_REG_FF_WU_SRC_1); 
    257 +       ff_wu_src_2 = reg_read(lis, LIS302DL_REG_FF_WU_SRC_2); 
    258         click_src = reg_read(lis, LIS302DL_REG_CLICK_SRC); 
    259   
     432- 
     433-       lis->working = 1; 
     434- 
     435-       status = reg_read(lis, LIS302DL_REG_STATUS); 
     436-       ff_wu_src_1 = reg_read(lis, LIS302DL_REG_FF_WU_SRC_1); 
     437-       click_src = reg_read(lis, LIS302DL_REG_CLICK_SRC); 
     438- 
    260439-       if (status & LIS302DL_STATUS_XDA) { 
    261440-               val = reg_read(lis, LIS302DL_REG_OUT_X); 
    262 +       if (status & LIS302DL_STATUS_XYZDA) { 
    263 +               val_x = reg_read(lis, LIS302DL_REG_OUT_X); 
    264                 if (lis->flags & LIS302DL_F_FS) 
     441-               if (lis->flags & LIS302DL_F_FS) 
    265442-                       val = val << 2; 
    266443-               input_report_rel(lis->input_dev, REL_X, val); 
     
    269446-       if (status & LIS302DL_STATUS_YDA) { 
    270447-               val = reg_read(lis, LIS302DL_REG_OUT_Y); 
    271 +                       val_x = val_x << 2; 
    272 +               input_report_rel(lis->input_dev, REL_X, val_x); 
    273 +               val_y = reg_read(lis, LIS302DL_REG_OUT_Y); 
    274                 if (lis->flags & LIS302DL_F_FS) 
     448-               if (lis->flags & LIS302DL_F_FS) 
    275449-                       val = val << 2; 
    276450-               input_report_rel(lis->input_dev, REL_Y, val); 
     
    279453-       if (status & LIS302DL_STATUS_ZDA) { 
    280454-               val = reg_read(lis, LIS302DL_REG_OUT_Z); 
    281 +                       val_y = val_y << 2; 
    282 +               input_report_rel(lis->input_dev, REL_Y, val_y); 
    283 +               val_z = reg_read(lis, LIS302DL_REG_OUT_Z); 
    284                 if (lis->flags & LIS302DL_F_FS) 
     455-               if (lis->flags & LIS302DL_F_FS) 
    285456-                       val = val << 2; 
    286457-               input_report_rel(lis->input_dev, REL_Z, val); 
    287 +                       val_z = val_z << 2; 
    288 +               input_report_rel(lis->input_dev, REL_Z, val_z); 
    289 +//             printk("%p: x=%d, y=%d, z=%d\n", lis, val_x, val_y, val_z); 
    290         } 
    291   
    292         if (status & 0xf0) 
    293 @@ -310,21 +316,15 @@ 
    294         enable_irq(lis->spi_dev->irq); 
    295  } 
    296   
     458-       } 
     459- 
     460-       if (status & 0xf0) 
     461-               dev_dbg(&lis->spi_dev->dev, "overrun!\n"); 
     462- 
     463-       /* FIXME: implement overrun statistics */ 
     464- 
     465-       if (ff_wu_src_1 & LIS302DL_FFWUSRC1_IA) { 
     466-               /* FIXME: free fall interrupt handling */ 
     467-       } 
     468- 
     469-       if (click_src & LIS302DL_CLICKSRC_IA) { 
     470-               if (click_src & LIS302DL_CLICKSRC_SINGLE_X) 
     471-                       _report_btn_single(lis->input_dev, BTN_X); 
     472-               if (click_src & LIS302DL_CLICKSRC_DOUBLE_X) 
     473-                       _report_btn_double(lis->input_dev, BTN_X); 
     474- 
     475-               if (click_src & LIS302DL_CLICKSRC_SINGLE_Y) 
     476-                       _report_btn_single(lis->input_dev, BTN_Y); 
     477-               if (click_src & LIS302DL_CLICKSRC_DOUBLE_Y) 
     478-                       _report_btn_double(lis->input_dev, BTN_Y); 
     479- 
     480-               if (click_src & LIS302DL_CLICKSRC_SINGLE_Z) 
     481-                       _report_btn_single(lis->input_dev, BTN_Z); 
     482-               if (click_src & LIS302DL_CLICKSRC_DOUBLE_Z) 
     483-                       _report_btn_double(lis->input_dev, BTN_Z); 
     484-       } 
     485- 
     486-       lis->working = 0; 
     487-       input_sync(lis->input_dev); 
     488-       put_device(&lis->spi_dev->dev); 
     489- 
     490-       enable_irq(lis->spi_dev->irq); 
     491-} 
     492- 
    297493-static void lis302dl_schedule_work(struct lis302dl_info *lis) 
    298494-{ 
     
    304500-               dev_dbg(&lis->spi_dev->dev, "work item may be lost\n"); 
    305501-} 
    306 - 
     502  
    307503 static irqreturn_t lis302dl_interrupt(int irq, void *_lis) 
    308504 { 
     
    310506  
    311507-       lis302dl_schedule_work(lis); 
    312 +       get_device(&lis->spi_dev->dev); 
    313 + 
    314 +       if (!schedule_work(&lis->work)) 
    315 +               if (!lis->working) 
    316 +                       dev_dbg(&lis->spi_dev->dev, "work item may be lost\n"); 
    317   
    318         /* Disable any further interrupts until we have processed 
    319          * the current one */ 
    320 @@ -388,6 +388,7 @@ 
     508- 
     509-       /* Disable any further interrupts until we have processed 
     510-        * the current one */ 
     511-       disable_irq(lis->spi_dev->irq); 
     512- 
     513+       (lis->pdata->lis302dl_bitbang_read)(lis); 
     514        return IRQ_HANDLED; 
     515 } 
     516  
     517@@ -388,6 +224,7 @@ 
    321518 static struct attribute *lis302dl_sysfs_entries[] = { 
    322519        &dev_attr_sample_rate.attr, 
     
    326523  
    327524 static struct attribute_group lis302dl_attr_group = { 
    328 @@ -416,7 +417,7 @@ 
     525@@ -402,9 +239,16 @@ 
     526        struct lis302dl_info *lis = inp->private; 
     527        u_int8_t ctrl1 = LIS302DL_CTRL1_PD | LIS302DL_CTRL1_Xen | 
     528                         LIS302DL_CTRL1_Yen | LIS302DL_CTRL1_Zen; 
     529+       unsigned long flags; 
     530  
     531+       local_save_flags(flags); 
     532        /* make sure we're powered up and generate data ready */ 
     533        reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1); 
     534+       local_irq_restore(flags); 
     535+ 
     536+       /* kick it off -- since we are edge triggered, if we missed the edge 
     537+        * permanent low interrupt is death for us */ 
     538+       (lis->pdata->lis302dl_bitbang_read)(lis); 
     539  
     540        return 0; 
     541 } 
     542@@ -414,9 +258,12 @@ 
     543        struct lis302dl_info *lis = inp->private; 
     544        u_int8_t ctrl1 = LIS302DL_CTRL1_Xen | LIS302DL_CTRL1_Yen | 
    329545                         LIS302DL_CTRL1_Zen; 
     546+       unsigned long flags; 
     547+ 
     548+       local_save_flags(flags); 
    330549  
    331550        /* since the input core already serializes access and makes sure we 
     
    335554        reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, 0x00); 
    336555  
    337 @@ -446,44 +447,38 @@ 
    338   
     556@@ -426,6 +273,7 @@ 
     557                reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD, 
     558                                 0x00); 
     559        } 
     560+       local_irq_restore(flags); 
     561 } 
     562  
     563 static int __devinit lis302dl_probe(struct spi_device *spi) 
     564@@ -433,84 +281,133 @@ 
     565        int rc; 
     566        struct lis302dl_info *lis; 
     567        u_int8_t wai; 
     568+       unsigned long flags; 
     569+       struct lis302dl_platform_data *pdata; 
     570  
     571        lis = kzalloc(sizeof(*lis), GFP_KERNEL); 
     572        if (!lis) 
     573                return -ENOMEM; 
     574  
     575+       local_save_flags(flags); 
     576+ 
     577        mutex_init(&lis->lock); 
     578-       INIT_WORK(&lis->work, lis302dl_work); 
     579        lis->spi_dev = spi; 
     580  
     581        spi_set_drvdata(spi, lis); 
     582  
     583+       pdata = spi->dev.platform_data; 
     584+ 
    339585        rc = spi_setup(spi); 
    340586        if (rc < 0) { 
     
    354600-               kfree(lis); 
    355601-               return -ENODEV; 
    356 +               rc = -ENODEV; 
    357 +               goto bail_free_lis; 
    358         } 
    359   
     602-       } 
     603- 
    360604-       /* switch interrupt to open collector */ 
    361605-       reg_write(lis, LIS302DL_CTRL3_PP_OD, 0x7c); 
     
    363607-       rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt, IRQF_DISABLED, 
    364608-                        "lis302dl", NULL); 
    365 +       rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt, 
    366 +                        IRQF_TRIGGER_LOW, "lis302dl", lis); 
    367         if (rc < 0) { 
    368                 dev_err(&spi->dev, "error requesting IRQ %d\n", 
    369                         lis->spi_dev->irq); 
     609-       if (rc < 0) { 
     610-               dev_err(&spi->dev, "error requesting IRQ %d\n", 
     611-                       lis->spi_dev->irq); 
    370612-               /* FIXME */ 
    371613-               return rc; 
     614+               rc = -ENODEV; 
    372615+               goto bail_free_lis; 
    373616        } 
     
    378621-               /* FIXME */ 
    379622-               return rc; 
    380 +               goto bail_irq; 
     623+               goto bail_free_lis; 
    381624        } 
    382625  
     
    390633  
    391634        set_bit(EV_REL, lis->input_dev->evbit); 
    392 @@ -498,9 +493,44 @@ 
     635-       set_bit(EV_KEY, lis->input_dev->evbit); 
     636+       set_bit(REL_X, lis->input_dev->relbit); 
     637+       set_bit(REL_Y, lis->input_dev->relbit); 
     638+       set_bit(REL_Z, lis->input_dev->relbit); 
     639+/*     set_bit(EV_KEY, lis->input_dev->evbit); 
     640        set_bit(BTN_X, lis->input_dev->keybit); 
     641        set_bit(BTN_Y, lis->input_dev->keybit); 
     642        set_bit(BTN_Z, lis->input_dev->keybit); 
     643- 
     644+*/ 
     645        lis->input_dev->private = lis; 
     646-       lis->input_dev->name = "lis302dl"; /* FIXME: platform data */ 
     647-       lis->input_dev->id.bustype = BUS_I2C; /* FIXME: SPI Bus */ 
     648+       lis->input_dev->name = pdata->name; 
     649+        /* SPI Bus not defined as a valid bus for input subsystem*/ 
     650+       lis->input_dev->id.bustype = BUS_I2C; /* lie about it */ 
    393651        lis->input_dev->open = lis302dl_input_open; 
    394652        lis->input_dev->close = lis302dl_input_close; 
     
    421679+       reg_read(lis, LIS302DL_REG_FF_WU_SRC_2); 
    422680+       reg_read(lis, LIS302DL_REG_CLICK_SRC); 
    423   
     681+ 
     682+       dev_info(&spi->dev, "Found %s\n", pdata->name); 
     683  
     684+       lis->pdata = pdata; 
     685+ 
     686+       rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt, 
     687+                        IRQF_TRIGGER_FALLING, "lis302dl", lis); 
     688+       if (rc < 0) { 
     689+               dev_err(&spi->dev, "error requesting IRQ %d\n", 
     690+                       lis->spi_dev->irq); 
     691+               goto bail_inp_reg; 
     692+       } 
     693+       local_irq_restore(flags); 
    424694        return 0; 
    425695+ 
     696+bail_inp_reg: 
     697+       input_unregister_device(lis->input_dev); 
    426698+bail_inp_dev: 
    427699+       input_free_device(lis->input_dev); 
    428700+bail_sysfs: 
    429701+       sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group); 
    430 +bail_irq: 
    431 +       free_irq(lis->spi_dev->irq, NULL); 
    432702+bail_free_lis: 
    433703+       kfree(lis); 
     704+       local_irq_restore(flags); 
    434705+       return rc; 
    435706 } 
    436707  
    437708 static int __devexit lis302dl_remove(struct spi_device *spi) 
    438 @@ -511,6 +541,8 @@ 
     709 { 
     710        struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); 
     711+       unsigned long flags; 
     712  
     713        /* power down the device */ 
     714+       local_save_flags(flags); 
    439715        reg_write(lis, LIS302DL_REG_CTRL1, 0x00); 
     716+       local_irq_restore(flags); 
     717+ 
    440718        sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group); 
    441719        input_unregister_device(lis->input_dev); 
     
    445723        kfree(lis); 
    446724  
     725@@ -521,6 +418,9 @@ 
     726 static int lis302dl_suspend(struct spi_device *spi, pm_message_t state) 
     727 { 
     728        struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); 
     729+       unsigned long flags; 
     730+ 
     731+       local_save_flags(flags); 
     732  
     733        /* save registers */ 
     734        lis->regs[LIS302DL_REG_CTRL1] = reg_read(lis, LIS302DL_REG_CTRL1); 
     735@@ -561,12 +461,17 @@ 
     736                reg_write(lis, LIS302DL_REG_CTRL1, tmp); 
     737        } 
     738  
     739+       local_irq_restore(flags); 
     740+ 
     741        return 0; 
     742 } 
     743  
     744 static int lis302dl_resume(struct spi_device *spi) 
     745 { 
     746        struct lis302dl_info *lis = dev_get_drvdata(&spi->dev); 
     747+       unsigned long flags; 
     748+ 
     749+       local_save_flags(flags); 
     750  
     751        /* restore registers after resume */ 
     752        reg_write(lis, LIS302DL_REG_CTRL1, lis->regs[LIS302DL_REG_CTRL1]); 
     753@@ -597,6 +502,8 @@ 
     754        reg_write(lis, LIS302DL_REG_CLICK_WINDOW, 
     755                  lis->regs[LIS302DL_REG_CLICK_WINDOW]); 
     756  
     757+       local_irq_restore(flags); 
     758+ 
     759        return 0; 
     760 } 
     761 #else 
    447762Index: linux-2.6.24/drivers/spi/spi_s3c24xx_gpio.c 
    448763=================================================================== 
     
    512827--- linux-2.6.24.orig/include/linux/lis302dl.h 
    513828+++ linux-2.6.24/include/linux/lis302dl.h 
    514 @@ -5,6 +5,7 @@ 
     829@@ -2,10 +2,111 @@ 
     830 #define _LINUX_LIS302DL_H 
     831  
     832 #include <linux/types.h> 
     833+#include <linux/spi/spi.h> 
     834+#include <linux/input.h> 
     835+ 
     836+ 
     837+struct lis302dl_info; 
    515838  
    516839 struct lis302dl_platform_data { 
    517840        char *name; 
    518841+       unsigned long pin_chip_select; 
    519  }; 
    520   
     842+       unsigned long pin_clk; 
     843+       unsigned long pin_mosi; 
     844+       unsigned long pin_miso; 
     845+       void (*lis302dl_bitbang_read)(struct lis302dl_info *); 
     846+}; 
     847+ 
     848+struct lis302dl_info { 
     849+       struct lis302dl_platform_data *pdata; 
     850+       struct spi_device *spi_dev; 
     851+       struct input_dev *input_dev; 
     852+       struct mutex lock; 
     853+       unsigned int flags; 
     854+       u_int8_t regs[0x40]; 
     855+}; 
     856+ 
     857+enum lis302dl_reg { 
     858+       LIS302DL_REG_WHO_AM_I           = 0x0f, 
     859+       LIS302DL_REG_CTRL1              = 0x20, 
     860+       LIS302DL_REG_CTRL2              = 0x21, 
     861+       LIS302DL_REG_CTRL3              = 0x22, 
     862+       LIS302DL_REG_HP_FILTER_RESET    = 0x23, 
     863+       LIS302DL_REG_STATUS             = 0x27, 
     864+       LIS302DL_REG_OUT_X              = 0x29, 
     865+       LIS302DL_REG_OUT_Y              = 0x2b, 
     866+       LIS302DL_REG_OUT_Z              = 0x2d, 
     867+       LIS302DL_REG_FF_WU_CFG_1        = 0x30, 
     868+       LIS302DL_REG_FF_WU_SRC_1        = 0x31, 
     869+       LIS302DL_REG_FF_WU_THS_1        = 0x32, 
     870+       LIS302DL_REG_FF_WU_DURATION_1   = 0x33, 
     871+       LIS302DL_REG_FF_WU_CFG_2        = 0x34, 
     872+       LIS302DL_REG_FF_WU_SRC_2        = 0x35, 
     873+       LIS302DL_REG_FF_WU_THS_2        = 0x36, 
     874+       LIS302DL_REG_FF_WU_DURATION_2   = 0x37, 
     875+       LIS302DL_REG_CLICK_CFG          = 0x38, 
     876+       LIS302DL_REG_CLICK_SRC          = 0x39, 
     877+       LIS302DL_REG_CLICK_THSY_X       = 0x3b, 
     878+       LIS302DL_REG_CLICK_THSZ         = 0x3c, 
     879+       LIS302DL_REG_CLICK_TIME_LIMIT   = 0x3d, 
     880+       LIS302DL_REG_CLICK_LATENCY      = 0x3e, 
     881+       LIS302DL_REG_CLICK_WINDOW       = 0x3f, 
     882+}; 
     883+ 
     884+enum lis302dl_reg_ctrl1 { 
     885+       LIS302DL_CTRL1_Xen              = 0x01, 
     886+       LIS302DL_CTRL1_Yen              = 0x02, 
     887+       LIS302DL_CTRL1_Zen              = 0x04, 
     888+       LIS302DL_CTRL1_STM              = 0x08, 
     889+       LIS302DL_CTRL1_STP              = 0x10, 
     890+       LIS302DL_CTRL1_FS               = 0x20, 
     891+       LIS302DL_CTRL1_PD               = 0x40, 
     892+       LIS302DL_CTRL1_DR               = 0x80, 
     893+}; 
     894+ 
     895+enum lis302dl_reg_ctrl3 { 
     896+       LIS302DL_CTRL3_PP_OD            = 0x40, 
     897+       LIS302DL_CTRL3_IHL              = 0x80, 
     898 }; 
     899  
     900+enum lis302dl_reg_status { 
     901+       LIS302DL_STATUS_XDA             = 0x01, 
     902+       LIS302DL_STATUS_YDA             = 0x02, 
     903+       LIS302DL_STATUS_ZDA             = 0x04, 
     904+       LIS302DL_STATUS_XYZDA           = 0x08, 
     905+       LIS302DL_STATUS_XOR             = 0x10, 
     906+       LIS302DL_STATUS_YOR             = 0x20, 
     907+       LIS302DL_STATUS_ZOR             = 0x40, 
     908+       LIS302DL_STATUS_XYZOR           = 0x80, 
     909+}; 
     910+ 
     911+enum lis302dl_reg_ffwusrc1 { 
     912+       LIS302DL_FFWUSRC1_XL            = 0x01, 
     913+       LIS302DL_FFWUSRC1_XH            = 0x02, 
     914+       LIS302DL_FFWUSRC1_YL            = 0x04, 
     915+       LIS302DL_FFWUSRC1_YH            = 0x08, 
     916+       LIS302DL_FFWUSRC1_ZL            = 0x10, 
     917+       LIS302DL_FFWUSRC1_ZH            = 0x20, 
     918+       LIS302DL_FFWUSRC1_IA            = 0x40, 
     919+}; 
     920+ 
     921+enum lis302dl_reg_cloik_src { 
     922+       LIS302DL_CLICKSRC_SINGLE_X      = 0x01, 
     923+       LIS302DL_CLICKSRC_DOUBLE_X      = 0x02, 
     924+       LIS302DL_CLICKSRC_SINGLE_Y      = 0x04, 
     925+       LIS302DL_CLICKSRC_DOUBLE_Y      = 0x08, 
     926+       LIS302DL_CLICKSRC_SINGLE_Z      = 0x10, 
     927+       LIS302DL_CLICKSRC_DOUBLE_Z      = 0x20, 
     928+       LIS302DL_CLICKSRC_IA            = 0x40, 
     929+}; 
     930+ 
     931+#define LIS302DL_WHO_AM_I_MAGIC                0x3b 
     932+ 
     933+#define LIS302DL_F_WUP_FF              0x0001  /* wake up from free fall */ 
     934+#define LIS302DL_F_WUP_CLICK           0x0002 
     935+#define LIS302DL_F_POWER               0x0010 
     936+#define LIS302DL_F_FS                  0x0020  /* ADC full scale */ 
     937+ 
     938+ 
    521939 #endif /* _LINUX_LIS302DL_H */ 
     940  
    522941Index: linux-2.6.24/arch/arm/mach-s3c2410/mach-gta01.c 
    523942=================================================================== 
Note: See TracChangeset for help on using the changeset viewer.