[ar71xx] preliminary support for the Ubiquiti RouterStation Pro
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1040-gta02-acc.patch.patch
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
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 | 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(-)
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 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);
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 @@ -113,9 +113,11 @@ static int s3c2410_spigpio_probe(struct platform_device *dev)
855
856 platform_set_drvdata(dev, sp);
857
858 - /* copy in the plkatform data */
859 + /* copy in the platform data */
860 info = sp->info = dev->dev.platform_data;
861
862 + master->num_chipselect = info->num_chipselect;
863 +
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 */
869
870 for (i = 0; i < sp->info->board_size; i++) {
871 + struct spi_device *spidev;
872 +
873 dev_info(&dev->dev, "registering %p: %s\n",
874 &sp->info->board_info[i],
875 sp->info->board_info[i].modalias);
876
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);
880 + if (spidev)
881 + spidev->max_speed_hz =
882 + sp->info->board_info[i].max_speed_hz;
883 }
884
885 return 0;
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;
892
893 int bus_num;
894 + int num_chipselect;
895
896 unsigned long board_size;
897 struct spi_board_info *board_info;
898
899 - void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
900 + void (*chip_select)(struct s3c2410_spigpio_info *spi, int csid, int cs);
901 };
902
903
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
908 @@ -2,10 +2,112 @@
909 #define _LINUX_LIS302DL_H
910
911 #include <linux/types.h>
912 +#include <linux/spi/spi.h>
913 +#include <linux/input.h>
914 +
915 +
916 +struct lis302dl_info;
917
918 struct lis302dl_platform_data {
919 char *name;
920 + unsigned long pin_chip_select;
921 + unsigned long pin_clk;
922 + unsigned long pin_mosi;
923 + unsigned long pin_miso;
924 + int open_drain;
925 + void (*lis302dl_bitbang_read)(struct lis302dl_info *);
926 +};
927 +
928 +struct lis302dl_info {
929 + struct lis302dl_platform_data *pdata;
930 + struct spi_device *spi_dev;
931 + struct input_dev *input_dev;
932 + struct mutex lock;
933 + unsigned int flags;
934 + u_int8_t regs[0x40];
935 +};
936 +
937 +enum lis302dl_reg {
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,
962 +};
963 +
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,
973 +};
974 +
975 +enum lis302dl_reg_ctrl3 {
976 + LIS302DL_CTRL3_PP_OD = 0x40,
977 + LIS302DL_CTRL3_IHL = 0x80,
978 };
979
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,
989 +};
990 +
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,
999 +};
1000 +
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,
1009 +};
1010 +
1011 +#define LIS302DL_WHO_AM_I_MAGIC 0x3b
1012 +
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 */
1017 +
1018 +
1019 #endif /* _LINUX_LIS302DL_H */
1020
1021 --
1022 1.5.6.5
1023
This page took 0.111134 seconds and 5 git commands to generate.