changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.26 / 0033-gta02-acc.patch.patch
1 From 0f43da072e28d0bad639cb6823a7759112ff3489 Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Wed, 16 Jul 2008 14:46:56 +0100
4 Subject: [PATCH] gta02-acc.patch
5
6 ---
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          |   23 ++-
12  include/asm-arm/arch-s3c2410/spi-gpio.h |    6 +-
13  include/linux/lis302dl.h                |  102 +++++++++
14  7 files changed, 429 insertions(+), 237 deletions(-)
15
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[] = {
21         },
22  };
23  
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)
26  {
27         switch (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 = {
34  
35  /* SPI */
36  
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)
39  {
40         switch (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
46 @@ -78,6 +78,9 @@
47  
48  #include <linux/glamofb.h>
49  
50 +/* arbitrates which sensor IRQ owns the shared SPI bus */
51 +static spinlock_t motion_irq_lock;
52 +
53  static struct map_desc gta02_iodesc[] __initdata = {
54         {
55                 .virtual        = 0xe0000000,
56 @@ -377,8 +380,6 @@ static struct platform_device *gta02_devices[] __initdata = {
57         &s3c_device_usbgadget,
58         &s3c_device_nand,
59         &s3c_device_ts,
60 -       &s3c_device_spi0,
61 -       &s3c_device_spi1,
62         &gta02_nor_flash,
63  };
64  
65 @@ -478,10 +479,12 @@ static struct spi_board_info gta02_spi_board_info[] = {
66         },
67  };
68  
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,
73  };
74 +#endif /* 0 */
75  
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 = {
79  
80  /* SPI: Accelerometers attached to SPI of s3c244x */
81  
82 -static void gta02_spi_acc_set_cs(struct s3c2410_spi_info *spi, int cs, int pol)
83 +/*
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.
89 + *
90 + * Foreground / interrupt arbitration is okay because the interrupts are
91 + * disabled around all the foreground SPI code.
92 + *
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.
96 + *
97 + * Servicing is typ 75 - 100us at 400MHz.
98 + */
99 +
100 +/* #define DEBUG_SPEW_MS */
101 +#define MG_PER_SAMPLE 18
102 +
103 +void gat02_lis302dl_bitbang_read(struct lis302dl_info *lis)
104  {
105 -       s3c2410_gpio_setpin(cs, pol);
106 +       struct lis302dl_platform_data *pdata = lis->pdata;
107 +       u8 shifter = 0xc0 | LIS302DL_REG_OUT_X; /* read, autoincrement */
108 +       int n, n1;
109 +       unsigned long flags;
110 +#ifdef DEBUG_SPEW_MS
111 +       s8 x, y, z;
112 +#endif
113 +
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);
120 +               shifter <<= 1;
121 +       }
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);
126 +                       shifter <<= 1;
127 +                       if (s3c2410_gpio_getpin(pdata->pin_miso))
128 +                               shifter |= 1;
129 +               }
130 +               switch (n) {
131 +               case 0:
132 +#ifdef DEBUG_SPEW_MS
133 +                       x = shifter;
134 +#endif
135 +                       input_report_rel(lis->input_dev, REL_X, MG_PER_SAMPLE * (s8)shifter);
136 +                       break;
137 +               case 2:
138 +#ifdef DEBUG_SPEW_MS
139 +                       y = shifter;
140 +#endif
141 +                       input_report_rel(lis->input_dev, REL_Y, MG_PER_SAMPLE * (s8)shifter);
142 +                       break;
143 +               case 4:
144 +#ifdef DEBUG_SPEW_MS
145 +                       z = shifter;
146 +#endif
147 +                       input_report_rel(lis->input_dev, REL_Z, MG_PER_SAMPLE * (s8)shifter);
148 +                       break;
149 +               }
150 +       }
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);
156 +#endif
157  }
158  
159 -static const struct lis302dl_platform_data lis302_pdata[] = {
160 +
161 +struct lis302dl_platform_data lis302_pdata[] = {
162         {
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,
171         }, {
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,
180         },
181  };
182  
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,
189                 .bus_num        = 1,
190 -               .chip_select    = S3C2410_GPD12,
191 +               .chip_select    = 0,
192                 .mode           = SPI_MODE_3,
193         },
194         {
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,
200                 .bus_num        = 1,
201 -               .chip_select    = S3C2410_GPD13,
202 +               .chip_select    = 1,
203                 .mode           = SPI_MODE_3,
204         },
205  };
206  
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,
210 +                      int csid, int cs)
211 +{
212 +       struct lis302dl_platform_data * plat_data =
213 +                               (struct lis302dl_platform_data *)spigpio_info->
214 +                                                    board_info->platform_data;
215 +       switch (cs) {
216 +       case BITBANG_CS_ACTIVE:
217 +               s3c2410_gpio_setpin(plat_data[csid].pin_chip_select, 0);
218 +               break;
219 +       case BITBANG_CS_INACTIVE:
220 +               s3c2410_gpio_setpin(plat_data[csid].pin_chip_select, 1);
221 +               break;
222 +       }
223 +}
224 +
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,
233 +};
234 +
235 +static struct resource s3c_spi_acc_resource[] = {
236 +       [0] = {
237 +               .start = S3C2410_GPG3,
238 +               .end   = S3C2410_GPG3,
239 +       },
240 +       [1] = {
241 +               .start = S3C2410_GPG5,
242 +               .end   = S3C2410_GPG5,
243 +       },
244 +       [2] = {
245 +               .start = S3C2410_GPG6,
246 +               .end   = S3C2410_GPG6,
247 +       },
248 +       [3] = {
249 +               .start = S3C2410_GPG7,
250 +               .end   = S3C2410_GPG7,
251 +       },
252 +};
253 +
254 +static struct platform_device s3c_device_spi_acc = {
255 +       .name             = "spi_s3c24xx_gpio",
256 +       .id               = 1,
257 +       .num_resources    = ARRAY_SIZE(s3c_spi_acc_resource),
258 +       .resource         = s3c_spi_acc_resource,
259 +       .dev = {
260 +               .platform_data = &spi_gpio_cfg,
261 +       },
262  };
263  
264  static struct resource gta02_led_resources[] = {
265 @@ -786,10 +921,21 @@ static void __init gta02_machine_init(void)
266  {
267         int rc;
268  
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;
274 +               break;
275 +       default:
276 +               break;
277 +       }
278 +
279 +       spin_lock_init(&motion_irq_lock);
280 +
281         s3c_device_usb.dev.platform_data = &gta02_usb_info;
282         s3c_device_nand.dev.platform_data = &gta02_nand_info;
283         s3c_device_sdi.dev.platform_data = &gta02_mmc_cfg;
284 -       s3c_device_spi1.dev.platform_data = &gta02_spi_acc_cfg;
285  
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)
289                 break;
290         }
291  
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);
297 +
298         INIT_WORK(&gta02_udc_vbus_drawer.work, __gta02_udc_vbus_draw);
299         s3c24xx_udc_set_platdata(&gta02_udc_cfg);
300         set_s3c2410ts_info(&gta02_ts_cfg);
301 @@ -829,6 +981,7 @@ static void __init gta02_machine_init(void)
302                 break;
303         }
304  
305 +       platform_device_register(&s3c_device_spi_acc);
306         platform_device_register(&gta01_button_dev);
307         platform_device_register(&gta01_pm_gsm_dev);
308  
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
313 @@ -33,117 +33,26 @@
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>
321  
322  #include <linux/lis302dl.h>
323  
324 -#include <linux/spi/spi.h>
325 -
326 -#define LIS302DL_WHO_AM_I_MAGIC                0x3b
327 -
328 -enum lis302dl_reg {
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,
353 -};
354 -
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,
364 -};
365 -
366 -enum lis302dl_reg_ctrl3 {
367 -       LIS302DL_CTRL3_PP_OD            = 0x40,
368 -};
369 -
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,
379 -};
380 -
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,
389 -};
390 -
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,
399 -};
400 -
401 -struct lis302dl_info {
402 -       struct spi_device *spi_dev;
403 -       struct input_dev *input_dev;
404 -       struct mutex lock;
405 -       struct work_struct work;
406 -       unsigned int flags;
407 -       unsigned int working;
408 -       u_int8_t regs[0x40];
409 -};
410 -
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 */
415 -
416  /* lowlevel register access functions */
417  
418 -#define READ_BIT       0x01
419 -#define MS_BIT         0x02
420 -#define ADDR_SHIFT     2
421 +#define READ_BIT               0x80
422 +#define READ_BIT_INC_ADS       0xc0
423 +#define        ADDR_MASK               0x3f
424  
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)
427  {
428         int rc;
429         u_int8_t cmd;
430  
431 -       cmd = (reg << ADDR_SHIFT) | READ_BIT;
432 +       BUG_ON(reg & ~ADDR_MASK);
433 +
434 +       cmd = reg | READ_BIT;
435  
436         rc = spi_w8r8(lis->spi_dev, cmd);
437  
438 @@ -161,11 +70,13 @@ static u_int8_t reg_read(struct lis302dl_info *lis, u_int8_t reg)
439         return ret;
440  }
441  
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)
444  {
445         u_int8_t buf[2];
446  
447 -       buf[0] = (reg << ADDR_SHIFT);
448 +       BUG_ON(reg & ~ADDR_MASK);
449 +
450 +       buf[0] = reg;
451         buf[1] = val;
452  
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,
466  };
467  
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,
470  {
471         struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
472  
473 -       if (int_pin == 1)
474 +       switch (int_pin) {
475 +       case 1:
476                 reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x07, mode);
477 -       else if (int_pin == 2)
478 +               break;
479 +       case 2:
480                 reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x38, mode << 3);
481 +               break;
482 +       default:
483 +               BUG();
484 +       }
485  }
486 -
487 +#if 0
488  static void _report_btn_single(struct input_dev *inp, int btn)
489  {
490         input_report_key(inp, btn, 1);
491 @@ -241,95 +158,14 @@ static void _report_btn_double(struct input_dev *inp, int btn)
492         input_sync(inp);
493         input_report_key(inp, btn, 0);
494  }
495 +#endif
496  
497 -static void lis302dl_work(struct work_struct *work)
498 -{
499 -       struct lis302dl_info *lis =
500 -                       container_of(work, struct lis302dl_info, work);
501 -
502 -       u_int8_t status, ff_wu_src_1, click_src;
503 -       u_int8_t val;
504 -
505 -       lis->working = 1;
506 -
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);
510 -
511 -       if (status & LIS302DL_STATUS_XDA) {
512 -               val = reg_read(lis, LIS302DL_REG_OUT_X);
513 -               if (lis->flags & LIS302DL_F_FS)
514 -                       val = val << 2;
515 -               input_report_rel(lis->input_dev, REL_X, val);
516 -       }
517 -
518 -       if (status & LIS302DL_STATUS_YDA) {
519 -               val = reg_read(lis, LIS302DL_REG_OUT_Y);
520 -               if (lis->flags & LIS302DL_F_FS)
521 -                       val = val << 2;
522 -               input_report_rel(lis->input_dev, REL_Y, val);
523 -       }
524 -
525 -       if (status & LIS302DL_STATUS_ZDA) {
526 -               val = reg_read(lis, LIS302DL_REG_OUT_Z);
527 -               if (lis->flags & LIS302DL_F_FS)
528 -                       val = val << 2;
529 -               input_report_rel(lis->input_dev, REL_Z, val);
530 -       }
531 -
532 -       if (status & 0xf0)
533 -               dev_dbg(&lis->spi_dev->dev, "overrun!\n");
534 -
535 -       /* FIXME: implement overrun statistics */
536 -
537 -       if (ff_wu_src_1 & LIS302DL_FFWUSRC1_IA) {
538 -               /* FIXME: free fall interrupt handling */
539 -       }
540 -
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);
546 -
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);
551 -
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);
556 -       }
557 -
558 -       lis->working = 0;
559 -       input_sync(lis->input_dev);
560 -       put_device(&lis->spi_dev->dev);
561 -
562 -       enable_irq(lis->spi_dev->irq);
563 -}
564 -
565 -static void lis302dl_schedule_work(struct lis302dl_info *lis)
566 -{
567 -       int status;
568 -
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");
573 -}
574  
575  static irqreturn_t lis302dl_interrupt(int irq, void *_lis)
576  {
577         struct lis302dl_info *lis = _lis;
578  
579 -       lis302dl_schedule_work(lis);
580 -
581 -       /* Disable any further interrupts until we have processed
582 -        * the current one */
583 -       disable_irq(lis->spi_dev->irq);
584 -
585 +       (lis->pdata->lis302dl_bitbang_read)(lis);
586         return IRQ_HANDLED;
587  }
588  
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,
593 +       NULL
594  };
595  
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;
602  
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);
607 +
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);
611  
612         return 0;
613  }
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 |
617                          LIS302DL_CTRL1_Zen;
618 +       unsigned long flags;
619 +
620 +       local_save_flags(flags);
621  
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);
627  
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,
630                                  0x00);
631         }
632 +       local_irq_restore(flags);
633  }
634  
635  static int __devinit lis302dl_probe(struct spi_device *spi)
636 @@ -433,84 +281,138 @@ static int __devinit lis302dl_probe(struct spi_device *spi)
637         int rc;
638         struct lis302dl_info *lis;
639         u_int8_t wai;
640 +       unsigned long flags;
641 +       struct lis302dl_platform_data *pdata;
642  
643         lis = kzalloc(sizeof(*lis), GFP_KERNEL);
644         if (!lis)
645                 return -ENOMEM;
646  
647 +       local_save_flags(flags);
648 +
649         mutex_init(&lis->lock);
650 -       INIT_WORK(&lis->work, lis302dl_work);
651         lis->spi_dev = spi;
652  
653         spi_set_drvdata(spi, lis);
654  
655 +       pdata = spi->dev.platform_data;
656 +
657         rc = spi_setup(spi);
658         if (rc < 0) {
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);
662 -               kfree(lis);
663 -               return rc;
664 +               goto bail_free_lis;
665         }
666  
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);
672 -               kfree(lis);
673 -               return -ENODEV;
674 -       }
675 -
676 -       /* switch interrupt to open collector */
677 -       reg_write(lis, LIS302DL_CTRL3_PP_OD, 0x7c);
678 -
679 -       rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt, IRQF_DISABLED,
680 -                        "lis302dl", NULL);
681 -       if (rc < 0) {
682 -               dev_err(&spi->dev, "error requesting IRQ %d\n",
683 -                       lis->spi_dev->irq);
684 -               /* FIXME */
685 -               return rc;
686 +               rc = -ENODEV;
687 +               goto bail_free_lis;
688         }
689  
690         rc = sysfs_create_group(&spi->dev.kobj, &lis302dl_attr_group);
691         if (rc) {
692                 dev_err(&spi->dev, "error creating sysfs group\n");
693 -               /* FIXME */
694 -               return rc;
695 +               goto bail_free_lis;
696         }
697  
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");
702 -               /* FIXME */
703 +               goto bail_sysfs;
704         }
705  
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);
715 -
716 +*/
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;
725  
726 -       input_register_device(lis->input_dev);
727 +       rc = input_register_device(lis->input_dev);
728 +       if (rc) {
729 +               dev_err(&spi->dev, "error %d registering input device\n", rc);
730 +               goto bail_inp_dev;
731 +       }
732 +
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);
738 +
739 +       reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_Xen |
740 +                                          LIS302DL_CTRL1_Yen |
741 +                                          LIS302DL_CTRL1_Zen);
742 +
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);
747 +       else
748 +               /* push-pull, active-low */
749 +               reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_IHL);
750 +
751 +       lis302dl_int_mode(spi, 1, LIS302DL_INTMODE_DATA_READY);
752 +       lis302dl_int_mode(spi, 2, LIS302DL_INTMODE_DATA_READY);
753 +
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);
758  
759 +       dev_info(&spi->dev, "Found %s\n", pdata->name);
760 +
761 +       lis->pdata = pdata;
762 +
763 +       rc = request_irq(lis->spi_dev->irq, lis302dl_interrupt,
764 +                        IRQF_TRIGGER_FALLING, "lis302dl", lis);
765 +       if (rc < 0) {
766 +               dev_err(&spi->dev, "error requesting IRQ %d\n",
767 +                       lis->spi_dev->irq);
768 +               goto bail_inp_reg;
769 +       }
770 +       local_irq_restore(flags);
771         return 0;
772 +
773 +bail_inp_reg:
774 +       input_unregister_device(lis->input_dev);
775 +bail_inp_dev:
776 +       input_free_device(lis->input_dev);
777 +bail_sysfs:
778 +       sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group);
779 +bail_free_lis:
780 +       kfree(lis);
781 +       local_irq_restore(flags);
782 +       return rc;
783  }
784  
785  static int __devexit lis302dl_remove(struct spi_device *spi)
786  {
787         struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
788 +       unsigned long flags;
789  
790         /* power down the device */
791 +       local_save_flags(flags);
792         reg_write(lis, LIS302DL_REG_CTRL1, 0x00);
793 +       local_irq_restore(flags);
794 +
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);
800         kfree(lis);
801  
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)
804  {
805         struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
806 +       unsigned long flags;
807 +
808 +       disable_irq(lis->spi_dev->irq);
809 +       local_save_flags(flags);
810  
811         /* save registers */
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);
815         }
816  
817 +       local_irq_restore(flags);
818 +
819         return 0;
820  }
821  
822  static int lis302dl_resume(struct spi_device *spi)
823  {
824         struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
825 +       unsigned long flags;
826 +
827 +       local_save_flags(flags);
828  
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]);
834  
835 +       local_irq_restore(flags);
836 +       enable_irq(lis->spi_dev->irq);
837 +
838         return 0;
839  }
840  #else
841 diff --git a/drivers/spi/spi_s3c24xx_gpio.c b/drivers/spi/spi_s3c24xx_gpio.c
842 index e33f614..ccadf35 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);
847  
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);
851  }
852  
853  static int s3c2410_spigpio_probe(struct platform_device *dev)
854 @@ -100,6 +100,7 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
855         struct spi_master       *master;
856         struct s3c2410_spigpio  *sp;
857         int ret;
858 +       int i;
859  
860         master = spi_alloc_master(&dev->dev, sizeof(struct s3c2410_spigpio));
861         if (master == NULL) {
862 @@ -112,9 +113,11 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
863  
864         platform_set_drvdata(dev, sp);
865  
866 -       /* copy in the plkatform data */
867 +       /* copy in the platform data */
868         info = sp->info = dev->dev.platform_data;
869  
870 +       master->num_chipselect = info->num_chipselect;
871 +
872         /* setup spi bitbang adaptor */
873         sp->bitbang.master = spi_master_get(master);
874         sp->bitbang.master->bus_num = info->bus_num;
875 @@ -142,6 +145,22 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
876         if (ret)
877                 goto err_no_bitbang;
878  
879 +       /* register the chips to go with the board */
880 +
881 +       for (i = 0; i < sp->info->board_size; i++) {
882 +               struct spi_device *spidev;
883 +
884 +               dev_info(&dev->dev, "registering %p: %s\n",
885 +                        &sp->info->board_info[i],
886 +                        sp->info->board_info[i].modalias);
887 +
888 +               sp->info->board_info[i].controller_data = sp;
889 +               spidev = spi_new_device(master, sp->info->board_info + i);
890 +               if (spidev)
891 +                       spidev->max_speed_hz =
892 +                                         sp->info->board_info[i].max_speed_hz;
893 +       }
894 +
895         return 0;
896  
897   err_no_bitbang:
898 diff --git a/include/asm-arm/arch-s3c2410/spi-gpio.h b/include/asm-arm/arch-s3c2410/spi-gpio.h
899 index 7380373..d4efc97 100644
900 --- a/include/asm-arm/arch-s3c2410/spi-gpio.h
901 +++ b/include/asm-arm/arch-s3c2410/spi-gpio.h
902 @@ -19,8 +19,12 @@ struct s3c2410_spigpio_info {
903         unsigned long            pin_miso;
904  
905         int                      bus_num;
906 +       int                      num_chipselect;
907  
908 -       void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
909 +       unsigned long            board_size;
910 +       struct spi_board_info   *board_info;
911 +
912 +       void (*chip_select)(struct s3c2410_spigpio_info *spi, int csid, int cs);
913  };
914  
915  
916 diff --git a/include/linux/lis302dl.h b/include/linux/lis302dl.h
917 index d0f31be..2dea813 100644
918 --- a/include/linux/lis302dl.h
919 +++ b/include/linux/lis302dl.h
920 @@ -2,10 +2,112 @@
921  #define _LINUX_LIS302DL_H
922  
923  #include <linux/types.h>
924 +#include <linux/spi/spi.h>
925 +#include <linux/input.h>
926 +
927 +
928 +struct lis302dl_info;
929  
930  struct lis302dl_platform_data {
931         char *name;
932 +       unsigned long pin_chip_select;
933 +       unsigned long pin_clk;
934 +       unsigned long pin_mosi;
935 +       unsigned long pin_miso;
936 +       int open_drain;
937 +       void (*lis302dl_bitbang_read)(struct lis302dl_info *);
938 +};
939 +
940 +struct lis302dl_info {
941 +       struct lis302dl_platform_data *pdata;
942 +       struct spi_device *spi_dev;
943 +       struct input_dev *input_dev;
944 +       struct mutex lock;
945 +       unsigned int flags;
946 +       u_int8_t regs[0x40];
947 +};
948 +
949 +enum lis302dl_reg {
950 +       LIS302DL_REG_WHO_AM_I           = 0x0f,
951 +       LIS302DL_REG_CTRL1              = 0x20,
952 +       LIS302DL_REG_CTRL2              = 0x21,
953 +       LIS302DL_REG_CTRL3              = 0x22,
954 +       LIS302DL_REG_HP_FILTER_RESET    = 0x23,
955 +       LIS302DL_REG_STATUS             = 0x27,
956 +       LIS302DL_REG_OUT_X              = 0x29,
957 +       LIS302DL_REG_OUT_Y              = 0x2b,
958 +       LIS302DL_REG_OUT_Z              = 0x2d,
959 +       LIS302DL_REG_FF_WU_CFG_1        = 0x30,
960 +       LIS302DL_REG_FF_WU_SRC_1        = 0x31,
961 +       LIS302DL_REG_FF_WU_THS_1        = 0x32,
962 +       LIS302DL_REG_FF_WU_DURATION_1   = 0x33,
963 +       LIS302DL_REG_FF_WU_CFG_2        = 0x34,
964 +       LIS302DL_REG_FF_WU_SRC_2        = 0x35,
965 +       LIS302DL_REG_FF_WU_THS_2        = 0x36,
966 +       LIS302DL_REG_FF_WU_DURATION_2   = 0x37,
967 +       LIS302DL_REG_CLICK_CFG          = 0x38,
968 +       LIS302DL_REG_CLICK_SRC          = 0x39,
969 +       LIS302DL_REG_CLICK_THSY_X       = 0x3b,
970 +       LIS302DL_REG_CLICK_THSZ         = 0x3c,
971 +       LIS302DL_REG_CLICK_TIME_LIMIT   = 0x3d,
972 +       LIS302DL_REG_CLICK_LATENCY      = 0x3e,
973 +       LIS302DL_REG_CLICK_WINDOW       = 0x3f,
974 +};
975 +
976 +enum lis302dl_reg_ctrl1 {
977 +       LIS302DL_CTRL1_Xen              = 0x01,
978 +       LIS302DL_CTRL1_Yen              = 0x02,
979 +       LIS302DL_CTRL1_Zen              = 0x04,
980 +       LIS302DL_CTRL1_STM              = 0x08,
981 +       LIS302DL_CTRL1_STP              = 0x10,
982 +       LIS302DL_CTRL1_FS               = 0x20,
983 +       LIS302DL_CTRL1_PD               = 0x40,
984 +       LIS302DL_CTRL1_DR               = 0x80,
985 +};
986 +
987 +enum lis302dl_reg_ctrl3 {
988 +       LIS302DL_CTRL3_PP_OD            = 0x40,
989 +       LIS302DL_CTRL3_IHL              = 0x80,
990  };
991  
992 +enum lis302dl_reg_status {
993 +       LIS302DL_STATUS_XDA             = 0x01,
994 +       LIS302DL_STATUS_YDA             = 0x02,
995 +       LIS302DL_STATUS_ZDA             = 0x04,
996 +       LIS302DL_STATUS_XYZDA           = 0x08,
997 +       LIS302DL_STATUS_XOR             = 0x10,
998 +       LIS302DL_STATUS_YOR             = 0x20,
999 +       LIS302DL_STATUS_ZOR             = 0x40,
1000 +       LIS302DL_STATUS_XYZOR           = 0x80,
1001 +};
1002 +
1003 +enum lis302dl_reg_ffwusrc1 {
1004 +       LIS302DL_FFWUSRC1_XL            = 0x01,
1005 +       LIS302DL_FFWUSRC1_XH            = 0x02,
1006 +       LIS302DL_FFWUSRC1_YL            = 0x04,
1007 +       LIS302DL_FFWUSRC1_YH            = 0x08,
1008 +       LIS302DL_FFWUSRC1_ZL            = 0x10,
1009 +       LIS302DL_FFWUSRC1_ZH            = 0x20,
1010 +       LIS302DL_FFWUSRC1_IA            = 0x40,
1011 +};
1012 +
1013 +enum lis302dl_reg_cloik_src {
1014 +       LIS302DL_CLICKSRC_SINGLE_X      = 0x01,
1015 +       LIS302DL_CLICKSRC_DOUBLE_X      = 0x02,
1016 +       LIS302DL_CLICKSRC_SINGLE_Y      = 0x04,
1017 +       LIS302DL_CLICKSRC_DOUBLE_Y      = 0x08,
1018 +       LIS302DL_CLICKSRC_SINGLE_Z      = 0x10,
1019 +       LIS302DL_CLICKSRC_DOUBLE_Z      = 0x20,
1020 +       LIS302DL_CLICKSRC_IA            = 0x40,
1021 +};
1022 +
1023 +#define LIS302DL_WHO_AM_I_MAGIC                0x3b
1024 +
1025 +#define LIS302DL_F_WUP_FF              0x0001  /* wake up from free fall */
1026 +#define LIS302DL_F_WUP_CLICK           0x0002
1027 +#define LIS302DL_F_POWER               0x0010
1028 +#define LIS302DL_F_FS                  0x0020  /* ADC full scale */
1029 +
1030 +
1031  #endif /* _LINUX_LIS302DL_H */
1032  
1033 -- 
1034 1.5.6.3
1035