changed Makefile and profiles, added patches for kernel 2.6.24
[openwrt.git] / target / linux / s3c24xx / patches-2.6.24 / 1056-fiq-hdq.patch.patch
1 From 7ffc881aa6a039b2e353449b97dca8a64ee3969a Mon Sep 17 00:00:00 2001
2 From: mokopatches <mokopatches@openmoko.org>
3 Date: Sun, 13 Apr 2008 07:23:52 +0100
4 Subject: [PATCH] fiq-hdq.patch
5
6 ---
7  arch/arm/mach-s3c2440/mach-gta02.c           |  204 +++++++++++++++++++++-
8  drivers/power/Kconfig                        |    8 +
9  drivers/power/Makefile                       |    2 +
10  drivers/power/gta02_hdq.c                    |  250 ++++++++++++++++++++++++++
11  include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h |   23 +++
12  include/asm-arm/arch-s3c2410/gta02.h         |    1 +
13  include/linux/gta02_hdq.h                    |    8 +
14  7 files changed, 495 insertions(+), 1 deletions(-)
15  create mode 100644 drivers/power/gta02_hdq.c
16  create mode 100644 include/linux/gta02_hdq.h
17
18 diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c
19 index 8c7bbe7..cea76e7 100644
20 --- a/arch/arm/mach-s3c2440/mach-gta02.c
21 +++ b/arch/arm/mach-s3c2440/mach-gta02.c
22 @@ -99,6 +99,19 @@ EXPORT_SYMBOL(fiq_ipc);
23  
24  #define FIQ_DIVISOR_VIBRATOR DIVISOR_FROM_US(100)
25  
26 +#ifdef CONFIG_GTA02_HDQ
27 +/* HDQ specific */
28 +#define HDQ_SAMPLE_PERIOD_US 20
29 +/* private HDQ FSM state -- all other info interesting for caller in fiq_ipc */
30 +static enum hdq_bitbang_states hdq_state;
31 +static u8 hdq_ctr;
32 +static u8 hdq_ctr2;
33 +static u8 hdq_bit;
34 +static u8 hdq_shifter;
35 +static u8 hdq_tx_data_done;
36 +
37 +#define FIQ_DIVISOR_HDQ DIVISOR_FROM_US(HDQ_SAMPLE_PERIOD_US)
38 +#endif
39  /* define FIQ ISR */
40  
41  FIQ_HANDLER_START()
42 @@ -121,9 +134,171 @@ FIQ_HANDLER_ENTRY(256, 512)
43                 divisor = FIQ_DIVISOR_VIBRATOR;
44         }
45  
46 -       /* TODO: HDQ servicing */
47 +#ifdef CONFIG_GTA02_HDQ
48 +       /* HDQ servicing */
49 +
50 +       switch (hdq_state) {
51 +       case HDQB_IDLE:
52 +               if (fiq_ipc.hdq_request_ctr == fiq_ipc.hdq_transaction_ctr)
53 +                       break;
54 +               hdq_ctr = 210 / HDQ_SAMPLE_PERIOD_US;
55 +               s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 0);
56 +               s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
57 +               hdq_tx_data_done = 0;
58 +               hdq_state = HDQB_TX_BREAK;
59 +               break;
60 +
61 +       case HDQB_TX_BREAK: /* issue low for > 190us */
62 +               if (--hdq_ctr == 0) {
63 +                       hdq_ctr = 60 / HDQ_SAMPLE_PERIOD_US;
64 +                       hdq_state = HDQB_TX_BREAK_RECOVERY;
65 +                       s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
66 +               }
67 +               break;
68 +
69 +       case HDQB_TX_BREAK_RECOVERY: /* issue low for > 40us */
70 +               if (--hdq_ctr)
71 +                       break;
72 +               hdq_shifter = fiq_ipc.hdq_ads;
73 +               hdq_bit = 8; /* 8 bits of ads / rw */
74 +               hdq_tx_data_done = 0; /* doing ads */
75 +               /* fallthru on last one */
76 +       case HDQB_ADS_CALC:
77 +               if (hdq_shifter & 1)
78 +                       hdq_ctr = 50 / HDQ_SAMPLE_PERIOD_US;
79 +               else
80 +                       hdq_ctr = 120 / HDQ_SAMPLE_PERIOD_US;
81 +               /* carefully precompute the other phase length */
82 +               hdq_ctr2 = (210 - (hdq_ctr * HDQ_SAMPLE_PERIOD_US)) /
83 +                               HDQ_SAMPLE_PERIOD_US;
84 +               hdq_state = HDQB_ADS_LOW;
85 +               hdq_shifter >>= 1;
86 +               hdq_bit--;
87 +               s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 0);
88 +               break;
89 +
90 +       case HDQB_ADS_LOW:
91 +               if (--hdq_ctr)
92 +                       break;
93 +               s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
94 +               hdq_state = HDQB_ADS_HIGH;
95 +               break;
96 +
97 +       case HDQB_ADS_HIGH:
98 +               if (--hdq_ctr2 > 1) /* account for HDQB_ADS_CALC */
99 +                       break;
100 +               if (hdq_bit) { /* more bits to do */
101 +                       hdq_state = HDQB_ADS_CALC;
102 +                       break;
103 +               }
104 +               /* no more bits, wait it out until hdq_ctr2 exhausted */
105 +               if (hdq_ctr2)
106 +                       break;
107 +               /* ok no more bits and very last state */
108 +               hdq_ctr = 60 / HDQ_SAMPLE_PERIOD_US;
109 +               /* FIXME 0 = read */
110 +               if (fiq_ipc.hdq_ads & 0x80) { /* write the byte out */
111 +                        /* set delay before payload */
112 +                       hdq_ctr = 300 / HDQ_SAMPLE_PERIOD_US;
113 +                       /* already high, no need to write */
114 +                       hdq_state = HDQB_WAIT_TX;
115 +                       break;
116 +               }
117 +               /* read the next byte */
118 +               hdq_bit = 8; /* 8 bits of data */
119 +               hdq_ctr = 3000 / HDQ_SAMPLE_PERIOD_US;
120 +               hdq_state = HDQB_WAIT_RX;
121 +               s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_INPUT);
122 +               break;
123 +
124 +       case HDQB_WAIT_TX: /* issue low for > 40us */
125 +               if (--hdq_ctr)
126 +                       break;
127 +               if (!hdq_tx_data_done) { /* was that the data sent? */
128 +                       hdq_tx_data_done++;
129 +                       hdq_shifter = fiq_ipc.hdq_tx_data;
130 +                       hdq_bit = 8; /* 8 bits of data */
131 +                       hdq_state = HDQB_ADS_CALC; /* start sending */
132 +                       break;
133 +               }
134 +               fiq_ipc.hdq_error = 0;
135 +               fiq_ipc.hdq_transaction_ctr++;
136 +               hdq_state = HDQB_IDLE; /* all tx is done */
137 +               /* idle in input mode, it's pulled up by 10K */
138 +               s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_INPUT);
139 +               break;
140 +
141 +       case HDQB_WAIT_RX: /* wait for battery to talk to us */
142 +               if (s3c2410_gpio_getpin(fiq_ipc.hdq_gpio_pin) == 0) {
143 +                       /* it talks to us! */
144 +                       hdq_ctr2 = 1;
145 +                       hdq_bit = 8; /* 8 bits of data */
146 +                       /* timeout */
147 +                       hdq_ctr = 300 / HDQ_SAMPLE_PERIOD_US;
148 +                       hdq_state = HDQB_DATA_RX_LOW;
149 +                       break;
150 +               }
151 +               if (--hdq_ctr == 0) { /* timed out, error */
152 +                       fiq_ipc.hdq_error = 1;
153 +                       fiq_ipc.hdq_transaction_ctr++;
154 +                       hdq_state = HDQB_IDLE; /* abort */
155 +               }
156 +               break;
157 +
158 +       /*
159 +        * HDQ basically works by measuring the low time of the bit cell
160 +        * 32-50us --> '1', 80 - 145us --> '0'
161 +        */
162 +
163 +       case HDQB_DATA_RX_LOW:
164 +               if (s3c2410_gpio_getpin(fiq_ipc.hdq_gpio_pin)) {
165 +                       fiq_ipc.hdq_rx_data >>= 1;
166 +                       if (hdq_ctr2 <= (65 / HDQ_SAMPLE_PERIOD_US))
167 +                               fiq_ipc.hdq_rx_data |= 0x80;
168 +
169 +                       if (--hdq_bit == 0) {
170 +                               fiq_ipc.hdq_error = 0;
171 +                               fiq_ipc.hdq_transaction_ctr++; /* done */
172 +                               hdq_state = HDQB_IDLE;
173 +                       } else
174 +                               hdq_state = HDQB_DATA_RX_HIGH;
175 +                       /* timeout */
176 +                       hdq_ctr = 1000 / HDQ_SAMPLE_PERIOD_US;
177 +                       hdq_ctr2 = 1;
178 +                       break;
179 +               }
180 +               hdq_ctr2++;
181 +               if (--hdq_ctr)
182 +                       break;
183 +                /* timed out, error */
184 +               fiq_ipc.hdq_error = 2;
185 +               fiq_ipc.hdq_transaction_ctr++;
186 +               hdq_state = HDQB_IDLE; /* abort */
187 +               break;
188  
189 +       case HDQB_DATA_RX_HIGH:
190 +               if (!s3c2410_gpio_getpin(fiq_ipc.hdq_gpio_pin)) {
191 +                       /* it talks to us! */
192 +                       hdq_ctr2 = 1;
193 +                       /* timeout */
194 +                       hdq_ctr = 400 / HDQ_SAMPLE_PERIOD_US;
195 +                       hdq_state = HDQB_DATA_RX_LOW;
196 +                       break;
197 +               }
198 +               if (--hdq_ctr)
199 +                       break;
200 +               /* timed out, error */
201 +               fiq_ipc.hdq_error = 3;
202 +               fiq_ipc.hdq_transaction_ctr++;
203 +               /* we're in input mode already */
204 +               hdq_state = HDQB_IDLE; /* abort */
205 +               break;
206 +       }
207  
208 +       if (hdq_state != HDQB_IDLE) /* ie, not idle */
209 +               if (divisor > FIQ_DIVISOR_HDQ)
210 +                       divisor = FIQ_DIVISOR_HDQ; /* keep us going */
211 +#endif
212  
213         /* disable further timer interrupts if nobody has any work
214          * or adjust rate according to who still has work
215 @@ -391,6 +566,23 @@ struct platform_device sc32440_fiq_device = {
216         .resource       = sc32440_fiq_resources,
217  };
218  
219 +#ifdef CONFIG_GTA02_HDQ
220 +/* HDQ */
221 +
222 +static struct resource gta02_hdq_resources[] = {
223 +       [0] = {
224 +               .start  = GTA02v5_GPIO_HDQ,
225 +               .end    = GTA02v5_GPIO_HDQ,
226 +       },
227 +};
228 +
229 +struct platform_device gta02_hdq_device = {
230 +       .name           = "gta02-hdq",
231 +       .num_resources  = 1,
232 +       .resource       = gta02_hdq_resources,
233 +};
234 +#endif
235 +
236  /* NOR Flash */
237  
238  #define GTA02_FLASH_BASE       0x18000000 /* GCS3 */
239 @@ -1074,6 +1266,16 @@ static void __init gta02_machine_init(void)
240  
241         platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
242  
243 +#ifdef CONFIG_GTA02_HDQ
244 +       switch (system_rev) {
245 +       case GTA02v5_SYSTEM_REV:
246 +       case GTA02v6_SYSTEM_REV:
247 +               platform_device_register(&gta02_hdq_device);
248 +               break;
249 +       default:
250 +               break;
251 +       }
252 +#endif
253         s3c2410_pm_init();
254  
255         /* Set LCD_RESET / XRES to high */
256 diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
257 index 58c806e..0a4515d 100644
258 --- a/drivers/power/Kconfig
259 +++ b/drivers/power/Kconfig
260 @@ -50,3 +50,11 @@ config BATTERY_OLPC
261           Say Y to enable support for the battery on the OLPC laptop.
262  
263  endif # POWER_SUPPLY
264 +
265 +config GTA02_HDQ
266 +       tristate "Neo Freerunner HDQ"
267 +       depends on MACH_NEO1973_GTA02 && FIQ && S3C2440_C_FIQ
268 +       help
269 +         Say Y to enable support for communicating with an HDQ battery
270 +         on the Neo Freerunner.  You probably want to select
271 +         at least BATTERY_BQ27000_HDQ as well
272 diff --git a/drivers/power/Makefile b/drivers/power/Makefile
273 index 6413ded..88f227f 100644
274 --- a/drivers/power/Makefile
275 +++ b/drivers/power/Makefile
276 @@ -20,3 +20,5 @@ obj-$(CONFIG_APM_POWER)               += apm_power.o
277  obj-$(CONFIG_BATTERY_DS2760)   += ds2760_battery.o
278  obj-$(CONFIG_BATTERY_PMU)      += pmu_battery.o
279  obj-$(CONFIG_BATTERY_OLPC)     += olpc_battery.o
280 +
281 +obj-$(CONFIG_GTA02_HDQ)                += gta02_hdq.o
282 diff --git a/drivers/power/gta02_hdq.c b/drivers/power/gta02_hdq.c
283 new file mode 100644
284 index 0000000..12c742e
285 --- /dev/null
286 +++ b/drivers/power/gta02_hdq.c
287 @@ -0,0 +1,250 @@
288 +/*
289 + * HDQ driver for the FIC Neo1973 GTA02 GSM phone
290 + *
291 + * (C) 2006-2007 by OpenMoko, Inc.
292 + * Author: Andy Green <andy@openmoko.com>
293 + * All rights reserved.
294 + *
295 + * This program is free software; you can redistribute it and/or modify
296 + * it under the terms of the GNU General Public License version 2 as
297 + * published by the Free Software Foundation.
298 + *
299 + */
300 +
301 +#include <linux/kernel.h>
302 +#include <linux/init.h>
303 +#include <linux/delay.h>
304 +#include <linux/platform_device.h>
305 +#include <asm/hardware.h>
306 +#include <asm/mach-types.h>
307 +#include <asm/arch/gta02.h>
308 +#include <asm/arch/fiq_ipc_gta02.h>
309 +
310 +
311 +
312 +#define HDQ_READ 0
313 +#define HDQ_WRITE 0x80
314 +
315 +
316 +int gta02hdq_initialized(void)
317 +{
318 +       return fiq_ipc.hdq_probed;
319 +}
320 +EXPORT_SYMBOL_GPL(gta02hdq_initialized);
321 +
322 +int gta02hdq_read(int address)
323 +{
324 +       int count_sleeps = 5;
325 +       int ret = -ETIME;
326 +
327 +       mutex_lock(&fiq_ipc.hdq_lock);
328 +
329 +       fiq_ipc.hdq_ads = address | HDQ_READ;
330 +       fiq_ipc.hdq_request_ctr++;
331 +       fiq_kick();
332 +       /*
333 +        * FIQ takes care of it while we block our calling process
334 +        * But we're not spinning -- other processes run normally while
335 +        * we wait for the result
336 +        */
337 +       while (count_sleeps--) {
338 +               msleep(10); /* valid transaction always completes in < 10ms */
339 +
340 +               if (fiq_ipc.hdq_request_ctr != fiq_ipc.hdq_transaction_ctr)
341 +                       continue;
342 +
343 +               if (fiq_ipc.hdq_error)
344 +                       goto done; /* didn't see a response in good time */
345 +
346 +               ret = fiq_ipc.hdq_rx_data;
347 +               goto done;
348 +       }
349 +       ret = -EINVAL;
350 +
351 +done:
352 +       mutex_unlock(&fiq_ipc.hdq_lock);
353 +       return ret;
354 +}
355 +EXPORT_SYMBOL_GPL(gta02hdq_read);
356 +
357 +int gta02hdq_write(int address, u8 data)
358 +{
359 +       int count_sleeps = 5;
360 +       int ret = -ETIME;
361 +
362 +       mutex_lock(&fiq_ipc.hdq_lock);
363 +
364 +       fiq_ipc.hdq_ads = address | HDQ_WRITE;
365 +       fiq_ipc.hdq_tx_data = data;
366 +       fiq_ipc.hdq_request_ctr++;
367 +       fiq_kick();
368 +       /*
369 +        * FIQ takes care of it while we block our calling process
370 +        * But we're not spinning -- other processes run normally while
371 +        * we wait for the result
372 +        */
373 +       while (count_sleeps--) {
374 +               msleep(10); /* valid transaction always completes in < 10ms */
375 +
376 +               if (fiq_ipc.hdq_request_ctr != fiq_ipc.hdq_transaction_ctr)
377 +                       continue; /* something bad with FIQ */
378 +
379 +               if (fiq_ipc.hdq_error)
380 +                       goto done; /* didn't see a response in good time */
381 +       }
382 +       ret = -EINVAL;
383 +
384 +done:
385 +       mutex_unlock(&fiq_ipc.hdq_lock);
386 +       return ret;
387 +}
388 +EXPORT_SYMBOL_GPL(gta02hdq_write);
389 +
390 +/* sysfs */
391 +
392 +static ssize_t hdq_sysfs_dump(struct device *dev, struct device_attribute *attr,
393 +                        char *buf)
394 +{
395 +       int n;
396 +       int v;
397 +       u8 u8a[128]; /* whole address space for HDQ */
398 +       char *end = buf;
399 +
400 +       /* the dump does not take care about 16 bit regs, because at this
401 +        * bus level we don't know about the chip details
402 +        */
403 +       for (n = 0; n < sizeof(u8a); n++) {
404 +               v = gta02hdq_read(n);
405 +               if (v < 0)
406 +                       goto bail;
407 +               u8a[n] = v;
408 +       }
409 +
410 +       for (n = 0; n < sizeof(u8a); n += 16) {
411 +               hex_dump_to_buffer(u8a + n, sizeof(u8a), 16, 1, end, 4096, 0);
412 +               end += strlen(end);
413 +               *end++ = '\n';
414 +               *end = '\0';
415 +       }
416 +       return (end - buf);
417 +
418 +bail:
419 +       return sprintf(buf, "ERROR %d\n", v);
420 +}
421 +
422 +/* you write by <address> <data>, eg, "34 128" */
423 +
424 +#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
425 +
426 +static ssize_t hdq_sysfs_write(struct device *dev,
427 +                              struct device_attribute *attr,
428 +                              const char *buf, size_t count)
429 +{
430 +       const char *end = buf + count;
431 +       int address = atoi(buf);
432 +
433 +       while ((buf != end) && (*buf != ' '))
434 +               buf++;
435 +       if (buf >= end)
436 +               return 0;
437 +       while ((buf < end) && (*buf == ' '))
438 +               buf++;
439 +       if (buf >= end)
440 +               return 0;
441 +
442 +       gta02hdq_write(address, atoi(buf));
443 +
444 +       return count;
445 +}
446 +
447 +static DEVICE_ATTR(dump, 0400, hdq_sysfs_dump, NULL);
448 +static DEVICE_ATTR(write, 0600, NULL, hdq_sysfs_write);
449 +
450 +static struct attribute *gta02hdq_sysfs_entries[] = {
451 +       &dev_attr_dump.attr,
452 +       &dev_attr_write.attr,
453 +       NULL
454 +};
455 +
456 +static struct attribute_group gta02hdq_attr_group = {
457 +       .name   = "hdq",
458 +       .attrs  = gta02hdq_sysfs_entries,
459 +};
460 +
461 +
462 +#ifdef CONFIG_PM
463 +static int gta02hdq_suspend(struct platform_device *pdev, pm_message_t state)
464 +{
465 +       /* after 18s of this, the battery monitor will also go to sleep */
466 +       s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 0);
467 +       s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
468 +       return 0;
469 +}
470 +
471 +static int gta02hdq_resume(struct platform_device *pdev)
472 +{
473 +       s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
474 +       s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
475 +       return 0;
476 +}
477 +#endif
478 +
479 +static int __init gta02hdq_probe(struct platform_device *pdev)
480 +{
481 +       struct resource *r = platform_get_resource(pdev, 0, 0);
482 +
483 +       if (!machine_is_neo1973_gta02())
484 +               return -EIO;
485 +
486 +       if (!r)
487 +               return -EINVAL;
488 +
489 +       platform_set_drvdata(pdev, NULL);
490 +
491 +       mutex_init(&fiq_ipc.hdq_lock);
492 +
493 +       /* set our HDQ comms pin from the platform data */
494 +       fiq_ipc.hdq_gpio_pin = r->start;
495 +
496 +       s3c2410_gpio_setpin(fiq_ipc.hdq_gpio_pin, 1);
497 +       s3c2410_gpio_cfgpin(fiq_ipc.hdq_gpio_pin, S3C2410_GPIO_OUTPUT);
498 +
499 +       fiq_ipc.hdq_probed = 1; /* we are ready to do stuff now */
500 +
501 +       return sysfs_create_group(&pdev->dev.kobj, &gta02hdq_attr_group);
502 +}
503 +
504 +static int gta02hdq_remove(struct platform_device *pdev)
505 +{
506 +       sysfs_remove_group(&pdev->dev.kobj, &gta02hdq_attr_group);
507 +       return 0;
508 +}
509 +
510 +static struct platform_driver gta02hdq_driver = {
511 +       .probe          = gta02hdq_probe,
512 +       .remove         = gta02hdq_remove,
513 +#ifdef CONFIG_PM
514 +       .suspend        = gta02hdq_suspend,
515 +       .resume         = gta02hdq_resume,
516 +#endif
517 +       .driver         = {
518 +               .name           = "gta02-hdq",
519 +       },
520 +};
521 +
522 +static int __init gta02hdq_init(void)
523 +{
524 +       return platform_driver_register(&gta02hdq_driver);
525 +}
526 +
527 +static void __exit gta02hdq_exit(void)
528 +{
529 +       platform_driver_unregister(&gta02hdq_driver);
530 +}
531 +
532 +module_init(gta02hdq_init);
533 +module_exit(gta02hdq_exit);
534 +
535 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
536 +MODULE_DESCRIPTION("GTA02 HDQ driver");
537 +MODULE_LICENSE("GPL");
538 diff --git a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
539 index 507d235..c5eb3df 100644
540 --- a/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
541 +++ b/include/asm-arm/arch-s3c2410/fiq_ipc_gta02.h
542 @@ -19,12 +19,35 @@
543  #include <asm/arch/pwm.h>
544  #include <asm/plat-s3c/regs-timer.h>
545  
546 +enum hdq_bitbang_states {
547 +       HDQB_IDLE = 0,
548 +       HDQB_TX_BREAK,
549 +       HDQB_TX_BREAK_RECOVERY,
550 +       HDQB_ADS_CALC,
551 +       HDQB_ADS_LOW,
552 +       HDQB_ADS_HIGH,
553 +       HDQB_WAIT_RX,
554 +       HDQB_DATA_RX_LOW,
555 +       HDQB_DATA_RX_HIGH,
556 +       HDQB_WAIT_TX,
557 +};
558  
559  struct fiq_ipc {
560         /* vibrator */
561         unsigned long vib_gpio_pin; /* which pin to meddle with */
562         u8 vib_pwm; /* 0 = OFF -- will ensure GPIO deasserted and stop FIQ */
563         u8 vib_pwm_latched;
564 +
565 +       /* hdq */
566 +       u8 hdq_probed; /* nonzero after HDQ driver probed */
567 +       struct mutex hdq_lock; /* if you want to use hdq, you have to take lock */
568 +       unsigned long hdq_gpio_pin; /* GTA02 = GPD14 which pin to meddle with */
569 +       u8 hdq_ads; /* b7..b6 = register address, b0 = r/w */
570 +       u8 hdq_tx_data; /* data to tx for write action */
571 +       u8 hdq_rx_data; /* data received in read action */
572 +       u8 hdq_request_ctr; /* incremented by "user" to request a transfer */
573 +       u8 hdq_transaction_ctr; /* incremented after each transfer */
574 +       u8 hdq_error; /* 0 = no error */
575  };
576  
577  /* actual definition lives in arch/arm/mach-s3c2440/fiq_c_isr.c */
578 diff --git a/include/asm-arm/arch-s3c2410/gta02.h b/include/asm-arm/arch-s3c2410/gta02.h
579 index fa49d93..f686a7a 100644
580 --- a/include/asm-arm/arch-s3c2410/gta02.h
581 +++ b/include/asm-arm/arch-s3c2410/gta02.h
582 @@ -37,6 +37,7 @@
583  
584  #define GTA02v3_GPIO_nG1_CS    S3C2410_GPD12   /* v3 + v4 only */
585  #define GTA02v3_GPIO_nG2_CS    S3C2410_GPD13   /* v3 + v4 only */
586 +#define GTA02v5_GPIO_HDQ       S3C2410_GPD14   /* v5 + */
587  
588  #define GTA02_GPIO_nG1_INT     S3C2410_GPF0
589  #define GTA02_GPIO_IO1         S3C2410_GPF1
590 diff --git a/include/linux/gta02_hdq.h b/include/linux/gta02_hdq.h
591 new file mode 100644
592 index 0000000..2f43a62
593 --- /dev/null
594 +++ b/include/linux/gta02_hdq.h
595 @@ -0,0 +1,8 @@
596 +#ifndef __GTA02HDQ_H__
597 +#define __GTA02HDQ_H__
598 +
599 +int gta02hdq_read(int address);
600 +int gta02hdq_write(int address, u8 data);
601 +int gta02hdq_initialized(void);
602 +
603 +#endif
604 -- 
605 1.5.6.5
606