[brcm63xx] add the Tecom GW6x00 (6000 and 6200) board profile
[openwrt.git] / target / linux / s3c24xx / patches-2.6.29 / 001-merge-openmoko.patch
1 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/include/asm/fiq.h linux-2.6.29-rc3.owrt.om/arch/arm/include/asm/fiq.h
2 --- linux-2.6.29-rc3.owrt/arch/arm/include/asm/fiq.h 2009-05-10 22:05:03.000000000 +0200
3 +++ linux-2.6.29-rc3.owrt.om/arch/arm/include/asm/fiq.h 2009-05-10 22:27:59.000000000 +0200
4 @@ -29,8 +29,9 @@
5 extern int claim_fiq(struct fiq_handler *f);
6 extern void release_fiq(struct fiq_handler *f);
7 extern void set_fiq_handler(void *start, unsigned int length);
8 -extern void set_fiq_regs(struct pt_regs *regs);
9 -extern void get_fiq_regs(struct pt_regs *regs);
10 +extern void set_fiq_c_handler(void (*handler)(void));
11 +extern void __attribute__((naked)) set_fiq_regs(struct pt_regs *regs);
12 +extern void __attribute__((naked)) get_fiq_regs(struct pt_regs *regs);
13 extern void enable_fiq(int fiq);
14 extern void disable_fiq(int fiq);
15
16 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/include/asm/hardware/tzic-sp890.h linux-2.6.29-rc3.owrt.om/arch/arm/include/asm/hardware/tzic-sp890.h
17 --- linux-2.6.29-rc3.owrt/arch/arm/include/asm/hardware/tzic-sp890.h 1970-01-01 01:00:00.000000000 +0100
18 +++ linux-2.6.29-rc3.owrt.om/arch/arm/include/asm/hardware/tzic-sp890.h 2009-05-10 22:27:59.000000000 +0200
19 @@ -0,0 +1,22 @@
20 +#ifndef __SP890_TZIC_H__
21 +#define __SP890_TZIC_H__
22 +
23 +#define SP890_TZIC_UNLOCK_MAGIC (0x0ACCE550)
24 +
25 +#define SP890_TZIC_FIQSTATUS 0
26 +#define SP890_TZIC_RAWINTR 4
27 +#define SP890_TZIC_INTSELECT 8
28 +#define SP890_TZIC_FIQENABLE 0xc
29 +#define SP890_TZIC_FIQENCLEAR 0x10
30 +#define SP890_TZIC_FIQBYPASS 0x14
31 +#define SP890_TZIC_PROTECTION 0x18
32 +#define SP890_TZIC_LOCK 0x1c
33 +#define SP890_TZIC_LOCKSTATUS 0x20
34 +#define SP890_TZIC_ITCR 0x300
35 +#define SP890_TZIC_ITIP1 0x304
36 +#define SP890_TZIC_ITIP2 0x308
37 +#define SP890_TZIC_ITOP1 0x30c
38 +#define SP890_TZIC_ITOP2 0x310
39 +#define SP890_TZIC_PERIPHIDO 0xfe0
40 +
41 +#endif
42 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/include/asm/irqflags.h linux-2.6.29-rc3.owrt.om/arch/arm/include/asm/irqflags.h
43 --- linux-2.6.29-rc3.owrt/arch/arm/include/asm/irqflags.h 2009-05-10 22:05:03.000000000 +0200
44 +++ linux-2.6.29-rc3.owrt.om/arch/arm/include/asm/irqflags.h 2009-05-10 22:27:59.000000000 +0200
45 @@ -5,6 +5,16 @@
46
47 #include <asm/ptrace.h>
48
49 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
50 +void iblock_start(void);
51 +void iblock_end(void);
52 +void iblock_end_maybe(unsigned long flags);
53 +#else
54 +#define iblock_start()
55 +#define iblock_end()
56 +#define iblock_end_maybe(x)
57 +#endif
58 +
59 /*
60 * CPU interrupt mask handling.
61 */
62 @@ -31,6 +41,7 @@
63 #define raw_local_irq_save(x) \
64 ({ \
65 unsigned long temp; \
66 + iblock_start(); \
67 (void) (&temp == &x); \
68 __asm__ __volatile__( \
69 "mrs %0, cpsr @ local_irq_save\n" \
70 @@ -47,6 +58,7 @@
71 #define raw_local_irq_enable() \
72 ({ \
73 unsigned long temp; \
74 + iblock_end(); \
75 __asm__ __volatile__( \
76 "mrs %0, cpsr @ local_irq_enable\n" \
77 " bic %0, %0, #128\n" \
78 @@ -62,6 +74,7 @@
79 #define raw_local_irq_disable() \
80 ({ \
81 unsigned long temp; \
82 + iblock_start(); \
83 __asm__ __volatile__( \
84 "mrs %0, cpsr @ local_irq_disable\n" \
85 " orr %0, %0, #128\n" \
86 @@ -117,11 +130,12 @@
87 * restore saved IRQ & FIQ state
88 */
89 #define raw_local_irq_restore(x) \
90 + ({ iblock_end_maybe(x); \
91 __asm__ __volatile__( \
92 "msr cpsr_c, %0 @ local_irq_restore\n" \
93 : \
94 : "r" (x) \
95 - : "memory", "cc")
96 + : "memory", "cc"); })
97
98 #define raw_irqs_disabled_flags(flags) \
99 ({ \
100 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/include/asm/kexec.h linux-2.6.29-rc3.owrt.om/arch/arm/include/asm/kexec.h
101 --- linux-2.6.29-rc3.owrt/arch/arm/include/asm/kexec.h 2009-05-10 22:05:03.000000000 +0200
102 +++ linux-2.6.29-rc3.owrt.om/arch/arm/include/asm/kexec.h 2009-05-10 22:27:59.000000000 +0200
103 @@ -1,8 +1,6 @@
104 #ifndef _ARM_KEXEC_H
105 #define _ARM_KEXEC_H
106
107 -#ifdef CONFIG_KEXEC
108 -
109 /* Maximum physical address we can use pages from */
110 #define KEXEC_SOURCE_MEMORY_LIMIT (-1UL)
111 /* Maximum address we can reach in physical address mode */
112 @@ -14,6 +12,10 @@
113
114 #define KEXEC_ARCH KEXEC_ARCH_ARM
115
116 +#define KEXEC_BOOT_PARAMS_SIZE 1536
117 +
118 +#ifdef CONFIG_KEXEC
119 +
120 #define KEXEC_ARM_ATAGS_OFFSET 0x1000
121 #define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
122
123 @@ -29,3 +31,4 @@
124 #endif /* CONFIG_KEXEC */
125
126 #endif /* _ARM_KEXEC_H */
127 +
128 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/Kconfig linux-2.6.29-rc3.owrt.om/arch/arm/Kconfig
129 --- linux-2.6.29-rc3.owrt/arch/arm/Kconfig 2009-05-10 22:05:03.000000000 +0200
130 +++ linux-2.6.29-rc3.owrt.om/arch/arm/Kconfig 2009-05-10 22:27:59.000000000 +0200
131 @@ -1086,7 +1086,8 @@
132
133 menu "CPU Power Management"
134
135 -if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX || ARCH_PXA)
136 +if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX || ARCH_PXA || \
137 + ARCH_S3C64XX)
138
139 source "drivers/cpufreq/Kconfig"
140
141 @@ -1126,6 +1127,10 @@
142 default y
143 select CPU_FREQ_DEFAULT_GOV_USERSPACE
144
145 +config CPU_FREQ_S3C64XX
146 + bool "CPUfreq support for S3C64xx CPUs"
147 + depends on CPU_FREQ && CPU_S3C6410
148 +
149 endif
150
151 source "drivers/cpuidle/Kconfig"
152 @@ -1305,6 +1310,8 @@
153
154 source "drivers/uwb/Kconfig"
155
156 +source "drivers/ar6000/Kconfig"
157 +
158 source "drivers/mmc/Kconfig"
159
160 source "drivers/memstick/Kconfig"
161 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/kernel/fiq.c linux-2.6.29-rc3.owrt.om/arch/arm/kernel/fiq.c
162 --- linux-2.6.29-rc3.owrt/arch/arm/kernel/fiq.c 2009-05-10 22:08:41.000000000 +0200
163 +++ linux-2.6.29-rc3.owrt.om/arch/arm/kernel/fiq.c 2009-05-10 22:27:59.000000000 +0200
164 @@ -8,6 +8,8 @@
165 *
166 * FIQ support re-written by Russell King to be more generic
167 *
168 + * FIQ handler in C supoprt written by Andy Green <andy@openmoko.com>
169 + *
170 * We now properly support a method by which the FIQ handlers can
171 * be stacked onto the vector. We still do not support sharing
172 * the FIQ vector itself.
173 @@ -124,6 +126,83 @@
174 : "r" (&regs->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
175 }
176
177 +/* -------- FIQ handler in C ---------
178 + *
179 + * Major Caveats for using this
180 + * ---------------------------
181 + * *
182 + * * 1) it CANNOT touch any vmalloc()'d memory, only memory
183 + * that was kmalloc()'d. Static allocations in the monolithic kernel
184 + * are kmalloc()'d so they are okay. You can touch memory-mapped IO, but
185 + * the pointer for it has to have been stored in kmalloc'd memory. The
186 + * reason for this is simple: every now and then Linux turns off interrupts
187 + * and reorders the paging tables. If a FIQ happens during this time, the
188 + * virtual memory space can be partly or entirely disordered or missing.
189 + *
190 + * 2) Because vmalloc() is used when a module is inserted, THIS FIQ
191 + * ISR HAS TO BE IN THE MONOLITHIC KERNEL, not a module. But the way
192 + * it is set up, you can all to enable and disable it from your module
193 + * and intercommunicate with it through struct fiq_ipc
194 + * fiq_ipc which you can define in
195 + * asm/archfiq_ipc_type.h. The reason is the same as above, a
196 + * FIQ could happen while even the ISR is not present in virtual memory
197 + * space due to pagetables being changed at the time.
198 + *
199 + * 3) You can't call any Linux API code except simple macros
200 + * - understand that FIQ can come in at any time, no matter what
201 + * state of undress the kernel may privately be in, thinking it
202 + * locked the door by turning off interrupts... FIQ is an
203 + * unstoppable monster force (which is its value)
204 + * - they are not vmalloc()'d memory safe
205 + * - they might do crazy stuff like sleep: FIQ pisses fire and
206 + * is not interested in 'sleep' that the weak seem to need
207 + * - calling APIs from FIQ can re-enter un-renterable things
208 + * - summary: you cannot interoperate with linux APIs directly in the FIQ ISR
209 + *
210 + * If you follow these rules, it is fantastic, an extremely powerful, solid,
211 + * genuine hard realtime feature.
212 + */
213 +
214 +static void (*current_fiq_c_isr)(void);
215 +#define FIQ_C_ISR_STACK_SIZE 256
216 +
217 +static void __attribute__((naked)) __jump_to_isr(void)
218 +{
219 + asm __volatile__ ("mov pc, r8");
220 +}
221 +
222 +
223 +static void __attribute__((naked)) __actual_isr(void)
224 +{
225 + asm __volatile__ (
226 + "stmdb sp!, {r0-r12, lr};"
227 + "mov fp, sp;"
228 + );
229 +
230 + current_fiq_c_isr();
231 +
232 + asm __volatile__ (
233 + "ldmia sp!, {r0-r12, lr};"
234 + "subs pc, lr, #4;"
235 + );
236 +}
237 +
238 +void set_fiq_c_handler(void (*isr)(void))
239 +{
240 + struct pt_regs regs;
241 +
242 + memset(&regs, 0, sizeof(regs));
243 + regs.ARM_r8 = (unsigned long) __actual_isr;
244 + regs.ARM_sp = 0xffff001c + FIQ_C_ISR_STACK_SIZE;
245 +
246 + set_fiq_handler(__jump_to_isr, 4);
247 +
248 + current_fiq_c_isr = isr;
249 +
250 + set_fiq_regs(&regs);
251 +}
252 +/* -------- FIQ handler in C ---------*/
253 +
254 int claim_fiq(struct fiq_handler *f)
255 {
256 int ret = 0;
257 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/kernel/iblock.c linux-2.6.29-rc3.owrt.om/arch/arm/kernel/iblock.c
258 --- linux-2.6.29-rc3.owrt/arch/arm/kernel/iblock.c 1970-01-01 01:00:00.000000000 +0100
259 +++ linux-2.6.29-rc3.owrt.om/arch/arm/kernel/iblock.c 2009-05-10 22:27:59.000000000 +0200
260 @@ -0,0 +1,158 @@
261 +/*
262 + *
263 + * /sys/kernel/iblock/
264 + * All times are in microseconds (us).
265 + *
266 + * - limit
267 + * Interrupt blocking time reporting limit, in microseconds.
268 + * 0 disables reporting. Auto-resets to zero after reporting.
269 + *
270 + * - max
271 + * Maximum blocking time recorded. Reset to zero by writing anything.
272 + *
273 + * - test
274 + * Force a delay with interrupts disabled.
275 + *
276 + */
277 +
278 +
279 +#include <linux/kernel.h>
280 +#include <linux/sysfs.h>
281 +#include <linux/kobject.h>
282 +#include <linux/device.h>
283 +#include <linux/init.h>
284 +#include <linux/delay.h>
285 +#include <asm/irqflags.h>
286 +
287 +
288 +unsigned long s3c2410_gettimeoffset(void);
289 +
290 +
291 +static unsigned long iblock_t0;
292 +int iblock_limit;
293 +static int iblock_max;
294 +
295 +
296 +void iblock_start(void)
297 +{
298 + unsigned long flags;
299 +
300 + raw_local_save_flags(flags);
301 + if (raw_irqs_disabled_flags(flags))
302 + return;
303 + iblock_t0 = s3c2410_gettimeoffset();
304 +}
305 +EXPORT_SYMBOL_GPL(iblock_start);
306 +
307 +void iblock_end(void)
308 +{
309 + unsigned long flags;
310 + unsigned long t, us;
311 +
312 + raw_local_save_flags(flags);
313 + if (!raw_irqs_disabled_flags(flags))
314 + return;
315 + if (!iblock_t0)
316 + return;
317 + t = s3c2410_gettimeoffset();
318 + us = t-iblock_t0;
319 + if (us > 40000000)
320 + return;
321 + if (us > iblock_max)
322 + iblock_max = us;
323 + if (!iblock_limit)
324 + return;
325 + if (us < iblock_limit)
326 + return;
327 +// iblock_limit = 0;
328 + printk(KERN_ERR "interrupts were disabled for %lu us !\n", us);
329 +// WARN_ON(1);
330 +}
331 +EXPORT_SYMBOL_GPL(iblock_end);
332 +
333 +void iblock_end_maybe(unsigned long flags)
334 +{
335 + if (raw_irqs_disabled_flags(flags))
336 + return;
337 + iblock_end();
338 +}
339 +EXPORT_SYMBOL_GPL(iblock_end_maybe);
340 +
341 +static ssize_t limit_read(struct device *dev, struct device_attribute *attr,
342 + char *buf)
343 +{
344 + return sprintf(buf, "%u us\n", iblock_limit);
345 +}
346 +
347 +
348 +static ssize_t limit_write(struct device *dev, struct device_attribute *attr,
349 + const char *buf, size_t count)
350 +{
351 + unsigned long tmp;
352 + char *end;
353 +
354 + tmp = simple_strtoul(buf, &end, 0);
355 + if (end == buf)
356 + return -EINVAL;
357 + iblock_limit = tmp;
358 + return count;
359 +}
360 +
361 +
362 +static ssize_t max_read(struct device *dev, struct device_attribute *attr,
363 + char *buf)
364 +{
365 + return sprintf(buf, "%u us\n", iblock_max);
366 +}
367 +
368 +
369 +static ssize_t max_write(struct device *dev, struct device_attribute *attr,
370 + const char *buf, size_t count)
371 +{
372 + iblock_max = 0;
373 + return count;
374 +}
375 +
376 +
377 +static ssize_t test_write(struct device *dev,
378 + struct device_attribute *attr, const char *buf, size_t count)
379 +{
380 + unsigned long tmp, flags;
381 + char *end;
382 +
383 + tmp = simple_strtoul(buf, &end, 0);
384 + if (end == buf)
385 + return -EINVAL;
386 + local_irq_save(flags);
387 + udelay(tmp);
388 + local_irq_restore(flags);
389 + return count;
390 +}
391 +
392 +
393 +static DEVICE_ATTR(limit, 0644, limit_read, limit_write);
394 +static DEVICE_ATTR(max, 0644, max_read, max_write);
395 +static DEVICE_ATTR(test, 0200, NULL, test_write);
396 +
397 +
398 +static struct attribute *sysfs_entries[] = {
399 + &dev_attr_limit.attr,
400 + &dev_attr_max.attr,
401 + &dev_attr_test.attr,
402 + NULL
403 +};
404 +
405 +
406 +static struct attribute_group attr_group = {
407 + .name = "iblock",
408 + .attrs = sysfs_entries,
409 +};
410 +
411 +
412 +static int __devinit iblock_init(void)
413 +{
414 + return sysfs_create_group(kernel_kobj, &attr_group);
415 +}
416 +
417 +
418 +module_init(iblock_init);
419 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/kernel/irq.c linux-2.6.29-rc3.owrt.om/arch/arm/kernel/irq.c
420 --- linux-2.6.29-rc3.owrt/arch/arm/kernel/irq.c 2009-05-10 22:08:41.000000000 +0200
421 +++ linux-2.6.29-rc3.owrt.om/arch/arm/kernel/irq.c 2009-05-10 22:27:59.000000000 +0200
422 @@ -104,6 +104,11 @@
423 .lock = SPIN_LOCK_UNLOCKED
424 };
425
426 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
427 +extern int iblock_limit;
428 +unsigned long s3c2410_gettimeoffset(void);
429 +#endif
430 +
431 /*
432 * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
433 * come via this function. Instead, they should provide their
434 @@ -112,9 +117,15 @@
435 asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
436 {
437 struct pt_regs *old_regs = set_irq_regs(regs);
438 -
439 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
440 + unsigned long us;
441 +#endif
442 irq_enter();
443
444 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
445 + us = s3c2410_gettimeoffset();
446 +#endif
447 +
448 /*
449 * Some hardware gives randomly wrong interrupts. Rather
450 * than crashing, do something sensible.
451 @@ -124,6 +135,12 @@
452 else
453 generic_handle_irq(irq);
454
455 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
456 + us = s3c2410_gettimeoffset() - us;
457 +
458 + if (iblock_limit && us > iblock_limit && us < 10000000)
459 + printk(KERN_ERR "asm_do_IRQ(%u): %lu us\n", irq, us);
460 +#endif
461 /* AT91 specific workaround */
462 irq_finish(irq);
463
464 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/kernel/Makefile linux-2.6.29-rc3.owrt.om/arch/arm/kernel/Makefile
465 --- linux-2.6.29-rc3.owrt/arch/arm/kernel/Makefile 2009-05-10 22:05:04.000000000 +0200
466 +++ linux-2.6.29-rc3.owrt.om/arch/arm/kernel/Makefile 2009-05-10 22:27:59.000000000 +0200
467 @@ -44,5 +44,6 @@
468
469 head-y := head$(MMUEXT).o
470 obj-$(CONFIG_DEBUG_LL) += debug.o
471 +obj-$(CONFIG_FIND_IRQ_BLOCKERS) += iblock.o
472
473 extra-y := $(head-y) init_task.o vmlinux.lds
474 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/kernel/vmlinux.lds.S linux-2.6.29-rc3.owrt.om/arch/arm/kernel/vmlinux.lds.S
475 --- linux-2.6.29-rc3.owrt/arch/arm/kernel/vmlinux.lds.S 2009-05-10 22:05:04.000000000 +0200
476 +++ linux-2.6.29-rc3.owrt.om/arch/arm/kernel/vmlinux.lds.S 2009-05-10 22:27:59.000000000 +0200
477 @@ -106,6 +106,8 @@
478 *(.got) /* Global offset table */
479 }
480
481 + NOTES
482 +
483 RODATA
484
485 _etext = .; /* End of text and rodata section */
486 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/dma.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/dma.c
487 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/dma.c 2009-05-10 22:05:04.000000000 +0200
488 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/dma.c 2009-05-10 22:27:59.000000000 +0200
489 @@ -17,18 +17,20 @@
490 #include <linux/sysdev.h>
491 #include <linux/serial_core.h>
492
493 +#include <mach/map.h>
494 #include <mach/dma.h>
495
496 #include <plat/cpu.h>
497 -#include <plat/dma.h>
498 +#include <plat/dma-plat.h>
499
500 #include <plat/regs-serial.h>
501 #include <mach/regs-gpio.h>
502 #include <plat/regs-ac97.h>
503 +#include <plat/regs-dma.h>
504 #include <mach/regs-mem.h>
505 #include <mach/regs-lcd.h>
506 #include <mach/regs-sdi.h>
507 -#include <asm/plat-s3c24xx/regs-iis.h>
508 +#include <plat/regs-iis.h>
509 #include <plat/regs-spi.h>
510
511 static struct s3c24xx_dma_map __initdata s3c2410_dma_mappings[] = {
512 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/audio.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/audio.h
513 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/audio.h 2009-05-10 22:05:04.000000000 +0200
514 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/audio.h 1970-01-01 01:00:00.000000000 +0100
515 @@ -1,45 +0,0 @@
516 -/* arch/arm/mach-s3c2410/include/mach/audio.h
517 - *
518 - * Copyright (c) 2004-2005 Simtec Electronics
519 - * http://www.simtec.co.uk/products/SWLINUX/
520 - * Ben Dooks <ben@simtec.co.uk>
521 - *
522 - * S3C24XX - Audio platfrom_device info
523 - *
524 - * This program is free software; you can redistribute it and/or modify
525 - * it under the terms of the GNU General Public License version 2 as
526 - * published by the Free Software Foundation.
527 -*/
528 -
529 -#ifndef __ASM_ARCH_AUDIO_H
530 -#define __ASM_ARCH_AUDIO_H __FILE__
531 -
532 -/* struct s3c24xx_iis_ops
533 - *
534 - * called from the s3c24xx audio core to deal with the architecture
535 - * or the codec's setup and control.
536 - *
537 - * the pointer to itself is passed through in case the caller wants to
538 - * embed this in an larger structure for easy reference to it's context.
539 -*/
540 -
541 -struct s3c24xx_iis_ops {
542 - struct module *owner;
543 -
544 - int (*startup)(struct s3c24xx_iis_ops *me);
545 - void (*shutdown)(struct s3c24xx_iis_ops *me);
546 - int (*suspend)(struct s3c24xx_iis_ops *me);
547 - int (*resume)(struct s3c24xx_iis_ops *me);
548 -
549 - int (*open)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
550 - int (*close)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
551 - int (*prepare)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm, struct snd_pcm_runtime *rt);
552 -};
553 -
554 -struct s3c24xx_platdata_iis {
555 - const char *codec_clk;
556 - struct s3c24xx_iis_ops *ops;
557 - int (*match_dev)(struct device *dev);
558 -};
559 -
560 -#endif /* __ASM_ARCH_AUDIO_H */
561 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/dma.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/dma.h
562 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/dma.h 2009-05-10 22:05:04.000000000 +0200
563 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/dma.h 2009-05-10 22:27:59.000000000 +0200
564 @@ -3,7 +3,7 @@
565 * Copyright (C) 2003,2004,2006 Simtec Electronics
566 * Ben Dooks <ben@simtec.co.uk>
567 *
568 - * Samsung S3C241XX DMA support
569 + * Samsung S3C24XX DMA support
570 *
571 * This program is free software; you can redistribute it and/or modify
572 * it under the terms of the GNU General Public License version 2 as
573 @@ -13,8 +13,8 @@
574 #ifndef __ASM_ARCH_DMA_H
575 #define __ASM_ARCH_DMA_H __FILE__
576
577 +#include <plat/dma.h>
578 #include <linux/sysdev.h>
579 -#include <mach/hardware.h>
580
581 #define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */
582
583 @@ -55,9 +55,9 @@
584
585 /* we have 4 dma channels */
586 #ifndef CONFIG_CPU_S3C2443
587 -#define S3C2410_DMA_CHANNELS (4)
588 +#define S3C_DMA_CHANNELS (4)
589 #else
590 -#define S3C2410_DMA_CHANNELS (6)
591 +#define S3C_DMA_CHANNELS (6)
592 #endif
593
594 /* types */
595 @@ -68,7 +68,6 @@
596 S3C2410_DMA_PAUSED
597 };
598
599 -
600 /* enum s3c2410_dma_loadst
601 *
602 * This represents the state of the DMA engine, wrt to the loaded / running
603 @@ -104,32 +103,6 @@
604 S3C2410_DMALOAD_1LOADED_1RUNNING,
605 };
606
607 -enum s3c2410_dma_buffresult {
608 - S3C2410_RES_OK,
609 - S3C2410_RES_ERR,
610 - S3C2410_RES_ABORT
611 -};
612 -
613 -enum s3c2410_dmasrc {
614 - S3C2410_DMASRC_HW, /* source is memory */
615 - S3C2410_DMASRC_MEM /* source is hardware */
616 -};
617 -
618 -/* enum s3c2410_chan_op
619 - *
620 - * operation codes passed to the DMA code by the user, and also used
621 - * to inform the current channel owner of any changes to the system state
622 -*/
623 -
624 -enum s3c2410_chan_op {
625 - S3C2410_DMAOP_START,
626 - S3C2410_DMAOP_STOP,
627 - S3C2410_DMAOP_PAUSE,
628 - S3C2410_DMAOP_RESUME,
629 - S3C2410_DMAOP_FLUSH,
630 - S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */
631 - S3C2410_DMAOP_STARTED, /* indicate channel started */
632 -};
633
634 /* flags */
635
636 @@ -137,19 +110,18 @@
637 * waiting for reloads */
638 #define S3C2410_DMAF_AUTOSTART (1<<1) /* auto-start if buffer queued */
639
640 +#define S3C2410_DMAF_CIRCULAR (0x00) /* circular enqueue not supp. */
641 +
642 /* dma buffer */
643
644 -struct s3c2410_dma_client {
645 - char *name;
646 -};
647 +struct s3c2410_dma_buf;
648
649 -/* s3c2410_dma_buf_s
650 +/* s3c2410_dma_buf
651 *
652 * internally used buffer structure to describe a queued or running
653 * buffer.
654 */
655
656 -struct s3c2410_dma_buf;
657 struct s3c2410_dma_buf {
658 struct s3c2410_dma_buf *next;
659 int magic; /* magic */
660 @@ -161,20 +133,6 @@
661
662 /* [1] is this updated for both recv/send modes? */
663
664 -struct s3c2410_dma_chan;
665 -
666 -/* s3c2410_dma_cbfn_t
667 - *
668 - * buffer callback routine type
669 -*/
670 -
671 -typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
672 - void *buf, int size,
673 - enum s3c2410_dma_buffresult result);
674 -
675 -typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
676 - enum s3c2410_chan_op );
677 -
678 struct s3c2410_dma_stats {
679 unsigned long loads;
680 unsigned long timeout_longest;
681 @@ -206,10 +164,10 @@
682
683 /* channel configuration */
684 enum s3c2410_dmasrc source;
685 + enum dma_ch req_ch;
686 unsigned long dev_addr;
687 unsigned long load_timeout;
688 unsigned int flags; /* channel flags */
689 - unsigned int hw_cfg; /* last hw config */
690
691 struct s3c24xx_dma_map *map; /* channel hw maps */
692
693 @@ -236,213 +194,12 @@
694 struct sys_device dev;
695 };
696
697 -/* the currently allocated channel information */
698 -extern struct s3c2410_dma_chan s3c2410_chans[];
699 -
700 -/* note, we don't really use dma_device_t at the moment */
701 typedef unsigned long dma_device_t;
702
703 -/* functions --------------------------------------------------------------- */
704 -
705 -/* s3c2410_dma_request
706 - *
707 - * request a dma channel exclusivley
708 -*/
709 -
710 -extern int s3c2410_dma_request(unsigned int channel,
711 - struct s3c2410_dma_client *, void *dev);
712 -
713 -
714 -/* s3c2410_dma_ctrl
715 - *
716 - * change the state of the dma channel
717 -*/
718 -
719 -extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
720 -
721 -/* s3c2410_dma_setflags
722 - *
723 - * set the channel's flags to a given state
724 -*/
725 -
726 -extern int s3c2410_dma_setflags(unsigned int channel,
727 - unsigned int flags);
728 -
729 -/* s3c2410_dma_free
730 - *
731 - * free the dma channel (will also abort any outstanding operations)
732 -*/
733 -
734 -extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
735 -
736 -/* s3c2410_dma_enqueue
737 - *
738 - * place the given buffer onto the queue of operations for the channel.
739 - * The buffer must be allocated from dma coherent memory, or the Dcache/WB
740 - * drained before the buffer is given to the DMA system.
741 -*/
742 -
743 -extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
744 - dma_addr_t data, int size);
745 -
746 -/* s3c2410_dma_config
747 - *
748 - * configure the dma channel
749 -*/
750 -
751 -extern int s3c2410_dma_config(unsigned int channel, int xferunit, int dcon);
752 -
753 -/* s3c2410_dma_devconfig
754 - *
755 - * configure the device we're talking to
756 -*/
757 -
758 -extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
759 - int hwcfg, unsigned long devaddr);
760 -
761 -/* s3c2410_dma_getposition
762 - *
763 - * get the position that the dma transfer is currently at
764 -*/
765 -
766 -extern int s3c2410_dma_getposition(unsigned int channel,
767 - dma_addr_t *src, dma_addr_t *dest);
768 -
769 -extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
770 -extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
771 -
772 -/* DMA Register definitions */
773 -
774 -#define S3C2410_DMA_DISRC (0x00)
775 -#define S3C2410_DMA_DISRCC (0x04)
776 -#define S3C2410_DMA_DIDST (0x08)
777 -#define S3C2410_DMA_DIDSTC (0x0C)
778 -#define S3C2410_DMA_DCON (0x10)
779 -#define S3C2410_DMA_DSTAT (0x14)
780 -#define S3C2410_DMA_DCSRC (0x18)
781 -#define S3C2410_DMA_DCDST (0x1C)
782 -#define S3C2410_DMA_DMASKTRIG (0x20)
783 -#define S3C2412_DMA_DMAREQSEL (0x24)
784 -#define S3C2443_DMA_DMAREQSEL (0x24)
785 -
786 -#define S3C2410_DISRCC_INC (1<<0)
787 -#define S3C2410_DISRCC_APB (1<<1)
788 -
789 -#define S3C2410_DMASKTRIG_STOP (1<<2)
790 -#define S3C2410_DMASKTRIG_ON (1<<1)
791 -#define S3C2410_DMASKTRIG_SWTRIG (1<<0)
792 -
793 -#define S3C2410_DCON_DEMAND (0<<31)
794 -#define S3C2410_DCON_HANDSHAKE (1<<31)
795 -#define S3C2410_DCON_SYNC_PCLK (0<<30)
796 -#define S3C2410_DCON_SYNC_HCLK (1<<30)
797 -
798 -#define S3C2410_DCON_INTREQ (1<<29)
799 -
800 -#define S3C2410_DCON_CH0_XDREQ0 (0<<24)
801 -#define S3C2410_DCON_CH0_UART0 (1<<24)
802 -#define S3C2410_DCON_CH0_SDI (2<<24)
803 -#define S3C2410_DCON_CH0_TIMER (3<<24)
804 -#define S3C2410_DCON_CH0_USBEP1 (4<<24)
805 -
806 -#define S3C2410_DCON_CH1_XDREQ1 (0<<24)
807 -#define S3C2410_DCON_CH1_UART1 (1<<24)
808 -#define S3C2410_DCON_CH1_I2SSDI (2<<24)
809 -#define S3C2410_DCON_CH1_SPI (3<<24)
810 -#define S3C2410_DCON_CH1_USBEP2 (4<<24)
811 -
812 -#define S3C2410_DCON_CH2_I2SSDO (0<<24)
813 -#define S3C2410_DCON_CH2_I2SSDI (1<<24)
814 -#define S3C2410_DCON_CH2_SDI (2<<24)
815 -#define S3C2410_DCON_CH2_TIMER (3<<24)
816 -#define S3C2410_DCON_CH2_USBEP3 (4<<24)
817 -
818 -#define S3C2410_DCON_CH3_UART2 (0<<24)
819 -#define S3C2410_DCON_CH3_SDI (1<<24)
820 -#define S3C2410_DCON_CH3_SPI (2<<24)
821 -#define S3C2410_DCON_CH3_TIMER (3<<24)
822 -#define S3C2410_DCON_CH3_USBEP4 (4<<24)
823 -
824 -#define S3C2410_DCON_SRCSHIFT (24)
825 -#define S3C2410_DCON_SRCMASK (7<<24)
826 -
827 -#define S3C2410_DCON_BYTE (0<<20)
828 -#define S3C2410_DCON_HALFWORD (1<<20)
829 -#define S3C2410_DCON_WORD (2<<20)
830 -
831 -#define S3C2410_DCON_AUTORELOAD (0<<22)
832 -#define S3C2410_DCON_NORELOAD (1<<22)
833 -#define S3C2410_DCON_HWTRIG (1<<23)
834 -
835 -#ifdef CONFIG_CPU_S3C2440
836 -#define S3C2440_DIDSTC_CHKINT (1<<2)
837 -
838 -#define S3C2440_DCON_CH0_I2SSDO (5<<24)
839 -#define S3C2440_DCON_CH0_PCMIN (6<<24)
840 -
841 -#define S3C2440_DCON_CH1_PCMOUT (5<<24)
842 -#define S3C2440_DCON_CH1_SDI (6<<24)
843 -
844 -#define S3C2440_DCON_CH2_PCMIN (5<<24)
845 -#define S3C2440_DCON_CH2_MICIN (6<<24)
846 -
847 -#define S3C2440_DCON_CH3_MICIN (5<<24)
848 -#define S3C2440_DCON_CH3_PCMOUT (6<<24)
849 -#endif
850 -
851 -#ifdef CONFIG_CPU_S3C2412
852 -
853 -#define S3C2412_DMAREQSEL_SRC(x) ((x)<<1)
854 -
855 -#define S3C2412_DMAREQSEL_HW (1)
856 -
857 -#define S3C2412_DMAREQSEL_SPI0TX S3C2412_DMAREQSEL_SRC(0)
858 -#define S3C2412_DMAREQSEL_SPI0RX S3C2412_DMAREQSEL_SRC(1)
859 -#define S3C2412_DMAREQSEL_SPI1TX S3C2412_DMAREQSEL_SRC(2)
860 -#define S3C2412_DMAREQSEL_SPI1RX S3C2412_DMAREQSEL_SRC(3)
861 -#define S3C2412_DMAREQSEL_I2STX S3C2412_DMAREQSEL_SRC(4)
862 -#define S3C2412_DMAREQSEL_I2SRX S3C2412_DMAREQSEL_SRC(5)
863 -#define S3C2412_DMAREQSEL_TIMER S3C2412_DMAREQSEL_SRC(9)
864 -#define S3C2412_DMAREQSEL_SDI S3C2412_DMAREQSEL_SRC(10)
865 -#define S3C2412_DMAREQSEL_USBEP1 S3C2412_DMAREQSEL_SRC(13)
866 -#define S3C2412_DMAREQSEL_USBEP2 S3C2412_DMAREQSEL_SRC(14)
867 -#define S3C2412_DMAREQSEL_USBEP3 S3C2412_DMAREQSEL_SRC(15)
868 -#define S3C2412_DMAREQSEL_USBEP4 S3C2412_DMAREQSEL_SRC(16)
869 -#define S3C2412_DMAREQSEL_XDREQ0 S3C2412_DMAREQSEL_SRC(17)
870 -#define S3C2412_DMAREQSEL_XDREQ1 S3C2412_DMAREQSEL_SRC(18)
871 -#define S3C2412_DMAREQSEL_UART0_0 S3C2412_DMAREQSEL_SRC(19)
872 -#define S3C2412_DMAREQSEL_UART0_1 S3C2412_DMAREQSEL_SRC(20)
873 -#define S3C2412_DMAREQSEL_UART1_0 S3C2412_DMAREQSEL_SRC(21)
874 -#define S3C2412_DMAREQSEL_UART1_1 S3C2412_DMAREQSEL_SRC(22)
875 -#define S3C2412_DMAREQSEL_UART2_0 S3C2412_DMAREQSEL_SRC(23)
876 -#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24)
877 -
878 -#endif
879 -
880 -#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1)
881 -
882 -#define S3C2443_DMAREQSEL_HW (1)
883
884 -#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0)
885 -#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1)
886 -#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2)
887 -#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3)
888 -#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4)
889 -#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5)
890 -#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9)
891 -#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10)
892 -#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17)
893 -#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18)
894 -#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19)
895 -#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20)
896 -#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21)
897 -#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22)
898 -#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23)
899 -#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24)
900 -#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25)
901 -#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26)
902 -#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27)
903 -#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28)
904 -#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29)
905 +static int s3c_dma_has_circular(void)
906 +{
907 + return 0;
908 +}
909
910 #endif /* __ASM_ARCH_DMA_H */
911 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gpio-core.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gpio-core.h
912 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gpio-core.h 2009-05-10 22:05:04.000000000 +0200
913 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gpio-core.h 2009-05-10 22:27:59.000000000 +0200
914 @@ -15,20 +15,7 @@
915 #ifndef __ASM_ARCH_GPIO_CORE_H
916 #define __ASM_ARCH_GPIO_CORE_H __FILE__
917
918 +/* currently we just include the platform support */
919 #include <plat/gpio-core.h>
920 -#include <mach/regs-gpio.h>
921 -
922 -extern struct s3c_gpio_chip s3c24xx_gpios[];
923 -
924 -static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
925 -{
926 - struct s3c_gpio_chip *chip;
927 -
928 - if (pin > S3C2410_GPG10)
929 - return NULL;
930 -
931 - chip = &s3c24xx_gpios[pin/32];
932 - return (S3C2410_GPIO_OFFSET(pin) > chip->chip.ngpio) ? chip : NULL;
933 -}
934
935 #endif /* __ASM_ARCH_GPIO_CORE_H */
936 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gpio.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gpio.h
937 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gpio.h 2009-05-10 22:05:04.000000000 +0200
938 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gpio.h 2009-05-10 22:27:59.000000000 +0200
939 @@ -22,4 +22,13 @@
940
941 #define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA)
942
943 +/* These two defines should be removed as soon as the
944 + * generic irq handling makes it upstream */
945 +#include <mach/hardware.h>
946 +#define irq_to_gpio(irq) s3c2410_gpio_irq2pin(irq)
947 +/* -- cut to here when generic irq makes it */
948 +
949 #include <asm-generic/gpio.h>
950 +#include <mach/gpio-nrs.h>
951 +
952 +#define S3C_GPIO_END (S3C2410_GPIO_BANKH + 32)
953 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
954 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h 1970-01-01 01:00:00.000000000 +0100
955 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gpio-nrs.h 2009-05-10 22:27:59.000000000 +0200
956 @@ -0,0 +1,23 @@
957 +/* arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
958 + *
959 + * Copyright (c) 2008 Simtec Electronics
960 + * http://armlinux.simtec.co.uk/
961 + * Ben Dooks <ben@simtec.co.uk>
962 + *
963 + * S3C2410 - GPIO bank numbering
964 + *
965 + * This program is free software; you can redistribute it and/or modify
966 + * it under the terms of the GNU General Public License version 2 as
967 + * published by the Free Software Foundation.
968 +*/
969 +
970 +#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
971 +
972 +#define S3C2410_GPIO_BANKA (32*0)
973 +#define S3C2410_GPIO_BANKB (32*1)
974 +#define S3C2410_GPIO_BANKC (32*2)
975 +#define S3C2410_GPIO_BANKD (32*3)
976 +#define S3C2410_GPIO_BANKE (32*4)
977 +#define S3C2410_GPIO_BANKF (32*5)
978 +#define S3C2410_GPIO_BANKG (32*6)
979 +#define S3C2410_GPIO_BANKH (32*7)
980 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gta01.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gta01.h
981 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gta01.h 1970-01-01 01:00:00.000000000 +0100
982 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gta01.h 2009-05-10 22:27:59.000000000 +0200
983 @@ -0,0 +1,76 @@
984 +#ifndef _GTA01_H
985 +#define _GTA01_H
986 +
987 +#include <mach/regs-gpio.h>
988 +#include <mach/irqs.h>
989 +
990 +/* Different hardware revisions, passed in ATAG_REVISION by u-boot */
991 +#define GTA01v3_SYSTEM_REV 0x00000130
992 +#define GTA01v4_SYSTEM_REV 0x00000140
993 +#define GTA01Bv2_SYSTEM_REV 0x00000220
994 +#define GTA01Bv3_SYSTEM_REV 0x00000230
995 +#define GTA01Bv4_SYSTEM_REV 0x00000240
996 +
997 +/* Backlight */
998 +
999 +extern void gta01bl_deferred_resume(void);
1000 +
1001 +struct gta01bl_machinfo {
1002 + unsigned int default_intensity;
1003 + unsigned int max_intensity;
1004 + unsigned int limit_mask;
1005 + unsigned int defer_resume_backlight;
1006 +};
1007 +
1008 +/* Definitions common to all revisions */
1009 +#define GTA01_GPIO_BACKLIGHT S3C2410_GPB0
1010 +#define GTA01_GPIO_GPS_PWRON S3C2410_GPB1
1011 +#define GTA01_GPIO_MODEM_RST S3C2410_GPB6
1012 +#define GTA01_GPIO_MODEM_ON S3C2410_GPB7
1013 +#define GTA01_GPIO_LCD_RESET S3C2410_GPC6
1014 +#define GTA01_GPIO_PMU_IRQ S3C2410_GPG8
1015 +#define GTA01_GPIO_JACK_INSERT S3C2410_GPF4
1016 +#define GTA01_GPIO_nSD_DETECT S3C2410_GPF5
1017 +#define GTA01_GPIO_AUX_KEY S3C2410_GPF6
1018 +#define GTA01_GPIO_HOLD_KEY S3C2410_GPF7
1019 +#define GTA01_GPIO_VIBRATOR_ON S3C2410_GPG11
1020 +
1021 +#define GTA01_IRQ_MODEM IRQ_EINT1
1022 +#define GTA01_IRQ_JACK_INSERT IRQ_EINT4
1023 +#define GTA01_IRQ_nSD_DETECT IRQ_EINT5
1024 +#define GTA01_IRQ_AUX_KEY IRQ_EINT6
1025 +#define GTA01_IRQ_PCF50606 IRQ_EINT16
1026 +
1027 +/* GTA01v3 */
1028 +#define GTA01v3_GPIO_nGSM_EN S3C2410_GPG9
1029 +
1030 +/* GTA01v4 */
1031 +#define GTA01_GPIO_MODEM_DNLOAD S3C2410_GPG0
1032 +
1033 +/* GTA01Bv2 */
1034 +#define GTA01Bv2_GPIO_nGSM_EN S3C2410_GPF2
1035 +#define GTA01Bv2_GPIO_VIBRATOR_ON S3C2410_GPB10
1036 +
1037 +/* GTA01Bv3 */
1038 +#define GTA01_GPIO_GPS_EN_3V3 S3C2410_GPG9
1039 +
1040 +#define GTA01_GPIO_SDMMC_ON S3C2410_GPB2
1041 +#define GTA01_GPIO_BT_EN S3C2410_GPB5
1042 +#define GTA01_GPIO_AB_DETECT S3C2410_GPB8
1043 +#define GTA01_GPIO_USB_PULLUP S3C2410_GPB9
1044 +#define GTA01_GPIO_USB_ATTACH S3C2410_GPB10
1045 +
1046 +#define GTA01_GPIO_GPS_EN_2V8 S3C2410_GPG9
1047 +#define GTA01_GPIO_GPS_EN_3V S3C2410_GPG10
1048 +#define GTA01_GPIO_GPS_RESET S3C2410_GPC0
1049 +
1050 +/* GTA01Bv4 */
1051 +#define GTA01Bv4_GPIO_nNAND_WP S3C2410_GPA16
1052 +#define GTA01Bv4_GPIO_VIBRATOR_ON S3C2410_GPB3
1053 +#define GTA01Bv4_GPIO_PMU_IRQ S3C2410_GPG1
1054 +
1055 +#define GTA01Bv4_IRQ_PCF50606 IRQ_EINT9
1056 +
1057 +extern struct pcf50606 *gta01_pcf;
1058 +
1059 +#endif /* _GTA01_H */
1060 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gta02-pm-wlan.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gta02-pm-wlan.h
1061 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/gta02-pm-wlan.h 1970-01-01 01:00:00.000000000 +0100
1062 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/gta02-pm-wlan.h 2009-05-10 22:27:59.000000000 +0200
1063 @@ -0,0 +1,10 @@
1064 +#ifndef __MACH_GTA02_PM_WLAN_H
1065 +#define __MACH_GTA02_PM_WLAN_H
1066 +
1067 +void gta02_wlan_reset(int assert_reset);
1068 +int gta02_wlan_query_rfkill_lock(void);
1069 +void gta02_wlan_query_rfkill_unlock(void);
1070 +void gta02_wlan_set_rfkill_cb(int (*cb)(void *user, int on), void *user);
1071 +void gta02_wlan_clear_rfkill_cb(void);
1072 +
1073 +#endif /* __MACH_GTA02_PM_WLAN_H */
1074 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/hardware.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/hardware.h
1075 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/hardware.h 2009-05-10 22:05:04.000000000 +0200
1076 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/hardware.h 2009-05-10 22:27:59.000000000 +0200
1077 @@ -131,7 +131,4 @@
1078
1079 /* machine specific hardware definitions should go after this */
1080
1081 -/* currently here until moved into config (todo) */
1082 -#define CONFIG_NO_MULTIWORD_IO
1083 -
1084 #endif /* __ASM_ARCH_HARDWARE_H */
1085 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/io.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/io.h
1086 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/io.h 2009-05-10 22:05:04.000000000 +0200
1087 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/io.h 2009-05-10 22:27:59.000000000 +0200
1088 @@ -9,7 +9,7 @@
1089 #ifndef __ASM_ARM_ARCH_IO_H
1090 #define __ASM_ARM_ARCH_IO_H
1091
1092 -#include <mach/hardware.h>
1093 +#include <mach/map.h>
1094
1095 #define IO_SPACE_LIMIT 0xffffffff
1096
1097 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/irqs.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/irqs.h
1098 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/irqs.h 2009-05-10 22:05:04.000000000 +0200
1099 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/irqs.h 2009-05-10 22:27:59.000000000 +0200
1100 @@ -80,7 +80,7 @@
1101 #define IRQ_EINT22 S3C2410_IRQ(50)
1102 #define IRQ_EINT23 S3C2410_IRQ(51)
1103
1104 -
1105 +#define IRQ_EINT_BIT(x) ((x) - IRQ_EINT4 + 4)
1106 #define IRQ_EINT(x) (((x) >= 4) ? (IRQ_EINT4 + (x) - 4) : (IRQ_EINT0 + (x)))
1107
1108 #define IRQ_LCD_FIFO S3C2410_IRQ(52)
1109 @@ -153,9 +153,9 @@
1110 #define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28)
1111
1112 #ifdef CONFIG_CPU_S3C2443
1113 -#define NR_IRQS (IRQ_S3C2443_AC97+1)
1114 +#define _NR_IRQS (IRQ_S3C2443_AC97+1)
1115 #else
1116 -#define NR_IRQS (IRQ_S3C2440_AC97+1)
1117 +#define _NR_IRQS (IRQ_S3C2440_AC97+1)
1118 #endif
1119
1120 /* compatibility define. */
1121 @@ -167,4 +167,33 @@
1122 /* Our FIQs are routable from IRQ_EINT0 to IRQ_ADCPARENT */
1123 #define FIQ_START IRQ_EINT0
1124
1125 +
1126 +/*
1127 + * The next 16 interrupts are for board specific purposes. Since
1128 + * the kernel can only run on one machine at a time, we can re-use
1129 + * these. If you need more, increase IRQ_BOARD_END, but keep it
1130 + * within sensible limits.
1131 + */
1132 +#define IRQ_BOARD_START _NR_IRQS
1133 +#define IRQ_BOARD_END (_NR_IRQS + 10)
1134 +
1135 +#if defined(CONFIG_MACH_NEO1973_GTA02)
1136 +#define NR_IRQS (IRQ_BOARD_END)
1137 +#else
1138 +#define NR_IRQS (IRQ_BOARD_START)
1139 +#endif
1140 +
1141 +/* Neo1973 GTA02 interrupts */
1142 +#define NEO1973_GTA02_IRQ(x) (IRQ_BOARD_START + (x))
1143 +#define IRQ_GLAMO(x) NEO1973_GTA02_IRQ(x)
1144 +#define IRQ_GLAMO_HOSTBUS IRQ_GLAMO(0)
1145 +#define IRQ_GLAMO_JPEG IRQ_GLAMO(1)
1146 +#define IRQ_GLAMO_MPEG IRQ_GLAMO(2)
1147 +#define IRQ_GLAMO_MPROC1 IRQ_GLAMO(3)
1148 +#define IRQ_GLAMO_MPROC0 IRQ_GLAMO(4)
1149 +#define IRQ_GLAMO_CMDQUEUE IRQ_GLAMO(5)
1150 +#define IRQ_GLAMO_2D IRQ_GLAMO(6)
1151 +#define IRQ_GLAMO_MMC IRQ_GLAMO(7)
1152 +#define IRQ_GLAMO_RISC IRQ_GLAMO(8)
1153 +
1154 #endif /* __ASM_ARCH_IRQ_H */
1155 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/map.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/map.h
1156 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/map.h 2009-05-10 22:05:04.000000000 +0200
1157 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/map.h 2009-05-10 22:27:59.000000000 +0200
1158 @@ -84,7 +84,6 @@
1159
1160 #define S3C24XX_PA_IRQ S3C2410_PA_IRQ
1161 #define S3C24XX_PA_MEMCTRL S3C2410_PA_MEMCTRL
1162 -#define S3C24XX_PA_USBHOST S3C2410_PA_USBHOST
1163 #define S3C24XX_PA_DMA S3C2410_PA_DMA
1164 #define S3C24XX_PA_CLKPWR S3C2410_PA_CLKPWR
1165 #define S3C24XX_PA_LCD S3C2410_PA_LCD
1166 @@ -102,6 +101,7 @@
1167
1168 #define S3C_PA_IIC S3C2410_PA_IIC
1169 #define S3C_PA_UART S3C24XX_PA_UART
1170 +#define S3C_PA_USBHOST S3C2410_PA_USBHOST
1171 #define S3C_PA_HSMMC0 S3C2443_PA_HSMMC
1172
1173 #endif /* __ASM_ARCH_MAP_H */
1174 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/mci.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/mci.h
1175 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/mci.h 1970-01-01 01:00:00.000000000 +0100
1176 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/mci.h 2009-05-10 22:27:59.000000000 +0200
1177 @@ -0,0 +1,13 @@
1178 +#ifndef _ARCH_MCI_H
1179 +#define _ARCH_MCI_H
1180 +
1181 +struct s3c24xx_mci_pdata {
1182 + unsigned int gpio_detect;
1183 + unsigned int gpio_wprotect;
1184 + unsigned long ocr_avail;
1185 + unsigned int do_dma;
1186 + void (*set_power)(unsigned char power_mode,
1187 + unsigned short vdd);
1188 +};
1189 +
1190 +#endif /* _ARCH_NCI_H */
1191 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/neo1973-pm-gsm.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/neo1973-pm-gsm.h
1192 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/neo1973-pm-gsm.h 1970-01-01 01:00:00.000000000 +0100
1193 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/neo1973-pm-gsm.h 2009-05-10 22:27:59.000000000 +0200
1194 @@ -0,0 +1 @@
1195 +extern int gta_gsm_interrupts;
1196 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/regs-gpio.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/regs-gpio.h
1197 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/regs-gpio.h 2009-05-10 22:05:04.000000000 +0200
1198 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/regs-gpio.h 2009-05-10 22:27:59.000000000 +0200
1199 @@ -14,16 +14,7 @@
1200 #ifndef __ASM_ARCH_REGS_GPIO_H
1201 #define __ASM_ARCH_REGS_GPIO_H
1202
1203 -#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
1204 -
1205 -#define S3C2410_GPIO_BANKA (32*0)
1206 -#define S3C2410_GPIO_BANKB (32*1)
1207 -#define S3C2410_GPIO_BANKC (32*2)
1208 -#define S3C2410_GPIO_BANKD (32*3)
1209 -#define S3C2410_GPIO_BANKE (32*4)
1210 -#define S3C2410_GPIO_BANKF (32*5)
1211 -#define S3C2410_GPIO_BANKG (32*6)
1212 -#define S3C2410_GPIO_BANKH (32*7)
1213 +#include <mach/gpio-nrs.h>
1214
1215 #ifdef CONFIG_CPU_S3C2400
1216 #define S3C24XX_GPIO_BASE(x) S3C2400_GPIO_BASE(x)
1217 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/regs-sdi.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/regs-sdi.h
1218 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/regs-sdi.h 2009-05-10 22:05:04.000000000 +0200
1219 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/regs-sdi.h 2009-05-10 22:27:59.000000000 +0200
1220 @@ -30,6 +30,7 @@
1221 #define S3C2410_SDIFSTA (0x38)
1222
1223 #define S3C2410_SDIDATA (0x3C)
1224 +#define S3C2410_SDIDATA_BYTE (0x3C)
1225 #define S3C2410_SDIIMSK (0x40)
1226
1227 #define S3C2440_SDIDATA (0x40)
1228 @@ -37,6 +38,8 @@
1229
1230 #define S3C2440_SDICON_SDRESET (1<<8)
1231 #define S3C2440_SDICON_MMCCLOCK (1<<5)
1232 +#define S3C2440_SDIDATA_BYTE (0x48)
1233 +
1234 #define S3C2410_SDICON_BYTEORDER (1<<4)
1235 #define S3C2410_SDICON_SDIOIRQ (1<<3)
1236 #define S3C2410_SDICON_RWAITEN (1<<2)
1237 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/s3c24xx-serial.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/s3c24xx-serial.h
1238 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/s3c24xx-serial.h 1970-01-01 01:00:00.000000000 +0100
1239 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/s3c24xx-serial.h 2009-05-10 22:27:59.000000000 +0200
1240 @@ -0,0 +1,5 @@
1241 +#include <linux/resume-dependency.h>
1242 +
1243 +extern void s3c24xx_serial_console_set_silence(int silence);
1244 +extern void s3c24xx_serial_register_resume_dependency(struct resume_dependency *
1245 + resume_dependency, int uart_index);
1246 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/spi-gpio.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/spi-gpio.h
1247 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/spi-gpio.h 2009-05-10 22:05:04.000000000 +0200
1248 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/spi-gpio.h 2009-05-10 22:27:59.000000000 +0200
1249 @@ -21,7 +21,8 @@
1250 int num_chipselect;
1251 int bus_num;
1252
1253 - void (*chip_select)(struct s3c2410_spigpio_info *spi, int cs);
1254 + int non_blocking_transfer;
1255 + void (*chip_select)(struct s3c2410_spigpio_info *spi, int csid, int cs);
1256 };
1257
1258
1259 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/ts.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/ts.h
1260 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/ts.h 1970-01-01 01:00:00.000000000 +0100
1261 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/ts.h 2009-05-10 22:27:59.000000000 +0200
1262 @@ -0,0 +1,35 @@
1263 +/* arch/arm/mach-s3c2410/include/mach/ts.h
1264 + *
1265 + * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
1266 + *
1267 + *
1268 + * This program is free software; you can redistribute it and/or modify
1269 + * it under the terms of the GNU General Public License version 2 as
1270 + * published by the Free Software Foundation.
1271 + *
1272 + *
1273 + * Changelog:
1274 + * 24-Mar-2005 RTP Created file
1275 + * 03-Aug-2005 RTP Renamed to ts.h
1276 + */
1277 +
1278 +#ifndef __ASM_ARM_TS_H
1279 +#define __ASM_ARM_TS_H
1280 +
1281 +#include <../drivers/input/touchscreen/ts_filter.h>
1282 +
1283 +struct s3c2410_ts_mach_info {
1284 + /* Touchscreen delay. */
1285 + int delay;
1286 + /* Prescaler value. */
1287 + int presc;
1288 + /*
1289 + * Null-terminated array of pointers to filter APIs and configurations
1290 + * we want to use. In the same order they will be applied.
1291 + */
1292 + const struct ts_filter_chain_configuration *filter_config;
1293 +};
1294 +
1295 +void set_s3c2410ts_info(const struct s3c2410_ts_mach_info *hard_s3c2410ts_info);
1296 +
1297 +#endif /* __ASM_ARM_TS_H */
1298 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/usb-control.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/usb-control.h
1299 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/include/mach/usb-control.h 2009-05-10 22:05:04.000000000 +0200
1300 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/include/mach/usb-control.h 1970-01-01 01:00:00.000000000 +0100
1301 @@ -1,41 +0,0 @@
1302 -/* arch/arm/mach-s3c2410/include/mach/usb-control.h
1303 - *
1304 - * Copyright (c) 2004 Simtec Electronics
1305 - * Ben Dooks <ben@simtec.co.uk>
1306 - *
1307 - * S3C2410 - usb port information
1308 - *
1309 - * This program is free software; you can redistribute it and/or modify
1310 - * it under the terms of the GNU General Public License version 2 as
1311 - * published by the Free Software Foundation.
1312 -*/
1313 -
1314 -#ifndef __ASM_ARCH_USBCONTROL_H
1315 -#define __ASM_ARCH_USBCONTROL_H "arch/arm/mach-s3c2410/include/mach/usb-control.h"
1316 -
1317 -#define S3C_HCDFLG_USED (1)
1318 -
1319 -struct s3c2410_hcd_port {
1320 - unsigned char flags;
1321 - unsigned char power;
1322 - unsigned char oc_status;
1323 - unsigned char oc_changed;
1324 -};
1325 -
1326 -struct s3c2410_hcd_info {
1327 - struct usb_hcd *hcd;
1328 - struct s3c2410_hcd_port port[2];
1329 -
1330 - void (*power_control)(int port, int to);
1331 - void (*enable_oc)(struct s3c2410_hcd_info *, int on);
1332 - void (*report_oc)(struct s3c2410_hcd_info *, int ports);
1333 -};
1334 -
1335 -static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
1336 -{
1337 - if (info->report_oc != NULL) {
1338 - (info->report_oc)(info, ports);
1339 - }
1340 -}
1341 -
1342 -#endif /*__ASM_ARCH_USBCONTROL_H */
1343 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/Kconfig linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/Kconfig
1344 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/Kconfig 2009-05-10 22:05:04.000000000 +0200
1345 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/Kconfig 2009-05-10 22:27:59.000000000 +0200
1346 @@ -10,6 +10,7 @@
1347 select CPU_ARM920T
1348 select S3C2410_CLOCK
1349 select S3C2410_GPIO
1350 + select S3C_PWM
1351 select CPU_LLSERIAL_S3C2410
1352 select S3C2410_PM if PM
1353 help
1354 @@ -45,6 +46,7 @@
1355 Internal node for machines with an BAST style IDE
1356 interface
1357
1358 +
1359 menu "S3C2410 Machines"
1360
1361 config ARCH_SMDK2410
1362 @@ -59,6 +61,7 @@
1363 bool "IPAQ H1940"
1364 select CPU_S3C2410
1365 select PM_H1940 if PM
1366 + select S3C_DEV_USB_HOST
1367 help
1368 Say Y here if you are using the HP IPAQ H1940
1369
1370 @@ -70,6 +73,7 @@
1371 config MACH_N30
1372 bool "Acer N30 family"
1373 select CPU_S3C2410
1374 + select S3C_DEV_USB_HOST
1375 help
1376 Say Y here if you want suppt for the Acer N30, Acer N35,
1377 Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs.
1378 @@ -82,6 +86,7 @@
1379 select MACH_BAST_IDE
1380 select S3C24XX_DCLK
1381 select ISA
1382 + select S3C_DEV_USB_HOST
1383 help
1384 Say Y here if you are using the Simtec Electronics EB2410ITX
1385 development board (also known as BAST)
1386 @@ -89,6 +94,7 @@
1387 config MACH_OTOM
1388 bool "NexVision OTOM Board"
1389 select CPU_S3C2410
1390 + select S3C_DEV_USB_HOST
1391 help
1392 Say Y here if you are using the Nex Vision OTOM board
1393
1394 @@ -96,6 +102,7 @@
1395 bool "AML M5900 Series"
1396 select CPU_S3C2410
1397 select PM_SIMTEC if PM
1398 + select S3C_DEV_USB_HOST
1399 help
1400 Say Y here if you are using the American Microsystems M5900 Series
1401 <http://www.amltd.com>
1402 @@ -111,6 +118,7 @@
1403 config MACH_TCT_HAMMER
1404 bool "TCT Hammer Board"
1405 select CPU_S3C2410
1406 + select S3C_DEV_USB_HOST
1407 help
1408 Say Y here if you are using the TinCanTools Hammer Board
1409 <http://www.tincantools.com>
1410 @@ -128,7 +136,27 @@
1411 config MACH_QT2410
1412 bool "QT2410"
1413 select CPU_S3C2410
1414 + select DISPLAY_JBT6K74
1415 help
1416 Say Y here if you are using the Armzone QT2410
1417
1418 +config MACH_NEO1973_GTA01
1419 + bool "FIC Neo1973 GSM Phone (GTA01 Hardware)"
1420 + select CPU_S3C2410
1421 + select MACH_NEO1973
1422 + select S3C_DEV_USB_HOST
1423 + select MFD_PCF50606
1424 + select INPUT_PCF50606_PMU
1425 + select PCF50606_ADC
1426 + select PCF50606_GPIO
1427 + select RTC_DRV_PCF50606
1428 + select REGULATOR_PCF50606
1429 + select CHARGER_PCF50606
1430 + select PCF50606_WATCHDOG
1431 + select POWER_SUPPLY
1432 + select BATTERY_GTA01
1433 +
1434 + help
1435 + Say Y here if you are using the FIC Neo1973 GSM Phone
1436 +
1437 endmenu
1438 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/mach-gta01.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/mach-gta01.c
1439 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/mach-gta01.c 1970-01-01 01:00:00.000000000 +0100
1440 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/mach-gta01.c 2009-05-10 22:27:59.000000000 +0200
1441 @@ -0,0 +1,1008 @@
1442 +/*
1443 + * linux/arch/arm/mach-s3c2410/mach-gta01.c
1444 + *
1445 + * S3C2410 Machine Support for the FIC Neo1973 GTA01
1446 + *
1447 + * Copyright (C) 2006-2007 by Openmoko, Inc.
1448 + * Author: Harald Welte <laforge@openmoko.org>
1449 + * All rights reserved.
1450 + *
1451 + * This program is free software; you can redistribute it and/or
1452 + * modify it under the terms of the GNU General Public License as
1453 + * published by the Free Software Foundation; either version 2 of
1454 + * the License, or (at your option) any later version.
1455 + *
1456 + * This program is distributed in the hope that it will be useful,
1457 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1458 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1459 + * GNU General Public License for more details.
1460 + *
1461 + * You should have received a copy of the GNU General Public License
1462 + * along with this program; if not, write to the Free Software
1463 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
1464 + * MA 02111-1307 USA
1465 + *
1466 + */
1467 +
1468 +#include <linux/kernel.h>
1469 +#include <linux/types.h>
1470 +#include <linux/interrupt.h>
1471 +#include <linux/list.h>
1472 +#include <linux/timer.h>
1473 +#include <linux/init.h>
1474 +#include <linux/workqueue.h>
1475 +#include <linux/platform_device.h>
1476 +#include <linux/i2c.h>
1477 +#include <linux/serial_core.h>
1478 +#include <mach/ts.h>
1479 +#include <linux/spi/spi.h>
1480 +#include <linux/spi/spi_bitbang.h>
1481 +#include <linux/mmc/mmc.h>
1482 +#include <linux/mmc/host.h>
1483 +
1484 +#include <linux/mtd/mtd.h>
1485 +#include <linux/mtd/nand.h>
1486 +#include <linux/mtd/nand_ecc.h>
1487 +#include <linux/mtd/partitions.h>
1488 +
1489 +#include <linux/mmc/host.h>
1490 +
1491 +#include <linux/mfd/pcf50606/core.h>
1492 +#include <linux/mfd/pcf50606/pmic.h>
1493 +#include <linux/mfd/pcf50606/mbc.h>
1494 +#include <linux/mfd/pcf50606/adc.h>
1495 +
1496 +#include <linux/gta01_battery.h>
1497 +
1498 +#include <linux/regulator/machine.h>
1499 +#include <linux/regulator/consumer.h>
1500 +
1501 +
1502 +#include <asm/mach/arch.h>
1503 +#include <asm/mach/map.h>
1504 +#include <asm/mach/irq.h>
1505 +
1506 +#include <mach/hardware.h>
1507 +#include <mach/io.h>
1508 +#include <asm/irq.h>
1509 +#include <asm/mach-types.h>
1510 +
1511 +#include <mach/regs-gpio.h>
1512 +#include <mach/fb.h>
1513 +#include <mach/spi.h>
1514 +#include <mach/spi-gpio.h>
1515 +#include <mach/cpu.h>
1516 +
1517 +#include <mach/gta01.h>
1518 +
1519 +#include <plat/regs-serial.h>
1520 +#include <plat/nand.h>
1521 +#include <plat/devs.h>
1522 +#include <plat/cpu.h>
1523 +#include <plat/pm.h>
1524 +#include <plat/udc.h>
1525 +#include <plat/iic.h>
1526 +#include <plat/mci.h>
1527 +#include <asm/plat-s3c24xx/neo1973.h>
1528 +#include <plat/usb-control.h>
1529 +#include <mach/neo1973-pm-gsm.h>
1530 +
1531 +#include <linux/jbt6k74.h>
1532 +
1533 +#include <../drivers/input/touchscreen/ts_filter_chain.h>
1534 +#ifdef CONFIG_TOUCHSCREEN_FILTER
1535 +#include <../drivers/input/touchscreen/ts_filter_linear.h>
1536 +#include <../drivers/input/touchscreen/ts_filter_mean.h>
1537 +#include <../drivers/input/touchscreen/ts_filter_median.h>
1538 +#include <../drivers/input/touchscreen/ts_filter_group.h>
1539 +#endif
1540 +
1541 +
1542 +static struct map_desc gta01_iodesc[] __initdata = {
1543 + {
1544 + .virtual = 0xe0000000,
1545 + .pfn = __phys_to_pfn(S3C2410_CS3+0x01000000),
1546 + .length = SZ_1M,
1547 + .type = MT_DEVICE
1548 + },
1549 +};
1550 +
1551 +#define UCON S3C2410_UCON_DEFAULT
1552 +#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
1553 +#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
1554 +/* UFCON for the gta01 sets the FIFO trigger level at 4, not 8 */
1555 +#define UFCON_GTA01_PORT0 S3C2410_UFCON_FIFOMODE
1556 +
1557 +static struct s3c2410_uartcfg gta01_uartcfgs[] = {
1558 + [0] = {
1559 + .hwport = 0,
1560 + .flags = 0,
1561 + .ucon = UCON,
1562 + .ulcon = ULCON,
1563 + .ufcon = UFCON_GTA01_PORT0,
1564 + },
1565 + [1] = {
1566 + .hwport = 1,
1567 + .flags = 0,
1568 + .ucon = UCON,
1569 + .ulcon = ULCON,
1570 + .ufcon = UFCON,
1571 + },
1572 +};
1573 +
1574 +/* TODO */
1575 +static void gta01_pmu_event_callback(struct pcf50606 *pcf, int irq)
1576 +{
1577 + /*TODO : Handle ACD here */
1578 +}
1579 +
1580 +/* FIXME : Goes away when ACD is handled above */
1581 +#if 0
1582 +static int pmu_callback(struct device *dev, unsigned int feature,
1583 + enum pmu_event event)
1584 +{
1585 + switch (feature) {
1586 + case PCF50606_FEAT_ACD:
1587 + switch (event) {
1588 + case PMU_EVT_INSERT:
1589 + pcf50606_charge_fast(pcf50606_global, 1);
1590 + break;
1591 + case PMU_EVT_REMOVE:
1592 + pcf50606_charge_fast(pcf50606_global, 0);
1593 + break;
1594 + default:
1595 + break;
1596 + }
1597 + break;
1598 + default:
1599 + break;
1600 + }
1601 +
1602 + return 0;
1603 +}
1604 +#endif
1605 +
1606 +struct pcf50606 *gta01_pcf;
1607 +
1608 +static struct platform_device gta01_pm_gsm_dev = {
1609 + .name = "neo1973-pm-gsm",
1610 +};
1611 +
1612 +static struct platform_device gta01_pm_bt_dev = {
1613 + .name = "neo1973-pm-bt",
1614 +};
1615 +static struct platform_device gta01_pm_gps_dev = {
1616 + .name = "neo1973-pm-gps",
1617 +};
1618 +
1619 +static struct regulator_consumer_supply ioreg_consumers[] = {
1620 + {
1621 + .dev = &gta01_pm_gps_dev.dev,
1622 + .supply = "GPS_2V8",
1623 + },
1624 +};
1625 +
1626 +static struct regulator_consumer_supply d1reg_consumers[] = {
1627 + {
1628 + .dev = &gta01_pm_gps_dev.dev,
1629 + .supply = "GPS_3V",
1630 + },
1631 + {
1632 + .dev = &gta01_pm_bt_dev.dev,
1633 + .supply = "BT_3V1",
1634 + },
1635 +};
1636 +
1637 +static struct regulator_consumer_supply dcd_consumers[] = {
1638 + {
1639 + .dev = &gta01_pm_gps_dev.dev,
1640 + .supply = "GPS_3V3",
1641 + },
1642 + {
1643 + .dev = &gta01_pm_gps_dev.dev,
1644 + .supply = "GPS_1V5",
1645 + },
1646 +};
1647 +
1648 +static struct regulator_consumer_supply d2reg_consumers[] = {
1649 + {
1650 + .dev = &gta01_pm_gps_dev.dev,
1651 + .supply = "GPS_2V5",
1652 + },
1653 + {
1654 + .dev = &s3c_device_sdi.dev,
1655 + .supply = "SD_3V3",
1656 + },
1657 +};
1658 +
1659 +static int gta01_bat_get_charging_status(void)
1660 +{
1661 + struct pcf50606 *pcf = gta01_pcf;
1662 + u8 mbcc1, chgmod;
1663 +
1664 + mbcc1 = pcf50606_reg_read(pcf, PCF50606_REG_MBCC1);
1665 + chgmod = mbcc1 & PCF50606_MBCC1_CHGMOD_MASK;
1666 +
1667 + if (chgmod == PCF50606_MBCC1_CHGMOD_IDLE)
1668 + return 0;
1669 + else
1670 + return 1;
1671 +}
1672 +
1673 +static int gta01_bat_get_voltage(void)
1674 +{
1675 + struct pcf50606 *pcf = gta01_pcf;
1676 + u16 adc, mv = 0;
1677 +
1678 + adc = pcf50606_adc_sync_read(pcf, PCF50606_ADCMUX_BATVOLT_RES);
1679 + mv = (adc * 6000) / 1024;
1680 +
1681 + return mv;
1682 +}
1683 +
1684 +static int gta01_bat_get_current(void)
1685 +{
1686 + struct pcf50606 *pcf = gta01_pcf;
1687 + u16 adc_battvolt, adc_adcin1;
1688 + s32 res;
1689 +
1690 + adc_battvolt = pcf50606_adc_sync_read(pcf, PCF50606_ADCMUX_BATVOLT_SUBTR);
1691 + adc_adcin1 = pcf50606_adc_sync_read(pcf, PCF50606_ADCMUX_ADCIN1_SUBTR);
1692 + res = (adc_adcin1 - adc_battvolt) * 2400;
1693 +
1694 + /*rsense is 220 milli */
1695 + return (res * 1000) / (220 * 1024);
1696 +}
1697 +
1698 +static struct gta01_bat_platform_data gta01_bat_pdata = {
1699 + .get_charging_status = gta01_bat_get_charging_status,
1700 + .get_voltage = gta01_bat_get_voltage,
1701 + .get_current = gta01_bat_get_current,
1702 +};
1703 +
1704 +struct platform_device gta01_bat = {
1705 + .name = "gta01_battery",
1706 + .id = -1,
1707 + .dev = {
1708 + .platform_data = &gta01_bat_pdata,
1709 + }
1710 +};
1711 +
1712 +static void gta01_pcf_probe_done(struct pcf50606 *pcf)
1713 +{
1714 + gta01_pcf = pcf;
1715 + gta01_bat.dev.parent = pcf->dev;
1716 + platform_device_register(&gta01_bat);
1717 +}
1718 +
1719 +static int gps_registered_regulators = 0;
1720 +
1721 +static void gta01_pmu_regulator_registered(struct pcf50606 *pcf, int id)
1722 +{
1723 + switch(id) {
1724 + case PCF50606_REGULATOR_D1REG:
1725 + platform_device_register(&gta01_pm_bt_dev);
1726 + gps_registered_regulators++;
1727 + break;
1728 + case PCF50606_REGULATOR_D2REG:
1729 + gps_registered_regulators++;
1730 + break;
1731 + case PCF50606_REGULATOR_IOREG:
1732 + case PCF50606_REGULATOR_DCD:
1733 + gps_registered_regulators++;
1734 + break;
1735 + }
1736 +
1737 + /* All GPS related regulators registered ? */
1738 + if (gps_registered_regulators == 4)
1739 + platform_device_register(&gta01_pm_gps_dev);
1740 +
1741 +}
1742 +
1743 +static struct pcf50606_platform_data gta01_pcf_pdata = {
1744 + .resumers = {
1745 + [0] = PCF50606_INT1_ALARM |
1746 + PCF50606_INT1_ONKEYF |
1747 + PCF50606_INT1_EXTONR,
1748 + [1] = PCF50606_INT2_CHGWD10S |
1749 + PCF50606_INT2_CHGPROT |
1750 + PCF50606_INT2_CHGERR,
1751 + [2] = PCF50606_INT3_LOWBAT |
1752 + PCF50606_INT3_HIGHTMP |
1753 + PCF50606_INT3_ACDINS,
1754 + },
1755 + .mbc_event_callback = gta01_pmu_event_callback,
1756 + .reg_init_data = {
1757 + [PCF50606_REGULATOR_D1REG] = {
1758 + .constraints = {
1759 + .min_uV = 3000000,
1760 + .max_uV = 3150000,
1761 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1762 + .apply_uV = 1,
1763 + },
1764 + .num_consumer_supplies = ARRAY_SIZE(d1reg_consumers),
1765 + .consumer_supplies = d1reg_consumers,
1766 + },
1767 +
1768 + [PCF50606_REGULATOR_D2REG] = {
1769 + .constraints = {
1770 + .min_uV = 1650000,
1771 + .max_uV = 3300000,
1772 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1773 + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
1774 + .apply_uV = 1,
1775 + },
1776 + .num_consumer_supplies = ARRAY_SIZE(d2reg_consumers),
1777 + .consumer_supplies = d2reg_consumers,
1778 +
1779 + },
1780 +
1781 + [PCF50606_REGULATOR_D3REG] = {
1782 + .constraints = {
1783 + .min_uV = 1800000,
1784 + .max_uV = 2100000,
1785 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1786 + .state_mem = {
1787 + .enabled = 1,
1788 + },
1789 + },
1790 + .num_consumer_supplies = 0,
1791 + },
1792 +
1793 + [PCF50606_REGULATOR_DCD] = {
1794 + .constraints = {
1795 + .min_uV = 1500000,
1796 + .max_uV = 1500000,
1797 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1798 + .apply_uV = 1,
1799 + },
1800 + .num_consumer_supplies = ARRAY_SIZE(dcd_consumers),
1801 + .consumer_supplies = dcd_consumers,
1802 + },
1803 +
1804 + [PCF50606_REGULATOR_DCDE] = {
1805 + .constraints = {
1806 + .min_uV = 3300000,
1807 + .max_uV = 3300000,
1808 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1809 + .apply_uV = 1,
1810 + .state_mem = {
1811 + .enabled = 1,
1812 + },
1813 + },
1814 + .num_consumer_supplies = 0,
1815 + },
1816 +
1817 + [PCF50606_REGULATOR_DCUD] = {
1818 + .constraints = {
1819 + .min_uV = 2100000,
1820 + .max_uV = 2100000,
1821 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1822 + .apply_uV = 1,
1823 + .state_mem = {
1824 + .enabled = 1,
1825 + },
1826 + },
1827 + .num_consumer_supplies = 0,
1828 + },
1829 +
1830 + [PCF50606_REGULATOR_IOREG] = {
1831 + .constraints = {
1832 + .min_uV = 3300000,
1833 + .max_uV = 3300000,
1834 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1835 + .apply_uV = 1,
1836 + },
1837 + .num_consumer_supplies = ARRAY_SIZE(ioreg_consumers),
1838 + .consumer_supplies = ioreg_consumers,
1839 +
1840 + },
1841 +
1842 + [PCF50606_REGULATOR_LPREG] = {
1843 + .constraints = {
1844 + .min_uV = 3300000,
1845 + .max_uV = 3300000,
1846 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1847 + .apply_uV = 1,
1848 + },
1849 + .num_consumer_supplies = 0,
1850 + },
1851 + },
1852 + .probe_done = gta01_pcf_probe_done,
1853 + .regulator_registered = gta01_pmu_regulator_registered,
1854 +};
1855 +
1856 +static void cfg_pmu_vrail(struct regulator_init_data *vrail,
1857 + unsigned int suspend_on, unsigned int min,
1858 + unsigned int max)
1859 +{
1860 + vrail->constraints.state_mem.enabled = suspend_on;
1861 + vrail->constraints.min_uV = min;
1862 + vrail->constraints.max_uV = min;
1863 + vrail->constraints.apply_uV = 1;
1864 +}
1865 +
1866 +static void mangle_pmu_pdata_by_system_rev(void)
1867 +{
1868 + struct regulator_init_data *reg_init_data;
1869 +
1870 + reg_init_data = gta01_pcf_pdata.reg_init_data;
1871 +
1872 + switch (S3C_SYSTEM_REV_ATAG) {
1873 + case GTA01Bv4_SYSTEM_REV:
1874 +
1875 + /* FIXME : gta01_pcf_pdata.used_features |= PCF50606_FEAT_ACD; */
1876 + break;
1877 + case GTA01Bv3_SYSTEM_REV:
1878 + case GTA01Bv2_SYSTEM_REV:
1879 + reg_init_data[PCF50606_REGULATOR_D3REG].constraints.state_mem.enabled = 1;
1880 + break;
1881 + case GTA01v4_SYSTEM_REV:
1882 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_DCUD],
1883 + 1, 18000000, 1800000);
1884 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_D1REG],
1885 + 0, 3000000, 3000000);
1886 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_D3REG],
1887 + 0, 2800000, 2800000);
1888 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_DCD],
1889 + 0, 3500000, 3500000);
1890 + break;
1891 + case GTA01v3_SYSTEM_REV:
1892 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_D1REG],
1893 + 0, 3000000, 3000000);
1894 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_D2REG],
1895 + 0, 3300000, 3300000);
1896 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_D3REG],
1897 + 0, 3300000, 3300000);
1898 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_DCD],
1899 + 0, 3300000, 3300000);
1900 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_DCUD],
1901 + 1, 1800000, 1800000);
1902 + cfg_pmu_vrail(&reg_init_data[PCF50606_REGULATOR_IOREG],
1903 + 0, 2800000, 2800000);
1904 + break;
1905 + }
1906 +}
1907 +
1908 +static void gta01_power_off(void)
1909 +{
1910 + pcf50606_reg_write(gta01_pcf, PCF50606_REG_OOCC1,
1911 + PCF50606_OOCC1_GOSTDBY);
1912 +}
1913 +
1914 +/* LCD driver info */
1915 +
1916 +/* Configuration for 480x640 toppoly TD028TTEC1.
1917 + * Do not mark this as __initdata or it will break! */
1918 +static struct s3c2410fb_display gta01_displays[] = {
1919 + {
1920 + .type = S3C2410_LCDCON1_TFT,
1921 + .width = 43,
1922 + .height = 58,
1923 + .xres = 480,
1924 + .yres = 640,
1925 + .bpp = 16,
1926 +
1927 + .pixclock = 40000, /* HCLK/4 */
1928 + .left_margin = 104,
1929 + .right_margin = 8,
1930 + .hsync_len = 8,
1931 + .upper_margin = 2,
1932 + .lower_margin = 16,
1933 + .vsync_len = 2,
1934 + .lcdcon5 = S3C2410_LCDCON5_FRM565 |
1935 + S3C2410_LCDCON5_INVVCLK |
1936 + S3C2410_LCDCON5_INVVLINE |
1937 + S3C2410_LCDCON5_INVVFRAME |
1938 + S3C2410_LCDCON5_PWREN |
1939 + S3C2410_LCDCON5_HWSWP,
1940 + },
1941 + {
1942 + .type = S3C2410_LCDCON1_TFT,
1943 + .width = 43,
1944 + .height = 58,
1945 + .xres = 480,
1946 + .yres = 640,
1947 + .bpp = 32,
1948 +
1949 + .pixclock = 40000, /* HCLK/4 */
1950 + .left_margin = 104,
1951 + .right_margin = 8,
1952 + .hsync_len = 8,
1953 + .upper_margin = 2,
1954 + .lower_margin = 16,
1955 + .vsync_len = 2,
1956 + .lcdcon5 = S3C2410_LCDCON5_FRM565 |
1957 + S3C2410_LCDCON5_INVVCLK |
1958 + S3C2410_LCDCON5_INVVLINE |
1959 + S3C2410_LCDCON5_INVVFRAME |
1960 + S3C2410_LCDCON5_PWREN |
1961 + S3C2410_LCDCON5_HWSWP,
1962 + },
1963 + {
1964 + .type = S3C2410_LCDCON1_TFT,
1965 + .width = 43,
1966 + .height = 58,
1967 + .xres = 240,
1968 + .yres = 320,
1969 + .bpp = 16,
1970 +
1971 + .pixclock = 40000, /* HCLK/4 */
1972 + .left_margin = 104,
1973 + .right_margin = 8,
1974 + .hsync_len = 8,
1975 + .upper_margin = 2,
1976 + .lower_margin = 16,
1977 + .vsync_len = 2,
1978 + .lcdcon5 = S3C2410_LCDCON5_FRM565 |
1979 + S3C2410_LCDCON5_INVVCLK |
1980 + S3C2410_LCDCON5_INVVLINE |
1981 + S3C2410_LCDCON5_INVVFRAME |
1982 + S3C2410_LCDCON5_PWREN |
1983 + S3C2410_LCDCON5_HWSWP,
1984 + },
1985 +};
1986 +
1987 +static struct s3c2410fb_mach_info gta01_lcd_cfg __initdata = {
1988 + .displays = gta01_displays,
1989 + .num_displays = ARRAY_SIZE(gta01_displays),
1990 + .default_display = 0,
1991 +
1992 + .lpcsel = ((0xCE6) & ~7) | 1<<4,
1993 +};
1994 +
1995 +static struct platform_device *gta01_devices[] __initdata = {
1996 + &s3c_device_usb,
1997 + &s3c_device_lcd,
1998 + &s3c_device_wdt,
1999 + &s3c_device_i2c0,
2000 + &s3c_device_iis,
2001 + &s3c_device_sdi,
2002 + &s3c_device_usbgadget,
2003 + &s3c_device_nand,
2004 + &s3c_device_ts,
2005 +};
2006 +
2007 +static struct s3c2410_nand_set gta01_nand_sets[] = {
2008 + [0] = {
2009 + .name = "neo1973-nand",
2010 + .nr_chips = 1,
2011 + .flags = S3C2410_NAND_BBT,
2012 + },
2013 +};
2014 +
2015 +static struct s3c2410_platform_nand gta01_nand_info = {
2016 + .tacls = 20,
2017 + .twrph0 = 60,
2018 + .twrph1 = 20,
2019 + .nr_sets = ARRAY_SIZE(gta01_nand_sets),
2020 + .sets = gta01_nand_sets,
2021 +};
2022 +
2023 +static struct regulator *s3c_sdi_regulator;
2024 +
2025 +static void gta01_mmc_set_power(unsigned char power_mode, unsigned short vdd)
2026 +{
2027 + int bit;
2028 + int mv = 1700; /* 1.7V for MMC_VDD_165_195 */
2029 + struct regulator *regulator;
2030 +
2031 + printk(KERN_DEBUG "mmc_set_power(power_mode=%u, vdd=%u)\n",
2032 + power_mode, vdd);
2033 +
2034 + if (!s3c_sdi_regulator) {
2035 + s3c_sdi_regulator =
2036 + regulator_get(&s3c_device_sdi.dev, "SD_3V3");
2037 + if (!s3c_sdi_regulator) {
2038 + printk(KERN_ERR "gta01_mmc_set_power : Cannot get regulator");
2039 + return;
2040 + }
2041 + }
2042 +
2043 + regulator = s3c_sdi_regulator;
2044 +
2045 + return;
2046 + switch (S3C_SYSTEM_REV_ATAG) {
2047 + case GTA01v3_SYSTEM_REV:
2048 + switch (power_mode) {
2049 + case MMC_POWER_OFF:
2050 + regulator_disable(regulator);
2051 + break;
2052 + case MMC_POWER_ON:
2053 + /* translate MMC_VDD_* VDD bit to mv */
2054 + for (bit = 8; bit != 24; bit++)
2055 + if (vdd == (1 << bit))
2056 + mv += 100 * (bit - 4);
2057 + regulator_set_voltage(regulator, mv * 1000, mv * 10000);
2058 + break;
2059 + case MMC_POWER_UP:
2060 + regulator_enable(regulator);
2061 + break;
2062 + }
2063 + break;
2064 + case GTA01v4_SYSTEM_REV:
2065 + case GTA01Bv2_SYSTEM_REV:
2066 + case GTA01Bv3_SYSTEM_REV:
2067 + case GTA01Bv4_SYSTEM_REV:
2068 + switch (power_mode) {
2069 + case MMC_POWER_OFF:
2070 + neo1973_gpb_setpin(GTA01_GPIO_SDMMC_ON, 1);
2071 + break;
2072 + case MMC_POWER_ON:
2073 + neo1973_gpb_setpin(GTA01_GPIO_SDMMC_ON, 0);
2074 + break;
2075 + }
2076 + break;
2077 + }
2078 +
2079 + if (regulator)
2080 + regulator_put(regulator);
2081 +}
2082 +
2083 +static struct s3c24xx_mci_pdata gta01_mmc_cfg = {
2084 + .gpio_detect = GTA01_GPIO_nSD_DETECT,
2085 + .set_power = &gta01_mmc_set_power,
2086 + .ocr_avail = MMC_VDD_165_195|MMC_VDD_20_21|
2087 + MMC_VDD_21_22|MMC_VDD_22_23|MMC_VDD_23_24|
2088 + MMC_VDD_24_25|MMC_VDD_25_26|MMC_VDD_26_27|
2089 + MMC_VDD_27_28|MMC_VDD_28_29|MMC_VDD_29_30|
2090 + MMC_VDD_30_31|MMC_VDD_31_32|MMC_VDD_32_33,
2091 +};
2092 +
2093 +static void gta01_udc_command(enum s3c2410_udc_cmd_e cmd)
2094 +{
2095 + printk(KERN_DEBUG "%s(%d)\n", __func__, cmd);
2096 +
2097 + switch (cmd) {
2098 + case S3C2410_UDC_P_ENABLE:
2099 + neo1973_gpb_setpin(GTA01_GPIO_USB_PULLUP, 1);
2100 + break;
2101 + case S3C2410_UDC_P_DISABLE:
2102 + neo1973_gpb_setpin(GTA01_GPIO_USB_PULLUP, 0);
2103 + break;
2104 + default:
2105 + break;
2106 + }
2107 +}
2108 +
2109 +/* use a work queue, since I2C API inherently schedules
2110 + * and we get called in hardirq context from UDC driver */
2111 +
2112 +struct vbus_draw {
2113 + struct work_struct work;
2114 + int ma;
2115 +};
2116 +static struct vbus_draw gta01_udc_vbus_drawer;
2117 +
2118 +static void __gta01_udc_vbus_draw(struct work_struct *work)
2119 +{
2120 + /*
2121 + * This is a fix to work around boot-time ordering problems if the
2122 + * s3c2410_udc is initialized before the pcf50606 driver has defined
2123 + * pcf50606_global
2124 + */
2125 + if (!gta01_pcf)
2126 + return;
2127 +
2128 + if (gta01_udc_vbus_drawer.ma >= 500) {
2129 + /* enable fast charge */
2130 + printk(KERN_DEBUG "udc: enabling fast charge\n");
2131 + pcf50606_charge_fast(gta01_pcf, 1);
2132 + } else {
2133 + /* disable fast charge */
2134 + printk(KERN_DEBUG "udc: disabling fast charge\n");
2135 + pcf50606_charge_fast(gta01_pcf, 0);
2136 + }
2137 +}
2138 +
2139 +static void gta01_udc_vbus_draw(unsigned int ma)
2140 +{
2141 + gta01_udc_vbus_drawer.ma = ma;
2142 + schedule_work(&gta01_udc_vbus_drawer.work);
2143 +}
2144 +
2145 +static struct s3c2410_udc_mach_info gta01_udc_cfg = {
2146 + .vbus_draw = gta01_udc_vbus_draw,
2147 +};
2148 +
2149 +/* Touchscreen configuration. */
2150 +
2151 +#ifdef CONFIG_TOUCHSCREEN_FILTER
2152 +const static struct ts_filter_group_configuration gta01_ts_group = {
2153 + .length = 12,
2154 + .close_enough = 10,
2155 + .threshold = 6, /* At least half of the points in a group. */
2156 + .attempts = 10,
2157 +};
2158 +
2159 +const static struct ts_filter_median_configuration gta01_ts_median = {
2160 + .extent = 20,
2161 + .decimation_below = 3,
2162 + .decimation_threshold = 8 * 3,
2163 + .decimation_above = 4,
2164 +};
2165 +
2166 +const static struct ts_filter_mean_configuration gta01_ts_mean = {
2167 + .length = 4,
2168 +};
2169 +
2170 +const static struct ts_filter_linear_configuration gta01_ts_linear = {
2171 + .constants = {1, 0, 0, 0, 1, 0, 1}, /* Don't modify coords. */
2172 + .coord0 = 0,
2173 + .coord1 = 1,
2174 +};
2175 +#endif
2176 +
2177 +const static struct ts_filter_chain_configuration gta01_filter_configuration[] =
2178 +{
2179 +#ifdef CONFIG_TOUCHSCREEN_FILTER
2180 + {&ts_filter_group_api, &gta01_ts_group.config},
2181 + {&ts_filter_median_api, &gta01_ts_median.config},
2182 + {&ts_filter_mean_api, &gta01_ts_mean.config},
2183 + {&ts_filter_linear_api, &gta01_ts_linear.config},
2184 +#endif
2185 + {NULL, NULL},
2186 +};
2187 +
2188 +const static struct s3c2410_ts_mach_info gta01_ts_cfg = {
2189 + .delay = 10000,
2190 + .presc = 0xff, /* slow as we can go */
2191 + .filter_config = gta01_filter_configuration,
2192 +};
2193 +
2194 +/* SPI */
2195 +
2196 +static void gta01_jbt6k74_reset(int devidx, int level)
2197 +{
2198 + /* empty place holder; gta01 does not yet use this */
2199 + printk(KERN_DEBUG "gta01_jbt6k74_reset\n");
2200 +}
2201 +
2202 +static void gta01_jbt6k74_resuming(int devidx)
2203 +{
2204 + gta01bl_deferred_resume();
2205 +}
2206 +
2207 +const struct jbt6k74_platform_data gta01_jbt6k74_pdata = {
2208 + .reset = gta01_jbt6k74_reset,
2209 + .resuming = gta01_jbt6k74_resuming,
2210 +};
2211 +
2212 +static struct spi_board_info gta01_spi_board_info[] = {
2213 + {
2214 + .modalias = "jbt6k74",
2215 + .platform_data = &gta01_jbt6k74_pdata,
2216 + /* controller_data */
2217 + /* irq */
2218 + .max_speed_hz = 10 * 1000 * 1000,
2219 + .bus_num = 1,
2220 + /* chip_select */
2221 + },
2222 +};
2223 +
2224 +static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int csidx, int cs)
2225 +{
2226 + switch (cs) {
2227 + case BITBANG_CS_ACTIVE:
2228 + s3c2410_gpio_setpin(S3C2410_GPG3, 0);
2229 + break;
2230 + case BITBANG_CS_INACTIVE:
2231 + s3c2410_gpio_setpin(S3C2410_GPG3, 1);
2232 + break;
2233 + }
2234 +}
2235 +
2236 +static struct s3c2410_spigpio_info spi_gpio_cfg = {
2237 + .pin_clk = S3C2410_GPG7,
2238 + .pin_mosi = S3C2410_GPG6,
2239 + .pin_miso = S3C2410_GPG5,
2240 + .chip_select = &spi_gpio_cs,
2241 + .num_chipselect = 2, /*** Should be 1 or 2 for gta01? ***/
2242 +};
2243 +
2244 +static struct resource s3c_spi_lcm_resource[] = {
2245 + [0] = {
2246 + .start = S3C2410_GPG3,
2247 + .end = S3C2410_GPG3,
2248 + },
2249 + [1] = {
2250 + .start = S3C2410_GPG5,
2251 + .end = S3C2410_GPG5,
2252 + },
2253 + [2] = {
2254 + .start = S3C2410_GPG6,
2255 + .end = S3C2410_GPG6,
2256 + },
2257 + [3] = {
2258 + .start = S3C2410_GPG7,
2259 + .end = S3C2410_GPG7,
2260 + },
2261 +};
2262 +
2263 +struct platform_device s3c_device_spi_lcm = {
2264 + .name = "spi_s3c24xx_gpio",
2265 + .id = 1,
2266 + .num_resources = ARRAY_SIZE(s3c_spi_lcm_resource),
2267 + .resource = s3c_spi_lcm_resource,
2268 + .dev = {
2269 + .platform_data = &spi_gpio_cfg,
2270 + },
2271 +};
2272 +
2273 +static struct gta01bl_machinfo backlight_machinfo = {
2274 + .default_intensity = 1,
2275 + .max_intensity = 1,
2276 + .limit_mask = 1,
2277 + .defer_resume_backlight = 1,
2278 +};
2279 +
2280 +static struct resource gta01_bl_resources[] = {
2281 + [0] = {
2282 + .start = GTA01_GPIO_BACKLIGHT,
2283 + .end = GTA01_GPIO_BACKLIGHT,
2284 + },
2285 +};
2286 +
2287 +struct platform_device gta01_bl_dev = {
2288 + .name = "gta01-bl",
2289 + .num_resources = ARRAY_SIZE(gta01_bl_resources),
2290 + .resource = gta01_bl_resources,
2291 + .dev = {
2292 + .platform_data = &backlight_machinfo,
2293 + },
2294 +};
2295 +
2296 +static struct resource gta01_led_resources[] = {
2297 + [0] = {
2298 + .start = GTA01_GPIO_VIBRATOR_ON,
2299 + .end = GTA01_GPIO_VIBRATOR_ON,
2300 + },
2301 +};
2302 +
2303 +struct platform_device gta01_led_dev = {
2304 + .name = "neo1973-vibrator",
2305 + .num_resources = ARRAY_SIZE(gta01_led_resources),
2306 + .resource = gta01_led_resources,
2307 +};
2308 +
2309 +static struct resource gta01_button_resources[] = {
2310 + [0] = {
2311 + .start = GTA01_GPIO_AUX_KEY,
2312 + .end = GTA01_GPIO_AUX_KEY,
2313 + },
2314 + [1] = {
2315 + .start = GTA01_GPIO_HOLD_KEY,
2316 + .end = GTA01_GPIO_HOLD_KEY,
2317 + },
2318 + [2] = {
2319 + .start = GTA01_GPIO_JACK_INSERT,
2320 + .end = GTA01_GPIO_JACK_INSERT,
2321 + },
2322 +};
2323 +
2324 +struct platform_device gta01_button_dev = {
2325 + .name = "neo1973-button",
2326 + .num_resources = ARRAY_SIZE(gta01_button_resources),
2327 + .resource = gta01_button_resources,
2328 +};
2329 +
2330 +/* USB */
2331 +static struct s3c2410_hcd_info gta01_usb_info = {
2332 + .port[0] = {
2333 + .flags = S3C_HCDFLG_USED,
2334 + },
2335 + .port[1] = {
2336 + .flags = 0,
2337 + },
2338 +};
2339 +
2340 +static void __init gta01_map_io(void)
2341 +{
2342 + s3c24xx_init_io(gta01_iodesc, ARRAY_SIZE(gta01_iodesc));
2343 + s3c24xx_init_clocks(12*1000*1000);
2344 + s3c24xx_init_uarts(gta01_uartcfgs, ARRAY_SIZE(gta01_uartcfgs));
2345 +}
2346 +
2347 +static irqreturn_t gta01_modem_irq(int irq, void *param)
2348 +{
2349 + printk(KERN_DEBUG "GSM wakeup interrupt (IRQ %d)\n", irq);
2350 + gta_gsm_interrupts++;
2351 + return IRQ_HANDLED;
2352 +}
2353 +
2354 +static struct i2c_board_info gta01_i2c_devs[] __initdata = {
2355 + {
2356 + I2C_BOARD_INFO("pcf50606", 0x08),
2357 + .irq = GTA01_IRQ_PCF50606,
2358 + .platform_data = &gta01_pcf_pdata,
2359 + },
2360 + {
2361 + I2C_BOARD_INFO("lm4857", 0x7c),
2362 + },
2363 + {
2364 + I2C_BOARD_INFO("wm8753", 0x1a),
2365 + },
2366 +};
2367 +
2368 +static void __init gta01_machine_init(void)
2369 +{
2370 + int rc;
2371 +
2372 + if (S3C_SYSTEM_REV_ATAG == GTA01v4_SYSTEM_REV ||
2373 + S3C_SYSTEM_REV_ATAG == GTA01Bv2_SYSTEM_REV ||
2374 + S3C_SYSTEM_REV_ATAG == GTA01Bv3_SYSTEM_REV ||
2375 + S3C_SYSTEM_REV_ATAG == GTA01Bv4_SYSTEM_REV) {
2376 + gta01_udc_cfg.udc_command = gta01_udc_command;
2377 + gta01_mmc_cfg.ocr_avail = MMC_VDD_32_33;
2378 + }
2379 +
2380 + s3c_device_usb.dev.platform_data = &gta01_usb_info;
2381 + s3c_device_nand.dev.platform_data = &gta01_nand_info;
2382 + s3c_device_sdi.dev.platform_data = &gta01_mmc_cfg;
2383 +
2384 + s3c24xx_fb_set_platdata(&gta01_lcd_cfg);
2385 +
2386 + INIT_WORK(&gta01_udc_vbus_drawer.work, __gta01_udc_vbus_draw);
2387 + s3c24xx_udc_set_platdata(&gta01_udc_cfg);
2388 + s3c_i2c0_set_platdata(NULL);
2389 + set_s3c2410ts_info(&gta01_ts_cfg);
2390 +
2391 + /* Set LCD_RESET / XRES to high */
2392 + s3c2410_gpio_cfgpin(S3C2410_GPC6, S3C2410_GPIO_OUTPUT);
2393 + s3c2410_gpio_setpin(S3C2410_GPC6, 1);
2394 +
2395 + /* SPI chip select is gpio output */
2396 + s3c2410_gpio_cfgpin(S3C2410_GPG3, S3C2410_GPIO_OUTPUT);
2397 + s3c2410_gpio_setpin(S3C2410_GPG3, 1);
2398 + platform_device_register(&s3c_device_spi_lcm);
2399 +
2400 + platform_device_register(&gta01_bl_dev);
2401 + platform_device_register(&gta01_button_dev);
2402 + platform_device_register(&gta01_pm_gsm_dev);
2403 +
2404 + switch (S3C_SYSTEM_REV_ATAG) {
2405 + case GTA01v3_SYSTEM_REV:
2406 + case GTA01v4_SYSTEM_REV:
2407 + /* just use the default (GTA01_IRQ_PCF50606) */
2408 + break;
2409 + case GTA01Bv2_SYSTEM_REV:
2410 + case GTA01Bv3_SYSTEM_REV:
2411 + /* just use the default (GTA01_IRQ_PCF50606) */
2412 + gta01_led_resources[0].start =
2413 + gta01_led_resources[0].end = GTA01Bv2_GPIO_VIBRATOR_ON;
2414 + break;
2415 + case GTA01Bv4_SYSTEM_REV:
2416 + gta01_i2c_devs[0].irq = GTA01Bv4_IRQ_PCF50606;
2417 + gta01_led_resources[0].start =
2418 + gta01_led_resources[0].end = GTA01Bv4_GPIO_VIBRATOR_ON;
2419 + break;
2420 + }
2421 + mangle_pmu_pdata_by_system_rev();
2422 + i2c_register_board_info(0, gta01_i2c_devs, ARRAY_SIZE(gta01_i2c_devs));
2423 + spi_register_board_info(gta01_spi_board_info, ARRAY_SIZE(gta01_spi_board_info));
2424 +
2425 + platform_device_register(&gta01_led_dev);
2426 +
2427 + platform_add_devices(gta01_devices, ARRAY_SIZE(gta01_devices));
2428 +
2429 + s3c_pm_init();
2430 +
2431 + set_irq_type(GTA01_IRQ_MODEM, IRQ_TYPE_EDGE_RISING);
2432 + rc = request_irq(GTA01_IRQ_MODEM, gta01_modem_irq, IRQF_DISABLED,
2433 + "modem", NULL);
2434 + enable_irq_wake(GTA01_IRQ_MODEM);
2435 + printk(KERN_DEBUG "Enabled GSM wakeup IRQ %d (rc=%d)\n",
2436 + GTA01_IRQ_MODEM, rc);
2437 +
2438 + pm_power_off = &gta01_power_off;
2439 +}
2440 +
2441 +MACHINE_START(NEO1973_GTA01, "GTA01")
2442 + .phys_io = S3C2410_PA_UART,
2443 + .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
2444 + .boot_params = S3C2410_SDRAM_PA + 0x100,
2445 + .map_io = gta01_map_io,
2446 + .init_irq = s3c24xx_init_irq,
2447 + .init_machine = gta01_machine_init,
2448 + .timer = &s3c24xx_timer,
2449 +MACHINE_END
2450 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/mach-h1940.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/mach-h1940.c
2451 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/mach-h1940.c 2009-05-10 22:05:04.000000000 +0200
2452 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/mach-h1940.c 2009-05-10 22:27:59.000000000 +0200
2453 @@ -131,6 +131,11 @@
2454 .vbus_pin_inverted = 1,
2455 };
2456
2457 +static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
2458 + .delay = 10000,
2459 + .presc = 49,
2460 + .oversampling_shift = 2,
2461 +};
2462
2463 /**
2464 * Set lcd on or off
2465 @@ -188,6 +193,7 @@
2466 &s3c_device_i2c0,
2467 &s3c_device_iis,
2468 &s3c_device_usbgadget,
2469 + &s3c_device_ts,
2470 &s3c_device_leds,
2471 &s3c_device_bluetooth,
2472 };
2473 @@ -203,7 +209,7 @@
2474 #ifdef CONFIG_PM_H1940
2475 memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
2476 #endif
2477 - s3c2410_pm_init();
2478 + s3c_pm_init();
2479 }
2480
2481 static void __init h1940_init_irq(void)
2482 @@ -216,6 +222,7 @@
2483 u32 tmp;
2484
2485 s3c24xx_fb_set_platdata(&h1940_fb_info);
2486 + set_s3c2410ts_info(&h1940_ts_cfg);
2487 s3c24xx_udc_set_platdata(&h1940_udc_cfg);
2488 s3c_i2c0_set_platdata(NULL);
2489
2490 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/mach-qt2410.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/mach-qt2410.c
2491 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/mach-qt2410.c 2009-05-10 22:05:04.000000000 +0200
2492 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/mach-qt2410.c 2009-05-10 22:27:59.000000000 +0200
2493 @@ -1,6 +1,6 @@
2494 /* linux/arch/arm/mach-s3c2410/mach-qt2410.c
2495 *
2496 - * Copyright (C) 2006 by OpenMoko, Inc.
2497 + * Copyright (C) 2006 by Openmoko, Inc.
2498 * Author: Harald Welte <laforge@openmoko.org>
2499 * All rights reserved.
2500 *
2501 @@ -214,7 +214,7 @@
2502
2503 /* SPI */
2504
2505 -static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int cs)
2506 +static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int csidx, int cs)
2507 {
2508 switch (cs) {
2509 case BITBANG_CS_ACTIVE:
2510 @@ -321,6 +321,24 @@
2511
2512 __setup("tft=", qt2410_tft_setup);
2513
2514 +static struct resource qt2410_button_resources[] = {
2515 + [0] = {
2516 + .start = S3C2410_GPF0,
2517 + .end = S3C2410_GPF0,
2518 + },
2519 + [1] = {
2520 + .start = S3C2410_GPF2,
2521 + .end = S3C2410_GPF2,
2522 + },
2523 +};
2524 +
2525 +struct platform_device qt2410_button_dev = {
2526 + .name ="qt2410-button",
2527 + .num_resources = ARRAY_SIZE(qt2410_button_resources),
2528 + .resource = qt2410_button_resources,
2529 +};
2530 +
2531 +
2532 static void __init qt2410_map_io(void)
2533 {
2534 s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
2535 @@ -355,7 +373,7 @@
2536 s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
2537
2538 platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
2539 - s3c2410_pm_init();
2540 + s3c_pm_init();
2541 }
2542
2543 MACHINE_START(QT2410, "QT2410")
2544 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/Makefile linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/Makefile
2545 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/Makefile 2009-05-10 22:05:04.000000000 +0200
2546 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/Makefile 2009-05-10 22:27:59.000000000 +0200
2547 @@ -15,6 +15,7 @@
2548 obj-$(CONFIG_CPU_S3C2410_DMA) += dma.o
2549 obj-$(CONFIG_S3C2410_PM) += pm.o sleep.o
2550 obj-$(CONFIG_S3C2410_GPIO) += gpio.o
2551 +#obj-$(CONFIG_S3C2410_CLOCK) += clock.o
2552
2553 # Machine support
2554
2555 @@ -37,3 +38,5 @@
2556 # machine additions
2557
2558 obj-$(CONFIG_MACH_BAST_IDE) += bast-ide.o
2559 +obj-$(CONFIG_MACH_NEO1973_GTA01)+= mach-gta01.o
2560 +
2561 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/pm.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/pm.c
2562 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2410/pm.c 2009-05-10 22:05:04.000000000 +0200
2563 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2410/pm.c 2009-05-10 22:27:59.000000000 +0200
2564 @@ -37,21 +37,14 @@
2565 #include <plat/cpu.h>
2566 #include <plat/pm.h>
2567
2568 -#ifdef CONFIG_S3C2410_PM_DEBUG
2569 -extern void pm_dbg(const char *fmt, ...);
2570 -#define DBG(fmt...) pm_dbg(fmt)
2571 -#else
2572 -#define DBG(fmt...) printk(KERN_DEBUG fmt)
2573 -#endif
2574 -
2575 static void s3c2410_pm_prepare(void)
2576 {
2577 /* ensure at least GSTATUS3 has the resume address */
2578
2579 - __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
2580 + __raw_writel(virt_to_phys(s3c_cpu_resume), S3C2410_GSTATUS3);
2581
2582 - DBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
2583 - DBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
2584 + S3C_PMDBG("GSTATUS3 0x%08x\n", __raw_readl(S3C2410_GSTATUS3));
2585 + S3C_PMDBG("GSTATUS4 0x%08x\n", __raw_readl(S3C2410_GSTATUS4));
2586
2587 if (machine_is_h1940()) {
2588 void *base = phys_to_virt(H1940_SUSPEND_CHECK);
2589 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/dma.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/dma.c
2590 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/dma.c 2009-05-10 22:05:04.000000000 +0200
2591 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/dma.c 2009-05-10 22:27:59.000000000 +0200
2592 @@ -20,17 +20,18 @@
2593
2594 #include <mach/dma.h>
2595
2596 -#include <plat/dma.h>
2597 +#include <plat/dma-plat.h>
2598 #include <plat/cpu.h>
2599
2600 #include <plat/regs-serial.h>
2601 #include <mach/regs-gpio.h>
2602 #include <plat/regs-ac97.h>
2603 +#include <plat/regs-dma.h>
2604 #include <mach/regs-mem.h>
2605 #include <mach/regs-lcd.h>
2606 #include <mach/regs-sdi.h>
2607 -#include <asm/plat-s3c24xx/regs-s3c2412-iis.h>
2608 -#include <asm/plat-s3c24xx/regs-iis.h>
2609 +#include <plat/regs-s3c2412-iis.h>
2610 +#include <plat/regs-iis.h>
2611 #include <plat/regs-spi.h>
2612
2613 #define MAP(x) { (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID, (x)| DMA_CH_VALID }
2614 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/Kconfig linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/Kconfig
2615 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/Kconfig 2009-05-10 22:05:04.000000000 +0200
2616 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/Kconfig 2009-05-10 22:27:59.000000000 +0200
2617 @@ -38,6 +38,7 @@
2618 config MACH_JIVE
2619 bool "Logitech Jive"
2620 select CPU_S3C2412
2621 + select S3C_DEV_USB_HOST
2622 help
2623 Say Y here if you are using the Logitech Jive.
2624
2625 @@ -50,6 +51,7 @@
2626 select CPU_S3C2412
2627 select MACH_S3C2413
2628 select MACH_SMDK
2629 + select S3C_DEV_USB_HOST
2630 help
2631 Say Y here if you are using an SMDK2413
2632
2633 @@ -72,6 +74,7 @@
2634 config MACH_VSTMS
2635 bool "VMSTMS"
2636 select CPU_S3C2412
2637 + select S3C_DEV_USB_HOST
2638 help
2639 Say Y here if you are using an VSTMS board
2640
2641 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/mach-jive.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/mach-jive.c
2642 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/mach-jive.c 2009-05-10 22:05:04.000000000 +0200
2643 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/mach-jive.c 2009-05-10 22:27:59.000000000 +0200
2644 @@ -494,7 +494,7 @@
2645 * correct address to resume from. */
2646
2647 __raw_writel(0x2BED, S3C2412_INFORM0);
2648 - __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2412_INFORM1);
2649 + __raw_writel(virt_to_phys(s3c_cpu_resume), S3C2412_INFORM1);
2650
2651 return 0;
2652 }
2653 @@ -630,7 +630,7 @@
2654
2655 /* initialise the power management now we've setup everything. */
2656
2657 - s3c2410_pm_init();
2658 + s3c_pm_init();
2659
2660 s3c_device_nand.dev.platform_data = &jive_nand_info;
2661
2662 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/pm.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/pm.c
2663 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/pm.c 2009-05-10 22:05:04.000000000 +0200
2664 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/pm.c 2009-05-10 22:27:59.000000000 +0200
2665 @@ -85,7 +85,7 @@
2666
2667 static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state)
2668 {
2669 - s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
2670 + s3c_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
2671 return 0;
2672 }
2673
2674 @@ -98,7 +98,7 @@
2675 tmp |= S3C2412_PWRCFG_STANDBYWFI_IDLE;
2676 __raw_writel(tmp, S3C2412_PWRCFG);
2677
2678 - s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
2679 + s3c_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
2680 return 0;
2681 }
2682
2683 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/s3c2412.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/s3c2412.c
2684 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2412/s3c2412.c 2009-05-10 22:05:04.000000000 +0200
2685 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2412/s3c2412.c 2009-05-10 22:27:59.000000000 +0200
2686 @@ -231,5 +231,8 @@
2687 {
2688 printk("S3C2412: Initialising architecture\n");
2689
2690 + /* make sure SD/MMC driver can distinguish 2412 from 2410 */
2691 + s3c_device_sdi.name = "s3c2412-sdi";
2692 +
2693 return sysdev_register(&s3c2412_sysdev);
2694 }
2695 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/dma.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/dma.c
2696 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/dma.c 2009-05-10 22:05:04.000000000 +0200
2697 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/dma.c 2009-05-10 22:27:59.000000000 +0200
2698 @@ -17,18 +17,20 @@
2699 #include <linux/sysdev.h>
2700 #include <linux/serial_core.h>
2701
2702 +#include <mach/map.h>
2703 #include <mach/dma.h>
2704
2705 -#include <plat/dma.h>
2706 +#include <plat/dma-plat.h>
2707 #include <plat/cpu.h>
2708
2709 #include <plat/regs-serial.h>
2710 #include <mach/regs-gpio.h>
2711 #include <plat/regs-ac97.h>
2712 +#include <plat/regs-dma.h>
2713 #include <mach/regs-mem.h>
2714 #include <mach/regs-lcd.h>
2715 #include <mach/regs-sdi.h>
2716 -#include <asm/plat-s3c24xx/regs-iis.h>
2717 +#include <plat/regs-iis.h>
2718 #include <plat/regs-spi.h>
2719
2720 static struct s3c24xx_dma_map __initdata s3c2440_dma_mappings[] = {
2721 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/Kconfig linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/Kconfig
2722 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/Kconfig 2009-05-10 22:05:04.000000000 +0200
2723 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/Kconfig 2009-05-10 22:27:59.000000000 +0200
2724 @@ -23,7 +23,6 @@
2725 help
2726 Support for S3C2440 specific DMA code5A
2727
2728 -
2729 menu "S3C2440 Machines"
2730
2731 config MACH_ANUBIS
2732 @@ -33,6 +32,7 @@
2733 select PM_SIMTEC if PM
2734 select HAVE_PATA_PLATFORM
2735 select S3C24XX_GPIO_EXTRA64
2736 + select S3C_DEV_USB_HOST
2737 help
2738 Say Y here if you are using the Simtec Electronics ANUBIS
2739 development system
2740 @@ -43,6 +43,7 @@
2741 select S3C24XX_DCLK
2742 select PM_SIMTEC if PM
2743 select S3C24XX_GPIO_EXTRA128
2744 + select S3C_DEV_USB_HOST
2745 help
2746 Say Y here if you are using the Simtec IM2440D20 module, also
2747 known as the Osiris.
2748 @@ -58,12 +59,14 @@
2749 bool "SMDK2440"
2750 select CPU_S3C2440
2751 select MACH_SMDK
2752 + select S3C_DEV_USB_HOST
2753 help
2754 Say Y here if you are using the SMDK2440.
2755
2756 config MACH_NEXCODER_2440
2757 bool "NexVision NEXCODER 2440 Light Board"
2758 select CPU_S3C2440
2759 + select S3C_DEV_USB_HOST
2760 help
2761 Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
2762
2763 @@ -76,8 +79,17 @@
2764 config MACH_AT2440EVB
2765 bool "Avantech AT2440EVB development board"
2766 select CPU_S3C2440
2767 + select S3C_DEV_USB_HOST
2768 help
2769 Say Y here if you are using the AT2440EVB development board
2770
2771 +config NEO1973_GTA02_2440
2772 + bool "Old FIC Neo1973 GTA02 hardware using S3C2440 CPU"
2773 + depends on MACH_NEO1973_GTA02
2774 + select CPU_S3C2440
2775 + help
2776 + Say Y here if you are using an early hardware revision
2777 + of the FIC/Openmoko Neo1973 GTA02 GSM Phone.
2778 +
2779 endmenu
2780
2781 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/mach-rx3715.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/mach-rx3715.c
2782 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/mach-rx3715.c 2009-05-10 22:05:04.000000000 +0200
2783 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/mach-rx3715.c 2009-05-10 22:27:59.000000000 +0200
2784 @@ -203,7 +203,7 @@
2785 #ifdef CONFIG_PM_H1940
2786 memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
2787 #endif
2788 - s3c2410_pm_init();
2789 + s3c_pm_init();
2790
2791 s3c24xx_fb_set_platdata(&rx3715_fb_info);
2792 platform_add_devices(rx3715_devices, ARRAY_SIZE(rx3715_devices));
2793 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/Makefile linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/Makefile
2794 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/Makefile 2009-05-10 22:05:04.000000000 +0200
2795 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/Makefile 2009-05-10 22:27:59.000000000 +0200
2796 @@ -22,3 +22,5 @@
2797 obj-$(CONFIG_ARCH_S3C2440) += mach-smdk2440.o
2798 obj-$(CONFIG_MACH_NEXCODER_2440) += mach-nexcoder.o
2799 obj-$(CONFIG_MACH_AT2440EVB) += mach-at2440evb.o
2800 +obj-$(CONFIG_MACH_HXD8) += mach-hxd8.o
2801 +
2802 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/s3c2440.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/s3c2440.c
2803 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2440/s3c2440.c 2009-05-10 22:05:04.000000000 +0200
2804 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2440/s3c2440.c 2009-05-10 22:27:59.000000000 +0200
2805 @@ -46,6 +46,9 @@
2806 s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
2807 s3c_device_wdt.resource[1].end = IRQ_S3C2440_WDT;
2808
2809 + /* make sure SD/MMC driver can distinguish 2440 from 2410 */
2810 + s3c_device_sdi.name = "s3c2440-sdi";
2811 +
2812 /* register our system device for everything else */
2813
2814 return sysdev_register(&s3c2440_sysdev);
2815 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/include/mach/gta02.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/include/mach/gta02.h
2816 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/include/mach/gta02.h 1970-01-01 01:00:00.000000000 +0100
2817 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/include/mach/gta02.h 2009-05-10 22:27:59.000000000 +0200
2818 @@ -0,0 +1,85 @@
2819 +#ifndef _GTA02_H
2820 +#define _GTA02_H
2821 +
2822 +#include <mach/regs-gpio.h>
2823 +#include <mach/irqs.h>
2824 +
2825 +/* Different hardware revisions, passed in ATAG_REVISION by u-boot */
2826 +#define GTA02v1_SYSTEM_REV 0x00000310
2827 +#define GTA02v2_SYSTEM_REV 0x00000320
2828 +#define GTA02v3_SYSTEM_REV 0x00000330
2829 +#define GTA02v4_SYSTEM_REV 0x00000340
2830 +#define GTA02v5_SYSTEM_REV 0x00000350
2831 +#define GTA02v6_SYSTEM_REV 0x00000360
2832 +
2833 +#define GTA02_GPIO_n3DL_GSM S3C2410_GPA13 /* v1 + v2 + v3 only */
2834 +
2835 +#define GTA02_GPIO_PWR_LED1 S3C2410_GPB0
2836 +#define GTA02_GPIO_PWR_LED2 S3C2410_GPB1
2837 +#define GTA02_GPIO_AUX_LED S3C2410_GPB2
2838 +#define GTA02_GPIO_VIBRATOR_ON S3C2410_GPB3
2839 +#define GTA02_GPIO_MODEM_RST S3C2410_GPB5
2840 +#define GTA02_GPIO_BT_EN S3C2410_GPB6
2841 +#define GTA02_GPIO_MODEM_ON S3C2410_GPB7
2842 +#define GTA02_GPIO_EXTINT8 S3C2410_GPB8
2843 +#define GTA02_GPIO_USB_PULLUP S3C2410_GPB9
2844 +
2845 +#define GTA02_GPIO_PIO5 S3C2410_GPC5 /* v3 + v4 only */
2846 +#define GTA02v3_GPIO_nG1_CS S3C2410_GPD12 /* v3 + v4 only */
2847 +#define GTA02v3_GPIO_nG2_CS S3C2410_GPD13 /* v3 + v4 only */
2848 +#define GTA02v5_GPIO_HDQ S3C2410_GPD14 /* v5 + */
2849 +
2850 +#define GTA02_GPIO_nG1_INT S3C2410_GPF0
2851 +#define GTA02_GPIO_IO1 S3C2410_GPF1
2852 +#define GTA02_GPIO_PIO_2 S3C2410_GPF2 /* v2 + v3 + v4 only */
2853 +#define GTA02_GPIO_JACK_INSERT S3C2410_GPF4
2854 +#define GTA02_GPIO_WLAN_GPIO1 S3C2410_GPF5 /* v2 + v3 + v4 only */
2855 +#define GTA02_GPIO_AUX_KEY S3C2410_GPF6
2856 +#define GTA02_GPIO_HOLD_KEY S3C2410_GPF7
2857 +
2858 +#define GTA02_GPIO_3D_IRQ S3C2410_GPG4
2859 +#define GTA02v2_GPIO_nG2_INT S3C2410_GPG8 /* v2 + v3 + v4 only */
2860 +#define GTA02v3_GPIO_nUSB_OC S3C2410_GPG9 /* v3 + v4 only */
2861 +#define GTA02v3_GPIO_nUSB_FLT S3C2410_GPG10 /* v3 + v4 only */
2862 +#define GTA02v3_GPIO_nGSM_OC S3C2410_GPG11 /* v3 + v4 only */
2863 +
2864 +#define GTA02_GPIO_AMP_SHUT S3C2440_GPJ1 /* v2 + v3 + v4 only */
2865 +#define GTA02v1_GPIO_WLAN_GPIO10 S3C2440_GPJ2
2866 +#define GTA02_GPIO_HP_IN S3C2440_GPJ2 /* v2 + v3 + v4 only */
2867 +#define GTA02_GPIO_INT0 S3C2440_GPJ3 /* v2 + v3 + v4 only */
2868 +#define GTA02_GPIO_nGSM_EN S3C2440_GPJ4
2869 +#define GTA02_GPIO_3D_RESET S3C2440_GPJ5
2870 +#define GTA02_GPIO_nDL_GSM S3C2440_GPJ6 /* v4 + v5 only */
2871 +#define GTA02_GPIO_WLAN_GPIO0 S3C2440_GPJ7
2872 +#define GTA02v1_GPIO_BAT_ID S3C2440_GPJ8
2873 +#define GTA02_GPIO_KEEPACT S3C2440_GPJ8
2874 +#define GTA02v1_GPIO_HP_IN S3C2440_GPJ10
2875 +#define GTA02_CHIP_PWD S3C2440_GPJ11 /* v2 + v3 + v4 only */
2876 +#define GTA02_GPIO_nWLAN_RESET S3C2440_GPJ12 /* v2 + v3 + v4 only */
2877 +
2878 +#define GTA02_IRQ_GSENSOR_1 IRQ_EINT0
2879 +#define GTA02_IRQ_MODEM IRQ_EINT1
2880 +#define GTA02_IRQ_PIO_2 IRQ_EINT2 /* v2 + v3 + v4 only */
2881 +#define GTA02_IRQ_nJACK_INSERT IRQ_EINT4
2882 +#define GTA02_IRQ_WLAN_GPIO1 IRQ_EINT5
2883 +#define GTA02_IRQ_AUX IRQ_EINT6
2884 +#define GTA02_IRQ_nHOLD IRQ_EINT7
2885 +#define GTA02_IRQ_PCF50633 IRQ_EINT9
2886 +#define GTA02_IRQ_3D IRQ_EINT12
2887 +#define GTA02_IRQ_GSENSOR_2 IRQ_EINT16 /* v2 + v3 + v4 only */
2888 +#define GTA02v3_IRQ_nUSB_OC IRQ_EINT17 /* v3 + v4 only */
2889 +#define GTA02v3_IRQ_nUSB_FLT IRQ_EINT18 /* v3 + v4 only */
2890 +#define GTA02v3_IRQ_nGSM_OC IRQ_EINT19 /* v3 + v4 only */
2891 +
2892 +/* returns 00 000 on GTA02 A5 and earlier, A6 returns 01 001 */
2893 +#define GTA02_PCB_ID1_0 S3C2410_GPC13
2894 +#define GTA02_PCB_ID1_1 S3C2410_GPC15
2895 +#define GTA02_PCB_ID1_2 S3C2410_GPD0
2896 +#define GTA02_PCB_ID2_0 S3C2410_GPD3
2897 +#define GTA02_PCB_ID2_1 S3C2410_GPD4
2898 +
2899 +int gta02_get_pcb_revision(void);
2900 +
2901 +extern struct pcf50633 *gta02_pcf;
2902 +
2903 +#endif /* _GTA02_H */
2904 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/Kconfig linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/Kconfig
2905 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/Kconfig 2009-05-10 22:05:02.000000000 +0200
2906 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/Kconfig 2009-05-10 22:27:59.000000000 +0200
2907 @@ -11,6 +11,7 @@
2908 select S3C2410_CLOCK
2909 select S3C2410_GPIO
2910 select S3C2410_PM if PM
2911 + select S3C2440_DMA if S3C2410_DMA
2912 select CPU_S3C244X
2913 select CPU_LLSERIAL_S3C2440
2914 help
2915 @@ -24,6 +25,20 @@
2916 depends on ARCH_S3C2440
2917 select CPU_S3C2442
2918
2919 +config MACH_NEO1973_GTA02
2920 + bool "FIC Neo1973 GSM Phone (GTA02 Hardware)"
2921 + select CPU_S3C2442
2922 + select MFD_PCF50633
2923 + select PCF50633_GPIO
2924 + select I2C
2925 + select POWER_SUPPLY
2926 + select MACH_NEO1973
2927 + select S3C_PWM
2928 + select FIQ
2929 + select S3C_DEV_USB_HOST
2930 + help
2931 + Say Y here if you are using the FIC Neo1973 GSM Phone
2932 +
2933
2934 endmenu
2935
2936 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/mach-gta02.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/mach-gta02.c
2937 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/mach-gta02.c 1970-01-01 01:00:00.000000000 +0100
2938 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/mach-gta02.c 2009-05-10 22:27:59.000000000 +0200
2939 @@ -0,0 +1,1706 @@
2940 +/*
2941 + * linux/arch/arm/mach-s3c2440/mach-gta02.c
2942 + *
2943 + * S3C2440 Machine Support for the FIC GTA02 (Neo1973)
2944 + *
2945 + * Copyright (C) 2006-2007 by Openmoko, Inc.
2946 + * Author: Harald Welte <laforge@openmoko.org>
2947 + * All rights reserved.
2948 + *
2949 + * This program is free software; you can redistribute it and/or
2950 + * modify it under the terms of the GNU General Public License as
2951 + * published by the Free Software Foundation; either version 2 of
2952 + * the License, or (at your option) any later version.
2953 + *
2954 + * This program is distributed in the hope that it will be useful,
2955 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2956 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2957 + * GNU General Public License for more details.
2958 + *
2959 + * You should have received a copy of the GNU General Public License
2960 + * along with this program; if not, write to the Free Software
2961 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
2962 + * MA 02111-1307 USA
2963 + *
2964 + */
2965 +
2966 +#include <linux/kernel.h>
2967 +#include <linux/types.h>
2968 +#include <linux/interrupt.h>
2969 +#include <linux/list.h>
2970 +#include <linux/delay.h>
2971 +#include <linux/timer.h>
2972 +#include <linux/init.h>
2973 +#include <linux/workqueue.h>
2974 +#include <linux/platform_device.h>
2975 +#include <linux/serial_core.h>
2976 +#include <linux/spi/spi.h>
2977 +#include <linux/spi/glamo.h>
2978 +#include <linux/spi/spi_bitbang.h>
2979 +#include <linux/mmc/host.h>
2980 +
2981 +#include <linux/mtd/mtd.h>
2982 +#include <linux/mtd/nand.h>
2983 +#include <linux/mtd/nand_ecc.h>
2984 +#include <linux/mtd/partitions.h>
2985 +#include <linux/mtd/physmap.h>
2986 +
2987 +#include <linux/i2c.h>
2988 +#include <linux/backlight.h>
2989 +#include <linux/regulator/machine.h>
2990 +
2991 +#include <linux/mfd/pcf50633/core.h>
2992 +#include <linux/mfd/pcf50633/mbc.h>
2993 +#include <linux/mfd/pcf50633/adc.h>
2994 +#include <linux/mfd/pcf50633/gpio.h>
2995 +#include <linux/mfd/pcf50633/pmic.h>
2996 +
2997 +#include <linux/lis302dl.h>
2998 +
2999 +#include <asm/mach/arch.h>
3000 +#include <asm/mach/map.h>
3001 +#include <asm/mach/irq.h>
3002 +
3003 +#include <mach/hardware.h>
3004 +#include <mach/io.h>
3005 +#include <asm/irq.h>
3006 +#include <asm/mach-types.h>
3007 +
3008 +#include <mach/regs-irq.h>
3009 +#include <mach/regs-gpio.h>
3010 +#include <mach/regs-gpioj.h>
3011 +#include <mach/fb.h>
3012 +#include <mach/mci.h>
3013 +#include <mach/ts.h>
3014 +#include <mach/spi.h>
3015 +#include <mach/spi-gpio.h>
3016 +#include <mach/regs-mem.h>
3017 +#include <mach/spi-gpio.h>
3018 +#include <plat/pwm.h>
3019 +#include <mach/cpu.h>
3020 +
3021 +#include <mach/gta02.h>
3022 +
3023 +#include <plat/regs-serial.h>
3024 +#include <plat/nand.h>
3025 +#include <plat/devs.h>
3026 +#include <plat/cpu.h>
3027 +#include <plat/pm.h>
3028 +#include <plat/udc.h>
3029 +#include <plat/iic.h>
3030 +#include <plat/usb-control.h>
3031 +#include <asm/plat-s3c24xx/neo1973.h>
3032 +#include <mach/neo1973-pm-gsm.h>
3033 +#include <mach/gta02-pm-wlan.h>
3034 +#include <plat/regs-timer.h>
3035 +
3036 +#include <linux/jbt6k74.h>
3037 +
3038 +#include <linux/glamofb.h>
3039 +
3040 +#include <linux/hdq.h>
3041 +#include <linux/bq27000_battery.h>
3042 +
3043 +#include "../plat-s3c24xx/neo1973_pm_gps.h"
3044 +
3045 +#include <../drivers/input/touchscreen/ts_filter_chain.h>
3046 +#ifdef CONFIG_TOUCHSCREEN_FILTER
3047 +#include <../drivers/input/touchscreen/ts_filter_linear.h>
3048 +#include <../drivers/input/touchscreen/ts_filter_mean.h>
3049 +#include <../drivers/input/touchscreen/ts_filter_median.h>
3050 +#include <../drivers/input/touchscreen/ts_filter_group.h>
3051 +#endif
3052 +
3053 +#include <asm/fiq.h>
3054 +
3055 +#include <linux/neo1973_vibrator.h>
3056 +
3057 +/* arbitrates which sensor IRQ owns the shared SPI bus */
3058 +static spinlock_t motion_irq_lock;
3059 +
3060 +
3061 +/* -------------------------------------------------------------------------------
3062 + * GTA02 FIQ related
3063 + *
3064 + * Calls into vibrator and hdq and based on the return values
3065 + * determines if we the FIQ source be kept alive
3066 + */
3067 +
3068 +#define DIVISOR_FROM_US(x) ((x) << 3)
3069 +
3070 +#ifdef CONFIG_HDQ_GPIO_BITBANG
3071 +#define FIQ_DIVISOR_HDQ DIVISOR_FROM_US(HDQ_SAMPLE_PERIOD_US)
3072 +extern int hdq_fiq_handler(void);
3073 +#endif
3074 +
3075 +#ifdef CONFIG_LEDS_NEO1973_VIBRATOR
3076 +#define FIQ_DIVISOR_VIBRATOR DIVISOR_FROM_US(100)
3077 +extern int neo1973_vibrator_fiq_handler(void);
3078 +#endif
3079 +
3080 +/* Global data related to our fiq source */
3081 +static u32 gta02_fiq_ack_mask;
3082 +static struct s3c2410_pwm gta02_fiq_pwm_timer;
3083 +static u16 gta02_fiq_timer_index;
3084 +static int gta02_fiq_irq;
3085 +
3086 +static void gta02_fiq_handler(void)
3087 +{
3088 + u16 divisor = 0xffff;
3089 +
3090 + /* Vibrator servicing */
3091 +
3092 + /* disable further timer interrupts if nobody has any work
3093 + * or adjust rate according to who still has work
3094 + *
3095 + * CAUTION: it means forground code must disable FIQ around
3096 + * its own non-atomic S3C2410_INTMSK changes... not common
3097 + * thankfully and taken care of by the fiq-basis patch
3098 + */
3099 +
3100 +#ifdef CONFIG_LEDS_NEO1973_VIBRATOR
3101 + if (neo1973_vibrator_fiq_handler())
3102 + divisor = FIQ_DIVISOR_VIBRATOR;
3103 +#endif
3104 +
3105 +#ifdef CONFIG_HDQ_GPIO_BITBANG
3106 + if (hdq_fiq_handler())
3107 + divisor = FIQ_DIVISOR_HDQ;
3108 +#endif
3109 +
3110 + if (divisor == 0xffff) /* mask the fiq irq source */
3111 + __raw_writel(__raw_readl(S3C2410_INTMSK) | gta02_fiq_ack_mask,
3112 + S3C2410_INTMSK);
3113 + else /* still working, maybe at a different rate */
3114 + __raw_writel(divisor, S3C2410_TCNTB(gta02_fiq_timer_index));
3115 +
3116 + __raw_writel(gta02_fiq_ack_mask, S3C2410_SRCPND);
3117 +}
3118 +
3119 +static void gta02_fiq_kick(void)
3120 +{
3121 + unsigned long flags;
3122 + u32 tcon;
3123 +
3124 + /* we have to take care about FIQ because this modification is
3125 + * non-atomic, FIQ could come in after the read and before the
3126 + * writeback and its changes to the register would be lost
3127 + * (platform INTMSK mod code is taken care of already)
3128 + */
3129 + local_save_flags(flags);
3130 + local_fiq_disable();
3131 + /* allow FIQs to resume */
3132 + __raw_writel(__raw_readl(S3C2410_INTMSK) &
3133 + ~(1 << (gta02_fiq_irq - S3C2410_CPUIRQ_OFFSET)),
3134 + S3C2410_INTMSK);
3135 + tcon = __raw_readl(S3C2410_TCON) & ~S3C2410_TCON_T3START;
3136 + /* fake the timer to a count of 1 */
3137 + __raw_writel(1, S3C2410_TCNTB(gta02_fiq_timer_index));
3138 + __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD, S3C2410_TCON);
3139 + __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD | S3C2410_TCON_T3START,
3140 + S3C2410_TCON);
3141 + __raw_writel(tcon | S3C2410_TCON_T3START, S3C2410_TCON);
3142 + local_irq_restore(flags);
3143 +}
3144 +
3145 +static int gta02_fiq_enable(void)
3146 +{
3147 + int irq_index_fiq = IRQ_TIMER3;
3148 + int rc = 0;
3149 +
3150 + local_fiq_disable();
3151 +
3152 + gta02_fiq_irq = irq_index_fiq;
3153 + gta02_fiq_ack_mask = 1 << (irq_index_fiq - S3C2410_CPUIRQ_OFFSET);
3154 + gta02_fiq_timer_index = (irq_index_fiq - IRQ_TIMER0);
3155 +
3156 + /* set up the timer to operate as a pwm device */
3157 +
3158 + rc = s3c2410_pwm_init(&gta02_fiq_pwm_timer);
3159 + if (rc)
3160 + goto bail;
3161 +
3162 + gta02_fiq_pwm_timer.timerid = PWM0 + gta02_fiq_timer_index;
3163 + gta02_fiq_pwm_timer.prescaler = (6 - 1) / 2;
3164 + gta02_fiq_pwm_timer.divider = S3C2410_TCFG1_MUX3_DIV2;
3165 + /* default rate == ~32us */
3166 + gta02_fiq_pwm_timer.counter = gta02_fiq_pwm_timer.comparer = 3000;
3167 +
3168 + rc = s3c2410_pwm_enable(&gta02_fiq_pwm_timer);
3169 + if (rc)
3170 + goto bail;
3171 +
3172 + s3c2410_pwm_start(&gta02_fiq_pwm_timer);
3173 +
3174 + /* let our selected interrupt be a magic FIQ interrupt */
3175 + __raw_writel(gta02_fiq_ack_mask, S3C2410_INTMOD);
3176 +
3177 + /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */
3178 + local_fiq_enable();
3179 +
3180 + set_fiq_c_handler(gta02_fiq_handler);
3181 +
3182 + return 0;
3183 +
3184 +bail:
3185 + printk(KERN_ERR "Could not initialize FIQ for GTA02: %d\n", rc);
3186 +
3187 + return rc;
3188 +}
3189 +
3190 +static void gta02_fiq_disable(void)
3191 +{
3192 + __raw_writel(0, S3C2410_INTMOD);
3193 + local_fiq_disable();
3194 + gta02_fiq_irq = 0; /* no active source interrupt now either */
3195 +
3196 +}
3197 +/* -------------------- /GTA02 FIQ Handler ------------------------------------- */
3198 +
3199 +/*
3200 + * this gets called every 1ms when we paniced.
3201 + */
3202 +
3203 +static long gta02_panic_blink(long count)
3204 +{
3205 + long delay = 0;
3206 + static long last_blink;
3207 + static char led;
3208 +
3209 + if (count - last_blink < 100) /* 200ms period, fast blink */
3210 + return 0;
3211 +
3212 + led ^= 1;
3213 + s3c2410_gpio_cfgpin(GTA02_GPIO_AUX_LED, S3C2410_GPIO_OUTPUT);
3214 + neo1973_gpb_setpin(GTA02_GPIO_AUX_LED, led);
3215 +
3216 + last_blink = count;
3217 + return delay;
3218 +}
3219 +
3220 +
3221 +/**
3222 + * returns PCB revision information in b9,b8 and b2,b1,b0
3223 + * Pre-GTA02 A6 returns 0x000
3224 + * GTA02 A6 returns 0x101
3225 + * ...
3226 + */
3227 +
3228 +int gta02_get_pcb_revision(void)
3229 +{
3230 + int n;
3231 + int u = 0;
3232 + static unsigned long pinlist[] = {
3233 + GTA02_PCB_ID1_0,
3234 + GTA02_PCB_ID1_1,
3235 + GTA02_PCB_ID1_2,
3236 + GTA02_PCB_ID2_0,
3237 + GTA02_PCB_ID2_1,
3238 + };
3239 + static int pin_offset[] = {
3240 + 0, 1, 2, 8, 9
3241 + };
3242 +
3243 + for (n = 0 ; n < ARRAY_SIZE(pinlist); n++) {
3244 + /*
3245 + * set the PCB version GPIO to be pulled-down input
3246 + * force low briefly first
3247 + */
3248 + s3c2410_gpio_cfgpin(pinlist[n], S3C2410_GPIO_OUTPUT);
3249 + s3c2410_gpio_setpin(pinlist[n], 0);
3250 + /* misnomer: it is a pullDOWN in 2442 */
3251 + s3c2410_gpio_pullup(pinlist[n], 1);
3252 + s3c2410_gpio_cfgpin(pinlist[n], S3C2410_GPIO_INPUT);
3253 +
3254 + udelay(10);
3255 +
3256 + if (s3c2410_gpio_getpin(pinlist[n]))
3257 + u |= 1 << pin_offset[n];
3258 +
3259 + /*
3260 + * when not being interrogated, all of the revision GPIO
3261 + * are set to output HIGH without pulldown so no current flows
3262 + * if they are NC or pulled up.
3263 + */
3264 + s3c2410_gpio_setpin(pinlist[n], 1);
3265 + s3c2410_gpio_cfgpin(pinlist[n], S3C2410_GPIO_OUTPUT);
3266 + /* misnomer: it is a pullDOWN in 2442 */
3267 + s3c2410_gpio_pullup(pinlist[n], 0);
3268 + }
3269 +
3270 + return u;
3271 +}
3272 +
3273 +struct platform_device gta02_version_device = {
3274 + .name = "neo1973-version",
3275 + .num_resources = 0,
3276 +};
3277 +
3278 +struct platform_device gta02_resume_reason_device = {
3279 + .name = "neo1973-resume",
3280 + .num_resources = 0,
3281 +};
3282 +
3283 +struct platform_device gta02_memconfig_device = {
3284 + .name = "neo1973-memconfig",
3285 + .num_resources = 0,
3286 +};
3287 +
3288 +static struct map_desc gta02_iodesc[] __initdata = {
3289 + {
3290 + .virtual = 0xe0000000,
3291 + .pfn = __phys_to_pfn(S3C2410_CS3+0x01000000),
3292 + .length = SZ_1M,
3293 + .type = MT_DEVICE
3294 + },
3295 +};
3296 +
3297 +#define UCON (S3C2410_UCON_DEFAULT | S3C2443_UCON_RXERR_IRQEN)
3298 +#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
3299 +#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
3300 +
3301 +static struct s3c2410_uartcfg gta02_uartcfgs[] = {
3302 + [0] = {
3303 + .hwport = 0,
3304 + .flags = 0,
3305 + .ucon = UCON,
3306 + .ulcon = ULCON,
3307 + .ufcon = UFCON,
3308 + },
3309 + [1] = {
3310 + .hwport = 1,
3311 + .flags = 0,
3312 + .ucon = UCON,
3313 + .ulcon = ULCON,
3314 + .ufcon = UFCON,
3315 + },
3316 + [2] = {
3317 + .hwport = 2,
3318 + .flags = 0,
3319 + .ucon = UCON,
3320 + .ulcon = ULCON,
3321 + .ufcon = UFCON,
3322 + },
3323 +
3324 +};
3325 +
3326 +struct pcf50633 *gta02_pcf;
3327 +
3328 +#ifdef CONFIG_CHARGER_PCF50633
3329 +static int gta02_get_charger_online_status(void)
3330 +{
3331 + struct pcf50633 *pcf = gta02_pcf;
3332 +
3333 + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ONLINE;
3334 +}
3335 +
3336 +static int gta02_get_charger_active_status(void)
3337 +{
3338 + struct pcf50633 *pcf = gta02_pcf;
3339 +
3340 + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ACTIVE;
3341 +}
3342 +
3343 +#define ADC_NOM_CHG_DETECT_1A 6
3344 +#define ADC_NOM_CHG_DETECT_USB 43
3345 +
3346 +static void
3347 +gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res)
3348 +{
3349 + int ma;
3350 +
3351 + /* Interpret charger type */
3352 + if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) {
3353 +
3354 + /* Stop GPO driving out now that we have a IA charger */
3355 + pcf50633_gpio_set(pcf, PCF50633_GPO, 0);
3356 +
3357 + ma = 1000;
3358 + } else
3359 + ma = 100;
3360 +
3361 + pcf50633_mbc_usb_curlim_set(pcf, ma);
3362 +}
3363 +
3364 +static struct delayed_work gta02_charger_work;
3365 +static int gta02_usb_vbus_draw;
3366 +
3367 +static void gta02_charger_worker(struct work_struct *work)
3368 +{
3369 + struct pcf50633 *pcf = gta02_pcf;
3370 +
3371 + if (gta02_usb_vbus_draw) {
3372 + pcf50633_mbc_usb_curlim_set(pcf, gta02_usb_vbus_draw);
3373 + return;
3374 + } else {
3375 +#ifdef CONFIG_PCF50633_ADC
3376 + pcf50633_adc_async_read(pcf,
3377 + PCF50633_ADCC1_MUX_ADCIN1,
3378 + PCF50633_ADCC1_AVERAGE_16,
3379 + gta02_configure_pmu_for_charger, NULL);
3380 +#else
3381 + /* If the PCF50633 ADC is disabled we fallback to a 100mA limit for safety. */
3382 + pcf50633_mbc_usb_curlim_set(pcf, 100);
3383 +#endif
3384 + return;
3385 + }
3386 +}
3387 +
3388 +#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000)
3389 +static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq)
3390 +{
3391 + if (irq == PCF50633_IRQ_USBINS) {
3392 + schedule_delayed_work(&gta02_charger_work,
3393 + GTA02_CHARGER_CONFIGURE_TIMEOUT);
3394 + return;
3395 + } else if (irq == PCF50633_IRQ_USBREM) {
3396 + cancel_delayed_work_sync(&gta02_charger_work);
3397 + gta02_usb_vbus_draw = 0;
3398 + }
3399 +}
3400 +
3401 +static void gta02_pmu_force_shutdown(struct pcf50633 *pcf)
3402 +{
3403 + pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_OOCSHDWN,
3404 + PCF50633_OOCSHDWN_GOSTDBY, PCF50633_OOCSHDWN_GOSTDBY);
3405 +}
3406 +
3407 +
3408 +static void gta02_udc_vbus_draw(unsigned int ma)
3409 +{
3410 + if (!gta02_pcf)
3411 + return;
3412 +
3413 + gta02_usb_vbus_draw = ma;
3414 +
3415 + schedule_delayed_work(&gta02_charger_work,
3416 + GTA02_CHARGER_CONFIGURE_TIMEOUT);
3417 +}
3418 +#else /* !CONFIG_CHARGER_PCF50633 */
3419 +#define gta02_get_charger_online_status NULL
3420 +#define gta02_get_charger_active_status NULL
3421 +#define gta02_pmu_event_callback NULL
3422 +#define gta02_udc_vbus_draw NULL
3423 +#endif
3424 +
3425 +static struct platform_device gta01_pm_gps_dev = {
3426 + .name = "neo1973-pm-gps",
3427 +};
3428 +
3429 +static struct platform_device gta01_pm_bt_dev = {
3430 + .name = "neo1973-pm-bt",
3431 +};
3432 +
3433 +static struct platform_device gta02_pm_gsm_dev = {
3434 + .name = "neo1973-pm-gsm",
3435 +};
3436 +
3437 +/* this is called when pc50633 is probed, unfortunately quite late in the
3438 + * day since it is an I2C bus device. Here we can belatedly define some
3439 + * platform devices with the advantage that we can mark the pcf50633 as the
3440 + * parent. This makes them get suspended and resumed with their parent
3441 + * the pcf50633 still around.
3442 + */
3443 +
3444 +static struct platform_device gta02_glamo_dev;
3445 +static void mangle_glamo_res_by_system_rev(void);
3446 +
3447 +static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf);
3448 +static void gta02_pmu_regulator_registered(struct pcf50633 *pcf, int id);
3449 +
3450 +static struct platform_device gta02_pm_wlan_dev = {
3451 + .name = "gta02-pm-wlan",
3452 +};
3453 +
3454 +static struct regulator_consumer_supply ldo4_consumers[] = {
3455 + {
3456 + .dev = &gta01_pm_bt_dev.dev,
3457 + .supply = "BT_3V2",
3458 + },
3459 +};
3460 +
3461 +static struct regulator_consumer_supply ldo5_consumers[] = {
3462 + {
3463 + .dev = &gta01_pm_gps_dev.dev,
3464 + .supply = "RF_3V",
3465 + },
3466 +};
3467 +
3468 +/*
3469 + * We need this dummy thing to fill the regulator consumers
3470 + */
3471 +static struct platform_device gta02_mmc_dev = {
3472 + /* details filled in by glamo core */
3473 +};
3474 +
3475 +static struct regulator_consumer_supply hcldo_consumers[] = {
3476 + {
3477 + .dev = &gta02_mmc_dev.dev,
3478 + .supply = "SD_3V3",
3479 + },
3480 +};
3481 +
3482 +static char *gta02_batteries[] = {
3483 + "battery",
3484 +};
3485 +
3486 +struct pcf50633_platform_data gta02_pcf_pdata = {
3487 + .resumers = {
3488 + [0] = PCF50633_INT1_USBINS |
3489 + PCF50633_INT1_USBREM |
3490 + PCF50633_INT1_ALARM,
3491 + [1] = PCF50633_INT2_ONKEYF,
3492 + [2] = PCF50633_INT3_ONKEY1S,
3493 + [3] = PCF50633_INT4_LOWSYS |
3494 + PCF50633_INT4_LOWBAT |
3495 + PCF50633_INT4_HIGHTMP,
3496 + },
3497 +
3498 + .batteries = gta02_batteries,
3499 + .num_batteries = ARRAY_SIZE(gta02_batteries),
3500 + .charging_restart_interval = (900 * HZ),
3501 + .chg_ref_current_ma = 1000,
3502 +
3503 + .reg_init_data = {
3504 + [PCF50633_REGULATOR_AUTO] = {
3505 + .constraints = {
3506 + .name = "IO_3V3",
3507 + .min_uV = 3300000,
3508 + .max_uV = 3300000,
3509 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3510 + .boot_on = 1,
3511 + .apply_uV = 1,
3512 + .state_mem = {
3513 + .enabled = 1,
3514 + },
3515 + },
3516 + .num_consumer_supplies = 0,
3517 + },
3518 + [PCF50633_REGULATOR_DOWN1] = {
3519 + .constraints = {
3520 + .name = "CORE_1V3",
3521 + .min_uV = 1300000,
3522 + .max_uV = 1600000,
3523 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3524 + .boot_on = 1,
3525 + .apply_uV = 1,
3526 + },
3527 + .num_consumer_supplies = 0,
3528 + },
3529 + [PCF50633_REGULATOR_DOWN2] = {
3530 + .constraints = {
3531 + .name = "IO_1V8",
3532 + .min_uV = 1800000,
3533 + .max_uV = 1800000,
3534 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3535 + .apply_uV = 1,
3536 + .boot_on = 1,
3537 + .state_mem = {
3538 + .enabled = 1,
3539 + },
3540 + },
3541 + .num_consumer_supplies = 0,
3542 + },
3543 + [PCF50633_REGULATOR_HCLDO] = {
3544 + .constraints = {
3545 + .name = "SD_3V3",
3546 + .min_uV = 2000000,
3547 + .max_uV = 3300000,
3548 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3549 + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
3550 + .boot_on = 1,
3551 + },
3552 + .num_consumer_supplies = 1,
3553 + .consumer_supplies = hcldo_consumers,
3554 + },
3555 + [PCF50633_REGULATOR_LDO1] = {
3556 + .constraints = {
3557 + .name = "GSENSOR_3V3",
3558 + .min_uV = 1300000,
3559 + .max_uV = 1300000,
3560 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3561 + .apply_uV = 1,
3562 + },
3563 + .num_consumer_supplies = 0,
3564 + },
3565 + [PCF50633_REGULATOR_LDO2] = {
3566 + .constraints = {
3567 + .name = "CODEC_3V3",
3568 + .min_uV = 3300000,
3569 + .max_uV = 3300000,
3570 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3571 + .apply_uV = 1,
3572 + },
3573 + .num_consumer_supplies = 0,
3574 + },
3575 + [PCF50633_REGULATOR_LDO3] = {
3576 + .constraints = {
3577 + .min_uV = 3000000,
3578 + .max_uV = 3000000,
3579 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3580 + .apply_uV = 1,
3581 + },
3582 + .num_consumer_supplies = 0,
3583 + },
3584 + [PCF50633_REGULATOR_LDO4] = {
3585 + .constraints = {
3586 + .name = "BT_3V2",
3587 + .min_uV = 3200000,
3588 + .max_uV = 3200000,
3589 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3590 + .apply_uV = 1,
3591 + },
3592 + .num_consumer_supplies = 1,
3593 + .consumer_supplies = ldo4_consumers,
3594 + },
3595 + [PCF50633_REGULATOR_LDO5] = {
3596 + .constraints = {
3597 + .name = "RF_3V",
3598 + .min_uV = 1500000,
3599 + .max_uV = 1500000,
3600 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3601 + .apply_uV = 1,
3602 + .state_mem = {
3603 + .enabled = 1,
3604 + },
3605 + },
3606 + .num_consumer_supplies = 1,
3607 + .consumer_supplies = ldo5_consumers,
3608 + },
3609 + [PCF50633_REGULATOR_LDO6] = {
3610 + .constraints = {
3611 + .name = "LCM_3V",
3612 + .min_uV = 0,
3613 + .max_uV = 3300000,
3614 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3615 + },
3616 + .num_consumer_supplies = 0,
3617 + },
3618 + [PCF50633_REGULATOR_MEMLDO] = {
3619 + .constraints = {
3620 + .min_uV = 1800000,
3621 + .max_uV = 1800000,
3622 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3623 + .state_mem = {
3624 + .enabled = 1,
3625 + },
3626 + },
3627 + .num_consumer_supplies = 0,
3628 + },
3629 +
3630 + },
3631 + .probe_done = gta02_pmu_attach_child_devices,
3632 + .regulator_registered = gta02_pmu_regulator_registered,
3633 + .mbc_event_callback = gta02_pmu_event_callback,
3634 + .force_shutdown = gta02_pmu_force_shutdown,
3635 +};
3636 +
3637 +static void mangle_pmu_pdata_by_system_rev(void)
3638 +{
3639 + struct regulator_init_data *reg_init_data;
3640 +
3641 + reg_init_data = gta02_pcf_pdata.reg_init_data;
3642 +
3643 + switch (S3C_SYSTEM_REV_ATAG) {
3644 + case GTA02v1_SYSTEM_REV:
3645 + /* FIXME: this is only in v1 due to wrong PMU variant */
3646 + reg_init_data[PCF50633_REGULATOR_DOWN2]
3647 + .constraints.state_mem.enabled = 1;
3648 + break;
3649 + case GTA02v2_SYSTEM_REV:
3650 + case GTA02v3_SYSTEM_REV:
3651 + case GTA02v4_SYSTEM_REV:
3652 + case GTA02v5_SYSTEM_REV:
3653 + case GTA02v6_SYSTEM_REV:
3654 + reg_init_data[PCF50633_REGULATOR_LDO1]
3655 + .constraints.min_uV = 3300000;
3656 + reg_init_data[PCF50633_REGULATOR_LDO1]
3657 + .constraints.min_uV = 3300000;
3658 + reg_init_data[PCF50633_REGULATOR_LDO1]
3659 + .constraints.state_mem.enabled = 0;
3660 +
3661 + reg_init_data[PCF50633_REGULATOR_LDO5]
3662 + .constraints.min_uV = 3000000;
3663 + reg_init_data[PCF50633_REGULATOR_LDO5]
3664 + .constraints.max_uV = 3000000;
3665 +
3666 + reg_init_data[PCF50633_REGULATOR_LDO6]
3667 + .constraints.min_uV = 3000000;
3668 + reg_init_data[PCF50633_REGULATOR_LDO6]
3669 + .constraints.max_uV = 3000000;
3670 + reg_init_data[PCF50633_REGULATOR_LDO6]
3671 + .constraints.apply_uV = 1;
3672 + break;
3673 + default:
3674 + break;
3675 + }
3676 +}
3677 +
3678 +#ifdef CONFIG_HDQ_GPIO_BITBANG
3679 +/* BQ27000 Battery */
3680 +
3681 +struct bq27000_platform_data bq27000_pdata = {
3682 + .name = "battery",
3683 + .rsense_mohms = 20,
3684 + .hdq_read = hdq_read,
3685 + .hdq_write = hdq_write,
3686 + .hdq_initialized = hdq_initialized,
3687 + .get_charger_online_status = gta02_get_charger_online_status,
3688 + .get_charger_active_status = gta02_get_charger_active_status
3689 +};
3690 +
3691 +struct platform_device bq27000_battery_device = {
3692 + .name = "bq27000-battery",
3693 + .dev = {
3694 + .platform_data = &bq27000_pdata,
3695 + },
3696 +};
3697 +
3698 +/* HDQ */
3699 +
3700 +static void gta02_hdq_attach_child_devices(struct device *parent_device)
3701 +{
3702 + switch (S3C_SYSTEM_REV_ATAG) {
3703 + case GTA02v5_SYSTEM_REV:
3704 + case GTA02v6_SYSTEM_REV:
3705 + bq27000_battery_device.dev.parent = parent_device;
3706 + platform_device_register(&bq27000_battery_device);
3707 + break;
3708 + default:
3709 + break;
3710 + }
3711 +}
3712 +
3713 +static void gta02_hdq_gpio_direction_out(void)
3714 +{
3715 + s3c2410_gpio_cfgpin(GTA02v5_GPIO_HDQ, S3C2410_GPIO_OUTPUT);
3716 +}
3717 +
3718 +static void gta02_hdq_gpio_direction_in(void)
3719 +{
3720 + s3c2410_gpio_cfgpin(GTA02v5_GPIO_HDQ, S3C2410_GPIO_INPUT);
3721 +}
3722 +
3723 +static void gta02_hdq_gpio_set_value(int val)
3724 +{
3725 +
3726 + s3c2410_gpio_setpin(GTA02v5_GPIO_HDQ, val);
3727 +}
3728 +
3729 +static int gta02_hdq_gpio_get_value(void)
3730 +{
3731 + return s3c2410_gpio_getpin(GTA02v5_GPIO_HDQ);
3732 +}
3733 +
3734 +static struct resource gta02_hdq_resources[] = {
3735 + [0] = {
3736 + .start = GTA02v5_GPIO_HDQ,
3737 + .end = GTA02v5_GPIO_HDQ,
3738 + },
3739 +};
3740 +
3741 +struct hdq_platform_data gta02_hdq_platform_data = {
3742 + .attach_child_devices = gta02_hdq_attach_child_devices,
3743 + .gpio_dir_out = gta02_hdq_gpio_direction_out,
3744 + .gpio_dir_in = gta02_hdq_gpio_direction_in,
3745 + .gpio_set = gta02_hdq_gpio_set_value,
3746 + .gpio_get = gta02_hdq_gpio_get_value,
3747 +
3748 + .enable_fiq = gta02_fiq_enable,
3749 + .disable_fiq = gta02_fiq_disable,
3750 + .kick_fiq = gta02_fiq_kick,
3751 +
3752 +};
3753 +
3754 +struct platform_device gta02_hdq_device = {
3755 + .name = "hdq",
3756 + .num_resources = 1,
3757 + .resource = gta02_hdq_resources,
3758 + .dev = {
3759 + .platform_data = &gta02_hdq_platform_data,
3760 + },
3761 +};
3762 +#endif
3763 +
3764 +
3765 +#ifdef CONFIG_LEDS_NEO1973_VIBRATOR
3766 +/* vibrator (child of FIQ) */
3767 +
3768 +static struct resource gta02_vibrator_resources[] = {
3769 + [0] = {
3770 + .start = GTA02_GPIO_VIBRATOR_ON,
3771 + .end = GTA02_GPIO_VIBRATOR_ON,
3772 + },
3773 +};
3774 +struct neo1973_vib_platform_data gta02_vib_pdata = {
3775 + .enable_fiq = gta02_fiq_enable,
3776 + .disable_fiq = gta02_fiq_disable,
3777 + .kick_fiq = gta02_fiq_kick,
3778 +};
3779 +
3780 +static struct platform_device gta02_vibrator_dev = {
3781 + .name = "neo1973-vibrator",
3782 + .num_resources = ARRAY_SIZE(gta02_vibrator_resources),
3783 + .resource = gta02_vibrator_resources,
3784 + .dev = {
3785 + .platform_data = &gta02_vib_pdata,
3786 + },
3787 +};
3788 +#endif
3789 +
3790 +/* NOR Flash */
3791 +
3792 +#define GTA02_FLASH_BASE 0x18000000 /* GCS3 */
3793 +#define GTA02_FLASH_SIZE 0x200000 /* 2MBytes */
3794 +
3795 +static struct physmap_flash_data gta02_nor_flash_data = {
3796 + .width = 2,
3797 +};
3798 +
3799 +static struct resource gta02_nor_flash_resource = {
3800 + .start = GTA02_FLASH_BASE,
3801 + .end = GTA02_FLASH_BASE + GTA02_FLASH_SIZE - 1,
3802 + .flags = IORESOURCE_MEM,
3803 +};
3804 +
3805 +static struct platform_device gta02_nor_flash = {
3806 + .name = "physmap-flash",
3807 + .id = 0,
3808 + .dev = {
3809 + .platform_data = &gta02_nor_flash_data,
3810 + },
3811 + .resource = &gta02_nor_flash_resource,
3812 + .num_resources = 1,
3813 +};
3814 +
3815 +
3816 +struct platform_device s3c24xx_pwm_device = {
3817 + .name = "s3c24xx_pwm",
3818 + .num_resources = 0,
3819 +};
3820 +
3821 +static struct i2c_board_info gta02_i2c_devs[] __initdata = {
3822 + {
3823 + I2C_BOARD_INFO("pcf50633", 0x73),
3824 + .irq = GTA02_IRQ_PCF50633,
3825 + .platform_data = &gta02_pcf_pdata,
3826 + },
3827 + {
3828 + I2C_BOARD_INFO("wm8753", 0x1a),
3829 + },
3830 +};
3831 +
3832 +static struct s3c2410_nand_set gta02_nand_sets[] = {
3833 + [0] = {
3834 + .name = "neo1973-nand",
3835 + .nr_chips = 1,
3836 + .flags = S3C2410_NAND_BBT,
3837 + },
3838 +};
3839 +
3840 +/* choose a set of timings derived from S3C@2442B MCP54
3841 + * data sheet (K5D2G13ACM-D075 MCP Memory)
3842 + */
3843 +
3844 +static struct s3c2410_platform_nand gta02_nand_info = {
3845 + .tacls = 0,
3846 + .twrph0 = 25,
3847 + .twrph1 = 15,
3848 + .nr_sets = ARRAY_SIZE(gta02_nand_sets),
3849 + .sets = gta02_nand_sets,
3850 + .software_ecc = 1,
3851 +};
3852 +
3853 +
3854 +static void gta02_s3c_mmc_set_power(unsigned char power_mode,
3855 + unsigned short vdd)
3856 +{
3857 + static int is_on = -1;
3858 + int on;
3859 +
3860 + on = power_mode == MMC_POWER_ON || power_mode == MMC_POWER_UP;
3861 + if (is_on != on)
3862 + gta02_wlan_reset(!on);
3863 + is_on = on;
3864 +}
3865 +
3866 +
3867 +static struct s3c24xx_mci_pdata gta02_s3c_mmc_cfg = {
3868 + .set_power = gta02_s3c_mmc_set_power,
3869 +};
3870 +
3871 +static void gta02_udc_command(enum s3c2410_udc_cmd_e cmd)
3872 +{
3873 + switch (cmd) {
3874 + case S3C2410_UDC_P_ENABLE:
3875 + printk(KERN_DEBUG "%s S3C2410_UDC_P_ENABLE\n", __func__);
3876 + neo1973_gpb_setpin(GTA02_GPIO_USB_PULLUP, 1);
3877 + break;
3878 + case S3C2410_UDC_P_DISABLE:
3879 + printk(KERN_DEBUG "%s S3C2410_UDC_P_DISABLE\n", __func__);
3880 + neo1973_gpb_setpin(GTA02_GPIO_USB_PULLUP, 0);
3881 + break;
3882 + case S3C2410_UDC_P_RESET:
3883 + printk(KERN_DEBUG "%s S3C2410_UDC_P_RESET\n", __func__);
3884 + /* FIXME! */
3885 + break;
3886 + default:
3887 + break;
3888 + }
3889 +}
3890 +
3891 +/* get PMU to set USB current limit accordingly */
3892 +
3893 +static struct s3c2410_udc_mach_info gta02_udc_cfg = {
3894 + .vbus_draw = gta02_udc_vbus_draw,
3895 + .udc_command = gta02_udc_command,
3896 +
3897 +};
3898 +
3899 +
3900 +/* Touchscreen configuration. */
3901 +
3902 +#ifdef CONFIG_TOUCHSCREEN_FILTER
3903 +const static struct ts_filter_group_configuration gta02_ts_group = {
3904 + .length = 12,
3905 + .close_enough = 10,
3906 + .threshold = 6, /* At least half of the points in a group. */
3907 + .attempts = 10,
3908 +};
3909 +
3910 +const static struct ts_filter_median_configuration gta02_ts_median = {
3911 + .extent = 20,
3912 + .decimation_below = 3,
3913 + .decimation_threshold = 8 * 3,
3914 + .decimation_above = 4,
3915 +};
3916 +
3917 +const static struct ts_filter_mean_configuration gta02_ts_mean = {
3918 + .length = 4,
3919 +};
3920 +
3921 +const static struct ts_filter_linear_configuration gta02_ts_linear = {
3922 + .constants = {1, 0, 0, 0, 1, 0, 1}, /* Don't modify coords. */
3923 + .coord0 = 0,
3924 + .coord1 = 1,
3925 +};
3926 +#endif
3927 +
3928 +const static struct ts_filter_chain_configuration gta02_filter_configuration[] =
3929 +{
3930 +#ifdef CONFIG_TOUCHSCREEN_FILTER
3931 + {&ts_filter_group_api, &gta02_ts_group.config},
3932 + {&ts_filter_median_api, &gta02_ts_median.config},
3933 + {&ts_filter_mean_api, &gta02_ts_mean.config},
3934 + {&ts_filter_linear_api, &gta02_ts_linear.config},
3935 +#endif
3936 + {NULL, NULL},
3937 +};
3938 +
3939 +const static struct s3c2410_ts_mach_info gta02_ts_cfg = {
3940 + .delay = 10000,
3941 + .presc = 0xff, /* slow as we can go */
3942 + .filter_config = gta02_filter_configuration,
3943 +};
3944 +
3945 +
3946 +
3947 +static void gta02_bl_set_intensity(int intensity)
3948 +{
3949 + struct pcf50633 *pcf = gta02_pcf;
3950 + int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
3951 + int ret;
3952 +
3953 + intensity >>= 2;
3954 +
3955 + /*
3956 + * One code path that leads here is from a kernel panic. Trying to turn
3957 + * the backlight on just gives us a nearly endless stream of complaints
3958 + * and accomplishes nothing. We can't win. Just give up.
3959 + *
3960 + * In the unlikely event that there's another path leading here while
3961 + * we're atomic, we print at least a warning.
3962 + */
3963 + if (in_atomic()) {
3964 + printk(KERN_ERR
3965 + "gta02_bl_set_intensity called while atomic\n");
3966 + return;
3967 + }
3968 +
3969 + if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3))
3970 + old_intensity = 0;
3971 + else
3972 + old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
3973 +
3974 + if (intensity == old_intensity)
3975 + return;
3976 +
3977 + /* We can't do this anywhere else */
3978 + pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5);
3979 +
3980 + /*
3981 + * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
3982 + * if seen, you have to re-enable the LED unit
3983 + */
3984 + if (!intensity || !old_intensity)
3985 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0);
3986 +
3987 + if (!intensity) /* illegal to set LEDOUT to 0 */
3988 + ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
3989 + 2);
3990 + else
3991 + ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
3992 + intensity);
3993 +
3994 + if (intensity)
3995 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2);
3996 +
3997 +}
3998 +
3999 +static struct generic_bl_info gta02_bl_info = {
4000 + .name = "gta02-bl",
4001 + .max_intensity = 0xff,
4002 + .default_intensity = 0xff,
4003 + .set_bl_intensity = gta02_bl_set_intensity,
4004 +};
4005 +
4006 +static struct platform_device gta02_bl_dev = {
4007 + .name = "generic-bl",
4008 + .id = 1,
4009 + .dev = {
4010 + .platform_data = &gta02_bl_info,
4011 + },
4012 +};
4013 +
4014 +/* SPI: LCM control interface attached to Glamo3362 */
4015 +
4016 +static void gta02_jbt6k74_reset(int devidx, int level)
4017 +{
4018 + glamo_lcm_reset(level);
4019 +}
4020 +
4021 +static void gta02_jbt6k74_probe_completed(struct device *dev)
4022 +{
4023 + struct pcf50633 *pcf = gta02_pcf;
4024 +
4025 + /* Switch on backlight. Qi does not do it for us */
4026 + pcf50633_reg_write(pcf, PCF50633_REG_LEDOUT, 0x01);
4027 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x00);
4028 + pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 0x01);
4029 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x01);
4030 +
4031 + gta02_bl_dev.dev.parent = dev;
4032 + platform_device_register(&gta02_bl_dev);
4033 +}
4034 +
4035 +const struct jbt6k74_platform_data jbt6k74_pdata = {
4036 + .reset = gta02_jbt6k74_reset,
4037 + .probe_completed = gta02_jbt6k74_probe_completed,
4038 +};
4039 +
4040 +#if 0 /* currently this is not used and we use gpio spi */
4041 +static struct glamo_spi_info glamo_spi_cfg = {
4042 + .board_size = ARRAY_SIZE(gta02_spi_board_info),
4043 + .board_info = gta02_spi_board_info,
4044 +};
4045 +#endif /* 0 */
4046 +
4047 +static struct glamo_spigpio_info glamo_spigpio_cfg = {
4048 + .pin_clk = GLAMO_GPIO10_OUTPUT,
4049 + .pin_mosi = GLAMO_GPIO11_OUTPUT,
4050 + .pin_cs = GLAMO_GPIO12_OUTPUT,
4051 + .pin_miso = 0,
4052 + .bus_num = 2,
4053 +};
4054 +
4055 +/*----------- SPI: Accelerometers attached to SPI of s3c244x ----------------- */
4056 +
4057 +void gta02_lis302dl_suspend_io(struct lis302dl_info *lis, int resume)
4058 +{
4059 + struct lis302dl_platform_data *pdata = lis->pdata;
4060 +
4061 + if (!resume) {
4062 + /*
4063 + * we don't want to power them with a high level
4064 + * because GSENSOR_3V3 is not up during suspend
4065 + */
4066 + s3c2410_gpio_setpin(pdata->pin_chip_select, 0);
4067 + s3c2410_gpio_setpin(pdata->pin_clk, 0);
4068 + s3c2410_gpio_setpin(pdata->pin_mosi, 0);
4069 + /* misnomer: it is a pullDOWN in 2442 */
4070 + s3c2410_gpio_pullup(pdata->pin_miso, 1);
4071 + return;
4072 + }
4073 +
4074 + /* back to normal */
4075 + s3c2410_gpio_setpin(pdata->pin_chip_select, 1);
4076 + s3c2410_gpio_setpin(pdata->pin_clk, 1);
4077 + /* misnomer: it is a pullDOWN in 2442 */
4078 + s3c2410_gpio_pullup(pdata->pin_miso, 0);
4079 +
4080 + s3c2410_gpio_cfgpin(pdata->pin_chip_select, S3C2410_GPIO_OUTPUT);
4081 + s3c2410_gpio_cfgpin(pdata->pin_clk, S3C2410_GPIO_OUTPUT);
4082 + s3c2410_gpio_cfgpin(pdata->pin_mosi, S3C2410_GPIO_OUTPUT);
4083 + s3c2410_gpio_cfgpin(pdata->pin_miso, S3C2410_GPIO_INPUT);
4084 +
4085 +}
4086 +
4087 +struct lis302dl_platform_data lis302_pdata_top = {
4088 + .name = "lis302-1 (top)",
4089 + .pin_chip_select= S3C2410_GPD12,
4090 + .pin_clk = S3C2410_GPG7,
4091 + .pin_mosi = S3C2410_GPG6,
4092 + .pin_miso = S3C2410_GPG5,
4093 + .interrupt = GTA02_IRQ_GSENSOR_1,
4094 + .open_drain = 1, /* altered at runtime by PCB rev */
4095 + .lis302dl_suspend_io = gta02_lis302dl_suspend_io,
4096 +};
4097 +
4098 +struct lis302dl_platform_data lis302_pdata_bottom = {
4099 + .name = "lis302-2 (bottom)",
4100 + .pin_chip_select= S3C2410_GPD13,
4101 + .pin_clk = S3C2410_GPG7,
4102 + .pin_mosi = S3C2410_GPG6,
4103 + .pin_miso = S3C2410_GPG5,
4104 + .interrupt = GTA02_IRQ_GSENSOR_2,
4105 + .open_drain = 1, /* altered at runtime by PCB rev */
4106 + .lis302dl_suspend_io = gta02_lis302dl_suspend_io,
4107 +};
4108 +
4109 +static struct spi_board_info gta02_spi_board_info[] = {
4110 + {
4111 + .modalias = "jbt6k74",
4112 + /* platform_data */
4113 + .platform_data = &jbt6k74_pdata,
4114 + /* controller_data */
4115 + /* irq */
4116 + .max_speed_hz = 100 * 1000,
4117 + .bus_num = 2,
4118 + /* chip_select */
4119 + },
4120 + {
4121 + .modalias = "lis302dl",
4122 + /* platform_data */
4123 + .platform_data = &lis302_pdata_top,
4124 + /* controller_data */
4125 + /* irq */
4126 + .max_speed_hz = 100 * 1000,
4127 + .bus_num = 3,
4128 + .chip_select = 0,
4129 + },
4130 +
4131 + {
4132 + .modalias = "lis302dl",
4133 + /* platform_data */
4134 + .platform_data = &lis302_pdata_bottom,
4135 + /* controller_data */
4136 + /* irq */
4137 + .max_speed_hz = 100 * 1000,
4138 + .bus_num = 3,
4139 + .chip_select = 1,
4140 + },
4141 +
4142 +};
4143 +
4144 +static void gta02_lis302_chip_select(struct s3c2410_spigpio_info *info, int csid, int cs)
4145 +{
4146 +
4147 + /*
4148 + * Huh... "quirk"... CS on this device is not really "CS" like you can
4149 + * expect.
4150 + *
4151 + * When it is 0 it selects SPI interface mode.
4152 + * When it is 1 it selects I2C interface mode.
4153 + *
4154 + * Because we have 2 devices on one interface we have to make sure
4155 + * that the "disabled" device (actually in I2C mode) don't think we're
4156 + * talking to it.
4157 + *
4158 + * When we talk to the "enabled" device, the "disabled" device sees
4159 + * the clocks as I2C clocks, creating havoc.
4160 + *
4161 + * I2C sees MOSI going LOW while CLK HIGH as a START action, thus we
4162 + * must ensure this is never issued.
4163 + */
4164 +
4165 + int cs_gpio, other_cs_gpio;
4166 +
4167 + cs_gpio = csid ? S3C2410_GPD13 : S3C2410_GPD12;
4168 + other_cs_gpio = (1 - csid) ? S3C2410_GPD13 : S3C2410_GPD12;
4169 +
4170 +
4171 + if (cs == BITBANG_CS_ACTIVE) {
4172 + s3c2410_gpio_setpin(other_cs_gpio, 1);
4173 + s3c2410_gpio_setpin(cs_gpio, 1);
4174 + s3c2410_gpio_setpin(info->pin_clk, 1);
4175 + s3c2410_gpio_setpin(cs_gpio, 0);
4176 + } else {
4177 + s3c2410_gpio_setpin(cs_gpio, 1);
4178 + s3c2410_gpio_setpin(other_cs_gpio, 1);
4179 + }
4180 +}
4181 +
4182 +static struct s3c2410_spigpio_info gta02_spigpio_cfg = {
4183 + .pin_clk = S3C2410_GPG7,
4184 + .pin_mosi = S3C2410_GPG6,
4185 + .pin_miso = S3C2410_GPG5,
4186 + .bus_num = 3,
4187 + .num_chipselect = 2,
4188 + .chip_select = gta02_lis302_chip_select,
4189 + .non_blocking_transfer = 1,
4190 +};
4191 +
4192 +static struct platform_device gta02_spi_gpio_dev = {
4193 + .name = "spi_s3c24xx_gpio",
4194 + .dev = {
4195 + .platform_data = &gta02_spigpio_cfg,
4196 + },
4197 +};
4198 +
4199 +/*----------- / SPI: Accelerometers attached to SPI of s3c244x ----------------- */
4200 +
4201 +static struct resource gta02_led_resources[] = {
4202 + {
4203 + .name = "gta02-power:orange",
4204 + .start = GTA02_GPIO_PWR_LED1,
4205 + .end = GTA02_GPIO_PWR_LED1,
4206 + }, {
4207 + .name = "gta02-power:blue",
4208 + .start = GTA02_GPIO_PWR_LED2,
4209 + .end = GTA02_GPIO_PWR_LED2,
4210 + }, {
4211 + .name = "gta02-aux:red",
4212 + .start = GTA02_GPIO_AUX_LED,
4213 + .end = GTA02_GPIO_AUX_LED,
4214 + },
4215 +};
4216 +
4217 +struct platform_device gta02_led_dev = {
4218 + .name = "gta02-led",
4219 + .num_resources = ARRAY_SIZE(gta02_led_resources),
4220 + .resource = gta02_led_resources,
4221 +};
4222 +
4223 +static struct resource gta02_button_resources[] = {
4224 + [0] = {
4225 + .start = GTA02_GPIO_AUX_KEY,
4226 + .end = GTA02_GPIO_AUX_KEY,
4227 + },
4228 + [1] = {
4229 + .start = GTA02_GPIO_HOLD_KEY,
4230 + .end = GTA02_GPIO_HOLD_KEY,
4231 + },
4232 + [2] = {
4233 + .start = GTA02_GPIO_JACK_INSERT,
4234 + .end = GTA02_GPIO_JACK_INSERT,
4235 + },
4236 + [3] = {
4237 + .start = 0,
4238 + .end = 0,
4239 + },
4240 + [4] = {
4241 + .start = 0,
4242 + .end = 0,
4243 + },
4244 +};
4245 +
4246 +static struct platform_device gta02_button_dev = {
4247 + .name = "neo1973-button",
4248 + .num_resources = ARRAY_SIZE(gta02_button_resources),
4249 + .resource = gta02_button_resources,
4250 +};
4251 +
4252 +
4253 +static struct platform_device gta02_pm_usbhost_dev = {
4254 + .name = "neo1973-pm-host",
4255 +};
4256 +
4257 +
4258 +/* USB */
4259 +static struct s3c2410_hcd_info gta02_usb_info = {
4260 + .port[0] = {
4261 + .flags = S3C_HCDFLG_USED,
4262 + },
4263 + .port[1] = {
4264 + .flags = 0,
4265 + },
4266 +};
4267 +
4268 +static int glamo_irq_is_wired(void)
4269 +{
4270 + int rc;
4271 + int count = 0;
4272 +
4273 + /*
4274 + * GTA02 S-Media IRQs prior to A5 are broken due to a lack of
4275 + * a pullup on the INT# line. Check for the bad behaviour.
4276 + */
4277 + s3c2410_gpio_setpin(S3C2410_GPG4, 0);
4278 + s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_OUTP);
4279 + s3c2410_gpio_cfgpin(S3C2410_GPG4, S3C2410_GPG4_INP);
4280 + /*
4281 + * we force it low ourselves for a moment and resume being input.
4282 + * If there is a pullup, it won't stay low for long. But if the
4283 + * level converter is there as on < A5 revision, the weak keeper
4284 + * on the input of the LC will hold the line low indefinitiely
4285 + */
4286 + do
4287 + rc = s3c2410_gpio_getpin(S3C2410_GPG4);
4288 + while ((!rc) && ((count++) < 10));
4289 + if (rc) { /* it got pulled back up, it's good */
4290 + printk(KERN_INFO "Detected S-Media IRQ# pullup, "
4291 + "enabling interrupt\n");
4292 + return 0;
4293 + } else /* Gah we can't work with this level converter */
4294 + printk(KERN_WARNING "** Detected bad IRQ# circuit found"
4295 + " on pre-A5 GTA02: S-Media interrupt disabled **\n");
4296 + return -ENODEV;
4297 +}
4298 +
4299 +static int gta02_glamo_can_set_mmc_power(void)
4300 +{
4301 + switch (S3C_SYSTEM_REV_ATAG) {
4302 + case GTA02v3_SYSTEM_REV:
4303 + case GTA02v4_SYSTEM_REV:
4304 + case GTA02v5_SYSTEM_REV:
4305 + case GTA02v6_SYSTEM_REV:
4306 + return 1;
4307 + }
4308 +
4309 + return 0;
4310 +}
4311 +
4312 +/* Smedia Glamo 3362 */
4313 +
4314 +/*
4315 + * we crank down SD Card clock dynamically when GPS is powered
4316 + */
4317 +
4318 +static int gta02_glamo_mci_use_slow(void)
4319 +{
4320 + return neo1973_pm_gps_is_on();
4321 +}
4322 +
4323 +static void gta02_glamo_external_reset(int level)
4324 +{
4325 + s3c2410_gpio_setpin(GTA02_GPIO_3D_RESET, level);
4326 + s3c2410_gpio_cfgpin(GTA02_GPIO_3D_RESET, S3C2410_GPIO_OUTPUT);
4327 +}
4328 +
4329 +static struct glamofb_platform_data gta02_glamo_pdata = {
4330 + .width = 43,
4331 + .height = 58,
4332 + /* 24.5MHz --> 40.816ns */
4333 + .pixclock = 40816,
4334 + .left_margin = 8,
4335 + .right_margin = 16,
4336 + .upper_margin = 2,
4337 + .lower_margin = 16,
4338 + .hsync_len = 8,
4339 + .vsync_len = 2,
4340 + .fb_mem_size = 0x400000, /* glamo has 8 megs of SRAM. we use 4 */
4341 + .xres = {
4342 + .min = 240,
4343 + .max = 640,
4344 + .defval = 480,
4345 + },
4346 + .yres = {
4347 + .min = 320,
4348 + .max = 640,
4349 + .defval = 640,
4350 + },
4351 + .bpp = {
4352 + .min = 16,
4353 + .max = 16,
4354 + .defval = 16,
4355 + },
4356 + //.spi_info = &glamo_spi_cfg,
4357 + .spigpio_info = &glamo_spigpio_cfg,
4358 +
4359 + /* glamo MMC function platform data */
4360 + .mmc_dev = &gta02_mmc_dev,
4361 + .glamo_can_set_mci_power = gta02_glamo_can_set_mmc_power,
4362 + .glamo_mci_use_slow = gta02_glamo_mci_use_slow,
4363 + .glamo_irq_is_wired = glamo_irq_is_wired,
4364 + .glamo_external_reset = gta02_glamo_external_reset
4365 +};
4366 +
4367 +static struct resource gta02_glamo_resources[] = {
4368 + [0] = {
4369 + .start = S3C2410_CS1,
4370 + .end = S3C2410_CS1 + 0x1000000 - 1,
4371 + .flags = IORESOURCE_MEM,
4372 + },
4373 + [1] = {
4374 + .start = GTA02_IRQ_3D,
4375 + .end = GTA02_IRQ_3D,
4376 + .flags = IORESOURCE_IRQ,
4377 + },
4378 + [2] = {
4379 + .start = GTA02_GPIO_3D_RESET,
4380 + .end = GTA02_GPIO_3D_RESET,
4381 + },
4382 +};
4383 +
4384 +static struct platform_device gta02_glamo_dev = {
4385 + .name = "glamo3362",
4386 + .num_resources = ARRAY_SIZE(gta02_glamo_resources),
4387 + .resource = gta02_glamo_resources,
4388 + .dev = {
4389 + .platform_data = &gta02_glamo_pdata,
4390 + },
4391 +};
4392 +
4393 +static void mangle_glamo_res_by_system_rev(void)
4394 +{
4395 + switch (S3C_SYSTEM_REV_ATAG) {
4396 + case GTA02v1_SYSTEM_REV:
4397 + break;
4398 + default:
4399 + gta02_glamo_resources[2].start = GTA02_GPIO_3D_RESET;
4400 + gta02_glamo_resources[2].end = GTA02_GPIO_3D_RESET;
4401 + break;
4402 + }
4403 +
4404 + switch (S3C_SYSTEM_REV_ATAG) {
4405 + case GTA02v1_SYSTEM_REV:
4406 + case GTA02v2_SYSTEM_REV:
4407 + case GTA02v3_SYSTEM_REV:
4408 + /* case GTA02v4_SYSTEM_REV: - FIXME: handle this later */
4409 + /* The hardware is missing a pull-up resistor and thus can't
4410 + * support the Smedia Glamo IRQ */
4411 + gta02_glamo_resources[1].start = 0;
4412 + gta02_glamo_resources[1].end = 0;
4413 + break;
4414 + }
4415 +}
4416 +
4417 +static void __init gta02_map_io(void)
4418 +{
4419 + s3c24xx_init_io(gta02_iodesc, ARRAY_SIZE(gta02_iodesc));
4420 + s3c24xx_init_clocks(12000000);
4421 + s3c24xx_init_uarts(gta02_uartcfgs, ARRAY_SIZE(gta02_uartcfgs));
4422 +}
4423 +
4424 +static irqreturn_t gta02_modem_irq(int irq, void *param)
4425 +{
4426 + printk(KERN_DEBUG "modem wakeup interrupt\n");
4427 + gta_gsm_interrupts++;
4428 + return IRQ_HANDLED;
4429 +}
4430 +
4431 +static irqreturn_t ar6000_wow_irq(int irq, void *param)
4432 +{
4433 + printk(KERN_DEBUG "ar6000_wow interrupt\n");
4434 + return IRQ_HANDLED;
4435 +}
4436 +
4437 +/*
4438 + * hardware_ecc=1|0
4439 + */
4440 +static char hardware_ecc_str[4] __initdata = "";
4441 +
4442 +static int __init hardware_ecc_setup(char *str)
4443 +{
4444 + if (str)
4445 + strlcpy(hardware_ecc_str, str, sizeof(hardware_ecc_str));
4446 + return 1;
4447 +}
4448 +
4449 +__setup("hardware_ecc=", hardware_ecc_setup);
4450 +
4451 +/* these are the guys that don't need to be children of PMU */
4452 +
4453 +static struct platform_device *gta02_devices[] __initdata = {
4454 + &gta02_version_device,
4455 + &s3c_device_usb,
4456 + &s3c_device_wdt,
4457 + &gta02_memconfig_device,
4458 + &s3c_device_sdi,
4459 + &s3c_device_usbgadget,
4460 + &s3c_device_nand,
4461 + &gta02_nor_flash,
4462 +
4463 + &s3c24xx_pwm_device,
4464 + &gta02_led_dev,
4465 + &gta02_pm_wlan_dev, /* not dependent on PMU */
4466 +
4467 + &s3c_device_iis,
4468 + &s3c_device_i2c0,
4469 +};
4470 +
4471 +/* these guys DO need to be children of PMU */
4472 +
4473 +static struct platform_device *gta02_devices_pmu_children[] = {
4474 + &s3c_device_ts, /* input 1 */
4475 + &gta02_pm_gsm_dev,
4476 + &gta02_pm_usbhost_dev,
4477 + &gta02_spi_gpio_dev, /* input 2 and 3 */
4478 + &gta02_button_dev, /* input 4 */
4479 + &gta02_resume_reason_device,
4480 +};
4481 +
4482 +static void gta02_pmu_regulator_registered(struct pcf50633 *pcf, int id)
4483 +{
4484 + struct platform_device *regulator, *pdev;
4485 +
4486 + gta02_pcf = pcf;
4487 +
4488 + regulator = pcf->regulator_pdev[id];
4489 +
4490 + switch(id) {
4491 + case PCF50633_REGULATOR_LDO4:
4492 + pdev = &gta01_pm_bt_dev;
4493 + break;
4494 + case PCF50633_REGULATOR_LDO5:
4495 + pdev = &gta01_pm_gps_dev;
4496 + break;
4497 + case PCF50633_REGULATOR_HCLDO:
4498 + pdev = &gta02_glamo_dev;
4499 + break;
4500 + default:
4501 + return;
4502 + }
4503 +
4504 + pdev->dev.parent = &regulator->dev;
4505 + platform_device_register(pdev);
4506 +}
4507 +
4508 +/* this is called when pc50633 is probed, unfortunately quite late in the
4509 + * day since it is an I2C bus device. Here we can belatedly define some
4510 + * platform devices with the advantage that we can mark the pcf50633 as the
4511 + * parent. This makes them get suspended and resumed with their parent
4512 + * the pcf50633 still around.
4513 + */
4514 +
4515 +static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf)
4516 +{
4517 + int n;
4518 +
4519 + for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++)
4520 + gta02_devices_pmu_children[n]->dev.parent = pcf->dev;
4521 +
4522 + mangle_glamo_res_by_system_rev();
4523 + platform_add_devices(gta02_devices_pmu_children,
4524 + ARRAY_SIZE(gta02_devices_pmu_children));
4525 +}
4526 +
4527 +static void gta02_poweroff(void)
4528 +{
4529 + pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN,
4530 + PCF50633_OOCSHDWN_GOSTDBY, PCF50633_OOCSHDWN_GOSTDBY);
4531 +}
4532 +
4533 +static void __init gta02_machine_init(void)
4534 +{
4535 + int rc;
4536 +
4537 + /* set the panic callback to make AUX blink fast */
4538 + panic_blink = gta02_panic_blink;
4539 +
4540 + switch (S3C_SYSTEM_REV_ATAG) {
4541 + case GTA02v6_SYSTEM_REV:
4542 + /* we need push-pull interrupt from motion sensors */
4543 + lis302_pdata_top.open_drain = 0;
4544 + lis302_pdata_bottom.open_drain = 0;
4545 + break;
4546 + default:
4547 + break;
4548 + }
4549 +
4550 + spin_lock_init(&motion_irq_lock);
4551 +
4552 +#ifdef CONFIG_CHARGER_PCF50633
4553 + INIT_DELAYED_WORK(&gta02_charger_work, gta02_charger_worker);
4554 +#endif
4555 +
4556 + /* Glamo chip select optimization */
4557 +/* *((u32 *)(S3C2410_MEMREG(((1 + 1) << 2)))) = 0x1280; */
4558 +
4559 + /* do not force soft ecc if we are asked to use hardware_ecc */
4560 + if (hardware_ecc_str[0] == '1')
4561 + gta02_nand_info.software_ecc = 0;
4562 +
4563 + s3c_device_usb.dev.platform_data = &gta02_usb_info;
4564 + s3c_device_nand.dev.platform_data = &gta02_nand_info;
4565 + s3c_device_sdi.dev.platform_data = &gta02_s3c_mmc_cfg;
4566 +
4567 + /* acc sensor chip selects */
4568 + s3c2410_gpio_setpin(S3C2410_GPD12, 1);
4569 + s3c2410_gpio_cfgpin(S3C2410_GPD12, S3C2410_GPIO_OUTPUT);
4570 + s3c2410_gpio_setpin(S3C2410_GPD13, 1);
4571 + s3c2410_gpio_cfgpin(S3C2410_GPD13, S3C2410_GPIO_OUTPUT);
4572 +
4573 + s3c24xx_udc_set_platdata(&gta02_udc_cfg);
4574 + s3c_i2c0_set_platdata(NULL);
4575 + set_s3c2410ts_info(&gta02_ts_cfg);
4576 +
4577 + mangle_glamo_res_by_system_rev();
4578 +
4579 + i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs));
4580 + spi_register_board_info(gta02_spi_board_info,
4581 + ARRAY_SIZE(gta02_spi_board_info));
4582 +
4583 + mangle_pmu_pdata_by_system_rev();
4584 +
4585 + platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
4586 +
4587 + s3c_pm_init();
4588 +
4589 + /* Make sure the modem can wake us up */
4590 + set_irq_type(GTA02_IRQ_MODEM, IRQ_TYPE_EDGE_RISING);
4591 + rc = request_irq(GTA02_IRQ_MODEM, gta02_modem_irq, IRQF_DISABLED,
4592 + "modem", NULL);
4593 + if (rc < 0)
4594 + printk(KERN_ERR "GTA02: can't request GSM modem wakeup IRQ\n");
4595 + enable_irq_wake(GTA02_IRQ_MODEM);
4596 +
4597 + /* Make sure the wifi module can wake us up*/
4598 + set_irq_type(GTA02_IRQ_WLAN_GPIO1, IRQ_TYPE_EDGE_RISING);
4599 + rc = request_irq(GTA02_IRQ_WLAN_GPIO1, ar6000_wow_irq, IRQF_DISABLED,
4600 + "ar6000", NULL);
4601 +
4602 + if (rc < 0)
4603 + printk(KERN_ERR "GTA02: can't request ar6k wakeup IRQ\n");
4604 + enable_irq_wake(GTA02_IRQ_WLAN_GPIO1);
4605 +
4606 + pm_power_off = gta02_poweroff;
4607 +
4608 + /* Register the HDQ and vibrator as children of pwm device */
4609 +#ifdef CONFIG_HDQ_GPIO_BITBANG
4610 + gta02_hdq_device.dev.parent = &s3c24xx_pwm_device.dev;
4611 + platform_device_register(&gta02_hdq_device);
4612 +#endif
4613 +#ifdef CONFIG_LEDS_NEO1973_VIBRATOR
4614 + gta02_vibrator_dev.dev.parent = &s3c24xx_pwm_device.dev;
4615 + platform_device_register(&gta02_vibrator_dev);
4616 +#endif
4617 +}
4618 +
4619 +void DEBUG_LED(int n)
4620 +{
4621 +// int *p = NULL;
4622 + switch (n) {
4623 + case 0:
4624 + neo1973_gpb_setpin(GTA02_GPIO_PWR_LED1, 1);
4625 + break;
4626 + case 1:
4627 + neo1973_gpb_setpin(GTA02_GPIO_PWR_LED2, 1);
4628 + break;
4629 + default:
4630 + neo1973_gpb_setpin(GTA02_GPIO_AUX_LED, 1);
4631 + break;
4632 + }
4633 +// printk(KERN_ERR"die %d\n", *p);
4634 +}
4635 +EXPORT_SYMBOL_GPL(DEBUG_LED);
4636 +
4637 +MACHINE_START(NEO1973_GTA02, "GTA02")
4638 + .phys_io = S3C2410_PA_UART,
4639 + .io_pg_offst = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
4640 + .boot_params = S3C2410_SDRAM_PA + 0x100,
4641 + .map_io = gta02_map_io,
4642 + .init_irq = s3c24xx_init_irq,
4643 + .init_machine = gta02_machine_init,
4644 + .timer = &s3c24xx_timer,
4645 +MACHINE_END
4646 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/Makefile linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/Makefile
4647 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/Makefile 2009-05-10 22:05:02.000000000 +0200
4648 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/Makefile 2009-05-10 22:27:59.000000000 +0200
4649 @@ -9,8 +9,11 @@
4650 obj-n :=
4651 obj- :=
4652
4653 +obj-$(CONFIG_S3C2440_C_FIQ) += fiq_c_isr.o
4654 +
4655 obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
4656 obj-$(CONFIG_CPU_S3C2442) += clock.o
4657 +obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o
4658
4659 # Machine support
4660
4661 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/s3c2442.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/s3c2442.c
4662 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2442/s3c2442.c 2009-05-10 22:05:02.000000000 +0200
4663 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2442/s3c2442.c 2009-05-10 22:27:59.000000000 +0200
4664 @@ -21,6 +21,7 @@
4665
4666 #include <plat/s3c2442.h>
4667 #include <plat/cpu.h>
4668 +#include <plat/devs.h>
4669
4670 static struct sys_device s3c2442_sysdev = {
4671 .cls = &s3c2442_sysclass,
4672 @@ -30,5 +31,8 @@
4673 {
4674 printk("S3C2442: Initialising architecture\n");
4675
4676 + /* make sure SD/MMC driver can distinguish 2440 from 2410 */
4677 + s3c_device_sdi.name = "s3c2440-sdi";
4678 +
4679 return sysdev_register(&s3c2442_sysdev);
4680 }
4681 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2443/dma.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2443/dma.c
4682 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c2443/dma.c 2009-05-10 22:05:03.000000000 +0200
4683 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c2443/dma.c 2009-05-10 22:27:59.000000000 +0200
4684 @@ -20,16 +20,17 @@
4685
4686 #include <mach/dma.h>
4687
4688 -#include <plat/dma.h>
4689 +#include <plat/dma-plat.h>
4690 #include <plat/cpu.h>
4691
4692 #include <plat/regs-serial.h>
4693 #include <mach/regs-gpio.h>
4694 #include <plat/regs-ac97.h>
4695 +#include <plat/regs-dma.h>
4696 #include <mach/regs-mem.h>
4697 #include <mach/regs-lcd.h>
4698 #include <mach/regs-sdi.h>
4699 -#include <asm/plat-s3c24xx/regs-iis.h>
4700 +#include <plat/regs-iis.h>
4701 #include <plat/regs-spi.h>
4702
4703 #define MAP(x) { \
4704 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c24a0/include/mach/io.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c24a0/include/mach/io.h
4705 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c24a0/include/mach/io.h 1970-01-01 01:00:00.000000000 +0100
4706 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c24a0/include/mach/io.h 2009-05-10 22:27:59.000000000 +0200
4707 @@ -0,0 +1,16 @@
4708 +/* arch/arm/mach-s3c24a0/include/mach/io.h
4709 + *
4710 + * Copyright 2008 Simtec Electronics
4711 + * Ben Dooks <ben-linux@fluff.org>
4712 + *
4713 + * IO access and mapping routines for the S3C24A0
4714 + */
4715 +
4716 +#ifndef __ASM_ARM_ARCH_IO_H
4717 +#define __ASM_ARM_ARCH_IO_H
4718 +
4719 +/* No current ISA/PCI bus support. */
4720 +#define __io(a) ((void __iomem *)(a))
4721 +#define __mem_pci(a) (a)
4722 +
4723 +#endif
4724 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c24a0/include/mach/irqs.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c24a0/include/mach/irqs.h
4725 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c24a0/include/mach/irqs.h 2009-05-10 22:05:03.000000000 +0200
4726 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c24a0/include/mach/irqs.h 2009-05-10 22:27:59.000000000 +0200
4727 @@ -70,6 +70,8 @@
4728 #define IRQ_EINT17 S3C2410_IRQ(49)
4729 #define IRQ_EINT18 S3C2410_IRQ(50)
4730
4731 +#define IRQ_EINT_BIT(x) ((x) - IRQ_EINT00)
4732 +
4733 /* SUB IRQS */
4734 #define IRQ_S3CUART_RX0 S3C2410_IRQ(51) /* 67 */
4735 #define IRQ_S3CUART_TX0 S3C2410_IRQ(52)
4736 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6400/include/mach/dma.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6400/include/mach/dma.h
4737 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6400/include/mach/dma.h 2009-05-10 22:05:04.000000000 +0200
4738 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6400/include/mach/dma.h 2009-05-10 22:27:59.000000000 +0200
4739 @@ -11,6 +11,63 @@
4740 #ifndef __ASM_ARCH_DMA_H
4741 #define __ASM_ARCH_DMA_H __FILE__
4742
4743 -/* currently nothing here, placeholder */
4744 +#define S3C_DMA_CHANNELS (16)
4745 +
4746 +/* see mach-s3c2410/dma.h for notes on dma channel numbers */
4747 +
4748 +/* Note, for the S3C64XX architecture we keep the DMACH_
4749 + * defines in the order they are allocated to [S]DMA0/[S]DMA1
4750 + * so that is easy to do DHACH_ -> DMA controller conversion
4751 + */
4752 +enum dma_ch {
4753 + /* DMA0/SDMA0 */
4754 + DMACH_UART0 = 0,
4755 + DMACH_UART0_SRC2,
4756 + DMACH_UART1,
4757 + DMACH_UART1_SRC2,
4758 + DMACH_UART2,
4759 + DMACH_UART2_SRC2,
4760 + DMACH_UART3,
4761 + DMACH_UART3_SRC2,
4762 + DMACH_PCM0_TX,
4763 + DMACH_PCM0_RX,
4764 + DMACH_I2S0_OUT,
4765 + DMACH_I2S0_IN,
4766 + DMACH_SPI0_TX,
4767 + DMACH_SPI0_RX,
4768 + DMACH_HSI_I2SV40_TX,
4769 + DMACH_HSI_I2SV40_RX,
4770 +
4771 + /* DMA1/SDMA1 */
4772 + DMACH_PCM1_TX = 16,
4773 + DMACH_PCM1_RX,
4774 + DMACH_I2S1_OUT,
4775 + DMACH_I2S1_IN,
4776 + DMACH_SPI1_TX,
4777 + DMACH_SPI1_RX,
4778 + DMACH_AC97_PCMOUT,
4779 + DMACH_AC97_PCMIN,
4780 + DMACH_AC97_MICIN,
4781 + DMACH_PWM,
4782 + DMACH_IRDA,
4783 + DMACH_EXTERNAL,
4784 + DMACH_RES1,
4785 + DMACH_RES2,
4786 + DMACH_SECURITY_RX, /* SDMA1 only */
4787 + DMACH_SECURITY_TX, /* SDMA1 only */
4788 + DMACH_MAX /* the end */
4789 +};
4790 +
4791 +static __inline__ int s3c_dma_has_circular(void)
4792 +{
4793 + /* we will be supporting ciruclar buffers as soon as we have DMA
4794 + * engine support.
4795 + */
4796 + return 1;
4797 +}
4798 +
4799 +#define S3C2410_DMAF_CIRCULAR (1 << 0)
4800 +
4801 +#include <plat/dma.h>
4802
4803 #endif /* __ASM_ARCH_IRQ_H */
4804 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6400/include/mach/map.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6400/include/mach/map.h
4805 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6400/include/mach/map.h 2009-05-10 22:05:03.000000000 +0200
4806 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6400/include/mach/map.h 2009-05-10 22:27:59.000000000 +0200
4807 @@ -40,6 +40,8 @@
4808
4809 #define S3C64XX_PA_FB (0x77100000)
4810 #define S3C64XX_PA_SYSCON (0x7E00F000)
4811 +#define S3C64XX_PA_IIS0 (0x7F002000)
4812 +#define S3C64XX_PA_IIS1 (0x7F003000)
4813 #define S3C64XX_PA_TIMER (0x7F006000)
4814 #define S3C64XX_PA_IIC0 (0x7F004000)
4815 #define S3C64XX_PA_IIC1 (0x7F00F000)
4816 @@ -49,12 +51,21 @@
4817 #define S3C64XX_SZ_GPIO SZ_4K
4818
4819 #define S3C64XX_PA_SDRAM (0x50000000)
4820 +#define S3C64XX_PA_TZIC0 (0x71000000)
4821 +#define S3C64XX_PA_TZIC1 (0x71100000)
4822 #define S3C64XX_PA_VIC0 (0x71200000)
4823 #define S3C64XX_PA_VIC1 (0x71300000)
4824
4825 +#define S3C64XX_PA_MODEM (0x74108000)
4826 +#define S3C64XX_VA_MODEM S3C_ADDR(0x00600000)
4827 +
4828 +#define S3C64XX_PA_USBHOST (0x74300000)
4829 +
4830 /* place VICs close together */
4831 #define S3C_VA_VIC0 (S3C_VA_IRQ + 0x00)
4832 #define S3C_VA_VIC1 (S3C_VA_IRQ + 0x10000)
4833 +#define S3C_VA_TZIC0 (S3C_VA_IRQ + 0x20000)
4834 +#define S3C_VA_TZIC1 (S3C_VA_IRQ + 0x30000)
4835
4836 /* compatibiltiy defines. */
4837 #define S3C_PA_TIMER S3C64XX_PA_TIMER
4838 @@ -64,5 +75,12 @@
4839 #define S3C_PA_IIC S3C64XX_PA_IIC0
4840 #define S3C_PA_IIC1 S3C64XX_PA_IIC1
4841 #define S3C_PA_FB S3C64XX_PA_FB
4842 +#define S3C_PA_USBHOST S3C64XX_PA_USBHOST
4843 +
4844 +#define S3C64XX_VA_OTG S3C_VA_OTG
4845 +#define S3C64XX_PA_OTG (0x7C000000)
4846 +
4847 +#define S3C64XX_VA_OTGSFR S3C_VA_OTGSFR
4848 +#define S3C64XX_PA_OTGSFR (0x7C100000)
4849
4850 #endif /* __ASM_ARCH_6400_MAP_H */
4851 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6400/include/mach/regs-clock.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6400/include/mach/regs-clock.h
4852 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6400/include/mach/regs-clock.h 1970-01-01 01:00:00.000000000 +0100
4853 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6400/include/mach/regs-clock.h 2009-05-10 22:27:59.000000000 +0200
4854 @@ -0,0 +1,16 @@
4855 +/* linux/arch/arm/mach-s3c6400/include/mach/regs-clock.h
4856 + *
4857 + * Copyright 2008 Openmoko, Inc.
4858 + * Copyright 2008 Simtec Electronics
4859 + * http://armlinux.simtec.co.uk/
4860 + * Ben Dooks <ben@simtec.co.uk>
4861 + *
4862 + * S3C64XX - clock register compatibility with s3c24xx
4863 + *
4864 + * This program is free software; you can redistribute it and/or modify
4865 + * it under the terms of the GNU General Public License version 2 as
4866 + * published by the Free Software Foundation.
4867 +*/
4868 +
4869 +#include <plat/regs-clock.h>
4870 +
4871 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6400/include/mach/system.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6400/include/mach/system.h
4872 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6400/include/mach/system.h 2009-05-10 22:05:04.000000000 +0200
4873 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6400/include/mach/system.h 2009-05-10 22:27:59.000000000 +0200
4874 @@ -11,9 +11,29 @@
4875 #ifndef __ASM_ARCH_SYSTEM_H
4876 #define __ASM_ARCH_SYSTEM_H __FILE__
4877
4878 +#include <linux/io.h>
4879 +#include <mach/map.h>
4880 +
4881 +#include <plat/regs-sys.h>
4882 +#include <plat/regs-syscon-power.h>
4883 +
4884 static void arch_idle(void)
4885 {
4886 - /* nothing here yet */
4887 + unsigned long flags;
4888 + u32 mode;
4889 +
4890 + /* ensure that if we execute the cpu idle sequence that we
4891 + * go into idle mode instead of powering off. */
4892 +
4893 + local_irq_save(flags);
4894 + mode = __raw_readl(S3C64XX_PWR_CFG);
4895 + mode &= ~S3C64XX_PWRCFG_CFG_WFI_MASK;
4896 + mode |= S3C64XX_PWRCFG_CFG_WFI_IDLE;
4897 + __raw_writel(mode, S3C64XX_PWR_CFG);
4898 +
4899 + local_irq_restore(flags);
4900 +
4901 + cpu_do_idle();
4902 }
4903
4904 static void arch_reset(char mode)
4905 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/include/mach/om-3d7k.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/include/mach/om-3d7k.h
4906 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/include/mach/om-3d7k.h 1970-01-01 01:00:00.000000000 +0100
4907 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/include/mach/om-3d7k.h 2009-05-10 22:27:59.000000000 +0200
4908 @@ -0,0 +1,98 @@
4909 +/*
4910 + * 3D7K GPIO Mappings
4911 + *
4912 + * (C) 2008 by Openmoko Inc.
4913 + * Author: Andy Green <andy@openmoko.com>
4914 + * All rights reserved.
4915 + *
4916 + * This program is free software; you can redistribute it and/or modify
4917 + * it under the terms of the GNU General Public License version 2 as
4918 + * published by the Free Software Foundation
4919 + *
4920 + */
4921 +
4922 +#ifndef _OM_3D7K_H
4923 +#define _OM_3D7K_H
4924 +
4925 +#include <mach/gpio.h>
4926 +#include <mach/irqs.h>
4927 +#include <linux/mfd/pcf50633/core.h>
4928 +
4929 +extern struct pcf50633 *om_3d7k_pcf;
4930 +
4931 +/* ATAG_REVISION from bootloader */
4932 +#define OM_3D7Kv1_SYSTEM_REV 0x00000001
4933 +
4934 +#define OM_3D7K_GPIO_VIBRATOR_ON S3C64XX_GPF(13)
4935 +#define OM_3D7K_GPIO_CLKOUT S3C64XX_GPF(14)
4936 +
4937 +#define OM_3D7K_GPIO_ACCEL_MISO S3C64XX_GPC(0)
4938 +#define OM_3D7K_GPIO_ACCEL_CLK S3C64XX_GPC(1)
4939 +#define OM_3D7K_GPIO_ACCEL_MOSI S3C64XX_GPC(2)
4940 +
4941 +#define OM_3D7K_GPIO_LCM_MISO S3C64XX_GPC(4)
4942 +#define OM_3D7K_GPIO_LCM_CLK S3C64XX_GPC(5)
4943 +#define OM_3D7K_GPIO_LCM_MOSI S3C64XX_GPC(6)
4944 +#define OM_3D7K_GPIO_LCM_CS S3C64XX_GPC(7)
4945 +
4946 +#define OM_3D7K_GPIO_BTPCM_SHARED_SCLK S3C64XX_GPE(0)
4947 +#define OM_3D7K_GPIO_BTPCM_SHARED_EXTCLK S3C64XX_GPE(1)
4948 +#define OM_3D7K_GPIO_BTPCM_SHARED_FSYNC S3C64XX_GPE(2)
4949 +#define OM_3D7K_GPIO_BTPCM_SHARED_SIN S3C64XX_GPE(3)
4950 +#define OM_3D7K_GPIO_BTPCM_SHARED_SOUT S3C64XX_GPE(4)
4951 +
4952 +#define OM_3D7K_GPIO_WLAN_RESET S3C64XX_GPH(6)
4953 +#define OM_3D7K_GPIO_HDQ S3C64XX_GPH(7)
4954 +#define OM_3D7K_GPIO_WLAN_PWRDN S3C64XX_GPH(8)
4955 +
4956 +#define OM_3D7K_GPIO_VERSION2 S3C64XX_GPI(0)
4957 +#define OM_3D7K_GPIO_VERSION1 S3C64XX_GPI(1)
4958 +#define OM_3D7K_GPIO_VERSION0 S3C64XX_GPI(8)
4959 +
4960 +#define OM_3D7K_GPIO_NWLAN_POWER S3C64XX_GPK(0)
4961 +#define OM_3D7K_GPIO_MODEM_ON S3C64XX_GPK(2)
4962 +#define OM_3D7K_GPIO_LED_TRIG S3C64XX_GPK(3)
4963 +#define OM_3D7K_GPIO_LED_EN S3C64XX_GPK(4)
4964 +#define OM_3D7K_GPIO_LCM_RESET S3C64XX_GPK(6)
4965 +
4966 +#define OM_3D7K_GPIO_LCM_SD S3C64XX_GPL(0)
4967 +
4968 +#define OM_3D7K_GPIO_TP_RESET S3C64XX_GPM(0)
4969 +#define OM_3D7K_GPIO_GPS_LNA_EN S3C64XX_GPM(2)
4970 +
4971 +#define OM_3D7K_GPIO_USB_FLT S3C64XX_GPM(4)
4972 +#define OM_3D7K_GPIO_USB_OC S3C64XX_GPM(5)
4973 +
4974 +#define OM_3D7K_GPIO_ACCEL_INT1 S3C64XX_GPN(0)
4975 +#define OM_3D7K_GPIO_KEY_MINUS S3C64XX_GPN(1)
4976 +#define OM_3D7K_GPIO_KEY_PLUS S3C64XX_GPN(2)
4977 +#define OM_3D7K_GPIO_PWR_IND S3C64XX_GPN(3)
4978 +#define OM_3D7K_GPIO_PWR_IRQ S3C64XX_GPN(4)
4979 +#define OM_3D7K_GPIO_TOUCH S3C64XX_GPN(5)
4980 +#define OM_3D7K_GPIO_JACK_INSERT S3C64XX_GPN(6)
4981 +#define OM_3D7K_GPIO_GPS_INT S3C64XX_GPN(7)
4982 +#define OM_3D7K_GPIO_HOLD S3C64XX_GPN(8)
4983 +#define OM_3D7K_GPIO_WLAN_WAKEUP S3C64XX_GPN(9)
4984 +#define OM_3D7K_GPIO_ACCEL_INT2 S3C64XX_GPN(10)
4985 +#define OM_3D7K_GPIO_IO1 S3C64XX_GPN(11)
4986 +#define OM_3D7K_GPIO_NONKEYWAKE S3C64XX_GPN(12)
4987 +
4988 +#define OM_3D7K_GPIO_N_MODEM_RESET S3C64XX_GPO(1)
4989 +
4990 +#define OM_3D7K_IRQ_GSENSOR_1 S3C_EINT(0)
4991 +#define OM_3D7K_IRQ_KEY_MINUS S3C_EINT(1)
4992 +#define OM_3D7K_IRQ_KEY_PLUS S3C_EINT(2)
4993 +#define OM_3D7K_IRQ_PWR_IND S3C_EINT(3)
4994 +#define OM_3D7K_IRQ_PMU S3C_EINT(4)
4995 +#define OM_3D7K_IRQ_TOUCH S3C_EINT(5)
4996 +#define OM_3D7K_IRQ_JACK_INSERT S3C_EINT(6)
4997 +#define OM_3D7K_IRQ_GPS_INT S3C_EINT(7)
4998 +#define OM_3D7K_IRQ_NHOLD S3C_EINT(8)
4999 +#define OM_3D7K_IRQ_WLAN_WAKEUP S3C_EINT(9)
5000 +#define OM_3D7K_IRQ_GSENSOR_2 S3C_EINT(10)
5001 +#define OM_3D7K_IRQ_IO1 S3C_EINT(11)
5002 +#define OM_3D7K_IRQ_NONKEYWAKE S3C_EINT(12)
5003 +
5004 +#define OM_3D7K_IRQ_LED IRQ_EINT_GROUP(6, 9)
5005 +
5006 +#endif /* _OM_3D7K_H */
5007 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/include/mach/spi-gpio.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/include/mach/spi-gpio.h
5008 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/include/mach/spi-gpio.h 1970-01-01 01:00:00.000000000 +0100
5009 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/include/mach/spi-gpio.h 2009-05-10 22:27:59.000000000 +0200
5010 @@ -0,0 +1,28 @@
5011 +/* arch/arm/mach-s3c6400/include/mach/spi-gpio.h
5012 + *
5013 + * Copyright (c) 2006 Simtec Electronics
5014 + * Ben Dooks <ben@simtec.co.uk>
5015 + *
5016 + * S3C64XX - SPI Controller platfrom_device info
5017 + *
5018 + * This program is free software; you can redistribute it and/or modify
5019 + * it under the terms of the GNU General Public License version 2 as
5020 + * published by the Free Software Foundation.
5021 +*/
5022 +
5023 +#ifndef __ASM_ARCH_SPIGPIO_H
5024 +#define __ASM_ARCH_SPIGPIO_H __FILE__
5025 +
5026 +struct s3c64xx_spigpio_info {
5027 + unsigned long pin_clk;
5028 + unsigned long pin_mosi;
5029 + unsigned long pin_miso;
5030 +
5031 + int bus_num;
5032 + int num_chipselect;
5033 +
5034 + void (*chip_select)(struct s3c64xx_spigpio_info *spi, int csid, int cs);
5035 +};
5036 +
5037 +
5038 +#endif /* __ASM_ARCH_SPIGPIO_H */
5039 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/Kconfig linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/Kconfig
5040 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/Kconfig 2009-05-10 22:05:04.000000000 +0200
5041 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/Kconfig 2009-05-10 22:27:59.000000000 +0200
5042 @@ -26,6 +26,7 @@
5043 select S3C_DEV_HSMMC1
5044 select S3C_DEV_I2C1
5045 select S3C_DEV_FB
5046 + select S3C_DEV_USB_HOST
5047 select S3C6410_SETUP_SDHCI
5048 select S3C64XX_SETUP_I2C1
5049 select S3C64XX_SETUP_FB_24BPP
5050 @@ -60,3 +61,25 @@
5051 channels 0 and 1 are the same.
5052
5053 endchoice
5054 +
5055 +config MACH_OM_3D7K
5056 + bool "Openmoko 3D7K Phone"
5057 + select CPU_S3C6410
5058 + select S3C_DEV_HSMMC
5059 + select S3C_DEV_HSMMC1
5060 + select S3C_DEV_I2C1
5061 + select S3C_DEV_USB_HOST
5062 + select S3C6410_SETUP_SDHCI
5063 + select S3C64XX_SETUP_I2C1
5064 + select S3C_DEV_FB
5065 + select S3C_DEV_CAMIF
5066 + select S3C64XX_SETUP_FB_24BPP
5067 +# select SENSORS_PCF50633
5068 + select POWER_SUPPLY
5069 + select HDQ_GPIO_BITBANG
5070 + select S3C_PWM
5071 + select FIQ
5072 + select MACH_NEO1973
5073 + help
5074 + Machine support for the Openmoko 3D7K Phone
5075 +
5076 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/mach-om-3d7k.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/mach-om-3d7k.c
5077 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/mach-om-3d7k.c 1970-01-01 01:00:00.000000000 +0100
5078 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/mach-om-3d7k.c 2009-05-10 22:27:59.000000000 +0200
5079 @@ -0,0 +1,1196 @@
5080 +/* linux/arch/arm/mach-s3c6410/mach-om-3d7k.c
5081 + *
5082 + * Copyright 2008 Openmoko, Inc.
5083 + * Andy Green <andy@openmoko.org>
5084 + *
5085 + * based on mach_smdk6410.c which is
5086 + *
5087 + * Copyright 2008 Openmoko, Inc.
5088 + * Copyright 2008 Simtec Electronics
5089 + * Ben Dooks <ben@simtec.co.uk>
5090 + * http://armlinux.simtec.co.uk/
5091 + *
5092 + * This program is free software; you can redistribute it and/or modify
5093 + * it under the terms of the GNU General Public License version 2 as
5094 + * published by the Free Software Foundation.
5095 + *
5096 +*/
5097 +
5098 +#include <linux/kernel.h>
5099 +#include <linux/types.h>
5100 +#include <linux/interrupt.h>
5101 +#include <linux/list.h>
5102 +#include <linux/timer.h>
5103 +#include <linux/init.h>
5104 +#include <linux/serial_core.h>
5105 +#include <linux/platform_device.h>
5106 +#include <linux/io.h>
5107 +#include <linux/i2c.h>
5108 +#include <linux/fb.h>
5109 +#include <linux/delay.h>
5110 +#include <linux/lis302dl.h>
5111 +#include <linux/lp5521.h>
5112 +#include <linux/spi/spi_bitbang.h>
5113 +#include <linux/l1k002.h>
5114 +#include <linux/pcap7200.h>
5115 +#include <linux/bq27000_battery.h>
5116 +#include <linux/hdq.h>
5117 +#include <linux/jbt6k74.h>
5118 +
5119 +#include <video/platform_lcd.h>
5120 +
5121 +#include <asm/mach/arch.h>
5122 +#include <asm/mach/map.h>
5123 +#include <asm/mach/irq.h>
5124 +
5125 +#include <mach/hardware.h>
5126 +#include <asm/hardware/vic.h>
5127 +#include <asm/hardware/tzic-sp890.h>
5128 +#include <mach/map.h>
5129 +#include <mach/regs-fb.h>
5130 +#include <mach/spi-gpio.h>
5131 +
5132 +#include <asm/irq.h>
5133 +#include <asm/mach-types.h>
5134 +#include <asm/fiq.h>
5135 +
5136 +#include <plat/regs-serial.h>
5137 +#include <plat/regs-timer.h>
5138 +#include <plat/regs-gpio.h>
5139 +#include <plat/iic.h>
5140 +#include <plat/fb.h>
5141 +#include <plat/gpio-cfg.h>
5142 +#include <plat/pm.h>
5143 +#include <plat/pwm.h>
5144 +
5145 +#include <plat/s3c6410.h>
5146 +#include <plat/clock.h>
5147 +#include <plat/devs.h>
5148 +#include <plat/cpu.h>
5149 +#include <plat/tzic-sp890.h>
5150 +#include <plat/usb-control.h>
5151 +
5152 +/* #include <plat/udc.h> */
5153 +#include <linux/i2c.h>
5154 +#include <linux/backlight.h>
5155 +#include <linux/regulator/machine.h>
5156 +
5157 +#include <mach/om-3d7k.h>
5158 +
5159 +#include <linux/mfd/pcf50633/core.h>
5160 +#include <linux/mfd/pcf50633/mbc.h>
5161 +#include <linux/mfd/pcf50633/adc.h>
5162 +#include <linux/mfd/pcf50633/gpio.h>
5163 +#include <linux/mfd/pcf50633/pmic.h>
5164 +
5165 +#include <plat/regs-usb-hs-otg.h>
5166 +
5167 +extern struct platform_device s3c_device_usbgadget;
5168 +extern struct platform_device s3c_device_camif; /* @@@ change plat/devs.h */
5169 +
5170 +
5171 +/* -------------------------------------------------------------------------------
5172 + * OM_3D7K FIQ related
5173 + *
5174 + * Calls into vibrator and hdq and based on the return values
5175 + * determines if we the FIQ source be kept alive
5176 + */
5177 +
5178 +#define DIVISOR_FROM_US(x) ((x) * 23)
5179 +
5180 +#ifdef CONFIG_HDQ_GPIO_BITBANG
5181 +#define FIQ_DIVISOR_HDQ DIVISOR_FROM_US(HDQ_SAMPLE_PERIOD_US)
5182 +extern int hdq_fiq_handler(void);
5183 +#endif
5184 +
5185 +/* Global data related to our fiq source */
5186 +static u32 om_3d7k_fiq_ack_mask;
5187 +static u32 om_3d7k_fiq_mod_mask;
5188 +static struct s3c2410_pwm om_3d7k_fiq_pwm_timer;
5189 +static u16 om_3d7k_fiq_timer_index;
5190 +static int om_3d7k_fiq_irq;
5191 +
5192 +/* Convinience defines */
5193 +#define S3C6410_INTMSK (S3C_VA_VIC0 + VIC_INT_ENABLE)
5194 +#define S3C6410_INTMOD (S3C_VA_VIC0 + VIC_INT_SELECT)
5195 +
5196 +
5197 +
5198 +static void om_3d7k_fiq_handler(void)
5199 +{
5200 + u16 divisor = 0xffff;
5201 +
5202 + /* Vibrator servicing */
5203 +
5204 + /* disable further timer interrupts if nobody has any work
5205 + * or adjust rate according to who still has work
5206 + *
5207 + * CAUTION: it means forground code must disable FIQ around
5208 + * its own non-atomic S3C2410_INTMSK changes... not common
5209 + * thankfully and taken care of by the fiq-basis patch
5210 + */
5211 +
5212 +#ifdef CONFIG_HDQ_GPIO_BITBANG
5213 + if (hdq_fiq_handler())
5214 + divisor = (u16)FIQ_DIVISOR_HDQ;
5215 +#endif
5216 +
5217 + if (divisor == 0xffff) /* mask the fiq irq source */
5218 + __raw_writel((__raw_readl(S3C64XX_TINT_CSTAT) & 0x1f) & ~(1 << 3),
5219 + S3C64XX_TINT_CSTAT);
5220 + else /* still working, maybe at a different rate */
5221 + __raw_writel(divisor, S3C2410_TCNTB(om_3d7k_fiq_timer_index));
5222 +
5223 + __raw_writel((__raw_readl(S3C64XX_TINT_CSTAT) & 0x1f ) | 1 << 8 , S3C64XX_TINT_CSTAT);
5224 +
5225 +}
5226 +
5227 +static void om_3d7k_fiq_kick(void)
5228 +{
5229 + unsigned long flags;
5230 + u32 tcon;
5231 +
5232 + /* we have to take care about FIQ because this modification is
5233 + * non-atomic, FIQ could come in after the read and before the
5234 + * writeback and its changes to the register would be lost
5235 + * (platform INTMSK mod code is taken care of already)
5236 + */
5237 + local_save_flags(flags);
5238 + local_fiq_disable();
5239 + /* allow FIQs to resume */
5240 + __raw_writel((__raw_readl(S3C64XX_TINT_CSTAT) & 0x1f)| 1 << 3,
5241 + S3C64XX_TINT_CSTAT);
5242 +
5243 + tcon = __raw_readl(S3C2410_TCON) & ~S3C2410_TCON_T3START;
5244 + /* fake the timer to a count of 1 */
5245 + __raw_writel(1, S3C2410_TCNTB(om_3d7k_fiq_timer_index));
5246 + __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD, S3C2410_TCON);
5247 + __raw_writel(tcon | S3C2410_TCON_T3MANUALUPD | S3C2410_TCON_T3START,
5248 + S3C2410_TCON);
5249 + __raw_writel(tcon | S3C2410_TCON_T3START, S3C2410_TCON);
5250 + local_irq_restore(flags);
5251 +}
5252 +
5253 +static int om_3d7k_fiq_enable(void)
5254 +{
5255 + int irq_index_fiq = IRQ_TIMER3_VIC;
5256 + int rc = 0;
5257 +
5258 + local_fiq_disable();
5259 +
5260 + om_3d7k_fiq_irq = irq_index_fiq;
5261 + om_3d7k_fiq_ack_mask = 1 << 3;
5262 + om_3d7k_fiq_mod_mask = 1 << 27;
5263 + om_3d7k_fiq_timer_index = 3;
5264 +
5265 + /* set up the timer to operate as a pwm device */
5266 +
5267 + rc = s3c2410_pwm_init(&om_3d7k_fiq_pwm_timer);
5268 + if (rc)
5269 + goto bail;
5270 +
5271 + om_3d7k_fiq_pwm_timer.timerid = PWM0 + om_3d7k_fiq_timer_index;
5272 + om_3d7k_fiq_pwm_timer.prescaler = ((6 - 1) / 2);
5273 + om_3d7k_fiq_pwm_timer.divider = S3C64XX_TCFG1_MUX_DIV2 << S3C2410_TCFG1_SHIFT(3);
5274 + /* default rate == ~32us */
5275 + om_3d7k_fiq_pwm_timer.counter = om_3d7k_fiq_pwm_timer.comparer = 3000;
5276 +
5277 + rc = s3c2410_pwm_enable(&om_3d7k_fiq_pwm_timer);
5278 + if (rc)
5279 + goto bail;
5280 +
5281 + /* let our selected interrupt be a magic FIQ interrupt */
5282 + __raw_writel(om_3d7k_fiq_mod_mask, S3C6410_INTMSK + 4);
5283 + __raw_writel(om_3d7k_fiq_mod_mask, S3C6410_INTMOD);
5284 + __raw_writel(om_3d7k_fiq_mod_mask, S3C6410_INTMSK);
5285 +
5286 + __raw_writel(SP890_TZIC_UNLOCK_MAGIC, S3C64XX_VA_TZIC0_LOCK);
5287 + __raw_writel(om_3d7k_fiq_mod_mask, S3C64XX_VA_TZIC0_FIQENABLE);
5288 + __raw_writel(om_3d7k_fiq_mod_mask, S3C64XX_VA_TZIC0_INTSELECT);
5289 +
5290 + s3c2410_pwm_start(&om_3d7k_fiq_pwm_timer);
5291 +
5292 + /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */
5293 + local_fiq_enable();
5294 +
5295 + set_fiq_c_handler(om_3d7k_fiq_handler);
5296 +
5297 + if (rc < 0)
5298 + goto bail;
5299 +
5300 + return 0;
5301 +bail:
5302 + printk(KERN_ERR "Count not initialize FIQ for OM_3D7K %d \n", rc);
5303 + return rc;
5304 +}
5305 +
5306 +static void om_3d7k_fiq_disable(void)
5307 +{
5308 + __raw_writel(0, S3C6410_INTMOD);
5309 + local_fiq_disable();
5310 + om_3d7k_fiq_irq = 0; /* no active source interrupt now either */
5311 +
5312 +}
5313 +/* -------------------- /OM_3D7K FIQ Handler ------------------------------------- */
5314 +
5315 +#define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
5316 +#define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
5317 +#define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
5318 +
5319 +static struct s3c2410_uartcfg om_3d7k_uartcfgs[] __initdata = {
5320 + [0] = {
5321 + .hwport = 0,
5322 + .flags = 0,
5323 + .ucon = 0x3c5,
5324 + .ulcon = 0x03,
5325 + .ufcon = 0x51,
5326 + },
5327 + [1] = {
5328 + .hwport = 1,
5329 + .flags = 0,
5330 + .ucon = 0x3c5,
5331 + .ulcon = 0x03,
5332 + .ufcon = 0x51,
5333 + },
5334 + [2] = {
5335 + .hwport = 2,
5336 + .flags = 0,
5337 + .ucon = 0x3c5,
5338 + .ulcon = 0x03,
5339 + .ufcon = 0x51,
5340 + },
5341 + [3] = {
5342 + .hwport = 3,
5343 + .flags = 0,
5344 + .ucon = 0x3c5,
5345 + .ulcon = 0x03,
5346 + .ufcon = 0x51,
5347 + },
5348 +};
5349 +
5350 +
5351 +/*
5352 + * Situation is that Linux SPI can't work in an interrupt context, so we
5353 + * implement our own bitbang here. Arbitration is needed because not only
5354 + * can this interrupt happen at any time even if foreground wants to use
5355 + * the bitbang API from Linux, but multiple motion sensors can be on the
5356 + * same SPI bus, and multiple interrupts can happen.
5357 + *
5358 + * Foreground / interrupt arbitration is okay because the interrupts are
5359 + * disabled around all the foreground SPI code.
5360 + *
5361 + * Interrupt / Interrupt arbitration is evidently needed, otherwise we
5362 + * lose edge-triggered service after a while due to the two sensors sharing
5363 + * the SPI bus having irqs at the same time eventually.
5364 + *
5365 + * Servicing is typ 75 - 100us at 400MHz.
5366 + */
5367 +
5368 +/* #define DEBUG_SPEW_MS */
5369 +#define MG_PER_SAMPLE 18
5370 +
5371 +struct lis302dl_platform_data lis302_pdata;
5372 +
5373 +/*
5374 + * generic SPI RX and TX bitbang
5375 + * only call with interrupts off!
5376 + */
5377 +
5378 +static void __3d7k_lis302dl_bitbang(struct lis302dl_info *lis, u8 *tx,
5379 + int tx_bytes, u8 *rx, int rx_bytes)
5380 +{
5381 + struct lis302dl_platform_data *pdata = lis->pdata;
5382 + int n;
5383 + u8 shifter = 0;
5384 +
5385 + gpio_direction_output(pdata->pin_chip_select, 1);
5386 + gpio_direction_output(pdata->pin_clk, 1);
5387 + gpio_direction_output(pdata->pin_chip_select, 0);
5388 +
5389 + /* send the register index, r/w and autoinc bits */
5390 + for (n = 0; n < (tx_bytes << 3); n++) {
5391 + if (!(n & 7))
5392 + shifter = ~tx[n >> 3];
5393 + gpio_direction_output(pdata->pin_clk, 0);
5394 + gpio_direction_output(pdata->pin_mosi, !(shifter & 0x80));
5395 + gpio_direction_output(pdata->pin_clk, 1);
5396 + shifter <<= 1;
5397 + }
5398 +
5399 + for (n = 0; n < (rx_bytes << 3); n++) { /* 8 bits each */
5400 + gpio_direction_output(pdata->pin_clk, 0);
5401 + shifter <<= 1;
5402 + if (gpio_direction_input(pdata->pin_miso))
5403 + shifter |= 1;
5404 + if ((n & 7) == 7)
5405 + rx[n >> 3] = shifter;
5406 + gpio_direction_output(pdata->pin_clk, 1);
5407 + }
5408 + gpio_direction_output(pdata->pin_chip_select, 1);
5409 +}
5410 +
5411 +
5412 +static int om_3d7k_lis302dl_bitbang_read_reg(struct lis302dl_info *lis, u8 reg)
5413 +{
5414 + u8 data = 0xc0 | reg; /* read, autoincrement */
5415 + unsigned long flags;
5416 +
5417 + local_irq_save(flags);
5418 +
5419 + __3d7k_lis302dl_bitbang(lis, &data, 1, &data, 1);
5420 +
5421 + local_irq_restore(flags);
5422 +
5423 + return data;
5424 +}
5425 +
5426 +static void om_3d7k_lis302dl_bitbang_write_reg(struct lis302dl_info *lis, u8 reg,
5427 + u8 val)
5428 +{
5429 + u8 data[2] = { 0x00 | reg, val }; /* write, no autoincrement */
5430 + unsigned long flags;
5431 +
5432 + local_irq_save(flags);
5433 +
5434 + __3d7k_lis302dl_bitbang(lis, &data[0], 2, NULL, 0);
5435 +
5436 + local_irq_restore(flags);
5437 +
5438 +}
5439 +
5440 +
5441 +void om_3d7k_lis302dl_suspend_io(struct lis302dl_info *lis, int resume)
5442 +{
5443 + struct lis302dl_platform_data *pdata = lis->pdata;
5444 +
5445 + if (!resume) {
5446 + /*
5447 + * we don't want to power them with a high level
5448 + * because GSENSOR_3V3 is not up during suspend
5449 + */
5450 + gpio_direction_output(pdata->pin_chip_select, 0);
5451 + gpio_direction_output(pdata->pin_clk, 0);
5452 + gpio_direction_output(pdata->pin_mosi, 0);
5453 + s3c_gpio_setpull(pdata->pin_miso, S3C_GPIO_PULL_DOWN);
5454 +
5455 + return;
5456 + }
5457 +
5458 + /* back to normal */
5459 + gpio_direction_output(pdata->pin_chip_select, 1);
5460 + gpio_direction_output(pdata->pin_clk, 1);
5461 + s3c_gpio_setpull(pdata->pin_miso, S3C_GPIO_PULL_NONE);
5462 +
5463 + s3c_gpio_cfgpin(pdata->pin_chip_select, S3C_GPIO_SFN(1));
5464 + s3c_gpio_cfgpin(pdata->pin_clk, S3C_GPIO_SFN(1));
5465 + s3c_gpio_cfgpin(pdata->pin_mosi, S3C_GPIO_SFN(1));
5466 + s3c_gpio_cfgpin(pdata->pin_miso, S3C_GPIO_SFN(0));
5467 +
5468 +}
5469 +#if 0
5470 +struct lis302dl_platform_data lis302_pdata = {
5471 + .name = "lis302",
5472 + .pin_chip_select= S3C64XX_GPC(3), /* NC */
5473 + .pin_clk = OM_3D7K_GPIO_ACCEL_CLK,
5474 + .pin_mosi = OM_3D7K_GPIO_ACCEL_MOSI,
5475 + .pin_miso = OM_3D7K_GPIO_ACCEL_MISO,
5476 + .interrupt = OM_3D7K_IRQ_GSENSOR_1,
5477 + .open_drain = 0,
5478 + .lis302dl_bitbang = __3d7k_lis302dl_bitbang,
5479 + .lis302dl_bitbang_reg_read = om_3d7k_lis302dl_bitbang_read_reg,
5480 + .lis302dl_bitbang_reg_write = om_3d7k_lis302dl_bitbang_write_reg,
5481 + .lis302dl_suspend_io = om_3d7k_lis302dl_suspend_io,
5482 +};
5483 +
5484 +static struct platform_device s3c_device_spi_acc1 = {
5485 + .name = "lis302dl",
5486 + .id = 1,
5487 + .dev = {
5488 + .platform_data = &lis302_pdata,
5489 + },
5490 +};
5491 +
5492 +#endif
5493 +
5494 +/* framebuffer and LCD setup. */
5495 +
5496 +/* GPF15 = LCD backlight control
5497 + * GPF13 => Panel power
5498 + * GPN5 = LCD nRESET signal
5499 + * PWM_TOUT1 => backlight brightness
5500 + */
5501 +
5502 +static void om_3d7k_lcd_power_set(struct plat_lcd_data *pd,
5503 + unsigned int power)
5504 +{
5505 +
5506 +}
5507 +
5508 +static struct plat_lcd_data om_3d7k_lcd_power_data = {
5509 + .set_power = om_3d7k_lcd_power_set,
5510 +};
5511 +
5512 +static struct platform_device om_3d7k_lcd_powerdev = {
5513 + .name = "platform-lcd",
5514 + .dev.parent = &s3c_device_fb.dev,
5515 + .dev.platform_data = &om_3d7k_lcd_power_data,
5516 +};
5517 +
5518 +static struct s3c_fb_pd_win om_3d7k_fb_win0 = {
5519 + /* this is to ensure we use win0 */
5520 + .win_mode = {
5521 + .pixclock = 40816,
5522 + .left_margin = 8,
5523 + .right_margin = 16,
5524 + .upper_margin = 2,
5525 + .lower_margin = 16,
5526 + .hsync_len = 8,
5527 + .vsync_len = 2,
5528 + .xres = 480,
5529 + .yres = 640,
5530 + },
5531 + .max_bpp = 32,
5532 + .default_bpp = 16,
5533 +};
5534 +
5535 +static void om_3d7k_fb_gpio_setup(void)
5536 +{
5537 + unsigned int gpio;
5538 +
5539 + /* GPI0, GPI1, GPI8 are for hardware version contrl.
5540 + * They should be set as input in order to prevent
5541 + * current leaking
5542 + */
5543 + for (gpio = S3C64XX_GPI(2); gpio <= S3C64XX_GPI(15); gpio++) {
5544 + if (gpio != S3C64XX_GPI(8)) {
5545 + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
5546 + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
5547 + }
5548 + }
5549 +
5550 + for (gpio = S3C64XX_GPJ(0); gpio <= S3C64XX_GPJ(11); gpio++) {
5551 + s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
5552 + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
5553 + }
5554 +}
5555 +
5556 +static struct s3c_fb_platdata om_3d7k_lcd_pdata __initdata = {
5557 + .setup_gpio = om_3d7k_fb_gpio_setup,
5558 + .win[0] = &om_3d7k_fb_win0,
5559 + .vidcon0 = VIDCON0_VIDOUT_RGB | VIDCON0_PNRMODE_RGB,
5560 + .vidcon1 = VIDCON1_INV_HSYNC | VIDCON1_INV_VSYNC,
5561 +};
5562 +
5563 +
5564 +struct map_desc om_3d7k_6410_iodesc[] = {};
5565 +
5566 +static struct resource om_3d7k_button_resources[] = {
5567 + [0] = {
5568 + .start = 0,
5569 + .end = 0,
5570 + },
5571 + [1] = {
5572 + .start = OM_3D7K_GPIO_HOLD,
5573 + .end = OM_3D7K_GPIO_HOLD,
5574 + },
5575 + [2] = {
5576 + .start = OM_3D7K_GPIO_JACK_INSERT,
5577 + .end = OM_3D7K_GPIO_JACK_INSERT,
5578 + },
5579 + [3] = {
5580 + .start = OM_3D7K_GPIO_KEY_PLUS,
5581 + .end = OM_3D7K_GPIO_KEY_PLUS,
5582 + },
5583 + [4] = {
5584 + .start = OM_3D7K_GPIO_KEY_MINUS,
5585 + .end = OM_3D7K_GPIO_KEY_MINUS,
5586 + },
5587 +};
5588 +
5589 +static struct platform_device om_3d7k_button_dev = {
5590 + .name = "neo1973-button",
5591 + .num_resources = ARRAY_SIZE(om_3d7k_button_resources),
5592 + .resource = om_3d7k_button_resources,
5593 +};
5594 +
5595 +
5596 +/********************** PMU ***************************/
5597 +/*
5598 + * OM_3D7K PMU Mapping info
5599 + *
5600 + * name maxcurr default Nom consumers
5601 + *
5602 + * AUTO 1100mA ON 3.3V 3.3V Main 3.3V rail
5603 + * DOWN1 500mA ON 1.2V 1.2V CPU VddARM, VddINT, VddMPLL, VddOTGI
5604 + * DOWN2 500mA ON 1.8V 1.8V CPU VddAlive via LDO, Memories, WLAN
5605 + * LED 25mA OFF 18V Backlight
5606 + * HCLDO 200mA OFF 2.8V Camera 2V8
5607 + * LDO1 50mA ON 3.3V 3.3V Accel
5608 + * LDO2 50mA OFF 1.5V Camera 1V5
5609 + * LDO3 50mA OFF 3.3V CODEC 3.3V
5610 + * LDO4 150mA ON 2.8V 2.7V uSD power
5611 + * LDO5 150mA OFF 3.0V GPS 3V
5612 + * LDO6 50mA ON 3.0V 3.0V LCM 3V
5613 + *
5614 + */
5615 +
5616 +
5617 +/* PMU driver info */
5618 +
5619 +
5620 +static struct regulator_consumer_supply ldo4_consumers[] = {
5621 + {
5622 + .dev = &s3c_device_hsmmc0.dev,
5623 + .supply = "SD_3V",
5624 + },
5625 +};
5626 +
5627 +static struct platform_device om_3d7k_features_dev = {
5628 + .name = "om-3d7k",
5629 +};
5630 +
5631 +static struct regulator_consumer_supply ldo5_consumers[] = {
5632 + {
5633 + .dev = &om_3d7k_features_dev.dev,
5634 + .supply = "RF_3V",
5635 + },
5636 +};
5637 +
5638 +
5639 +static void om_3d7k_pmu_event_callback(struct pcf50633 *pcf, int irq)
5640 +{
5641 +#if 0
5642 + if (irq == PCF50633_IRQ_USBINS) {
5643 + schedule_delayed_work(&om_3d7k_charger_work,
5644 + GTA02_CHARGER_CONFIGURE_TIMEOUT);
5645 + return;
5646 + } else if (irq == PCF50633_IRQ_USBREM) {
5647 + cancel_delayed_work_sync(&om_3d7k_charger_work);
5648 + pcf50633_mbc_usb_curlim_set(pcf, 0);
5649 + om_3d7k_usb_vbus_draw = 0;
5650 + }
5651 +
5652 + bq27000_charging_state_change(&bq27000_battery_device);
5653 +#endif
5654 +}
5655 +
5656 +static void om_3d7k_pcf50633_attach_child_devices(struct pcf50633 *pcf);
5657 +static void om_3d7k_pmu_regulator_registered(struct pcf50633 *pcf, int id);
5658 +
5659 +/* Global reference */
5660 +struct pcf50633 *om_3d7k_pcf;
5661 +
5662 +struct pcf50633_platform_data om_3d7k_pcf_pdata = {
5663 +
5664 + .resumers = {
5665 + [0] = PCF50633_INT1_USBINS |
5666 + PCF50633_INT1_USBREM |
5667 + PCF50633_INT1_ALARM,
5668 + [1] = PCF50633_INT2_ONKEYF,
5669 + [2] = PCF50633_INT3_ONKEY1S
5670 + },
5671 + .chg_ref_current_ma = 1000,
5672 + .reg_init_data = {
5673 + /* OM_3D7K: Main 3.3V rail */
5674 + [PCF50633_REGULATOR_AUTO] = {
5675 + .constraints = {
5676 + .min_uV = 3300000,
5677 + .max_uV = 3300000,
5678 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5679 + .apply_uV = 1,
5680 + .state_mem = {
5681 + .enabled = 1,
5682 + },
5683 + },
5684 + .num_consumer_supplies = 0,
5685 + },
5686 + /* OM_3D7K: CPU core power */
5687 + [PCF50633_REGULATOR_DOWN1] = {
5688 + .constraints = {
5689 + .min_uV = 900000,
5690 + .max_uV = 1200000,
5691 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5692 + .apply_uV = 1,
5693 + },
5694 + .num_consumer_supplies = 0,
5695 + },
5696 + /* OM_3D7K: Memories */
5697 + [PCF50633_REGULATOR_DOWN2] = {
5698 + .constraints = {
5699 + .min_uV = 1800000,
5700 + .max_uV = 1800000,
5701 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5702 + .apply_uV = 1,
5703 + .state_mem = {
5704 + .enabled = 1,
5705 + },
5706 + },
5707 + .num_consumer_supplies = 0,
5708 + },
5709 + /* OM_3D7K: Camera 2V8 */
5710 + [PCF50633_REGULATOR_HCLDO] = {
5711 + .constraints = {
5712 + .min_uV = 2800000,
5713 + .max_uV = 2800000,
5714 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5715 + },
5716 + .num_consumer_supplies = 0,
5717 +/* .consumer_supplies = hcldo_consumers, */
5718 + },
5719 +
5720 + /* OM_3D7K: Accel 3V3 */
5721 + [PCF50633_REGULATOR_LDO1] = {
5722 + .constraints = {
5723 + .min_uV = 3300000,
5724 + .max_uV = 3300000,
5725 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5726 + .apply_uV = 1,
5727 + },
5728 + .num_consumer_supplies = 0,
5729 + },
5730 + /* OM_3D7K: Camera 1V5 */
5731 + [PCF50633_REGULATOR_LDO2] = {
5732 + .constraints = {
5733 + .min_uV = 1500000,
5734 + .max_uV = 1500000,
5735 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5736 + .apply_uV = 1,
5737 + },
5738 + .num_consumer_supplies = 0,
5739 + },
5740 + /* OM_3D7K: Codec 3.3V */
5741 + [PCF50633_REGULATOR_LDO3] = {
5742 + .constraints = {
5743 + .min_uV = 3300000,
5744 + .max_uV = 3300000,
5745 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5746 + .apply_uV = 1,
5747 + .always_on = 1,
5748 + },
5749 + .num_consumer_supplies = 0,
5750 + },
5751 + /* OM_3D7K: uSD Power */
5752 + [PCF50633_REGULATOR_LDO4] = {
5753 + .constraints = {
5754 + .min_uV = 3000000,
5755 + .max_uV = 3000000,
5756 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5757 + .apply_uV = 1,
5758 + },
5759 + .num_consumer_supplies = 1,
5760 + .consumer_supplies = ldo4_consumers,
5761 + },
5762 + /* OM_3D7K: GPS 3V */
5763 + [PCF50633_REGULATOR_LDO5] = {
5764 + .constraints = {
5765 + .min_uV = 3000000,
5766 + .max_uV = 3000000,
5767 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5768 + .apply_uV = 1,
5769 + },
5770 + .num_consumer_supplies = 1,
5771 + .consumer_supplies = ldo5_consumers,
5772 + },
5773 + /* OM_3D7K: LCM 3V */
5774 + [PCF50633_REGULATOR_LDO6] = {
5775 + .constraints = {
5776 + .min_uV = 3000000,
5777 + .max_uV = 3000000,
5778 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5779 + .state_mem = {
5780 + .enabled = 1,
5781 + },
5782 + },
5783 + .num_consumer_supplies = 0,
5784 + },
5785 + /* power for memories in suspend */
5786 + [PCF50633_REGULATOR_MEMLDO] = {
5787 + .constraints = {
5788 + .min_uV = 1800000,
5789 + .max_uV = 1800000,
5790 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5791 + .state_mem = {
5792 + .enabled = 1,
5793 + },
5794 + },
5795 + .num_consumer_supplies = 0,
5796 + },
5797 +
5798 + },
5799 + .probe_done = om_3d7k_pcf50633_attach_child_devices,
5800 + .regulator_registered = om_3d7k_pmu_regulator_registered,
5801 + .mbc_event_callback = om_3d7k_pmu_event_callback,
5802 +};
5803 +
5804 +static void om_3d7k_bl_set_intensity(int intensity)
5805 +{
5806 + struct pcf50633 *pcf = om_3d7k_pcf;
5807 + int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
5808 + int ret;
5809 +
5810 + intensity >>= 2;
5811 +
5812 + /*
5813 + * One code path that leads here is from a kernel panic. Trying to turn
5814 + * the backlight on just gives us a nearly endless stream of complaints
5815 + * and accomplishes nothing. We can't win. Just give up.
5816 + *
5817 + * In the unlikely event that there's another path leading here while
5818 + * we're atomic, we print at least a warning.
5819 + */
5820 + if (in_atomic()) {
5821 + printk(KERN_ERR
5822 + "3d7k_bl_set_intensity called while atomic\n");
5823 + return;
5824 + }
5825 +
5826 + old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
5827 + if (intensity == old_intensity)
5828 + return;
5829 +
5830 + /* We can't do this anywhere else */
5831 + pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5);
5832 +
5833 + if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3))
5834 + old_intensity = 0;
5835 +
5836 + /*
5837 + * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
5838 + * if seen, you have to re-enable the LED unit
5839 + */
5840 + if (!intensity || !old_intensity)
5841 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0);
5842 +
5843 + if (!intensity) /* illegal to set LEDOUT to 0 */
5844 + ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
5845 + 2);
5846 + else
5847 + ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
5848 + intensity);
5849 +
5850 + if (intensity)
5851 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2);
5852 +
5853 +}
5854 +
5855 +static struct generic_bl_info om_3d7k_bl_info = {
5856 + .name = "om-3d7k-bl",
5857 + .max_intensity = 0xff,
5858 + .default_intensity = 0x7f,
5859 + .set_bl_intensity = om_3d7k_bl_set_intensity,
5860 +};
5861 +
5862 +static struct platform_device om_3d7k_bl_dev = {
5863 + .name = "generic-bl",
5864 + .id = 1,
5865 + .dev = {
5866 + .platform_data = &om_3d7k_bl_info,
5867 + },
5868 +};
5869 +
5870 +/* BQ27000 Battery */
5871 +static int om_3d7k_get_charger_online_status(void)
5872 +{
5873 + struct pcf50633 *pcf = om_3d7k_pcf;
5874 +
5875 + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ONLINE;
5876 +}
5877 +
5878 +static int om_3d7k_get_charger_active_status(void)
5879 +{
5880 + struct pcf50633 *pcf = om_3d7k_pcf;
5881 +
5882 + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ACTIVE;
5883 +}
5884 +
5885 +
5886 +struct bq27000_platform_data bq27000_pdata = {
5887 + .name = "battery",
5888 + .rsense_mohms = 20,
5889 + .hdq_read = hdq_read,
5890 + .hdq_write = hdq_write,
5891 + .hdq_initialized = hdq_initialized,
5892 + .get_charger_online_status = om_3d7k_get_charger_online_status,
5893 + .get_charger_active_status = om_3d7k_get_charger_active_status
5894 +};
5895 +
5896 +struct platform_device bq27000_battery_device = {
5897 + .name = "bq27000-battery",
5898 + .dev = {
5899 + .platform_data = &bq27000_pdata,
5900 + },
5901 +};
5902 +
5903 +#ifdef CONFIG_HDQ_GPIO_BITBANG
5904 +/* HDQ */
5905 +
5906 +static void om_3d7k_hdq_attach_child_devices(struct device *parent_device)
5907 +{
5908 + bq27000_battery_device.dev.parent = parent_device;
5909 + platform_device_register(&bq27000_battery_device);
5910 +}
5911 +
5912 +static void om_3d7k_hdq_gpio_direction_out(void)
5913 +{
5914 + unsigned long con;
5915 + void __iomem *regcon = S3C64XX_GPH_BASE;
5916 +
5917 + con = __raw_readl(regcon);
5918 + con &= ~(0xf << 28);
5919 + con |= 0x01 << 28;
5920 + __raw_writel(con, regcon);
5921 +
5922 + /* Set pull-up enabled */
5923 + con = __raw_readl(regcon + 0x0c);
5924 + con |= 3 << 14;
5925 + __raw_writel(con, regcon + 0x0c);
5926 +}
5927 +
5928 +static void om_3d7k_hdq_gpio_direction_in(void)
5929 +{
5930 + unsigned long con;
5931 + void __iomem *regcon = S3C64XX_GPH_BASE;
5932 +
5933 + con = __raw_readl(regcon);
5934 + con &= ~(0xf << 28);
5935 + __raw_writel(con, regcon);
5936 +}
5937 +
5938 +static void om_3d7k_hdq_gpio_set_value(int val)
5939 +{
5940 + u32 dat;
5941 + void __iomem *base = S3C64XX_GPH_BASE;
5942 +
5943 + dat = __raw_readl(base + 0x08);
5944 + if (val)
5945 + dat |= 1 << 7;
5946 + else
5947 + dat &= ~(1 << 7);
5948 +
5949 + __raw_writel(dat, base + 0x08);
5950 +}
5951 +
5952 +static int om_3d7k_hdq_gpio_get_value(void)
5953 +{
5954 + u32 dat;
5955 + void *base = S3C64XX_GPH_BASE;
5956 +
5957 + dat = __raw_readl(base + 0x08);
5958 +
5959 + return dat & (1 << 7);
5960 +}
5961 +
5962 +static struct resource om_3d7k_hdq_resources[] = {
5963 + [0] = {
5964 + .start = S3C64XX_GPH(7),
5965 + .end = S3C64XX_GPH(7),
5966 + },
5967 +};
5968 +
5969 +struct hdq_platform_data om_3d7k_hdq_platform_data = {
5970 + .attach_child_devices = om_3d7k_hdq_attach_child_devices,
5971 + .gpio_dir_out = om_3d7k_hdq_gpio_direction_out,
5972 + .gpio_dir_in = om_3d7k_hdq_gpio_direction_in,
5973 + .gpio_set = om_3d7k_hdq_gpio_set_value,
5974 + .gpio_get = om_3d7k_hdq_gpio_get_value,
5975 +
5976 + .enable_fiq = om_3d7k_fiq_enable,
5977 + .disable_fiq = om_3d7k_fiq_disable,
5978 + .kick_fiq = om_3d7k_fiq_kick,
5979 +
5980 +};
5981 +
5982 +struct platform_device om_3d7k_hdq_device = {
5983 + .name = "hdq",
5984 + .num_resources = 1,
5985 + .resource = om_3d7k_hdq_resources,
5986 + .dev = {
5987 + .platform_data = &om_3d7k_hdq_platform_data,
5988 + },
5989 +};
5990 +#endif
5991 +
5992 +static void om_3d7k_lp5521_chip_enable(int level)
5993 +{
5994 + gpio_direction_output(OM_3D7K_GPIO_LED_EN, level);
5995 + udelay(500);
5996 +}
5997 +
5998 +static struct lp5521_platform_data om_3d7k_lp5521_pdata = {
5999 + .channels = {
6000 + [LP5521_BLUE] = LP5521_CONNECTED,
6001 + [LP5521_GREEN] = LP5521_CONNECTED,
6002 + [LP5521_RED] = LP5521_NC,
6003 + },
6004 + .ext_enable = om_3d7k_lp5521_chip_enable,
6005 +};
6006 +
6007 +static void om_3d7k_pcap7200_reset(void)
6008 +{
6009 + gpio_direction_output(OM_3D7K_GPIO_TP_RESET, 1);
6010 + udelay(10);
6011 + gpio_direction_output(OM_3D7K_GPIO_TP_RESET, 0);
6012 +}
6013 +
6014 +static struct pcap7200_platform_data om_3d7k_pcap7200_pdata = {
6015 + .mode = MULTI_TOUCH,
6016 + .reset = om_3d7k_pcap7200_reset,
6017 +};
6018 +
6019 +static struct i2c_board_info om_3d7k_i2c_devs[] __initdata = {
6020 + {
6021 + I2C_BOARD_INFO("pcf50633", 0x73),
6022 + .irq = OM_3D7K_IRQ_PMU,
6023 + .platform_data = &om_3d7k_pcf_pdata,
6024 + },
6025 + {
6026 + I2C_BOARD_INFO("pcap7200", 0x0a),
6027 + .irq = OM_3D7K_IRQ_TOUCH,
6028 + .platform_data = &om_3d7k_pcap7200_pdata,
6029 + },
6030 + {
6031 + I2C_BOARD_INFO("lp5521", 0x32),
6032 + /* mark this temporarily, since LED INT is connected
6033 + * to EXT group6_9, the handling of EXT group1~group9
6034 + * is not implemented. Besides, we don't need this IRQ
6035 + * now
6036 + */
6037 +#if 0
6038 + .irq = OM_3D7K_IRQ_LED,
6039 +#endif
6040 + .platform_data = &om_3d7k_lp5521_pdata,
6041 + },
6042 + {
6043 + I2C_BOARD_INFO("wm8753", 0x1a),
6044 + },
6045 +};
6046 +
6047 +struct platform_device s3c24xx_pwm_device = {
6048 + .name = "s3c24xx_pwm",
6049 + .num_resources = 0,
6050 +};
6051 +
6052 +struct platform_device om_3d7k_device_spi_lcm;
6053 +
6054 +static struct platform_device *om_3d7k_devices[] __initdata = {
6055 + &s3c_device_fb,
6056 + &s3c_device_i2c0,
6057 + &om_3d7k_device_spi_lcm,
6058 + &s3c_device_usbgadget,
6059 + &s3c24xx_pwm_device,
6060 +#ifdef CONFIG_S3C_DEV_CAMIF
6061 + &s3c_device_camif,
6062 +#endif
6063 +};
6064 +
6065 +
6066 +static void om_3d7k_pmu_regulator_registered(struct pcf50633 *pcf, int id)
6067 +{
6068 + struct platform_device *regulator, *pdev;
6069 +
6070 + regulator = pcf->regulator_pdev[id];
6071 +
6072 + switch(id) {
6073 + case PCF50633_REGULATOR_LDO4:
6074 + pdev = &s3c_device_hsmmc0; /* uSD card */
6075 + break;
6076 + case PCF50633_REGULATOR_LDO5: /* GPS regulator */
6077 + pdev = &om_3d7k_features_dev;
6078 + break;
6079 + case PCF50633_REGULATOR_LDO6:
6080 + pdev = &om_3d7k_lcd_powerdev;
6081 + break;
6082 + default:
6083 + return;
6084 + }
6085 +
6086 + pdev->dev.parent = &regulator->dev;
6087 + platform_device_register(pdev);
6088 +}
6089 +
6090 +static struct platform_device *om_3d7k_devices_pmu_children[] = {
6091 + &om_3d7k_button_dev,
6092 +// &s3c_device_spi_acc1, /* relies on PMU reg for power */
6093 + &s3c_device_usb,
6094 +};
6095 +
6096 +/* this is called when pc50633 is probed, unfortunately quite late in the
6097 + * day since it is an I2C bus device. Here we can belatedly define some
6098 + * platform devices with the advantage that we can mark the pcf50633 as the
6099 + * parent. This makes them get suspended and resumed with their parent
6100 + * the pcf50633 still around.
6101 + */
6102 +
6103 +static void om_3d7k_pcf50633_attach_child_devices(struct pcf50633 *pcf)
6104 +{
6105 + int n;
6106 +
6107 + om_3d7k_pcf = pcf;
6108 +
6109 + for (n = 0; n < ARRAY_SIZE(om_3d7k_devices_pmu_children); n++)
6110 + om_3d7k_devices_pmu_children[n]->dev.parent = pcf->dev;
6111 +
6112 + platform_add_devices(om_3d7k_devices_pmu_children,
6113 + ARRAY_SIZE(om_3d7k_devices_pmu_children));
6114 +
6115 + /* backlight device should be registered until pcf50633 probe is done */
6116 + om_3d7k_bl_dev.dev.parent = &om_3d7k_device_spi_lcm.dev;
6117 + platform_device_register(&om_3d7k_bl_dev);
6118 +
6119 + /* Switch on backlight. Qi does not do it for us */
6120 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x00);
6121 + pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 0x01);
6122 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x01);
6123 +}
6124 +
6125 +static void om_3d7k_l1k002_pwronoff(int level)
6126 +{
6127 + gpio_direction_output(OM_3D7K_GPIO_LCM_SD, 1);
6128 + udelay(15);
6129 +
6130 + gpio_direction_output(OM_3D7K_GPIO_LCM_RESET, !!level);
6131 +
6132 + if (level){
6133 + udelay(15);
6134 + gpio_direction_output(OM_3D7K_GPIO_LCM_SD, 0);
6135 + }
6136 +}
6137 +
6138 +const struct l1k002_platform_data om_3d7k_l1k002_pdata = {
6139 + .pwr_onoff = om_3d7k_l1k002_pwronoff,
6140 +};
6141 +
6142 +static struct spi_board_info om_3d7k_spi_board_info[] = {
6143 + {
6144 + .modalias = "l1k002",
6145 + .platform_data = &om_3d7k_l1k002_pdata,
6146 + /* controller_data */
6147 + /* irq */
6148 + .max_speed_hz = 10 * 1000 * 1000,
6149 + .bus_num = 1,
6150 + /* chip_select */
6151 + },
6152 +};
6153 +
6154 +static void om_3d7k_jbt6k74_probe_completed(struct device *dev)
6155 +{
6156 + dev_info(dev, "device attached\n");
6157 +}
6158 +
6159 +const struct jbt6k74_platform_data jbt6k74_pdata = {
6160 + .probe_completed = om_3d7k_jbt6k74_probe_completed,
6161 +};
6162 +
6163 +static struct spi_board_info alt_om_3d7k_spi_board_info[] = {
6164 + {
6165 + .modalias = "jbt6k74",
6166 + .platform_data = &jbt6k74_pdata,
6167 + /* controller_data */
6168 + /* irq */
6169 + .max_speed_hz = 100 * 1000,
6170 + .bus_num = 1,
6171 + /* chip_select */
6172 + },
6173 +};
6174 +
6175 +static void spi_gpio_cs(struct s3c64xx_spigpio_info *spi, int csidx, int cs)
6176 +{
6177 + switch (cs) {
6178 + case BITBANG_CS_ACTIVE:
6179 + gpio_direction_output(OM_3D7K_GPIO_LCM_CS, 0);
6180 + break;
6181 + case BITBANG_CS_INACTIVE:
6182 + gpio_direction_output(OM_3D7K_GPIO_LCM_CS, 1);
6183 + break;
6184 + }
6185 +}
6186 +
6187 +static struct s3c64xx_spigpio_info spi_gpio_cfg = {
6188 + .pin_clk = OM_3D7K_GPIO_LCM_CLK,
6189 + .pin_mosi = OM_3D7K_GPIO_LCM_MOSI,
6190 + /* no pinout to MISO */
6191 + .chip_select = &spi_gpio_cs,
6192 + .num_chipselect = 1,
6193 + .bus_num = 1,
6194 +};
6195 +
6196 +struct platform_device om_3d7k_device_spi_lcm = {
6197 + .name = "spi_s3c64xx_gpio",
6198 + .id = 1,
6199 + .dev = {
6200 + .platform_data = &spi_gpio_cfg,
6201 + },
6202 +};
6203 +
6204 +static int attached_lcm;
6205 +
6206 +static int __init om3d7k_lcm_probe(char *s)
6207 +{
6208 + if (!strcmp(s, "jbt6k74"))
6209 + attached_lcm = 1;
6210 +
6211 + return 1;
6212 +}
6213 +__setup("om_3d7k_lcm=", om3d7k_lcm_probe);
6214 +
6215 +extern void s3c64xx_init_io(struct map_desc *, int);
6216 +
6217 +struct s3c_plat_otg_data s3c_hs_otg_plat_data = {
6218 + .phyclk = 0
6219 +};
6220 +
6221 +/* USB */
6222 +static struct s3c2410_hcd_info om3d7k_usb_info = {
6223 + .port[0] = {
6224 + .flags = S3C_HCDFLG_USED,
6225 + },
6226 + .port[1] = {
6227 + .flags = 0,
6228 + },
6229 +};
6230 +
6231 +static void __init om_3d7k_map_io(void)
6232 +{
6233 + s3c64xx_init_io(om_3d7k_6410_iodesc, ARRAY_SIZE(om_3d7k_6410_iodesc));
6234 + s3c24xx_init_clocks(12000000);
6235 + s3c24xx_init_uarts(om_3d7k_uartcfgs, ARRAY_SIZE(om_3d7k_uartcfgs));
6236 +}
6237 +
6238 +static void __init om_3d7k_machine_init(void)
6239 +{
6240 + s3c_pm_init();
6241 +
6242 + s3c_device_usb.dev.platform_data = &om3d7k_usb_info;
6243 + s3c_device_usbgadget.dev.platform_data = &s3c_hs_otg_plat_data;
6244 +
6245 + s3c_i2c0_set_platdata(NULL);
6246 + s3c_fb_set_platdata(&om_3d7k_lcd_pdata);
6247 +
6248 + i2c_register_board_info(0, om_3d7k_i2c_devs,
6249 + ARRAY_SIZE(om_3d7k_i2c_devs));
6250 + if (attached_lcm)
6251 + spi_register_board_info(alt_om_3d7k_spi_board_info,
6252 + ARRAY_SIZE(alt_om_3d7k_spi_board_info));
6253 + else
6254 + spi_register_board_info(om_3d7k_spi_board_info,
6255 + ARRAY_SIZE(om_3d7k_spi_board_info));
6256 +
6257 + platform_add_devices(om_3d7k_devices, ARRAY_SIZE(om_3d7k_devices));
6258 +
6259 + /* Register the HDQ and vibrator as children of pwm device */
6260 + om_3d7k_hdq_device.dev.parent = &s3c24xx_pwm_device.dev;
6261 + platform_device_register(&om_3d7k_hdq_device);
6262 +}
6263 +
6264 +MACHINE_START(OM_3D7K, "OM-3D7K")
6265 + /* Maintainer: Andy Green <andy@openmoko.com> */
6266 + .phys_io = S3C_PA_UART & 0xfff00000,
6267 + .io_pg_offst = (((u32)S3C_VA_UART) >> 18) & 0xfffc,
6268 + .boot_params = S3C64XX_PA_SDRAM + 0x100,
6269 +
6270 + .init_irq = s3c6410_init_irq,
6271 + .map_io = om_3d7k_map_io,
6272 + .init_machine = om_3d7k_machine_init,
6273 + .timer = &s3c24xx_timer,
6274 +MACHINE_END
6275 +
6276 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/mach-smdk6410.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/mach-smdk6410.c
6277 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/mach-smdk6410.c 2009-05-10 22:08:41.000000000 +0200
6278 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/mach-smdk6410.c 2009-05-10 22:27:59.000000000 +0200
6279 @@ -39,14 +39,20 @@
6280 #include <asm/mach-types.h>
6281
6282 #include <plat/regs-serial.h>
6283 +#include <plat/regs-modem.h>
6284 +#include <plat/regs-gpio.h>
6285 +#include <plat/regs-sys.h>
6286 #include <plat/iic.h>
6287 #include <plat/fb.h>
6288 +#include <plat/pm.h>
6289
6290 #include <plat/s3c6410.h>
6291 #include <plat/clock.h>
6292 #include <plat/devs.h>
6293 #include <plat/cpu.h>
6294
6295 +#include <plat/regs-usb-hs-otg.h>
6296 +
6297 #define UCON S3C2410_UCON_DEFAULT | S3C2410_UCON_UCLK
6298 #define ULCON S3C2410_LCON_CS8 | S3C2410_LCON_PNONE | S3C2410_LCON_STOPB
6299 #define UFCON S3C2410_UFCON_RXTRIG8 | S3C2410_UFCON_FIFOMODE
6300 @@ -141,7 +147,10 @@
6301 &s3c_device_i2c0,
6302 &s3c_device_i2c1,
6303 &s3c_device_fb,
6304 + &s3c_device_usb,
6305 &smdk6410_lcd_powerdev,
6306 + &s3c_device_usbgadget,
6307 +
6308 };
6309
6310 static struct i2c_board_info i2c_devs0[] __initdata = {
6311 @@ -155,13 +164,36 @@
6312
6313 static void __init smdk6410_map_io(void)
6314 {
6315 + u32 tmp;
6316 +
6317 s3c64xx_init_io(smdk6410_iodesc, ARRAY_SIZE(smdk6410_iodesc));
6318 s3c24xx_init_clocks(12000000);
6319 s3c24xx_init_uarts(smdk6410_uartcfgs, ARRAY_SIZE(smdk6410_uartcfgs));
6320 +
6321 + /* set the LCD type */
6322 +
6323 + tmp = __raw_readl(S3C64XX_SPCON);
6324 + tmp &= ~S3C64XX_SPCON_LCD_SEL_MASK;
6325 + tmp |= S3C64XX_SPCON_LCD_SEL_RGB;
6326 + __raw_writel(tmp, S3C64XX_SPCON);
6327 +
6328 + /* remove the lcd bypass */
6329 + tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
6330 + tmp &= ~MIFPCON_LCD_BYPASS;
6331 + __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
6332 }
6333
6334 +struct s3c_plat_otg_data s3c_hs_otg_plat_data = {
6335 + .phyclk = REF_CLK_OSCC
6336 +};
6337 +
6338 +
6339 static void __init smdk6410_machine_init(void)
6340 {
6341 + s3c_pm_init();
6342 +
6343 + s3c_device_usbgadget.dev.platform_data = &s3c_hs_otg_plat_data;
6344 +
6345 s3c_i2c0_set_platdata(NULL);
6346 s3c_i2c1_set_platdata(NULL);
6347 s3c_fb_set_platdata(&smdk6410_lcd_pdata);
6348 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/Makefile linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/Makefile
6349 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/Makefile 2009-05-10 22:05:04.000000000 +0200
6350 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/Makefile 2009-05-10 22:27:59.000000000 +0200
6351 @@ -21,3 +21,6 @@
6352 # machine support
6353
6354 obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o
6355 +obj-$(CONFIG_MACH_OM_3D7K) += mach-om-3d7k.o \
6356 + om-3d7k-features.o
6357 +
6358 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/om-3d7k-features.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/om-3d7k-features.c
6359 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/om-3d7k-features.c 1970-01-01 01:00:00.000000000 +0100
6360 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/om-3d7k-features.c 2009-05-10 22:27:59.000000000 +0200
6361 @@ -0,0 +1,273 @@
6362 +/*
6363 + * Support for features of Openmoko 3D7K
6364 + *
6365 + * (C) 2008 by Openmoko Inc.
6366 + * Author: Andy Green <andy@openmoko.com>
6367 + * All rights reserved.
6368 + *
6369 + * Somewhat based on the GTA01 / 02 neo1973_pm_ stuff mainly by Harald Welte
6370 + *
6371 + * This program is free software; you can redistribute it and/or modify
6372 + * it under the terms of the GNU General Public License version 2 as
6373 + * published by the Free Software Foundation
6374 + *
6375 + */
6376 +
6377 +#include <linux/module.h>
6378 +#include <linux/init.h>
6379 +#include <linux/kernel.h>
6380 +#include <linux/delay.h>
6381 +#include <linux/platform_device.h>
6382 +
6383 +#include <mach/hardware.h>
6384 +#include <mach/om-3d7k.h>
6385 +#include <asm/mach-types.h>
6386 +
6387 +#include <linux/regulator/consumer.h>
6388 +#include <linux/mfd/pcf50633/core.h>
6389 +#include <linux/mfd/pcf50633/gpio.h>
6390 +#include <linux/mmc/host.h>
6391 +
6392 +#include <plat/sdhci.h>
6393 +#include <plat/devs.h>
6394 +
6395 +#include <plat/gpio-cfg.h>
6396 +
6397 +enum feature {
6398 + OM_3D7K_GSM, /* GSM module */
6399 + OM_3D7K_USBHOST, /* USB Host power generation */
6400 + OM_3D7K_VIB, /* Vibrator */
6401 +
6402 + OM_3D7K_FEATURE_COUNT /* always last */
6403 +};
6404 +
6405 +
6406 +struct om_3d7k_feature_info {
6407 + const char * name;
6408 + int depower_on_suspend;
6409 + int on;
6410 +};
6411 +
6412 +static struct om_3d7k_feature_info feature_info[OM_3D7K_FEATURE_COUNT] = {
6413 + [OM_3D7K_GSM] = { "gsm_power", 0, 0 },
6414 + [OM_3D7K_USBHOST] = { "usbhost_power", 1, 0 },
6415 + [OM_3D7K_VIB] = { "vibrator_power", 1, 0 },
6416 +};
6417 +
6418 +static struct regulator *gps_regulator;
6419 +
6420 +
6421 +
6422 +static void om_3d7k_features_pwron_set_on(enum feature feature)
6423 +{
6424 + switch (feature) {
6425 + case OM_3D7K_GSM:
6426 + /* give power to GSM module */
6427 + s3c_gpio_setpull(OM_3D7K_GPIO_N_MODEM_RESET, S3C_GPIO_PULL_NONE);
6428 + s3c_gpio_setpull(OM_3D7K_GPIO_MODEM_ON, S3C_GPIO_PULL_NONE);
6429 + s3c_gpio_cfgpin(OM_3D7K_GPIO_N_MODEM_RESET, S3C_GPIO_SFN(1));
6430 + s3c_gpio_cfgpin(OM_3D7K_GPIO_MODEM_ON, S3C_GPIO_SFN(1));
6431 + gpio_direction_output(OM_3D7K_GPIO_N_MODEM_RESET, 0);
6432 + gpio_direction_output(OM_3D7K_GPIO_MODEM_ON, 1);
6433 + msleep(10);
6434 + gpio_direction_output(OM_3D7K_GPIO_MODEM_ON, 0);
6435 + msleep(150);
6436 + gpio_direction_output(OM_3D7K_GPIO_N_MODEM_RESET, 1);
6437 + msleep(300);
6438 + gpio_direction_output(OM_3D7K_GPIO_MODEM_ON, 1);
6439 + break;
6440 + case OM_3D7K_USBHOST:
6441 + pcf50633_gpio_set(om_3d7k_pcf, PCF50633_GPO, 1);
6442 + break;
6443 + case OM_3D7K_VIB:
6444 + gpio_direction_output(OM_3D7K_GPIO_VIBRATOR_ON, 1);
6445 + break;
6446 + default:
6447 + break;
6448 + }
6449 +}
6450 +
6451 +static void om_3d7k_features_pwron_set_off(enum feature feature)
6452 +{
6453 + switch (feature) {
6454 + case OM_3D7K_GSM:
6455 + /* remove power from WLAN / BT module */
6456 + s3c_gpio_cfgpin(OM_3D7K_GPIO_MODEM_ON, S3C_GPIO_SFN(1));
6457 + gpio_direction_output(OM_3D7K_GPIO_MODEM_ON, 0);
6458 + msleep(1100);
6459 + gpio_direction_output(OM_3D7K_GPIO_MODEM_ON, 1);
6460 + break;
6461 + case OM_3D7K_USBHOST:
6462 + pcf50633_gpio_set(om_3d7k_pcf, PCF50633_GPO, 0);
6463 + break;
6464 + case OM_3D7K_VIB:
6465 + gpio_direction_output(OM_3D7K_GPIO_VIBRATOR_ON, 0);
6466 + break;
6467 + default:
6468 + break;
6469 + }
6470 +}
6471 +
6472 +static void om_3d7k_features_pwron_set(enum feature feature, int on)
6473 +{
6474 + if ((on) && (!feature_info[feature].on))
6475 + om_3d7k_features_pwron_set_on(feature);
6476 + else
6477 + if ((!on) && (feature_info[feature].on))
6478 + om_3d7k_features_pwron_set_off(feature);
6479 +}
6480 +
6481 +static ssize_t om_3d7k_feature_read(struct device *dev,
6482 + struct device_attribute *attr, char *buf)
6483 +{
6484 + int on;
6485 + int feature = 0;
6486 + int hit = 0;
6487 +
6488 + while (!hit && feature < OM_3D7K_FEATURE_COUNT) {
6489 + if (!strcmp(attr->attr.name, feature_info[feature].name))
6490 + hit = 1;
6491 + else
6492 + feature++;
6493 + }
6494 +
6495 + if (!hit)
6496 + return -EINVAL;
6497 +
6498 + switch (feature) {
6499 + case OM_3D7K_USBHOST:
6500 + on = pcf50633_gpio_get(om_3d7k_pcf, PCF50633_GPO);
6501 + break;
6502 + default:
6503 + on = feature_info[feature].on;
6504 + }
6505 +
6506 + *buf++ = '0' + on;
6507 + *buf++='\n';
6508 + *buf = '\0';
6509 +
6510 + return 3;
6511 +}
6512 +
6513 +static ssize_t om_3d7k_feature_write(struct device *dev,
6514 + struct device_attribute *attr,
6515 + const char *buf, size_t count)
6516 +{
6517 + int on = !!simple_strtoul(buf, NULL, 10);
6518 + int feature = 0;
6519 + int hit = 0;
6520 +
6521 + while (!hit && feature < OM_3D7K_FEATURE_COUNT) {
6522 + if (!strcmp(attr->attr.name, feature_info[feature].name))
6523 + hit = 1;
6524 + else
6525 + feature++;
6526 + }
6527 +
6528 + if (!hit)
6529 + return -EINVAL;
6530 +
6531 + om_3d7k_features_pwron_set(feature, on);
6532 + feature_info[feature].on = on;
6533 +
6534 + return count;
6535 +}
6536 +
6537 +
6538 +static DEVICE_ATTR(gsm_power, 0644, om_3d7k_feature_read,
6539 + om_3d7k_feature_write);
6540 +
6541 +static DEVICE_ATTR(usbhost_power, 0644, om_3d7k_feature_read,
6542 + om_3d7k_feature_write);
6543 +
6544 +static DEVICE_ATTR(vibrator_power, 0644, om_3d7k_feature_read,
6545 + om_3d7k_feature_write);
6546 +
6547 +
6548 +static struct attribute *om_3d7k_features_sysfs_entries[] = {
6549 + &dev_attr_gsm_power.attr,
6550 + &dev_attr_usbhost_power.attr,
6551 + &dev_attr_vibrator_power.attr,
6552 + NULL
6553 +};
6554 +
6555 +
6556 +static struct attribute_group om_3d7k_features_attr_group = {
6557 + .name = NULL,
6558 + .attrs = om_3d7k_features_sysfs_entries,
6559 +};
6560 +
6561 +static int __init om_3d7k_features_probe(struct platform_device *pdev)
6562 +{
6563 + gps_regulator = regulator_get(&pdev->dev, "RF_3V");
6564 + dev_info(&pdev->dev, "starting\n");
6565 +
6566 + return sysfs_create_group(&pdev->dev.kobj,
6567 + &om_3d7k_features_attr_group);
6568 +}
6569 +
6570 +static int om_3d7k_features_remove(struct platform_device *pdev)
6571 +{
6572 +
6573 + regulator_put(gps_regulator);
6574 + sysfs_remove_group(&pdev->dev.kobj, &om_3d7k_features_attr_group);
6575 +
6576 + return 0;
6577 +}
6578 +
6579 +
6580 +#ifdef CONFIG_PM
6581 +static int om_3d7k_features_suspend(struct platform_device *pdev,
6582 + pm_message_t state)
6583 +{
6584 + int feature;
6585 +
6586 + for (feature = 0; feature < OM_3D7K_FEATURE_COUNT; feature++)
6587 + if (feature_info[feature].depower_on_suspend)
6588 + om_3d7k_features_pwron_set_off(feature);
6589 +
6590 + return 0;
6591 +}
6592 +
6593 +static int om_3d7k_features_resume(struct platform_device *pdev)
6594 +{
6595 + int feature;
6596 +
6597 + for (feature = 0; feature < OM_3D7K_FEATURE_COUNT; feature++)
6598 + if (feature_info[feature].depower_on_suspend)
6599 + if (feature_info[feature].on)
6600 + om_3d7k_features_pwron_set_on(feature);
6601 +
6602 + return 0;
6603 +}
6604 +#else
6605 +#define om_3d7k_features_suspend NULL
6606 +#define om_3d7k_features_resume NULL
6607 +#endif
6608 +
6609 +static struct platform_driver om_3d7k_features_driver = {
6610 + .probe = om_3d7k_features_probe,
6611 + .remove = om_3d7k_features_remove,
6612 + .suspend = om_3d7k_features_suspend,
6613 + .resume = om_3d7k_features_resume,
6614 + .driver = {
6615 + .name = "om-3d7k",
6616 + },
6617 +};
6618 +
6619 +static int __devinit om_3d7k_features_init(void)
6620 +{
6621 + return platform_driver_register(&om_3d7k_features_driver);
6622 +}
6623 +
6624 +static void om_3d7k_features_exit(void)
6625 +{
6626 + platform_driver_unregister(&om_3d7k_features_driver);
6627 +}
6628 +
6629 +module_init(om_3d7k_features_init);
6630 +module_exit(om_3d7k_features_exit);
6631 +
6632 +MODULE_LICENSE("GPL");
6633 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
6634 +MODULE_DESCRIPTION("Openmoko OM_3D7K Feature Driver");
6635 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/setup-sdhci.c linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/setup-sdhci.c
6636 --- linux-2.6.29-rc3.owrt/arch/arm/mach-s3c6410/setup-sdhci.c 2009-05-10 22:05:04.000000000 +0200
6637 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-s3c6410/setup-sdhci.c 2009-05-10 22:27:59.000000000 +0200
6638 @@ -48,7 +48,8 @@
6639 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
6640 }
6641
6642 - s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
6643 + /* FIXME this needs defining in machine as to if we even have CD */
6644 + s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_DOWN);
6645 s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(2));
6646 }
6647
6648 @@ -79,7 +80,7 @@
6649 else
6650 ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
6651
6652 - printk(KERN_INFO "%s: CTRL 2=%08x, 3=%08x\n", __func__, ctrl2, ctrl3);
6653 + printk(KERN_INFO "%s: %p CTRL 2=%08x, 3=%08x\n", __func__, r, ctrl2, ctrl3);
6654 writel(ctrl2, r + S3C_SDHCI_CONTROL2);
6655 writel(ctrl3, r + S3C_SDHCI_CONTROL3);
6656 }
6657 @@ -94,9 +95,9 @@
6658 /* Set all the necessary GPG pins to special-function 0 */
6659 for (gpio = S3C64XX_GPH(0); gpio < end; gpio++) {
6660 s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
6661 - s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
6662 + s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
6663 }
6664
6665 - s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
6666 - s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
6667 +// s3c_gpio_setpull(S3C64XX_GPG(6), S3C_GPIO_PULL_UP);
6668 +// s3c_gpio_cfgpin(S3C64XX_GPG(6), S3C_GPIO_SFN(3));
6669 }
6670 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/mach-shark/include/mach/io.h linux-2.6.29-rc3.owrt.om/arch/arm/mach-shark/include/mach/io.h
6671 --- linux-2.6.29-rc3.owrt/arch/arm/mach-shark/include/mach/io.h 2009-05-10 22:05:04.000000000 +0200
6672 +++ linux-2.6.29-rc3.owrt.om/arch/arm/mach-shark/include/mach/io.h 2009-05-10 22:27:59.000000000 +0200
6673 @@ -14,7 +14,7 @@
6674 #define PCIO_BASE 0xe0000000
6675 #define IO_SPACE_LIMIT 0xffffffff
6676
6677 -#define __io(a) ((void __iomem *)(PCIO_BASE + (a)))
6678 +#define __io(a) __typesafe_io(PCIO_BASE + (a))
6679 #define __mem_pci(addr) (addr)
6680
6681 #endif
6682 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/Makefile linux-2.6.29-rc3.owrt.om/arch/arm/Makefile
6683 --- linux-2.6.29-rc3.owrt/arch/arm/Makefile 2009-05-10 22:05:04.000000000 +0200
6684 +++ linux-2.6.29-rc3.owrt.om/arch/arm/Makefile 2009-05-10 22:27:59.000000000 +0200
6685 @@ -55,7 +55,8 @@
6686 arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
6687 endif
6688 arch-$(CONFIG_CPU_32v5) :=-D__LINUX_ARM_ARCH__=5 $(call cc-option,-march=armv5te,-march=armv4t)
6689 -arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4t
6690 +# We can't load armv4t modules, but still need to assemble some armv4t code to be linked in.
6691 +arch-$(CONFIG_CPU_32v4T) :=-D__LINUX_ARM_ARCH__=4 -march=armv4 -Wa,-march=armv4t
6692 arch-$(CONFIG_CPU_32v4) :=-D__LINUX_ARM_ARCH__=4 -march=armv4
6693 arch-$(CONFIG_CPU_32v3) :=-D__LINUX_ARM_ARCH__=3 -march=armv3
6694
6695 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/dev-camif.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/dev-camif.c
6696 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/dev-camif.c 1970-01-01 01:00:00.000000000 +0100
6697 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/dev-camif.c 2009-05-10 22:27:59.000000000 +0200
6698 @@ -0,0 +1,65 @@
6699 +/* linux/arch/arm/plat-s3c/dev-camif.c
6700 + *
6701 + * Copyright 2009 Openmoko, Inc.
6702 + * Werner Almesberger <werner@openmoko.org>
6703 + *
6704 + * based on dev-hsmmc.c which is
6705 + *
6706 + * Copyright (c) 2008 Simtec Electronics
6707 + * Ben Dooks <ben@simtec.co.uk>
6708 + * http://armlinux.simtec.co.uk/
6709 + *
6710 + * S3C series device definition for camera interface devices
6711 + *
6712 + * This program is free software; you can redistribute it and/or modify
6713 + * it under the terms of the GNU General Public License version 2 as
6714 + * published by the Free Software Foundation.
6715 +*/
6716 +
6717 +#include <linux/kernel.h>
6718 +#include <linux/platform_device.h>
6719 +#include <linux/mmc/host.h>
6720 +
6721 +#include <mach/map.h>
6722 +#include <plat/devs.h>
6723 +#include <plat/cpu.h>
6724 +
6725 +
6726 +#define S3C6400_PA_CAMIF 0x78000000
6727 +#define S3C24XX_SZ_CAMIF (0x1000)
6728 +
6729 +
6730 +static struct resource s3c_camif_resource[] = {
6731 + [0] = {
6732 + .start = S3C6400_PA_CAMIF,
6733 + .end = S3C6400_PA_CAMIF + S3C24XX_SZ_CAMIF - 1,
6734 + .flags = IORESOURCE_MEM,
6735 + },
6736 + [1] = {
6737 + .start = IRQ_CAMIF_C,
6738 + .end = IRQ_CAMIF_C,
6739 + .flags = IORESOURCE_IRQ,
6740 + },
6741 + [2] = {
6742 + .start = IRQ_CAMIF_P,
6743 + .end = IRQ_CAMIF_P,
6744 + .flags = IORESOURCE_IRQ,
6745 + }
6746 +
6747 +};
6748 +
6749 +static u64 s3c_device_camif_dmamask = 0xffffffffUL;
6750 +
6751 +struct platform_device s3c_device_camif = {
6752 + .name = "s3c-camif",
6753 + .id = -1,
6754 + .num_resources = ARRAY_SIZE(s3c_camif_resource),
6755 + .resource = s3c_camif_resource,
6756 + .dev = {
6757 + .dma_mask = &s3c_device_camif_dmamask,
6758 + .coherent_dma_mask = 0xffffffffUL
6759 + }
6760 +};
6761 +
6762 +EXPORT_SYMBOL(s3c_device_camif);
6763 +
6764 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/dev-i2c0.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/dev-i2c0.c
6765 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/dev-i2c0.c 2009-05-10 22:05:04.000000000 +0200
6766 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/dev-i2c0.c 2009-05-10 22:27:59.000000000 +0200
6767 @@ -51,8 +51,8 @@
6768 .flags = 0,
6769 .slave_addr = 0x10,
6770 .bus_freq = 100*1000,
6771 - .max_freq = 400*1000,
6772 - .sda_delay = S3C2410_IICLC_SDA_DELAY5 | S3C2410_IICLC_FILTER_ON,
6773 + .max_freq = 100*1000,
6774 + .sda_delay = S3C2410_IICLC_SDA_DELAY15 | S3C2410_IICLC_FILTER_ON,
6775 };
6776
6777 void __init s3c_i2c0_set_platdata(struct s3c2410_platform_i2c *pd)
6778 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/dev-usb.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/dev-usb.c
6779 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/dev-usb.c 1970-01-01 01:00:00.000000000 +0100
6780 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/dev-usb.c 2009-05-10 22:27:59.000000000 +0200
6781 @@ -0,0 +1,50 @@
6782 +/* linux/arch/arm/plat-s3c/dev-usb.c
6783 + *
6784 + * Copyright 2008 Simtec Electronics
6785 + * Ben Dooks <ben@simtec.co.uk>
6786 + * http://armlinux.simtec.co.uk/
6787 + *
6788 + * S3C series device definition for USB host
6789 + *
6790 + * This program is free software; you can redistribute it and/or modify
6791 + * it under the terms of the GNU General Public License version 2 as
6792 + * published by the Free Software Foundation.
6793 +*/
6794 +
6795 +#include <linux/kernel.h>
6796 +#include <linux/string.h>
6797 +#include <linux/platform_device.h>
6798 +
6799 +#include <mach/irqs.h>
6800 +#include <mach/map.h>
6801 +
6802 +#include <plat/devs.h>
6803 +
6804 +
6805 +static struct resource s3c_usb_resource[] = {
6806 + [0] = {
6807 + .start = S3C_PA_USBHOST,
6808 + .end = S3C_PA_USBHOST + 0x100 - 1,
6809 + .flags = IORESOURCE_MEM,
6810 + },
6811 + [1] = {
6812 + .start = IRQ_USBH,
6813 + .end = IRQ_USBH,
6814 + .flags = IORESOURCE_IRQ,
6815 + }
6816 +};
6817 +
6818 +static u64 s3c_device_usb_dmamask = 0xffffffffUL;
6819 +
6820 +struct platform_device s3c_device_usb = {
6821 + .name = "s3c-ohci",
6822 + .id = -1,
6823 + .num_resources = ARRAY_SIZE(s3c_usb_resource),
6824 + .resource = s3c_usb_resource,
6825 + .dev = {
6826 + .dma_mask = &s3c_device_usb_dmamask,
6827 + .coherent_dma_mask = 0xffffffffUL
6828 + }
6829 +};
6830 +
6831 +EXPORT_SYMBOL(s3c_device_usb);
6832 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/dma.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/dma.c
6833 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/dma.c 1970-01-01 01:00:00.000000000 +0100
6834 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/dma.c 2009-05-10 22:27:59.000000000 +0200
6835 @@ -0,0 +1,86 @@
6836 +/* linux/arch/arm/plat-s3c/dma.c
6837 + *
6838 + * Copyright (c) 2003-2005,2006,2009 Simtec Electronics
6839 + * Ben Dooks <ben@simtec.co.uk>
6840 + * http://armlinux.simtec.co.uk/
6841 + *
6842 + * S3C DMA core
6843 + *
6844 + * This program is free software; you can redistribute it and/or modify
6845 + * it under the terms of the GNU General Public License version 2 as
6846 + * published by the Free Software Foundation.
6847 +*/
6848 +
6849 +struct s3c2410_dma_buf;
6850 +
6851 +#include <linux/kernel.h>
6852 +#include <linux/module.h>
6853 +#include <linux/errno.h>
6854 +
6855 +#include <mach/dma.h>
6856 +#include <mach/irqs.h>
6857 +
6858 +#include <plat/dma-plat.h>
6859 +
6860 +/* dma channel state information */
6861 +struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
6862 +struct s3c2410_dma_chan *s3c_dma_chan_map[DMACH_MAX];
6863 +
6864 +/* s3c_dma_lookup_channel
6865 + *
6866 + * change the dma channel number given into a real dma channel id
6867 +*/
6868 +
6869 +struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel)
6870 +{
6871 + if (channel & DMACH_LOW_LEVEL)
6872 + return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
6873 + else
6874 + return s3c_dma_chan_map[channel];
6875 +}
6876 +
6877 +/* do we need to protect the settings of the fields from
6878 + * irq?
6879 +*/
6880 +
6881 +int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
6882 +{
6883 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
6884 +
6885 + if (chan == NULL)
6886 + return -EINVAL;
6887 +
6888 + pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
6889 +
6890 + chan->op_fn = rtn;
6891 +
6892 + return 0;
6893 +}
6894 +EXPORT_SYMBOL(s3c2410_dma_set_opfn);
6895 +
6896 +int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
6897 +{
6898 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
6899 +
6900 + if (chan == NULL)
6901 + return -EINVAL;
6902 +
6903 + pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
6904 +
6905 + chan->callback_fn = rtn;
6906 +
6907 + return 0;
6908 +}
6909 +EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
6910 +
6911 +int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
6912 +{
6913 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
6914 +
6915 + if (chan == NULL)
6916 + return -EINVAL;
6917 +
6918 + chan->flags = flags;
6919 + return 0;
6920 +}
6921 +EXPORT_SYMBOL(s3c2410_dma_setflags);
6922 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/gpio.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/gpio.c
6923 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/gpio.c 2009-05-10 22:05:04.000000000 +0200
6924 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/gpio.c 2009-05-10 22:27:59.000000000 +0200
6925 @@ -16,7 +16,7 @@
6926 #include <linux/io.h>
6927 #include <linux/gpio.h>
6928
6929 -#include <plat/gpio-core.h>
6930 +#include <mach/gpio-core.h>
6931
6932 #ifdef CONFIG_S3C_GPIO_TRACK
6933 struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
6934 @@ -140,6 +140,15 @@
6935 if (!gc->get)
6936 gc->get = s3c_gpiolib_get;
6937
6938 +#ifdef CONFIG_PM
6939 + if (chip->pm != NULL) {
6940 + if (!chip->pm->save || !chip->pm->resume)
6941 + printk(KERN_ERR "gpio: %s has missing PM functions\n",
6942 + gc->label);
6943 + } else
6944 + printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
6945 +#endif
6946 +
6947 /* gpiochip_add() prints own failure message on error. */
6948 ret = gpiochip_add(gc);
6949 if (ret >= 0)
6950 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/gpio-config.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/gpio-config.c
6951 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/gpio-config.c 2009-05-10 22:05:04.000000000 +0200
6952 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/gpio-config.c 2009-05-10 22:27:59.000000000 +0200
6953 @@ -13,6 +13,7 @@
6954 */
6955
6956 #include <linux/kernel.h>
6957 +#include <linux/module.h>
6958 #include <linux/gpio.h>
6959 #include <linux/io.h>
6960
6961 @@ -38,6 +39,7 @@
6962
6963 return ret;
6964 }
6965 +EXPORT_SYMBOL(s3c_gpio_cfgpin);
6966
6967 int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
6968 {
6969 @@ -56,6 +58,7 @@
6970
6971 return ret;
6972 }
6973 +EXPORT_SYMBOL(s3c_gpio_setpull);
6974
6975 #ifdef CONFIG_S3C_GPIO_CFG_S3C24XX
6976 int s3c_gpio_setcfg_s3c24xx_banka(struct s3c_gpio_chip *chip,
6977 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/mach/cpu.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/mach/cpu.h
6978 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/mach/cpu.h 1970-01-01 01:00:00.000000000 +0100
6979 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/mach/cpu.h 2009-05-10 22:27:59.000000000 +0200
6980 @@ -0,0 +1,165 @@
6981 +/*
6982 + * arch/arm/plat-s3c/include/mach/cpu.h
6983 + *
6984 + * S3C cpu type detection
6985 + *
6986 + * Copyright (C) 2008 Samsung Electronics
6987 + * Kyungmin Park <kyungmin.park@samsung.com>
6988 + *
6989 + * Derived from OMAP cpu.h
6990 + *
6991 + * This program is free software; you can redistribute it and/or modify
6992 + * it under the terms of the GNU General Public License as published by
6993 + * the Free Software Foundation; either version 2 of the License, or
6994 + * (at your option) any later version.
6995 + *
6996 + * This program is distributed in the hope that it will be useful,
6997 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
6998 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6999 + * GNU General Public License for more details.
7000 + *
7001 + * You should have received a copy of the GNU General Public License
7002 + * along with this program; if not, write to the Free Software
7003 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
7004 + */
7005 +
7006 +#ifndef __ASM_ARCH_S3C_CPU_H
7007 +#define __ASM_ARCH_S3C_CPU_H
7008 +
7009 +extern unsigned int system_rev;
7010 +
7011 +#define S3C_SYSTEM_REV_ATAG (system_rev & 0xffff)
7012 +#define S3C_SYSTEM_REV_CPU (system_rev & 0xffff0000)
7013 +
7014 +/*
7015 + * cpu_is_s3c24xx(): True for s3c2400, s3c2410, s3c2440 and so on
7016 + * cpu_is_s3c241x(): True fro s3c2410, s3c2412
7017 + * cpu_is_s3c244x(): True fro s3c2440, s3c2442, s3c2443
7018 + * cpu_is_s3c64xx(): True for s3c6400, s3c6410
7019 + */
7020 +#define GET_S3C_CLASS ((system_rev >> 24) & 0xff)
7021 +
7022 +#define IS_S3C_CLASS(class, id) \
7023 +static inline int is_s3c ##class (void) \
7024 +{ \
7025 + return (GET_S3C_CLASS == (id)) ? 1 : 0; \
7026 +}
7027 +
7028 +#define GET_S3C_SUBCLASS ((system_rev >> 20) & 0xfff)
7029 +
7030 +#define IS_S3C_SUBCLASS(subclass, id) \
7031 +static inline int is_s3c ##subclass (void) \
7032 +{ \
7033 + return (GET_S3C_SUBCLASS == (id)) ? 1 : 0; \
7034 +}
7035 +
7036 +IS_S3C_CLASS(24xx, 0x24)
7037 +IS_S3C_CLASS(64xx, 0x64)
7038 +
7039 +IS_S3C_SUBCLASS(241x, 0x241)
7040 +IS_S3C_SUBCLASS(244x, 0x244)
7041 +
7042 +#define cpu_is_s3c24xx() 0
7043 +#define cpu_is_s3c241x() 0
7044 +#define cpu_is_s3c244x() 0
7045 +#define cpu_is_s3c64xx() 0
7046 +
7047 +#if defined(CONFIG_ARCH_S3C2410)
7048 +# undef cpu_is_s3c24xx
7049 +# undef cpu_is_s3c241x
7050 +# undef cpu_is_s3c244x
7051 +# define cpu_is_s3c24xx() is_s3c24xx()
7052 +# define cpu_is_s3c241x() is_s3c241x()
7053 +# define cpu_is_s3c244x() is_s3c244x()
7054 +#endif
7055 +
7056 +#if defined(CONFIG_ARCH_S3C64XX)
7057 +# undef cpu_is_s3c64xx
7058 +# define cpu_is_s3c64xx() is_s3c64xx()
7059 +#endif
7060 +
7061 +/*
7062 + * Macros to detect individual cpu types.
7063 + * cpu_is_s3c2410(): True for s3c2410
7064 + * cpu_is_s3c2440(): True for s3c2440
7065 + * cpu_is_s3c6400(): True for s3c6400
7066 + * cpu_is_s3c6410(): True for s3c6410
7067 + *
7068 + * Exception:
7069 + * Store Revision A to 1
7070 + * s3c2410a -> s3c2411
7071 + * s3c2440a -> s3c2441
7072 + */
7073 +
7074 +#define GET_S3C_TYPE ((system_rev >> 16) & 0xffff)
7075 +
7076 +#define IS_S3C_TYPE(type, id) \
7077 +static inline int is_s3c ##type (void) \
7078 +{ \
7079 + return (GET_S3C_TYPE == (id)) ? 1 : 0; \
7080 +}
7081 +
7082 +IS_S3C_TYPE(2400, 0x2400)
7083 +IS_S3C_TYPE(2410, 0x2410)
7084 +IS_S3C_TYPE(2410a, 0x2411)
7085 +IS_S3C_TYPE(2412, 0x2412)
7086 +IS_S3C_TYPE(2440, 0x2440)
7087 +IS_S3C_TYPE(2440a, 0x2441)
7088 +IS_S3C_TYPE(2442, 0x2442)
7089 +IS_S3C_TYPE(2443, 0x2443)
7090 +IS_S3C_TYPE(6400, 0x6400)
7091 +IS_S3C_TYPE(6410, 0x6410)
7092 +
7093 +#define cpu_is_s3c2400() 0
7094 +#define cpu_is_s3c2410() 0
7095 +#define cpu_is_s3c2410a() 0
7096 +#define cpu_is_s3c2412() 0
7097 +#define cpu_is_s3c2440() 0
7098 +#define cpu_is_s3c2440a() 0
7099 +#define cpu_is_s3c2442() 0
7100 +#define cpu_is_s3c2443() 0
7101 +#define cpu_is_s3c6400() 0
7102 +#define cpu_is_s3c6410() 0
7103 +
7104 +#if defined(CONFIG_ARCH_S3C2410)
7105 +# undef cpu_is_s3c2400
7106 +# define cpu_is_s3c2400() is_s3c2400()
7107 +#endif
7108 +
7109 +#if defined(CONFIG_CPU_S3C2410)
7110 +# undef cpu_is_s3c2410
7111 +# undef cpu_is_s3c2410a
7112 +# define cpu_is_s3c2410() is_s3c2410()
7113 +# define cpu_is_s3c2410a() is_s3c2410a()
7114 +#endif
7115 +
7116 +#if defined(CONFIG_CPU_S3C2412)
7117 +# undef cpu_is_s3c2412
7118 +# define cpu_is_s3c2412() is_s3c2412()
7119 +#endif
7120 +
7121 +#if defined(CONFIG_CPU_S3C2440)
7122 +# undef cpu_is_s3c2440
7123 +# undef cpu_is_s3c2440a
7124 +# define cpu_is_s3c2440() is_s3c2440()
7125 +# define cpu_is_s3c2440a() is_s3c2440a()
7126 +#endif
7127 +
7128 +#if defined(CONFIG_CPU_S3C2442)
7129 +# undef cpu_is_s3c2442
7130 +# define cpu_is_s3c2442() is_s3c2442()
7131 +#endif
7132 +
7133 +#if defined(CONFIG_CPU_S3C2443)
7134 +# undef cpu_is_s3c2443
7135 +# define cpu_is_s3c2443() is_s3c2443()
7136 +#endif
7137 +
7138 +#if defined(CONFIG_ARCH_S3C64XX)
7139 +# undef cpu_is_s3c6400
7140 +# undef cpu_is_s3c6410
7141 +# define cpu_is_s3c6400() is_s3c6400()
7142 +# define cpu_is_s3c6410() is_s3c6410()
7143 +#endif
7144 +
7145 +#endif
7146 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/mach/io.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/mach/io.h
7147 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/mach/io.h 2009-05-10 22:05:04.000000000 +0200
7148 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/mach/io.h 2009-05-10 22:27:59.000000000 +0200
7149 @@ -10,6 +10,7 @@
7150 #define __ASM_ARM_ARCH_IO_H
7151
7152 /* No current ISA/PCI bus support. */
7153 +
7154 #define __io(a) __typesafe_io(a)
7155 #define __mem_pci(a) (a)
7156
7157 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/audio.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/audio.h
7158 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/audio.h 1970-01-01 01:00:00.000000000 +0100
7159 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/audio.h 2009-05-10 22:27:59.000000000 +0200
7160 @@ -0,0 +1,45 @@
7161 +/* arch/arm/mach-s3c2410/include/mach/audio.h
7162 + *
7163 + * Copyright (c) 2004-2005 Simtec Electronics
7164 + * http://www.simtec.co.uk/products/SWLINUX/
7165 + * Ben Dooks <ben@simtec.co.uk>
7166 + *
7167 + * S3C24XX - Audio platfrom_device info
7168 + *
7169 + * This program is free software; you can redistribute it and/or modify
7170 + * it under the terms of the GNU General Public License version 2 as
7171 + * published by the Free Software Foundation.
7172 +*/
7173 +
7174 +#ifndef __ASM_ARCH_AUDIO_H
7175 +#define __ASM_ARCH_AUDIO_H __FILE__
7176 +
7177 +/* struct s3c24xx_iis_ops
7178 + *
7179 + * called from the s3c24xx audio core to deal with the architecture
7180 + * or the codec's setup and control.
7181 + *
7182 + * the pointer to itself is passed through in case the caller wants to
7183 + * embed this in an larger structure for easy reference to it's context.
7184 +*/
7185 +
7186 +struct s3c24xx_iis_ops {
7187 + struct module *owner;
7188 +
7189 + int (*startup)(struct s3c24xx_iis_ops *me);
7190 + void (*shutdown)(struct s3c24xx_iis_ops *me);
7191 + int (*suspend)(struct s3c24xx_iis_ops *me);
7192 + int (*resume)(struct s3c24xx_iis_ops *me);
7193 +
7194 + int (*open)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
7195 + int (*close)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm);
7196 + int (*prepare)(struct s3c24xx_iis_ops *me, struct snd_pcm_substream *strm, struct snd_pcm_runtime *rt);
7197 +};
7198 +
7199 +struct s3c24xx_platdata_iis {
7200 + const char *codec_clk;
7201 + struct s3c24xx_iis_ops *ops;
7202 + int (*match_dev)(struct device *dev);
7203 +};
7204 +
7205 +#endif /* __ASM_ARCH_AUDIO_H */
7206 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/clock.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/clock.h
7207 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/clock.h 2009-05-10 22:05:04.000000000 +0200
7208 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/clock.h 2009-05-10 22:27:59.000000000 +0200
7209 @@ -50,6 +50,7 @@
7210 extern struct clk clk_ext;
7211
7212 /* S3C64XX specific clocks */
7213 +extern struct clk clk_h2;
7214 extern struct clk clk_27m;
7215 extern struct clk clk_48m;
7216
7217 @@ -80,6 +81,7 @@
7218
7219 /* S3C64XX specific functions and clocks */
7220
7221 +extern int s3c64xx_hclk_ctrl(struct clk *clk, int enable);
7222 extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
7223
7224 /* Init for pwm clock code */
7225 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/cpu.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/cpu.h
7226 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/cpu.h 2009-05-10 22:05:04.000000000 +0200
7227 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/cpu.h 2009-05-10 22:27:59.000000000 +0200
7228 @@ -69,3 +69,6 @@
7229 extern struct sysdev_class s3c2440_sysclass;
7230 extern struct sysdev_class s3c2442_sysclass;
7231 extern struct sysdev_class s3c2443_sysclass;
7232 +extern struct sysdev_class s3c6410_sysclass;
7233 +extern struct sysdev_class s3c64xx_sysclass;
7234 +
7235 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/devs.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/devs.h
7236 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/devs.h 2009-05-10 22:05:04.000000000 +0200
7237 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/devs.h 2009-05-10 22:27:59.000000000 +0200
7238 @@ -16,6 +16,10 @@
7239 unsigned long nr_resources;
7240 };
7241
7242 +struct s3c_plat_otg_data {
7243 + int phyclk;
7244 +};
7245 +
7246 extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
7247 extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
7248
7249 @@ -45,10 +49,11 @@
7250
7251 extern struct platform_device s3c_device_usbgadget;
7252
7253 +extern struct platform_device s3c_device_ts;
7254 +
7255 /* s3c2440 specific devices */
7256
7257 #ifdef CONFIG_CPU_S3C2440
7258
7259 extern struct platform_device s3c_device_camif;
7260 -
7261 #endif
7262 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/dma-core.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/dma-core.h
7263 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/dma-core.h 1970-01-01 01:00:00.000000000 +0100
7264 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/dma-core.h 2009-05-10 22:27:59.000000000 +0200
7265 @@ -0,0 +1,22 @@
7266 +/* arch/arm/plat-s3c/include/plat/dma.h
7267 + *
7268 + * Copyright 2008 Openmoko, Inc.
7269 + * Copyright 2008 Simtec Electronics
7270 + * Ben Dooks <ben@simtec.co.uk>
7271 + * http://armlinux.simtec.co.uk/
7272 + *
7273 + * Samsung S3C DMA core support
7274 + *
7275 + * This program is free software; you can redistribute it and/or modify
7276 + * it under the terms of the GNU General Public License version 2 as
7277 + * published by the Free Software Foundation.
7278 +*/
7279 +
7280 +extern struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel);
7281 +
7282 +extern struct s3c2410_dma_chan *s3c_dma_chan_map[];
7283 +
7284 +/* the currently allocated channel information */
7285 +extern struct s3c2410_dma_chan s3c2410_chans[];
7286 +
7287 +
7288 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/dma.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/dma.h
7289 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/dma.h 1970-01-01 01:00:00.000000000 +0100
7290 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/dma.h 2009-05-10 22:27:59.000000000 +0200
7291 @@ -0,0 +1,128 @@
7292 +/* arch/arm/plat-s3c/include/plat/dma.h
7293 + *
7294 + * Copyright (C) 2003,2004,2006 Simtec Electronics
7295 + * Ben Dooks <ben@simtec.co.uk>
7296 + *
7297 + * Samsung S3C DMA support
7298 + *
7299 + * This program is free software; you can redistribute it and/or modify
7300 + * it under the terms of the GNU General Public License version 2 as
7301 + * published by the Free Software Foundation.
7302 +*/
7303 +
7304 +enum s3c2410_dma_buffresult {
7305 + S3C2410_RES_OK,
7306 + S3C2410_RES_ERR,
7307 + S3C2410_RES_ABORT
7308 +};
7309 +
7310 +enum s3c2410_dmasrc {
7311 + S3C2410_DMASRC_HW, /* source is memory */
7312 + S3C2410_DMASRC_MEM /* source is hardware */
7313 +};
7314 +
7315 +/* enum s3c2410_chan_op
7316 + *
7317 + * operation codes passed to the DMA code by the user, and also used
7318 + * to inform the current channel owner of any changes to the system state
7319 +*/
7320 +
7321 +enum s3c2410_chan_op {
7322 + S3C2410_DMAOP_START,
7323 + S3C2410_DMAOP_STOP,
7324 + S3C2410_DMAOP_PAUSE,
7325 + S3C2410_DMAOP_RESUME,
7326 + S3C2410_DMAOP_FLUSH,
7327 + S3C2410_DMAOP_TIMEOUT, /* internal signal to handler */
7328 + S3C2410_DMAOP_STARTED, /* indicate channel started */
7329 +};
7330 +
7331 +struct s3c2410_dma_client {
7332 + char *name;
7333 +};
7334 +
7335 +struct s3c2410_dma_chan;
7336 +
7337 +/* s3c2410_dma_cbfn_t
7338 + *
7339 + * buffer callback routine type
7340 +*/
7341 +
7342 +typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
7343 + void *buf, int size,
7344 + enum s3c2410_dma_buffresult result);
7345 +
7346 +typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
7347 + enum s3c2410_chan_op );
7348 +
7349 +
7350 +
7351 +/* s3c2410_dma_request
7352 + *
7353 + * request a dma channel exclusivley
7354 +*/
7355 +
7356 +extern int s3c2410_dma_request(unsigned int channel,
7357 + struct s3c2410_dma_client *, void *dev);
7358 +
7359 +
7360 +/* s3c2410_dma_ctrl
7361 + *
7362 + * change the state of the dma channel
7363 +*/
7364 +
7365 +extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
7366 +
7367 +/* s3c2410_dma_setflags
7368 + *
7369 + * set the channel's flags to a given state
7370 +*/
7371 +
7372 +extern int s3c2410_dma_setflags(unsigned int channel,
7373 + unsigned int flags);
7374 +
7375 +/* s3c2410_dma_free
7376 + *
7377 + * free the dma channel (will also abort any outstanding operations)
7378 +*/
7379 +
7380 +extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
7381 +
7382 +/* s3c2410_dma_enqueue
7383 + *
7384 + * place the given buffer onto the queue of operations for the channel.
7385 + * The buffer must be allocated from dma coherent memory, or the Dcache/WB
7386 + * drained before the buffer is given to the DMA system.
7387 +*/
7388 +
7389 +extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
7390 + dma_addr_t data, int size);
7391 +
7392 +
7393 +/* s3c2410_dma_config
7394 + *
7395 + * configure the dma channel
7396 +*/
7397 +
7398 +extern int s3c2410_dma_config(unsigned int channel, int xferunit);
7399 +
7400 +/* s3c2410_dma_devconfig
7401 + *
7402 + * configure the device we're talking to
7403 +*/
7404 +
7405 +extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
7406 + unsigned long devaddr);
7407 +
7408 +/* s3c2410_dma_getposition
7409 + *
7410 + * get the position that the dma transfer is currently at
7411 +*/
7412 +
7413 +extern int s3c2410_dma_getposition(unsigned int channel,
7414 + dma_addr_t *src, dma_addr_t *dest);
7415 +
7416 +extern int s3c2410_dma_set_opfn(unsigned int, s3c2410_dma_opfn_t rtn);
7417 +extern int s3c2410_dma_set_buffdone_fn(unsigned int, s3c2410_dma_cbfn_t rtn);
7418 +
7419 +
7420 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/gpio-core.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/gpio-core.h
7421 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/gpio-core.h 2009-05-10 22:05:04.000000000 +0200
7422 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/gpio-core.h 2009-05-10 22:27:59.000000000 +0200
7423 @@ -20,6 +20,19 @@
7424 * specific code.
7425 */
7426
7427 +struct s3c_gpio_chip;
7428 +
7429 +/**
7430 + * struct s3c_gpio_pm - power management (suspend/resume) information
7431 + * @save: Routine to save the state of the GPIO block
7432 + * @resume: Routine to resume the GPIO block.
7433 + */
7434 +struct s3c_gpio_pm {
7435 + void (*save)(struct s3c_gpio_chip *chip);
7436 + void (*resume)(struct s3c_gpio_chip *chip);
7437 +};
7438 +
7439 +
7440 struct s3c_gpio_cfg;
7441
7442 /**
7443 @@ -27,6 +40,7 @@
7444 * @chip: The chip structure to be exported via gpiolib.
7445 * @base: The base pointer to the gpio configuration registers.
7446 * @config: special function and pull-resistor control information.
7447 + * @pm_save: Save information for suspend/resume support.
7448 *
7449 * This wrapper provides the necessary information for the Samsung
7450 * specific gpios being registered with gpiolib.
7451 @@ -34,7 +48,11 @@
7452 struct s3c_gpio_chip {
7453 struct gpio_chip chip;
7454 struct s3c_gpio_cfg *config;
7455 + struct s3c_gpio_pm *pm;
7456 void __iomem *base;
7457 +#ifdef CONFIG_PM
7458 + u32 pm_save[4];
7459 +#endif
7460 };
7461
7462 static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
7463 @@ -75,3 +93,16 @@
7464
7465 static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
7466 #endif
7467 +
7468 +#ifdef CONFIG_PM
7469 +extern struct s3c_gpio_pm s3c_gpio_pm_1bit;
7470 +extern struct s3c_gpio_pm s3c_gpio_pm_2bit;
7471 +extern struct s3c_gpio_pm s3c_gpio_pm_4bit;
7472 +#define __gpio_pm(x) x
7473 +#else
7474 +#define s3c_gpio_pm_1bit NULL
7475 +#define s3c_gpio_pm_2bit NULL
7476 +#define s3c_gpio_pm_4bit NULL
7477 +#define __gpio_pm(x) NULL
7478 +
7479 +#endif /* CONFIG_PM */
7480 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/map-base.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/map-base.h
7481 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/map-base.h 2009-05-10 22:05:04.000000000 +0200
7482 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/map-base.h 2009-05-10 22:27:59.000000000 +0200
7483 @@ -36,5 +36,7 @@
7484 #define S3C_VA_TIMER S3C_ADDR(0x00300000) /* timer block */
7485 #define S3C_VA_WATCHDOG S3C_ADDR(0x00400000) /* watchdog */
7486 #define S3C_VA_UART S3C_ADDR(0x01000000) /* UART */
7487 +#define S3C_VA_OTG S3C_ADDR(0x03900000) /* OTG */
7488 +#define S3C_VA_OTGSFR S3C_ADDR(0x03a00000) /* OTGSFR */
7489
7490 #endif /* __ASM_PLAT_MAP_H */
7491 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/nand.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/nand.h
7492 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/nand.h 2009-05-10 22:05:04.000000000 +0200
7493 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/nand.h 2009-05-10 22:27:59.000000000 +0200
7494 @@ -21,11 +21,14 @@
7495 * partitions = mtd partition list
7496 */
7497
7498 +#define S3C2410_NAND_BBT 0x0001
7499 +
7500 struct s3c2410_nand_set {
7501 unsigned int disable_ecc : 1;
7502
7503 int nr_chips;
7504 int nr_partitions;
7505 + unsigned int flags;
7506 char *name;
7507 int *nr_map;
7508 struct mtd_partition *partitions;
7509 @@ -44,6 +47,9 @@
7510 int nr_sets;
7511 struct s3c2410_nand_set *sets;
7512
7513 + /* force software_ecc at runtime */
7514 + int software_ecc;
7515 +
7516 void (*select_chip)(struct s3c2410_nand_set *,
7517 int chip);
7518 };
7519 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/pm.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/pm.h
7520 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/pm.h 1970-01-01 01:00:00.000000000 +0100
7521 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/pm.h 2009-05-10 22:27:59.000000000 +0200
7522 @@ -0,0 +1,184 @@
7523 +/* linux/include/asm-arm/plat-s3c24xx/pm.h
7524 + *
7525 + * Copyright (c) 2004 Simtec Electronics
7526 + * http://armlinux.simtec.co.uk/
7527 + * Written by Ben Dooks, <ben@simtec.co.uk>
7528 + *
7529 + * This program is free software; you can redistribute it and/or modify
7530 + * it under the terms of the GNU General Public License version 2 as
7531 + * published by the Free Software Foundation.
7532 +*/
7533 +
7534 +#include <linux/sysdev.h>
7535 +
7536 +/* s3c_pm_init
7537 + *
7538 + * called from board at initialisation time to setup the power
7539 + * management
7540 +*/
7541 +
7542 +#ifdef CONFIG_PM
7543 +
7544 +extern __init int s3c_pm_init(void);
7545 +
7546 +#else
7547 +
7548 +static inline int s3c_pm_init(void)
7549 +{
7550 + return 0;
7551 +}
7552 +#endif
7553 +
7554 +/* configuration for the IRQ mask over sleep */
7555 +extern unsigned long s3c_irqwake_intmask;
7556 +extern unsigned long s3c_irqwake_eintmask;
7557 +
7558 +/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
7559 +extern unsigned long s3c_irqwake_intallow;
7560 +extern unsigned long s3c_irqwake_eintallow;
7561 +
7562 +/* per-cpu sleep functions */
7563 +
7564 +extern void (*pm_cpu_prep)(void);
7565 +extern void (*pm_cpu_sleep)(void);
7566 +
7567 +/* Flags for PM Control */
7568 +
7569 +extern unsigned long s3c_pm_flags;
7570 +
7571 +extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
7572 +
7573 +/* from sleep.S */
7574 +
7575 +extern int s3c_cpu_save(unsigned long *saveblk);
7576 +extern void s3c_cpu_resume(void);
7577 +
7578 +extern void s3c2410_cpu_suspend(void);
7579 +
7580 +extern unsigned long s3c_sleep_save_phys;
7581 +
7582 +/* sleep save info */
7583 +
7584 +/**
7585 + * struct sleep_save - save information for shared peripherals.
7586 + * @reg: Pointer to the register to save.
7587 + * @val: Holder for the value saved from reg.
7588 + *
7589 + * This describes a list of registers which is used by the pm core and
7590 + * other subsystem to save and restore register values over suspend.
7591 + */
7592 +struct sleep_save {
7593 + void __iomem *reg;
7594 + unsigned long val;
7595 +};
7596 +
7597 +#define SAVE_ITEM(x) \
7598 + { .reg = (x) }
7599 +
7600 +/**
7601 + * struct pm_uart_save - save block for core UART
7602 + * @ulcon: Save value for S3C2410_ULCON
7603 + * @ucon: Save value for S3C2410_UCON
7604 + * @ufcon: Save value for S3C2410_UFCON
7605 + * @umcon: Save value for S3C2410_UMCON
7606 + * @ubrdiv: Save value for S3C2410_UBRDIV
7607 + *
7608 + * Save block for UART registers to be held over sleep and restored if they
7609 + * are needed (say by debug).
7610 +*/
7611 +struct pm_uart_save {
7612 + u32 ulcon;
7613 + u32 ucon;
7614 + u32 ufcon;
7615 + u32 umcon;
7616 + u32 ubrdiv;
7617 + u32 udivslot;
7618 +};
7619 +
7620 +/* helper functions to save/restore lists of registers. */
7621 +
7622 +extern void s3c_pm_do_save(struct sleep_save *ptr, int count);
7623 +extern void s3c_pm_do_restore(struct sleep_save *ptr, int count);
7624 +extern void s3c_pm_do_restore_core(struct sleep_save *ptr, int count);
7625 +
7626 +#ifdef CONFIG_PM
7627 +extern int s3c_irqext_wake(unsigned int irqno, unsigned int state);
7628 +extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
7629 +extern int s3c24xx_irq_resume(struct sys_device *dev);
7630 +#else
7631 +#define s3c_irqext_wake NULL
7632 +#define s3c24xx_irq_suspend NULL
7633 +#define s3c24xx_irq_resume NULL
7634 +#endif
7635 +
7636 +/* PM debug functions */
7637 +
7638 +#ifdef CONFIG_S3C2410_PM_DEBUG
7639 +/**
7640 + * s3c_pm_dbg() - low level debug function for use in suspend/resume.
7641 + * @msg: The message to print.
7642 + *
7643 + * This function is used mainly to debug the resume process before the system
7644 + * can rely on printk/console output. It uses the low-level debugging output
7645 + * routine printascii() to do its work.
7646 + */
7647 +extern void s3c_pm_dbg(const char *msg, ...);
7648 +
7649 +#define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt)
7650 +#else
7651 +#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
7652 +#endif
7653 +
7654 +#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
7655 +/**
7656 + * s3c_pm_debug_smdkled() - Debug PM suspend/resume via SMDK Board LEDs
7657 + * @set: set bits for the state of the LEDs
7658 + * @clear: clear bits for the state of the LEDs.
7659 + */
7660 +extern void s3c_pm_debug_smdkled(u32 set, u32 clear);
7661 +
7662 +#else
7663 +static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
7664 +#endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */
7665 +
7666 +/* suspend memory checking */
7667 +
7668 +#ifdef CONFIG_S3C2410_PM_CHECK
7669 +extern void s3c_pm_check_prepare(void);
7670 +extern void s3c_pm_check_restore(void);
7671 +extern void s3c_pm_check_cleanup(void);
7672 +extern void s3c_pm_check_store(void);
7673 +#else
7674 +#define s3c_pm_check_prepare() do { } while(0)
7675 +#define s3c_pm_check_restore() do { } while(0)
7676 +#define s3c_pm_check_cleanup() do { } while(0)
7677 +#define s3c_pm_check_store() do { } while(0)
7678 +#endif
7679 +
7680 +/**
7681 + * s3c_pm_configure_extint() - ensure pins are correctly set for IRQ
7682 + *
7683 + * Setup all the necessary GPIO pins for waking the system on external
7684 + * interrupt.
7685 + */
7686 +extern void s3c_pm_configure_extint(void);
7687 +
7688 +/**
7689 + * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
7690 + *
7691 + * Restore the state of the GPIO pins after sleep, which may involve ensuring
7692 + * that we do not glitch the state of the pins from that the bootloader's
7693 + * resume code has done.
7694 +*/
7695 +extern void s3c_pm_restore_gpios(void);
7696 +
7697 +/**
7698 + * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
7699 + *
7700 + * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
7701 + */
7702 +extern void s3c_pm_save_gpios(void);
7703 +
7704 +extern void s3c_pm_save_core(void);
7705 +extern void s3c_pm_restore_core(void);
7706 +
7707 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/pwm.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/pwm.h
7708 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/pwm.h 1970-01-01 01:00:00.000000000 +0100
7709 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/pwm.h 2009-05-10 22:27:59.000000000 +0200
7710 @@ -0,0 +1,45 @@
7711 +#ifndef __S3C2410_PWM_H
7712 +#define __S3C2410_PWM_H
7713 +
7714 +#include <linux/err.h>
7715 +#include <linux/platform_device.h>
7716 +#include <linux/clk.h>
7717 +
7718 +#include <mach/io.h>
7719 +#include <mach/hardware.h>
7720 +#include <asm/mach-types.h>
7721 +#include <plat/regs-timer.h>
7722 +
7723 +enum pwm_timer {
7724 + PWM0,
7725 + PWM1,
7726 + PWM2,
7727 + PWM3,
7728 + PWM4
7729 +};
7730 +
7731 +struct s3c2410_pwm {
7732 + enum pwm_timer timerid;
7733 + struct clk *pclk;
7734 + unsigned long pclk_rate;
7735 + unsigned long prescaler;
7736 + unsigned long divider;
7737 + unsigned long counter;
7738 + unsigned long comparer;
7739 +};
7740 +
7741 +struct s3c24xx_pwm_platform_data{
7742 + /* callback to attach platform children (to enforce suspend / resume
7743 + * ordering */
7744 + void (*attach_child_devices)(struct device *parent_device);
7745 +};
7746 +
7747 +int s3c2410_pwm_init(struct s3c2410_pwm *s3c2410_pwm);
7748 +int s3c2410_pwm_enable(struct s3c2410_pwm *s3c2410_pwm);
7749 +int s3c2410_pwm_disable(struct s3c2410_pwm *s3c2410_pwm);
7750 +int s3c2410_pwm_start(struct s3c2410_pwm *s3c2410_pwm);
7751 +int s3c2410_pwm_stop(struct s3c2410_pwm *s3c2410_pwm);
7752 +int s3c2410_pwm_duty_cycle(int reg_value, struct s3c2410_pwm *s3c2410_pwm);
7753 +int s3c2410_pwm_dumpregs(void);
7754 +
7755 +#endif /* __S3C2410_PWM_H */
7756 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h
7757 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h 1970-01-01 01:00:00.000000000 +0100
7758 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/regs-s3c2412-iis.h 2009-05-10 22:27:59.000000000 +0200
7759 @@ -0,0 +1,75 @@
7760 +/* linux/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h
7761 + *
7762 + * Copyright 2007 Simtec Electronics <linux@simtec.co.uk>
7763 + * http://armlinux.simtec.co.uk/
7764 + *
7765 + * This program is free software; you can redistribute it and/or modify
7766 + * it under the terms of the GNU General Public License version 2 as
7767 + * published by the Free Software Foundation.
7768 + *
7769 + * S3C2412 IIS register definition
7770 +*/
7771 +
7772 +#ifndef __ASM_ARCH_REGS_S3C2412_IIS_H
7773 +#define __ASM_ARCH_REGS_S3C2412_IIS_H
7774 +
7775 +#define S3C2412_IISCON (0x00)
7776 +#define S3C2412_IISMOD (0x04)
7777 +#define S3C2412_IISFIC (0x08)
7778 +#define S3C2412_IISPSR (0x0C)
7779 +#define S3C2412_IISTXD (0x10)
7780 +#define S3C2412_IISRXD (0x14)
7781 +
7782 +#define S3C2412_IISCON_LRINDEX (1 << 11)
7783 +#define S3C2412_IISCON_TXFIFO_EMPTY (1 << 10)
7784 +#define S3C2412_IISCON_RXFIFO_EMPTY (1 << 9)
7785 +#define S3C2412_IISCON_TXFIFO_FULL (1 << 8)
7786 +#define S3C2412_IISCON_RXFIFO_FULL (1 << 7)
7787 +#define S3C2412_IISCON_TXDMA_PAUSE (1 << 6)
7788 +#define S3C2412_IISCON_RXDMA_PAUSE (1 << 5)
7789 +#define S3C2412_IISCON_TXCH_PAUSE (1 << 4)
7790 +#define S3C2412_IISCON_RXCH_PAUSE (1 << 3)
7791 +#define S3C2412_IISCON_TXDMA_ACTIVE (1 << 2)
7792 +#define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1)
7793 +#define S3C2412_IISCON_IIS_ACTIVE (1 << 0)
7794 +
7795 +#define S3C64XX_IISMOD_IMS_PCLK (0 << 10)
7796 +#define S3C64XX_IISMOD_IMS_SYSMUX (1 << 10)
7797 +
7798 +#define S3C2412_IISMOD_MASTER_INTERNAL (0 << 10)
7799 +#define S3C2412_IISMOD_MASTER_EXTERNAL (1 << 10)
7800 +#define S3C2412_IISMOD_SLAVE (2 << 10)
7801 +#define S3C2412_IISMOD_MASTER_MASK (3 << 10)
7802 +#define S3C2412_IISMOD_MODE_TXONLY (0 << 8)
7803 +#define S3C2412_IISMOD_MODE_RXONLY (1 << 8)
7804 +#define S3C2412_IISMOD_MODE_TXRX (2 << 8)
7805 +#define S3C2412_IISMOD_MODE_MASK (3 << 8)
7806 +#define S3C2412_IISMOD_LR_LLOW (0 << 7)
7807 +#define S3C2412_IISMOD_LR_RLOW (1 << 7)
7808 +#define S3C2412_IISMOD_SDF_IIS (0 << 5)
7809 +#define S3C2412_IISMOD_SDF_MSB (1 << 5)
7810 +#define S3C2412_IISMOD_SDF_LSB (2 << 5)
7811 +#define S3C2412_IISMOD_SDF_MASK (3 << 5)
7812 +#define S3C2412_IISMOD_RCLK_256FS (0 << 3)
7813 +#define S3C2412_IISMOD_RCLK_512FS (1 << 3)
7814 +#define S3C2412_IISMOD_RCLK_384FS (2 << 3)
7815 +#define S3C2412_IISMOD_RCLK_768FS (3 << 3)
7816 +#define S3C2412_IISMOD_RCLK_MASK (3 << 3)
7817 +#define S3C2412_IISMOD_BCLK_32FS (0 << 1)
7818 +#define S3C2412_IISMOD_BCLK_48FS (1 << 1)
7819 +#define S3C2412_IISMOD_BCLK_16FS (2 << 1)
7820 +#define S3C2412_IISMOD_BCLK_24FS (3 << 1)
7821 +#define S3C2412_IISMOD_BCLK_MASK (3 << 1)
7822 +#define S3C2412_IISMOD_8BIT (1 << 0)
7823 +
7824 +#define S3C2412_IISPSR_PSREN (1 << 15)
7825 +
7826 +#define S3C2412_IISFIC_TXFLUSH (1 << 15)
7827 +#define S3C2412_IISFIC_RXFLUSH (1 << 7)
7828 +#define S3C2412_IISFIC_TXCOUNT(x) (((x) >> 8) & 0xf)
7829 +#define S3C2412_IISFIC_RXCOUNT(x) (((x) >> 0) & 0xf)
7830 +
7831 +
7832 +
7833 +#endif /* __ASM_ARCH_REGS_S3C2412_IIS_H */
7834 +
7835 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/regs-serial.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/regs-serial.h
7836 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/regs-serial.h 2009-05-10 22:05:04.000000000 +0200
7837 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/regs-serial.h 2009-05-10 22:27:59.000000000 +0200
7838 @@ -189,6 +189,11 @@
7839
7840 #define S3C2443_DIVSLOT (0x2C)
7841
7842 +/* S3C64XX interrupt registers. */
7843 +#define S3C64XX_UINTP 0x30
7844 +#define S3C64XX_UINTSP 0x34
7845 +#define S3C64XX_UINTM 0x38
7846 +
7847 #ifndef __ASSEMBLY__
7848
7849 /* struct s3c24xx_uart_clksrc
7850 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/regs-timer.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/regs-timer.h
7851 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/regs-timer.h 2009-05-10 22:05:04.000000000 +0200
7852 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/regs-timer.h 2009-05-10 22:27:59.000000000 +0200
7853 @@ -10,6 +10,8 @@
7854 * S3C2410 Timer configuration
7855 */
7856
7857 +#include <plat/map-base.h>
7858 +
7859 #ifndef __ASM_ARCH_REGS_TIMER_H
7860 #define __ASM_ARCH_REGS_TIMER_H
7861
7862 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/regs-usb-hs-otg.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/regs-usb-hs-otg.h
7863 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/regs-usb-hs-otg.h 1970-01-01 01:00:00.000000000 +0100
7864 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/regs-usb-hs-otg.h 2009-05-10 22:27:59.000000000 +0200
7865 @@ -0,0 +1,360 @@
7866 +/* linux/include/asm-arm/arch-s3c2410/regs-udc.h
7867 + *
7868 + * Copyright (C) 2008 Samsung Electronics
7869 + * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
7870 + *
7871 + * This include file is free software; you can redistribute it and/or
7872 + * modify it under the terms of the GNU General Public License as
7873 + * published by the Free Software Foundation; either version 2 of
7874 + * the License, or (at your option) any later version.
7875 +*/
7876 +
7877 +#ifndef __ASM_ARCH_REGS_USB_HS_OTG_H
7878 +#define __ASM_ARCH_REGS_USB_HS_OTG_H
7879 +
7880 +/* USB2.0 OTG Controller register */
7881 +#define S3C_USBOTG_PHYREG(x) ((x) + 0x100000 /* S3C64XX_VA_OTGSFR */)
7882 +#define S3C_USBOTG_PHYPWR S3C_USBOTG_PHYREG(0x0)
7883 +#define S3C_USBOTG_PHYCLK S3C_USBOTG_PHYREG(0x4)
7884 +#define S3C_USBOTG_RSTCON S3C_USBOTG_PHYREG(0x8)
7885 +
7886 +/* USB2.0 OTG Controller register */
7887 +/* Core Global Registers */
7888 +#define S3C_USBOTGREG(x) ((x) /*+ S3C64XX_VA_OTG */)
7889 +/* OTG Control & Status */
7890 +#define S3C_UDC_OTG_GOTGCTL S3C_USBOTGREG(0x000)
7891 +/* OTG Interrupt */
7892 +#define S3C_UDC_OTG_GOTGINT S3C_USBOTGREG(0x004)
7893 +/* Core AHB Configuration */
7894 +#define S3C_UDC_OTG_GAHBCFG S3C_USBOTGREG(0x008)
7895 +/* Core USB Configuration */
7896 +#define S3C_UDC_OTG_GUSBCFG S3C_USBOTGREG(0x00C)
7897 +/* Core Reset */
7898 +#define S3C_UDC_OTG_GRSTCTL S3C_USBOTGREG(0x010)
7899 +/* Core Interrupt */
7900 +#define S3C_UDC_OTG_GINTSTS S3C_USBOTGREG(0x014)
7901 +/* Core Interrupt Mask */
7902 +#define S3C_UDC_OTG_GINTMSK S3C_USBOTGREG(0x018)
7903 +/* Receive Status Debug Read/Status Read */
7904 +#define S3C_UDC_OTG_GRXSTSR S3C_USBOTGREG(0x01C)
7905 +/* Receive Status Debug Pop/Status Pop */
7906 +#define S3C_UDC_OTG_GRXSTSP S3C_USBOTGREG(0x020)
7907 +/* Receive FIFO Size */
7908 +#define S3C_UDC_OTG_GRXFSIZ S3C_USBOTGREG(0x024)
7909 +/* Non-Periodic Transmit FIFO Size */
7910 +#define S3C_UDC_OTG_GNPTXFSIZ S3C_USBOTGREG(0x028)
7911 +/* Non-Periodic Transmit FIFO/Queue Status */
7912 +#define S3C_UDC_OTG_GNPTXSTS S3C_USBOTGREG(0x02C)
7913 +
7914 +/* Host Periodic Transmit FIFO Size */
7915 +#define S3C_UDC_OTG_HPTXFSIZ S3C_USBOTGREG(0x100)
7916 +/* Device Periodic Transmit FIFO-1 Size */
7917 +#define S3C_UDC_OTG_DPTXFSIZ1 S3C_USBOTGREG(0x104)
7918 +/* Device Periodic Transmit FIFO-2 Size */
7919 +#define S3C_UDC_OTG_DPTXFSIZ2 S3C_USBOTGREG(0x108)
7920 +/* Device Periodic Transmit FIFO-3 Size */
7921 +#define S3C_UDC_OTG_DPTXFSIZ3 S3C_USBOTGREG(0x10C)
7922 +/* Device Periodic Transmit FIFO-4 Size */
7923 +#define S3C_UDC_OTG_DPTXFSIZ4 S3C_USBOTGREG(0x110)
7924 +/* Device Periodic Transmit FIFO-5 Size */
7925 +#define S3C_UDC_OTG_DPTXFSIZ5 S3C_USBOTGREG(0x114)
7926 +/* Device Periodic Transmit FIFO-6 Size */
7927 +#define S3C_UDC_OTG_DPTXFSIZ6 S3C_USBOTGREG(0x118)
7928 +/* Device Periodic Transmit FIFO-7 Size */
7929 +#define S3C_UDC_OTG_DPTXFSIZ7 S3C_USBOTGREG(0x11C)
7930 +/* Device Periodic Transmit FIFO-8 Size */
7931 +#define S3C_UDC_OTG_DPTXFSIZ8 S3C_USBOTGREG(0x120)
7932 +/* Device Periodic Transmit FIFO-9 Size */
7933 +#define S3C_UDC_OTG_DPTXFSIZ9 S3C_USBOTGREG(0x124)
7934 +/* Device Periodic Transmit FIFO-10 Size */
7935 +#define S3C_UDC_OTG_DPTXFSIZ10 S3C_USBOTGREG(0x128)
7936 +/* Device Periodic Transmit FIFO-11 Size */
7937 +#define S3C_UDC_OTG_DPTXFSIZ11 S3C_USBOTGREG(0x12C)
7938 +/* Device Periodic Transmit FIFO-12 Size */
7939 +#define S3C_UDC_OTG_DPTXFSIZ12 S3C_USBOTGREG(0x130)
7940 +/* Device Periodic Transmit FIFO-13 Size */
7941 +#define S3C_UDC_OTG_DPTXFSIZ13 S3C_USBOTGREG(0x134)
7942 +/* Device Periodic Transmit FIFO-14 Size */
7943 +#define S3C_UDC_OTG_DPTXFSIZ14 S3C_USBOTGREG(0x138)
7944 +/* Device Periodic Transmit FIFO-15 Size */
7945 +#define S3C_UDC_OTG_DPTXFSIZ15 S3C_USBOTGREG(0x13C)
7946 +
7947 +/* Host Mode Registers
7948 + * Host Global Registers */
7949 +/* Host Configuration */
7950 +#define S3C_UDC_OTG_HCFG S3C_USBOTGREG(0x400)
7951 +/* Host Frame Interval */
7952 +#define S3C_UDC_OTG_HFIR S3C_USBOTGREG(0x404)
7953 +/* Host Frame Number/Frame Time Remaining */
7954 +#define S3C_UDC_OTG_HFNUM S3C_USBOTGREG(0x408)
7955 +/* Host Periodic Transmit FIFO/Queue Status */
7956 +#define S3C_UDC_OTG_HPTXSTS S3C_USBOTGREG(0x410)
7957 +/* Host All Channels Interrupt */
7958 +#define S3C_UDC_OTG_HAINT S3C_USBOTGREG(0x414)
7959 +/* Host All Channels Interrupt Mask */
7960 +#define S3C_UDC_OTG_HAINTMSK S3C_USBOTGREG(0x418)
7961 +
7962 +/* Host Port Control & Status Registers */
7963 +#define S3C_UDC_OTG_HPRT S3C_USBOTGREG(0x440)
7964 +
7965 +/* Host Channel-Specific Registers */
7966 +/* Host Channel-0 Characteristics */
7967 +#define S3C_UDC_OTG_HCCHAR0 S3C_USBOTGREG(0x500)
7968 +/* Host Channel-0 Split Control */
7969 +#define S3C_UDC_OTG_HCSPLT0 S3C_USBOTGREG(0x504)
7970 +/* Host Channel-0 Interrupt */
7971 +#define S3C_UDC_OTG_HCINT0 S3C_USBOTGREG(0x508)
7972 +/* Host Channel-0 Interrupt Mask */
7973 +#define S3C_UDC_OTG_HCINTMSK0 S3C_USBOTGREG(0x50C)
7974 +/* Host Channel-0 Transfer Size */
7975 +#define S3C_UDC_OTG_HCTSIZ0 S3C_USBOTGREG(0x510)
7976 +/* Host Channel-0 DMA Address */
7977 +#define S3C_UDC_OTG_HCDMA0 S3C_USBOTGREG(0x514)
7978 +
7979 +/* Device Mode Registers
7980 + * Device Global Registers */
7981 +/* Device Configuration */
7982 +#define S3C_UDC_OTG_DCFG S3C_USBOTGREG(0x800)
7983 +/* Device Control */
7984 +#define S3C_UDC_OTG_DCTL S3C_USBOTGREG(0x804)
7985 +/* Device Status */
7986 +#define S3C_UDC_OTG_DSTS S3C_USBOTGREG(0x808)
7987 +/* Device IN Endpoint Common Interrupt Mask */
7988 +#define S3C_UDC_OTG_DIEPMSK S3C_USBOTGREG(0x810)
7989 +/* Device OUT Endpoint Common Interrupt Mask */
7990 +#define S3C_UDC_OTG_DOEPMSK S3C_USBOTGREG(0x814)
7991 +/* Device All Endpoints Interrupt */
7992 +#define S3C_UDC_OTG_DAINT S3C_USBOTGREG(0x818)
7993 +/* Device All Endpoints Interrupt Mask */
7994 +#define S3C_UDC_OTG_DAINTMSK S3C_USBOTGREG(0x81C)
7995 +/* Device IN Token Sequence Learning Queue Read 1 */
7996 +#define S3C_UDC_OTG_DTKNQR1 S3C_USBOTGREG(0x820)
7997 +/* Device IN Token Sequence Learning Queue Read 2 */
7998 +#define S3C_UDC_OTG_DTKNQR2 S3C_USBOTGREG(0x824)
7999 +/* Device VBUS Discharge Time */
8000 +#define S3C_UDC_OTG_DVBUSDIS S3C_USBOTGREG(0x828)
8001 +/* Device VBUS Pulsing Time */
8002 +#define S3C_UDC_OTG_DVBUSPULSE S3C_USBOTGREG(0x82C)
8003 +/* Device IN Token Sequence Learning Queue Read 3 */
8004 +#define S3C_UDC_OTG_DTKNQR3 S3C_USBOTGREG(0x830)
8005 +/* Device IN Token Sequence Learning Queue Read 4 */
8006 +#define S3C_UDC_OTG_DTKNQR4 S3C_USBOTGREG(0x834)
8007 +
8008 +/* Device Logical IN Endpoint-Specific Registers */
8009 +/* Device IN Endpoint 0 Control */
8010 +#define S3C_UDC_OTG_DIEPCTL0 S3C_USBOTGREG(0x900)
8011 +/* Device IN Endpoint 0 Interrupt */
8012 +#define S3C_UDC_OTG_DIEPINT0 S3C_USBOTGREG(0x908)
8013 +/* Device IN Endpoint 0 Transfer Size */
8014 +#define S3C_UDC_OTG_DIEPTSIZ0 S3C_USBOTGREG(0x910)
8015 +/* Device IN Endpoint 0 DMA Address */
8016 +#define S3C_UDC_OTG_DIEPDMA0 S3C_USBOTGREG(0x914)
8017 +
8018 +/* Device IN Endpoint 2 Control */
8019 +#define S3C_UDC_OTG_DIEPCTL2 S3C_USBOTGREG(0x940)
8020 +/* Device IN Endpoint 2 Interrupt */
8021 +#define S3C_UDC_OTG_DIEPINT2 S3C_USBOTGREG(0x948)
8022 +/* Device IN Endpoint 2 Transfer Size */
8023 +#define S3C_UDC_OTG_DIEPTSIZ2 S3C_USBOTGREG(0x950)
8024 +/* Device IN Endpoint 2 DMA Address */
8025 +#define S3C_UDC_OTG_DIEPDMA2 S3C_USBOTGREG(0x954)
8026 +
8027 +/* Device IN Endpoint 3 Control */
8028 +#define S3C_UDC_OTG_DIEPCTL3 S3C_USBOTGREG(0x960)
8029 +/* Device IN Endpoint 3 Interrupt */
8030 +#define S3C_UDC_OTG_DIEPINT3 S3C_USBOTGREG(0x968)
8031 +/* Device IN Endpoint 3 Transfer Size */
8032 +#define S3C_UDC_OTG_DIEPTSIZ3 S3C_USBOTGREG(0x970)
8033 +/* Device IN Endpoint 3 DMA Address */
8034 +#define S3C_UDC_OTG_DIEPDMA3 S3C_USBOTGREG(0x974)
8035 +
8036 +/* Device Logical OUT Endpoint-Specific Registers */
8037 +/* Device OUT Endpoint 0 Control */
8038 +#define S3C_UDC_OTG_DOEPCTL0 S3C_USBOTGREG(0xB00)
8039 +/* Device OUT Endpoint 0 Interrupt */
8040 +#define S3C_UDC_OTG_DOEPINT0 S3C_USBOTGREG(0xB08)
8041 +/* Device OUT Endpoint 0 Transfer Size */
8042 +#define S3C_UDC_OTG_DOEPTSIZ0 S3C_USBOTGREG(0xB10)
8043 +/* Device OUT Endpoint 0 DMA Address */
8044 +#define S3C_UDC_OTG_DOEPDMA0 S3C_USBOTGREG(0xB14)
8045 +
8046 +/* Device OUT Endpoint 1 Control */
8047 +#define S3C_UDC_OTG_DOEPCTL1 S3C_USBOTGREG(0xB20)
8048 +/* Device OUT Endpoint 1 Interrupt */
8049 +#define S3C_UDC_OTG_DOEPINT1 S3C_USBOTGREG(0xB28)
8050 +/* Device OUT Endpoint 1 Transfer Size */
8051 +#define S3C_UDC_OTG_DOEPTSIZ1 S3C_USBOTGREG(0xB30)
8052 +/* Device OUT Endpoint 1 DMA Address */
8053 +#define S3C_UDC_OTG_DOEPDMA1 S3C_USBOTGREG(0xB34)
8054 +
8055 +/* Endpoint FIFO address */
8056 +#define S3C_UDC_OTG_EP0_FIFO S3C_USBOTGREG(0x1000)
8057 +#define S3C_UDC_OTG_EP1_FIFO S3C_USBOTGREG(0x2000)
8058 +#define S3C_UDC_OTG_EP2_FIFO S3C_USBOTGREG(0x3000)
8059 +#define S3C_UDC_OTG_EP3_FIFO S3C_USBOTGREG(0x4000)
8060 +#define S3C_UDC_OTG_EP4_FIFO S3C_USBOTGREG(0x5000)
8061 +#define S3C_UDC_OTG_EP5_FIFO S3C_USBOTGREG(0x6000)
8062 +#define S3C_UDC_OTG_EP6_FIFO S3C_USBOTGREG(0x7000)
8063 +#define S3C_UDC_OTG_EP7_FIFO S3C_USBOTGREG(0x8000)
8064 +#define S3C_UDC_OTG_EP8_FIFO S3C_USBOTGREG(0x9000)
8065 +
8066 +/* S3C_USBOTG_PHYPWR */
8067 +#define OTG_ENABLE (0x0<<4)
8068 +#define OTG_DISABLE (0x1<<4)
8069 +#define ANALOG_PWR_UP (0x0<<3)
8070 +#define ANALOG_PWR_DOWN (0x1<<3)
8071 +#define SUSPEND_DISABLE (0x0<<0)
8072 +#define SUSPEND_ENABLE (0x1<<0)
8073 +
8074 +/* S3C_USBOTG_PHYCLK */
8075 +#define REF_CLK_CRYSTAL (0x0<<5)
8076 +#define REF_CLK_OSCC (0x1<<5)
8077 +
8078 +/* S3C_USBOTG_RSTCON */
8079 +#define SW_RST_OFF (0x0<<0)
8080 +#define SW_RST_ON (0x1<<0)
8081 +
8082 +/* S3C_UDC_OTG_GOTGCTL */
8083 +#define B_SESSION_VALID (0x1<<19)
8084 +#define A_SESSION_VALID (0x1<<18)
8085 +
8086 +/* S3C_UDC_OTG_GAHBCFG */
8087 +#define PTXFE_HALF (0x0<<8)
8088 +#define PTXFE_ZERO (0x1<<8)
8089 +#define NPTXFE_HALF (0x0<<7)
8090 +#define NPTXFE_ZERO (0x1<<7)
8091 +#define MODE_SLAVE (0x0<<5)
8092 +#define MODE_DMA (0x1<<5)
8093 +#define BURST_SINGLE (0x0<<1)
8094 +#define BURST_INCR (0x1<<1)
8095 +#define BURST_INCR4 (0x3<<1)
8096 +#define BURST_INCR8 (0x5<<1)
8097 +#define BURST_INCR16 (0x7<<1)
8098 +#define GBL_INT_UNMASK (0x1<<0)
8099 +#define GBL_INT_MASK (0x0<<0)
8100 +
8101 +/* S3C_UDC_OTG_GUSBCFG */
8102 +#define PHY_CLK_480M (0x0<<15)
8103 +#define PHY_CLK_48M (0x1<<15)
8104 +#define TXFIFO_RE_DIS (0x0<<14)
8105 +#define TXFIFO_RE_EN (0x1<<14)
8106 +#define TURN_AROUND (0x5<<10)
8107 +#define HNP_DISABLE (0x0<<9)
8108 +#define HNP_ENABLE (0x1<<9)
8109 +#define SRP_DISABLE (0x0<<8)
8110 +#define SRP_ENABLE (0x1<<8)
8111 +#define ULPI_DDR (0x0<<7)
8112 +#define HS_UTMI (0x0<<6)
8113 +#define INTERF_UTMI (0x0<<4)
8114 +#define INTERF_ULPI (0x1<<4)
8115 +#define PHY_INTERF_8 (0x0<<3)
8116 +#define PHY_INTERF_16 (0x1<<3)
8117 +#define TIME_OUT_CAL (0x7<<0)
8118 +
8119 +/* S3C_UDC_OTG_GRSTCTL */
8120 +#define AHB_MASTER_IDLE (1u<<31)
8121 +#define CORE_SOFT_RESET (0x1<<0)
8122 +
8123 +/* S3C_UDC_OTG_GINTSTS/S3C_UDC_OTG_GINTMSK core interrupt register */
8124 +#define INT_RESUME (0x1<<31)
8125 +#define INT_DISCONN (0x1<<29)
8126 +#define INT_CONN_CNG (0x1<<28)
8127 +#define INT_OUT_EP (0x1<<19)
8128 +#define INT_IN_EP (0x1<<18)
8129 +#define INT_ENUMDONE (0x1<<13)
8130 +#define INT_RESET (0x1<<12)
8131 +#define INT_SUSPEND (0x1<<11)
8132 +#define INT_EARLY_SUSPEND (0x1<<10)
8133 +#define INT_TX_FIFO_EMPTY (0x1<<5)
8134 +#define INT_RX_FIFO_NOT_EMPTY (0x1<<4)
8135 +#define INT_SOF (0x1<<3)
8136 +#define INT_DEV_MODE (0x0<<0)
8137 +#define INT_HOST_MODE (0x1<<1)
8138 +
8139 +#define FULL_SPEED_CONTROL_PKT_SIZE 8
8140 +#define FULL_SPEED_BULK_PKT_SIZE 64
8141 +
8142 +#define HIGH_SPEED_CONTROL_PKT_SIZE 64
8143 +#define HIGH_SPEED_BULK_PKT_SIZE 512
8144 +
8145 +/* S3C_UDC_OTG_DSTS */
8146 +#define RX_FIFO_SIZE (2048<<0)
8147 +#define NPTX_FIFO_START_ADDR (RX_FIFO_SIZE<<0)
8148 +#define NPTX_FIFO_SIZE (2048<<16)
8149 +#define PTX_FIFO_SIZE (2048<<16)
8150 +#define USB_HIGH_30_60MHZ (0x0<<1)
8151 +#define USB_FULL_30_60MHZ (0x1<<1)
8152 +#define USB_LOW_6MHZ (0x2<<1)
8153 +#define USB_FULL_48MHZ (0x3<<1)
8154 +
8155 +/* S3C_UDC_OTG_GRXSTSP */
8156 +#define BYTE_COUNT(x) ((x & (0x7FF<<4)) >> 4)
8157 +#define PKT_STS(x) ((x & (0xF<<17)) >> 17)
8158 +#define EP_NUM(x) (x & 0xF)
8159 +
8160 +#define OUT_PKT_RECEIVED (0x2)
8161 +#define OUT_COMPLELTED (0x3)
8162 +#define SETUP_COMPLETED (0x4)
8163 +#define SETUP_PKT_RECEIVED (0x6)
8164 +
8165 +/* S3C_UDC_OTG_DCFG */
8166 +#define EP_MIS_CNT(x) (x<<18)
8167 +#define DEVICE_ADDR(x) (x<<4)
8168 +#define SPEED_2_HIGH (0x0<<0)
8169 +#define SPEED_2_FULL (0x1<<0)
8170 +#define SPEED_1_LOW (0x2<<0)
8171 +#define SPEED_1_FULL (0x3<<0)
8172 +
8173 +/* S3C_UDC_OTG_DCTL device control register */
8174 +#define NORMAL_OPERATION (0x1<<0)
8175 +#define SOFT_DISCONNECT (0x1<<1)
8176 +
8177 +/* S3C_UDC_OTG_DSTS */
8178 +#define ENUM_SPEED(x) (x & (0x3<<1))
8179 +#define FRAME_CNT(x) (x & (0x3ff<<8))
8180 +
8181 +/* S3C_UDC_OTG_DAINT device all endpoint interrupt register */
8182 +#define S3C_UDC_INT_IN_EP0 (0x1<<0)
8183 +#define S3C_UDC_INT_IN_EP2 (0x1<<2)
8184 +#define S3C_UDC_INT_IN_EP3 (0x1<<3)
8185 +#define S3C_UDC_INT_OUT_EP0 (0x1<<16)
8186 +#define S3C_UDC_INT_OUT_EP1 (0x1<<17)
8187 +#define S3C_UDC_INT_OUT_EP4 (0x1<<20)
8188 +
8189 +/* S3C_UDC_OTG_DIEPCTL0/DOEPCTL0 device control
8190 + IN/OUT endpoint 0 control register */
8191 +#define DEPCTL_EPENA (0x1<<31)
8192 +#define DEPCTL_EPDIS (0x1<<30)
8193 +#define DEPCTL_SNAK (0x1<<27)
8194 +#define DEPCTL_CNAK (0x1<<26)
8195 +#define DEPCTL_CTRL_TYPE (0x0<<18)
8196 +#define DEPCTL_ISO_TYPE (0x1<<18)
8197 +#define DEPCTL_BULK_TYPE (0x2<<18)
8198 +#define DEPCTL_INTR_TYPE (0x3<<18)
8199 +#define DEPCTL_USBACTEP (0x1<<15)
8200 +#define DEPCTL0_MPS_64 (0x0<<0)
8201 +#define DEPCTL0_MPS_32 (0x1<<0)
8202 +#define DEPCTL0_MPS_16 (0x2<<0)
8203 +#define DEPCTL0_MPS_8 (0x3<<0)
8204 +
8205 +/* S3C_UDC_OTG_DIEPINTn */
8206 +#define IN_EP_NAK_EFF (0x1<<6)
8207 +#define IN_TK_EPMIS (0x1<<5)
8208 +#define IN_TK_TXFEMP (0x1<<4)
8209 +#define IN_EP_TIMEOUT (0x1<<3)
8210 +
8211 +/* S3C_UDC_OTG_DOEPINTn */
8212 +#define BACK2BACK_SETUP (0x1<<6)
8213 +#define OUT_TK_EP_DIS (0x1<<4)
8214 +#define SETUP_PHASE_DONE (0x1<<3)
8215 +
8216 +/* S3C_UDC_OTG_DIEPINTn/DOEPINTn */
8217 +#define AHB_ERROR (0x1<<2)
8218 +#define EPDISBLD (0x1<<1)
8219 +#define TRANSFER_DONE (0x1<<0)
8220 +
8221 +/* S3C_UDC_OTG_DIEPTSIZn */
8222 +#define PKT_CNT(x) (x<<19)
8223 +#define XFERSIZE(x) (x<<0)
8224 +
8225 +#endif
8226 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/sdhci.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/sdhci.h
8227 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/sdhci.h 2009-05-10 22:05:04.000000000 +0200
8228 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/sdhci.h 2009-05-10 22:27:59.000000000 +0200
8229 @@ -29,6 +29,7 @@
8230 * is necessary the controllers and/or GPIO blocks require the
8231 * changing of driver-strength and other controls dependant on
8232 * the card and speed of operation.
8233 + * sdhci_host: Pointer kept during init, allows presence change notification
8234 *
8235 * Initialisation data specific to either the machine or the platform
8236 * for the device driver to use or call-back when configuring gpio or
8237 @@ -45,8 +46,11 @@
8238 void __iomem *regbase,
8239 struct mmc_ios *ios,
8240 struct mmc_card *card);
8241 + struct sdhci_host * sdhci_host;
8242 };
8243
8244 +extern void sdhci_s3c_force_presence_change(struct platform_device *pdev);
8245 +
8246 /**
8247 * s3c_sdhci0_set_platdata - Set platform data for S3C SDHCI device.
8248 * @pd: Platform data to register to device.
8249 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/usb-control.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/usb-control.h
8250 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/include/plat/usb-control.h 1970-01-01 01:00:00.000000000 +0100
8251 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/include/plat/usb-control.h 2009-05-10 22:27:59.000000000 +0200
8252 @@ -0,0 +1,41 @@
8253 +/* arch/arm/plat-s3c/include/plat/usb-control.h
8254 + *
8255 + * Copyright (c) 2004 Simtec Electronics
8256 + * Ben Dooks <ben@simtec.co.uk>
8257 + *
8258 + * S3C2410 - usb port information
8259 + *
8260 + * This program is free software; you can redistribute it and/or modify
8261 + * it under the terms of the GNU General Public License version 2 as
8262 + * published by the Free Software Foundation.
8263 +*/
8264 +
8265 +#ifndef __ASM_ARCH_USBCONTROL_H
8266 +#define __ASM_ARCH_USBCONTROL_H "arch/arm/plat-s3c/include/plat/usb-control.h"
8267 +
8268 +#define S3C_HCDFLG_USED (1)
8269 +
8270 +struct s3c2410_hcd_port {
8271 + unsigned char flags;
8272 + unsigned char power;
8273 + unsigned char oc_status;
8274 + unsigned char oc_changed;
8275 +};
8276 +
8277 +struct s3c2410_hcd_info {
8278 + struct usb_hcd *hcd;
8279 + struct s3c2410_hcd_port port[2];
8280 +
8281 + void (*power_control)(int port, int to);
8282 + void (*enable_oc)(struct s3c2410_hcd_info *, int on);
8283 + void (*report_oc)(struct s3c2410_hcd_info *, int ports);
8284 +};
8285 +
8286 +static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
8287 +{
8288 + if (info->report_oc != NULL) {
8289 + (info->report_oc)(info, ports);
8290 + }
8291 +}
8292 +
8293 +#endif /*__ASM_ARCH_USBCONTROL_H */
8294 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/init.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/init.c
8295 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/init.c 2009-05-10 22:05:04.000000000 +0200
8296 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/init.c 2009-05-10 22:27:59.000000000 +0200
8297 @@ -31,6 +31,34 @@
8298
8299 static struct cpu_table *cpu;
8300
8301 +static void __init set_system_rev(unsigned int idcode)
8302 +{
8303 + /*
8304 + * system_rev encoding is as follows
8305 + * system_rev & 0xff000000 -> S3C Class (24xx/64xx)
8306 + * system_rev & 0xfff00000 -> S3C Sub Class (241x/244x)
8307 + * system_rev & 0xffff0000 -> S3C Type (2410/2440/6400/6410)
8308 + *
8309 + * Remaining[15:0] are preserved from the value set by ATAG
8310 + *
8311 + * Exception:
8312 + * Store Revision A to 1 such as
8313 + * s3c2410A to s3c2411
8314 + * s3c2440A to s3c2441
8315 + */
8316 +
8317 + system_rev &= 0xffff;
8318 + system_rev |= (idcode & 0x0ffff000) << 4;
8319 +
8320 + if (idcode == 0x32410002 || idcode == 0x32440001)
8321 + system_rev |= (0x1 << 16);
8322 + if (idcode == 0x32440aaa /* s3c2442 */
8323 + || idcode == 0x32440aab) /* s3c2442b */
8324 + system_rev |= (0x2 << 16);
8325 + if (idcode == 0x0) /* s3c2400 */
8326 + system_rev |= (0x2400 << 16);
8327 +}
8328 +
8329 static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode,
8330 struct cpu_table *tab,
8331 unsigned int count)
8332 @@ -53,6 +81,8 @@
8333 panic("Unknown S3C24XX CPU");
8334 }
8335
8336 + set_system_rev(idcode);
8337 +
8338 printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
8339
8340 if (cpu->map_io == NULL || cpu->init == NULL) {
8341 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/Kconfig linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/Kconfig
8342 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/Kconfig 2009-05-10 22:05:04.000000000 +0200
8343 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/Kconfig 2009-05-10 22:27:59.000000000 +0200
8344 @@ -71,6 +71,15 @@
8345 Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
8346 for more information.
8347
8348 +config S3C_PM_DEBUG_LED_SMDK
8349 + bool "SMDK LED suspend/resume debugging"
8350 + depends on PM && (MACH_SMDK6410)
8351 + help
8352 + Say Y here to enable the use of the SMDK LEDs on the baseboard
8353 + for debugging of the state of the suspend and resume process.
8354 +
8355 + Note, this currently only works for S3C64XX based SMDK boards.
8356 +
8357 config S3C2410_PM_CHECK
8358 bool "S3C2410 PM Suspend Memory CRC"
8359 depends on PM && CRC32
8360 @@ -150,6 +159,18 @@
8361 Internal configuration to enable S3C64XX style GPIO configuration
8362 functions.
8363
8364 +# DMA
8365 +
8366 +config S3C_DMA
8367 + bool
8368 + help
8369 + Internal configuration for S3C DMA core
8370 +
8371 +config S3C_PWM
8372 + bool
8373 + help
8374 + PWM timer code for the S3C2410, and similar processors
8375 +
8376 # device definitions to compile in
8377
8378 config S3C_DEV_HSMMC
8379 @@ -172,4 +193,14 @@
8380 help
8381 Compile in platform device definition for framebuffer
8382
8383 +config S3C_DEV_USB_HOST
8384 + bool
8385 + help
8386 + Compile in platform device definition for USB host.
8387 +
8388 +config S3C_DEV_CAMIF
8389 + bool
8390 + help
8391 + Compile in platform device definitions for camera interface code
8392 +
8393 endif
8394 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/Makefile linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/Makefile
8395 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/Makefile 2009-05-10 22:05:04.000000000 +0200
8396 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/Makefile 2009-05-10 22:27:59.000000000 +0200
8397 @@ -18,6 +18,16 @@
8398 obj-y += gpio.o
8399 obj-y += gpio-config.o
8400
8401 +# DMA support
8402 +
8403 +obj-$(CONFIG_S3C_DMA) += dma.o
8404 +
8405 +# PM support
8406 +
8407 +obj-$(CONFIG_PM) += pm.o
8408 +obj-$(CONFIG_PM) += pm-gpio.o
8409 +obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o
8410 +
8411 # devices
8412
8413 obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.o
8414 @@ -25,3 +35,9 @@
8415 obj-y += dev-i2c0.o
8416 obj-$(CONFIG_S3C_DEV_I2C1) += dev-i2c1.o
8417 obj-$(CONFIG_S3C_DEV_FB) += dev-fb.o
8418 +obj-$(CONFIG_S3C_DEV_USB_HOST) += dev-usb.o
8419 +obj-$(CONFIG_S3C_DEV_CAMIF) += dev-camif.o
8420 +
8421 +obj-$(CONFIG_S3C_PWM) += pwm.o
8422 +obj-$(CONFIG_S3C_DMA) += dma.o
8423 +
8424 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/pm.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/pm.c
8425 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/pm.c 1970-01-01 01:00:00.000000000 +0100
8426 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/pm.c 2009-05-10 22:27:59.000000000 +0200
8427 @@ -0,0 +1,375 @@
8428 +/* linux/arch/arm/plat-s3c/pm.c
8429 + *
8430 + * Copyright 2008 Openmoko, Inc.
8431 + * Copyright 2004,2006,2008 Simtec Electronics
8432 + * Ben Dooks <ben@simtec.co.uk>
8433 + * http://armlinux.simtec.co.uk/
8434 + *
8435 + * S3C common power management (suspend to ram) support.
8436 + *
8437 + * This program is free software; you can redistribute it and/or modify
8438 + * it under the terms of the GNU General Public License version 2 as
8439 + * published by the Free Software Foundation.
8440 +*/
8441 +
8442 +#include <linux/init.h>
8443 +#include <linux/suspend.h>
8444 +#include <linux/errno.h>
8445 +#include <linux/delay.h>
8446 +#include <linux/serial_core.h>
8447 +#include <linux/io.h>
8448 +
8449 +#include <asm/cacheflush.h>
8450 +#include <mach/hardware.h>
8451 +#include <mach/map.h>
8452 +
8453 +#include <plat/regs-serial.h>
8454 +#include <mach/regs-clock.h>
8455 +#include <mach/regs-irq.h>
8456 +#include <asm/irq.h>
8457 +
8458 +#include <plat/pm.h>
8459 +#include <plat/pm-core.h>
8460 +
8461 +/* for external use */
8462 +
8463 +unsigned long s3c_pm_flags;
8464 +
8465 +/* Debug code:
8466 + *
8467 + * This code supports debug output to the low level UARTs for use on
8468 + * resume before the console layer is available.
8469 +*/
8470 +
8471 +#ifdef CONFIG_S3C2410_PM_DEBUG
8472 +extern void printascii(const char *);
8473 +
8474 +void s3c_pm_dbg(const char *fmt, ...)
8475 +{
8476 + va_list va;
8477 + char buff[256];
8478 +
8479 + va_start(va, fmt);
8480 + vsprintf(buff, fmt, va);
8481 + va_end(va);
8482 +
8483 + printascii(buff);
8484 +}
8485 +
8486 +static inline void s3c_pm_debug_init(void)
8487 +{
8488 + /* restart uart clocks so we can use them to output */
8489 + s3c_pm_debug_init_uart();
8490 +}
8491 +
8492 +#else
8493 +#define s3c_pm_debug_init() do { } while(0)
8494 +
8495 +#endif /* CONFIG_S3C2410_PM_DEBUG */
8496 +
8497 +/* Save the UART configurations if we are configured for debug. */
8498 +
8499 +unsigned char pm_uart_udivslot;
8500 +
8501 +#ifdef CONFIG_S3C2410_PM_DEBUG
8502 +
8503 +struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
8504 +
8505 +static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
8506 +{
8507 + void __iomem *regs = S3C_VA_UARTx(uart);
8508 +
8509 + save->ulcon = __raw_readl(regs + S3C2410_ULCON);
8510 + save->ucon = __raw_readl(regs + S3C2410_UCON);
8511 + save->ufcon = __raw_readl(regs + S3C2410_UFCON);
8512 + save->umcon = __raw_readl(regs + S3C2410_UMCON);
8513 + save->ubrdiv = __raw_readl(regs + S3C2410_UBRDIV);
8514 +
8515 + if (pm_uart_udivslot)
8516 + save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
8517 +
8518 + S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
8519 + uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
8520 +}
8521 +
8522 +static void s3c_pm_save_uarts(void)
8523 +{
8524 + struct pm_uart_save *save = uart_save;
8525 + unsigned int uart;
8526 +
8527 + for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
8528 + s3c_pm_save_uart(uart, save);
8529 +}
8530 +
8531 +static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
8532 +{
8533 + void __iomem *regs = S3C_VA_UARTx(uart);
8534 +
8535 + s3c_pm_arch_update_uart(regs, save);
8536 +
8537 + __raw_writel(save->ulcon, regs + S3C2410_ULCON);
8538 + __raw_writel(save->ucon, regs + S3C2410_UCON);
8539 + __raw_writel(save->ufcon, regs + S3C2410_UFCON);
8540 + __raw_writel(save->umcon, regs + S3C2410_UMCON);
8541 + __raw_writel(save->ubrdiv, regs + S3C2410_UBRDIV);
8542 +
8543 + if (pm_uart_udivslot)
8544 + __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
8545 +}
8546 +
8547 +static void s3c_pm_restore_uarts(void)
8548 +{
8549 + struct pm_uart_save *save = uart_save;
8550 + unsigned int uart;
8551 +
8552 + for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
8553 + s3c_pm_restore_uart(uart, save);
8554 +}
8555 +#else
8556 +static void s3c_pm_save_uarts(void) { }
8557 +static void s3c_pm_restore_uarts(void) { }
8558 +#endif
8559 +
8560 +/* The IRQ ext-int code goes here, it is too small to currently bother
8561 + * with its own file. */
8562 +
8563 +unsigned long s3c_irqwake_intmask = 0xffffffffL;
8564 +unsigned long s3c_irqwake_eintmask = 0xffffffffL;
8565 +
8566 +int s3c_irqext_wake(unsigned int irqno, unsigned int state)
8567 +{
8568 + unsigned long bit = 1L << IRQ_EINT_BIT(irqno);
8569 +
8570 + if (!(s3c_irqwake_eintallow & bit))
8571 + return -ENOENT;
8572 +
8573 + printk(KERN_INFO "wake %s for irq %d\n",
8574 + state ? "enabled" : "disabled", irqno);
8575 +
8576 + if (!state)
8577 + s3c_irqwake_eintmask |= bit;
8578 + else
8579 + s3c_irqwake_eintmask &= ~bit;
8580 +
8581 + return 0;
8582 +}
8583 +
8584 +/* helper functions to save and restore register state */
8585 +
8586 +/**
8587 + * s3c_pm_do_save() - save a set of registers for restoration on resume.
8588 + * @ptr: Pointer to an array of registers.
8589 + * @count: Size of the ptr array.
8590 + *
8591 + * Run through the list of registers given, saving their contents in the
8592 + * array for later restoration when we wakeup.
8593 + */
8594 +void s3c_pm_do_save(struct sleep_save *ptr, int count)
8595 +{
8596 + for (; count > 0; count--, ptr++) {
8597 + ptr->val = __raw_readl(ptr->reg);
8598 + S3C_PMDBG("saved %p value %08lx\n", ptr->reg, ptr->val);
8599 + }
8600 +}
8601 +
8602 +/**
8603 + * s3c_pm_do_restore() - restore register values from the save list.
8604 + * @ptr: Pointer to an array of registers.
8605 + * @count: Size of the ptr array.
8606 + *
8607 + * Restore the register values saved from s3c_pm_do_save().
8608 + *
8609 + * Note, we do not use S3C_PMDBG() in here, as the system may not have
8610 + * restore the UARTs state yet
8611 +*/
8612 +
8613 +void s3c_pm_do_restore(struct sleep_save *ptr, int count)
8614 +{
8615 + for (; count > 0; count--, ptr++) {
8616 + printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
8617 + ptr->reg, ptr->val, __raw_readl(ptr->reg));
8618 +
8619 + __raw_writel(ptr->val, ptr->reg);
8620 + }
8621 +}
8622 +
8623 +/**
8624 + * s3c_pm_do_restore_core() - early restore register values from save list.
8625 + *
8626 + * This is similar to s3c_pm_do_restore() except we try and minimise the
8627 + * side effects of the function in case registers that hardware might need
8628 + * to work has been restored.
8629 + *
8630 + * WARNING: Do not put any debug in here that may effect memory or use
8631 + * peripherals, as things may be changing!
8632 +*/
8633 +
8634 +void s3c_pm_do_restore_core(struct sleep_save *ptr, int count)
8635 +{
8636 + for (; count > 0; count--, ptr++)
8637 + __raw_writel(ptr->val, ptr->reg);
8638 +}
8639 +
8640 +/* s3c2410_pm_show_resume_irqs
8641 + *
8642 + * print any IRQs asserted at resume time (ie, we woke from)
8643 +*/
8644 +static void s3c_pm_show_resume_irqs(int start, unsigned long which,
8645 + unsigned long mask)
8646 +{
8647 + int i;
8648 +
8649 + which &= ~mask;
8650 +
8651 + for (i = 0; i <= 31; i++) {
8652 + if (which & (1L<<i)) {
8653 + S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
8654 + }
8655 + }
8656 +}
8657 +
8658 +
8659 +void (*pm_cpu_prep)(void);
8660 +void (*pm_cpu_sleep)(void);
8661 +
8662 +#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
8663 +
8664 +/* s3c_pm_enter
8665 + *
8666 + * central control for sleep/resume process
8667 +*/
8668 +
8669 +static int s3c_pm_enter(suspend_state_t state)
8670 +{
8671 + unsigned long regs_save[16];
8672 +
8673 + /* ensure the debug is initialised (if enabled) */
8674 +
8675 + s3c_pm_debug_init();
8676 +
8677 + S3C_PMDBG("%s(%d)\n", __func__, state);
8678 +
8679 + if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
8680 + printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__);
8681 + return -EINVAL;
8682 + }
8683 +
8684 + /* check if we have anything to wake-up with... bad things seem
8685 + * to happen if you suspend with no wakeup (system will often
8686 + * require a full power-cycle)
8687 + */
8688 +
8689 + if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
8690 + !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
8691 + printk(KERN_ERR "%s: No wake-up sources!\n", __func__);
8692 + printk(KERN_ERR "%s: Aborting sleep\n", __func__);
8693 + return -EINVAL;
8694 + }
8695 +
8696 + /* store the physical address of the register recovery block */
8697 +
8698 + s3c_sleep_save_phys = virt_to_phys(regs_save);
8699 +
8700 + S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
8701 +
8702 + /* save all necessary core registers not covered by the drivers */
8703 +
8704 + s3c_pm_save_gpios();
8705 + s3c_pm_save_uarts();
8706 + s3c_pm_save_core();
8707 +
8708 + /* set the irq configuration for wake */
8709 +
8710 + s3c_pm_configure_extint();
8711 +
8712 + S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n",
8713 + s3c_irqwake_intmask, s3c_irqwake_eintmask);
8714 +
8715 + s3c_pm_arch_prepare_irqs();
8716 +
8717 + /* call cpu specific preparation */
8718 +
8719 + pm_cpu_prep();
8720 +
8721 + /* flush cache back to ram */
8722 +
8723 + flush_cache_all();
8724 +
8725 + s3c_pm_check_store();
8726 +
8727 + /* send the cpu to sleep... */
8728 +
8729 + s3c_pm_arch_stop_clocks();
8730 +
8731 + /* s3c2410_cpu_save will also act as our return point from when
8732 + * we resume as it saves its own register state, so use the return
8733 + * code to differentiate return from save and return from sleep */
8734 +
8735 + if (s3c_cpu_save(regs_save) == 0) {
8736 + flush_cache_all();
8737 + pm_cpu_sleep();
8738 + }
8739 +
8740 + /* restore the cpu state using the kernel's cpu init code. */
8741 +
8742 + cpu_init();
8743 +
8744 + /* restore the system state */
8745 +
8746 + s3c_pm_restore_core();
8747 + s3c_pm_restore_uarts();
8748 + s3c_pm_restore_gpios();
8749 +
8750 + s3c_pm_debug_init();
8751 +
8752 + /* check what irq (if any) restored the system */
8753 +
8754 + s3c_pm_arch_show_resume_irqs();
8755 +
8756 + S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
8757 +
8758 + s3c_pm_check_restore();
8759 +
8760 + /* LEDs should now be 1110 */
8761 + s3c_pm_debug_smdkled(1 << 1, 0);
8762 +
8763 + /* ok, let's return from sleep */
8764 +
8765 + S3C_PMDBG("S3C PM Resume (post-restore)\n");
8766 + return 0;
8767 +}
8768 +
8769 +static int s3c_pm_prepare(void)
8770 +{
8771 + /* prepare check area if configured */
8772 +
8773 + s3c_pm_check_prepare();
8774 + return 0;
8775 +}
8776 +
8777 +static void s3c_pm_finish(void)
8778 +{
8779 + s3c_pm_check_cleanup();
8780 +}
8781 +
8782 +static struct platform_suspend_ops s3c_pm_ops = {
8783 + .enter = s3c_pm_enter,
8784 + .prepare = s3c_pm_prepare,
8785 + .finish = s3c_pm_finish,
8786 + .valid = suspend_valid_only_mem,
8787 +};
8788 +
8789 +/* s3c_pm_init
8790 + *
8791 + * Attach the power management functions. This should be called
8792 + * from the board specific initialisation if the board supports
8793 + * it.
8794 +*/
8795 +
8796 +int __init s3c_pm_init(void)
8797 +{
8798 + printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
8799 +
8800 + suspend_set_ops(&s3c_pm_ops);
8801 + return 0;
8802 +}
8803 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/pm-check.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/pm-check.c
8804 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/pm-check.c 1970-01-01 01:00:00.000000000 +0100
8805 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/pm-check.c 2009-05-10 22:27:59.000000000 +0200
8806 @@ -0,0 +1,242 @@
8807 +/* linux/arch/arm/plat-s3c/pm-check.c
8808 + * originally in linux/arch/arm/plat-s3c24xx/pm.c
8809 + *
8810 + * Copyright (c) 2004,2006,2008 Simtec Electronics
8811 + * http://armlinux.simtec.co.uk
8812 + * Ben Dooks <ben@simtec.co.uk>
8813 + *
8814 + * S3C Power Mangament - suspend/resume memory corruptiuon check.
8815 + *
8816 + * This program is free software; you can redistribute it and/or modify
8817 + * it under the terms of the GNU General Public License version 2 as
8818 + * published by the Free Software Foundation.
8819 +*/
8820 +
8821 +#include <linux/kernel.h>
8822 +#include <linux/suspend.h>
8823 +#include <linux/init.h>
8824 +#include <linux/crc32.h>
8825 +#include <linux/ioport.h>
8826 +
8827 +#include <plat/pm.h>
8828 +
8829 +#if CONFIG_S3C2410_PM_CHECK_CHUNKSIZE < 1
8830 +#error CONFIG_S3C2410_PM_CHECK_CHUNKSIZE must be a positive non-zero value
8831 +#endif
8832 +
8833 +/* suspend checking code...
8834 + *
8835 + * this next area does a set of crc checks over all the installed
8836 + * memory, so the system can verify if the resume was ok.
8837 + *
8838 + * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
8839 + * increasing it will mean that the area corrupted will be less easy to spot,
8840 + * and reducing the size will cause the CRC save area to grow
8841 +*/
8842 +
8843 +#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
8844 +
8845 +static u32 crc_size; /* size needed for the crc block */
8846 +static u32 *crcs; /* allocated over suspend/resume */
8847 +
8848 +typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
8849 +
8850 +/* s3c_pm_run_res
8851 + *
8852 + * go through the given resource list, and look for system ram
8853 +*/
8854 +
8855 +static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
8856 +{
8857 + while (ptr != NULL) {
8858 + if (ptr->child != NULL)
8859 + s3c_pm_run_res(ptr->child, fn, arg);
8860 +
8861 + if ((ptr->flags & IORESOURCE_MEM) &&
8862 + strcmp(ptr->name, "System RAM") == 0) {
8863 + S3C_PMDBG("Found system RAM at %08lx..%08lx\n",
8864 + (unsigned long)ptr->start,
8865 + (unsigned long)ptr->end);
8866 + arg = (fn)(ptr, arg);
8867 + }
8868 +
8869 + ptr = ptr->sibling;
8870 + }
8871 +}
8872 +
8873 +static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
8874 +{
8875 + s3c_pm_run_res(&iomem_resource, fn, arg);
8876 +}
8877 +
8878 +static u32 *s3c_pm_countram(struct resource *res, u32 *val)
8879 +{
8880 + u32 size = (u32)(res->end - res->start)+1;
8881 +
8882 + size += CHECK_CHUNKSIZE-1;
8883 + size /= CHECK_CHUNKSIZE;
8884 +
8885 + S3C_PMDBG("Area %08lx..%08lx, %d blocks\n",
8886 + (unsigned long)res->start, (unsigned long)res->end, size);
8887 +
8888 + *val += size * sizeof(u32);
8889 + return val;
8890 +}
8891 +
8892 +/* s3c_pm_prepare_check
8893 + *
8894 + * prepare the necessary information for creating the CRCs. This
8895 + * must be done before the final save, as it will require memory
8896 + * allocating, and thus touching bits of the kernel we do not
8897 + * know about.
8898 +*/
8899 +
8900 +void s3c_pm_check_prepare(void)
8901 +{
8902 + crc_size = 0;
8903 +
8904 + s3c_pm_run_sysram(s3c_pm_countram, &crc_size);
8905 +
8906 + S3C_PMDBG("s3c_pm_prepare_check: %u checks needed\n", crc_size);
8907 +
8908 + crcs = kmalloc(crc_size+4, GFP_KERNEL);
8909 + if (crcs == NULL)
8910 + printk(KERN_ERR "Cannot allocated CRC save area\n");
8911 +}
8912 +
8913 +static u32 *s3c_pm_makecheck(struct resource *res, u32 *val)
8914 +{
8915 + unsigned long addr, left;
8916 +
8917 + for (addr = res->start; addr < res->end;
8918 + addr += CHECK_CHUNKSIZE) {
8919 + left = res->end - addr;
8920 +
8921 + if (left > CHECK_CHUNKSIZE)
8922 + left = CHECK_CHUNKSIZE;
8923 +
8924 + *val = crc32_le(~0, phys_to_virt(addr), left);
8925 + val++;
8926 + }
8927 +
8928 + return val;
8929 +}
8930 +
8931 +/* s3c_pm_check_store
8932 + *
8933 + * compute the CRC values for the memory blocks before the final
8934 + * sleep.
8935 +*/
8936 +
8937 +void s3c_pm_check_store(void)
8938 +{
8939 + if (crcs != NULL)
8940 + s3c_pm_run_sysram(s3c_pm_makecheck, crcs);
8941 +}
8942 +
8943 +/* in_region
8944 + *
8945 + * return TRUE if the area defined by ptr..ptr+size contains the
8946 + * what..what+whatsz
8947 +*/
8948 +
8949 +static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
8950 +{
8951 + if ((what+whatsz) < ptr)
8952 + return 0;
8953 +
8954 + if (what > (ptr+size))
8955 + return 0;
8956 +
8957 + return 1;
8958 +}
8959 +
8960 +/**
8961 + * s3c_pm_runcheck() - helper to check a resource on restore.
8962 + * @res: The resource to check
8963 + * @vak: Pointer to list of CRC32 values to check.
8964 + *
8965 + * Called from the s3c_pm_check_restore() via s3c_pm_run_sysram(), this
8966 + * function runs the given memory resource checking it against the stored
8967 + * CRC to ensure that memory is restored. The function tries to skip as
8968 + * many of the areas used during the suspend process.
8969 + */
8970 +static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
8971 +{
8972 + void *save_at = phys_to_virt(s3c_sleep_save_phys);
8973 + unsigned long addr;
8974 + unsigned long left;
8975 + void *stkpage;
8976 + void *ptr;
8977 + u32 calc;
8978 +
8979 + stkpage = (void *)((u32)&calc & ~PAGE_MASK);
8980 +
8981 + for (addr = res->start; addr < res->end;
8982 + addr += CHECK_CHUNKSIZE) {
8983 + left = res->end - addr;
8984 +
8985 + if (left > CHECK_CHUNKSIZE)
8986 + left = CHECK_CHUNKSIZE;
8987 +
8988 + ptr = phys_to_virt(addr);
8989 +
8990 + if (in_region(ptr, left, stkpage, 4096)) {
8991 + S3C_PMDBG("skipping %08lx, has stack in\n", addr);
8992 + goto skip_check;
8993 + }
8994 +
8995 + if (in_region(ptr, left, crcs, crc_size)) {
8996 + S3C_PMDBG("skipping %08lx, has crc block in\n", addr);
8997 + goto skip_check;
8998 + }
8999 +
9000 + if (in_region(ptr, left, save_at, 32*4 )) {
9001 + S3C_PMDBG("skipping %08lx, has save block in\n", addr);
9002 + goto skip_check;
9003 + }
9004 +
9005 + /* calculate and check the checksum */
9006 +
9007 + calc = crc32_le(~0, ptr, left);
9008 + if (calc != *val) {
9009 + printk(KERN_ERR "Restore CRC error at "
9010 + "%08lx (%08x vs %08x)\n", addr, calc, *val);
9011 +
9012 + S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n",
9013 + addr, calc, *val);
9014 + }
9015 +
9016 + skip_check:
9017 + val++;
9018 + }
9019 +
9020 + return val;
9021 +}
9022 +
9023 +/**
9024 + * s3c_pm_check_restore() - memory check called on resume
9025 + *
9026 + * check the CRCs after the restore event and free the memory used
9027 + * to hold them
9028 +*/
9029 +void s3c_pm_check_restore(void)
9030 +{
9031 + if (crcs != NULL)
9032 + s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
9033 +}
9034 +
9035 +/**
9036 + * s3c_pm_check_cleanup() - free memory resources
9037 + *
9038 + * Free the resources that where allocated by the suspend
9039 + * memory check code. We do this separately from the
9040 + * s3c_pm_check_restore() function as we cannot call any
9041 + * functions that might sleep during that resume.
9042 + */
9043 +void s3c_pm_check_cleanup(void)
9044 +{
9045 + kfree(crcs);
9046 + crcs = NULL;
9047 +}
9048 +
9049 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/pm-gpio.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/pm-gpio.c
9050 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/pm-gpio.c 1970-01-01 01:00:00.000000000 +0100
9051 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/pm-gpio.c 2009-05-10 22:27:59.000000000 +0200
9052 @@ -0,0 +1,378 @@
9053 +/* linux/arch/arm/plat-s3c/pm-gpio.c
9054 + *
9055 + * Copyright 2008 Openmoko, Inc.
9056 + * Copyright 2008 Simtec Electronics
9057 + * Ben Dooks <ben@simtec.co.uk>
9058 + * http://armlinux.simtec.co.uk/
9059 + *
9060 + * S3C series GPIO PM code
9061 + *
9062 + * This program is free software; you can redistribute it and/or modify
9063 + * it under the terms of the GNU General Public License version 2 as
9064 + * published by the Free Software Foundation.
9065 +*/
9066 +
9067 +#include <linux/kernel.h>
9068 +#include <linux/init.h>
9069 +#include <linux/io.h>
9070 +#include <linux/gpio.h>
9071 +
9072 +#include <mach/gpio-core.h>
9073 +#include <plat/pm.h>
9074 +
9075 +/* PM GPIO helpers */
9076 +
9077 +#define OFFS_CON (0x00)
9078 +#define OFFS_DAT (0X04)
9079 +#define OFFS_UP (0X08)
9080 +
9081 +static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
9082 +{
9083 + chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
9084 + chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
9085 +}
9086 +
9087 +static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
9088 +{
9089 + void __iomem *base = chip->base;
9090 + u32 old_gpcon = __raw_readl(base + OFFS_CON);
9091 + u32 old_gpdat = __raw_readl(base + OFFS_DAT);
9092 + u32 gps_gpcon = chip->pm_save[0];
9093 + u32 gps_gpdat = chip->pm_save[1];
9094 + u32 gpcon;
9095 +
9096 + /* GPACON only has one bit per control / data and no PULLUPs.
9097 + * GPACON[x] = 0 => Output, 1 => SFN */
9098 +
9099 + /* first set all SFN bits to SFN */
9100 +
9101 + gpcon = old_gpcon | gps_gpcon;
9102 + __raw_writel(gpcon, base + OFFS_CON);
9103 +
9104 + /* now set all the other bits */
9105 +
9106 + __raw_writel(gps_gpdat, base + OFFS_DAT);
9107 + __raw_writel(gps_gpcon, base + OFFS_CON);
9108 +
9109 + S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
9110 + chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
9111 +}
9112 +
9113 +struct s3c_gpio_pm s3c_gpio_pm_1bit = {
9114 + .save = s3c_gpio_pm_1bit_save,
9115 + .resume = s3c_gpio_pm_1bit_resume,
9116 +};
9117 +
9118 +static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
9119 +{
9120 + chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
9121 + chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
9122 + chip->pm_save[2] = __raw_readl(chip->base + OFFS_UP);
9123 +}
9124 +
9125 +/* Test whether the given masked+shifted bits of an GPIO configuration
9126 + * are one of the SFN (special function) modes. */
9127 +
9128 +static inline int is_sfn(unsigned long con)
9129 +{
9130 + return con >= 2;
9131 +}
9132 +
9133 +/* Test if the given masked+shifted GPIO configuration is an input */
9134 +
9135 +static inline int is_in(unsigned long con)
9136 +{
9137 + return con == 0;
9138 +}
9139 +
9140 +/* Test if the given masked+shifted GPIO configuration is an output */
9141 +
9142 +static inline int is_out(unsigned long con)
9143 +{
9144 + return con == 1;
9145 +}
9146 +
9147 +/**
9148 + * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
9149 + * @chip: The chip information to resume.
9150 + *
9151 + * Restore one of the GPIO banks that was saved during suspend. This is
9152 + * not as simple as once thought, due to the possibility of glitches
9153 + * from the order that the CON and DAT registers are set in.
9154 + *
9155 + * The three states the pin can be are {IN,OUT,SFN} which gives us 9
9156 + * combinations of changes to check. Three of these, if the pin stays
9157 + * in the same configuration can be discounted. This leaves us with
9158 + * the following:
9159 + *
9160 + * { IN => OUT } Change DAT first
9161 + * { IN => SFN } Change CON first
9162 + * { OUT => SFN } Change CON first, so new data will not glitch
9163 + * { OUT => IN } Change CON first, so new data will not glitch
9164 + * { SFN => IN } Change CON first
9165 + * { SFN => OUT } Change DAT first, so new data will not glitch [1]
9166 + *
9167 + * We do not currently deal with the UP registers as these control
9168 + * weak resistors, so a small delay in change should not need to bring
9169 + * these into the calculations.
9170 + *
9171 + * [1] this assumes that writing to a pin DAT whilst in SFN will set the
9172 + * state for when it is next output.
9173 + */
9174 +static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
9175 +{
9176 + void __iomem *base = chip->base;
9177 + u32 old_gpcon = __raw_readl(base + OFFS_CON);
9178 + u32 old_gpdat = __raw_readl(base + OFFS_DAT);
9179 + u32 gps_gpcon = chip->pm_save[0];
9180 + u32 gps_gpdat = chip->pm_save[1];
9181 + u32 gpcon, old, new, mask;
9182 + u32 change_mask = 0x0;
9183 + int nr;
9184 +
9185 + /* restore GPIO pull-up settings */
9186 + __raw_writel(chip->pm_save[2], base + OFFS_UP);
9187 +
9188 + /* Create a change_mask of all the items that need to have
9189 + * their CON value changed before their DAT value, so that
9190 + * we minimise the work between the two settings.
9191 + */
9192 +
9193 + for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
9194 + old = (old_gpcon & mask) >> nr;
9195 + new = (gps_gpcon & mask) >> nr;
9196 +
9197 + /* If there is no change, then skip */
9198 +
9199 + if (old == new)
9200 + continue;
9201 +
9202 + /* If both are special function, then skip */
9203 +
9204 + if (is_sfn(old) && is_sfn(new))
9205 + continue;
9206 +
9207 + /* Change is IN => OUT, do not change now */
9208 +
9209 + if (is_in(old) && is_out(new))
9210 + continue;
9211 +
9212 + /* Change is SFN => OUT, do not change now */
9213 +
9214 + if (is_sfn(old) && is_out(new))
9215 + continue;
9216 +
9217 + /* We should now be at the case of IN=>SFN,
9218 + * OUT=>SFN, OUT=>IN, SFN=>IN. */
9219 +
9220 + change_mask |= mask;
9221 + }
9222 +
9223 +
9224 + /* Write the new CON settings */
9225 +
9226 + gpcon = old_gpcon & ~change_mask;
9227 + gpcon |= gps_gpcon & change_mask;
9228 +
9229 + __raw_writel(gpcon, base + OFFS_CON);
9230 +
9231 + /* Now change any items that require DAT,CON */
9232 +
9233 + __raw_writel(gps_gpdat, base + OFFS_DAT);
9234 + __raw_writel(gps_gpcon, base + OFFS_CON);
9235 +
9236 + S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
9237 + chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
9238 +}
9239 +
9240 +struct s3c_gpio_pm s3c_gpio_pm_2bit = {
9241 + .save = s3c_gpio_pm_2bit_save,
9242 + .resume = s3c_gpio_pm_2bit_resume,
9243 +};
9244 +
9245 +#ifdef CONFIG_ARCH_S3C64XX
9246 +static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
9247 +{
9248 + chip->pm_save[1] = __raw_readl(chip->base + OFFS_CON);
9249 + chip->pm_save[2] = __raw_readl(chip->base + OFFS_DAT);
9250 + chip->pm_save[3] = __raw_readl(chip->base + OFFS_UP);
9251 +
9252 + if (chip->chip.ngpio > 8)
9253 + chip->pm_save[0] = __raw_readl(chip->base - 4);
9254 +}
9255 +
9256 +static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
9257 +{
9258 + u32 old, new, mask;
9259 + u32 change_mask = 0x0;
9260 + int nr;
9261 +
9262 + for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
9263 + old = (old_gpcon & mask) >> nr;
9264 + new = (gps_gpcon & mask) >> nr;
9265 +
9266 + /* If there is no change, then skip */
9267 +
9268 + if (old == new)
9269 + continue;
9270 +
9271 + /* If both are special function, then skip */
9272 +
9273 + if (is_sfn(old) && is_sfn(new))
9274 + continue;
9275 +
9276 + /* Change is IN => OUT, do not change now */
9277 +
9278 + if (is_in(old) && is_out(new))
9279 + continue;
9280 +
9281 + /* Change is SFN => OUT, do not change now */
9282 +
9283 + if (is_sfn(old) && is_out(new))
9284 + continue;
9285 +
9286 + /* We should now be at the case of IN=>SFN,
9287 + * OUT=>SFN, OUT=>IN, SFN=>IN. */
9288 +
9289 + change_mask |= mask;
9290 + }
9291 +
9292 + return change_mask;
9293 +}
9294 +
9295 +static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
9296 +{
9297 + void __iomem *con = chip->base + (index * 4);
9298 + u32 old_gpcon = __raw_readl(con);
9299 + u32 gps_gpcon = chip->pm_save[index + 1];
9300 + u32 gpcon, mask;
9301 +
9302 + mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
9303 +
9304 + gpcon = old_gpcon & ~mask;
9305 + gpcon |= gps_gpcon & mask;
9306 +
9307 + __raw_writel(gpcon, con);
9308 +}
9309 +
9310 +static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
9311 +{
9312 + void __iomem *base = chip->base;
9313 + u32 old_gpcon[2];
9314 + u32 old_gpdat = __raw_readl(base + OFFS_DAT);
9315 + u32 gps_gpdat = chip->pm_save[2];
9316 +
9317 + /* First, modify the CON settings */
9318 +
9319 + old_gpcon[0] = 0;
9320 + old_gpcon[1] = __raw_readl(base + OFFS_CON);
9321 +
9322 + s3c_gpio_pm_4bit_con(chip, 0);
9323 + if (chip->chip.ngpio > 8) {
9324 + old_gpcon[0] = __raw_readl(base - 4);
9325 + s3c_gpio_pm_4bit_con(chip, -1);
9326 + }
9327 +
9328 + /* Now change the configurations that require DAT,CON */
9329 +
9330 + __raw_writel(chip->pm_save[2], base + OFFS_DAT);
9331 + __raw_writel(chip->pm_save[1], base + OFFS_CON);
9332 + if (chip->chip.ngpio > 8)
9333 + __raw_writel(chip->pm_save[0], base - 4);
9334 +
9335 + __raw_writel(chip->pm_save[2], base + OFFS_DAT);
9336 + __raw_writel(chip->pm_save[3], base + OFFS_UP);
9337 +
9338 + if (chip->chip.ngpio > 8) {
9339 + S3C_PMDBG("%s: CON4 %08x,%08x => %08x,%08x, DAT %08x => %08x\n",
9340 + chip->chip.label, old_gpcon[0], old_gpcon[1],
9341 + __raw_readl(base - 4),
9342 + __raw_readl(base + OFFS_CON),
9343 + old_gpdat, gps_gpdat);
9344 + } else
9345 + S3C_PMDBG("%s: CON4 %08x => %08x, DAT %08x => %08x\n",
9346 + chip->chip.label, old_gpcon[1],
9347 + __raw_readl(base + OFFS_CON),
9348 + old_gpdat, gps_gpdat);
9349 +}
9350 +
9351 +struct s3c_gpio_pm s3c_gpio_pm_4bit = {
9352 + .save = s3c_gpio_pm_4bit_save,
9353 + .resume = s3c_gpio_pm_4bit_resume,
9354 +};
9355 +#endif /* CONFIG_ARCH_S3C64XX */
9356 +
9357 +/**
9358 + * s3c_pm_save_gpio() - save gpio chip data for suspend
9359 + * @ourchip: The chip for suspend.
9360 + */
9361 +static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
9362 +{
9363 + struct s3c_gpio_pm *pm = ourchip->pm;
9364 +
9365 + if (pm == NULL || pm->save == NULL)
9366 + S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
9367 + else
9368 + pm->save(ourchip);
9369 +}
9370 +
9371 +/**
9372 + * s3c_pm_save_gpios() - Save the state of the GPIO banks.
9373 + *
9374 + * For all the GPIO banks, save the state of each one ready for going
9375 + * into a suspend mode.
9376 + */
9377 +void s3c_pm_save_gpios(void)
9378 +{
9379 + struct s3c_gpio_chip *ourchip;
9380 + unsigned int gpio_nr;
9381 +
9382 + for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
9383 + ourchip = s3c_gpiolib_getchip(gpio_nr);
9384 + if (!ourchip)
9385 + continue;
9386 +
9387 + s3c_pm_save_gpio(ourchip);
9388 +
9389 + S3C_PMDBG("%s: save %08x,%08x,%08x,%08x\n",
9390 + ourchip->chip.label,
9391 + ourchip->pm_save[0],
9392 + ourchip->pm_save[1],
9393 + ourchip->pm_save[2],
9394 + ourchip->pm_save[3]);
9395 +
9396 + gpio_nr += ourchip->chip.ngpio;
9397 + gpio_nr += CONFIG_S3C_GPIO_SPACE;
9398 + }
9399 +}
9400 +
9401 +/**
9402 + * s3c_pm_resume_gpio() - restore gpio chip data after suspend
9403 + * @ourchip: The suspended chip.
9404 + */
9405 +static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
9406 +{
9407 + struct s3c_gpio_pm *pm = ourchip->pm;
9408 +
9409 + if (pm == NULL || pm->resume == NULL)
9410 + S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
9411 + else
9412 + pm->resume(ourchip);
9413 +}
9414 +
9415 +void s3c_pm_restore_gpios(void)
9416 +{
9417 + struct s3c_gpio_chip *ourchip;
9418 + unsigned int gpio_nr;
9419 +
9420 + for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
9421 + ourchip = s3c_gpiolib_getchip(gpio_nr);
9422 + if (!ourchip)
9423 + continue;
9424 +
9425 + s3c_pm_resume_gpio(ourchip);
9426 +
9427 + gpio_nr += ourchip->chip.ngpio;
9428 + gpio_nr += CONFIG_S3C_GPIO_SPACE;
9429 + }
9430 +}
9431 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/pwm.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/pwm.c
9432 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/pwm.c 1970-01-01 01:00:00.000000000 +0100
9433 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/pwm.c 2009-05-10 22:27:59.000000000 +0200
9434 @@ -0,0 +1,288 @@
9435 +/*
9436 + * arch/arm/plat-s3c/pwm.c
9437 + *
9438 + * Copyright (c) by Javi Roman <javiroman@kernel-labs.org>
9439 + * for the Openmoko Project.
9440 + *
9441 + * S3C2410A SoC PWM support
9442 + *
9443 + * This program is free software; you can redistribute it and/or modify
9444 + * it under the terms of the GNU General Public License as published by
9445 + * the Free Software Foundation; either version 2 of the License, or
9446 + * (at your option) any later version.
9447 + *
9448 + * You should have received a copy of the GNU General Public License
9449 + * along with this program; if not, write to the Free Software
9450 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
9451 + *
9452 + */
9453 +
9454 +#include <linux/kernel.h>
9455 +#include <linux/init.h>
9456 +#include <linux/clk.h>
9457 +#include <linux/device.h>
9458 +#include <mach/hardware.h>
9459 +#include <plat/regs-timer.h>
9460 +#include <plat/pwm.h>
9461 +#include <asm/io.h>
9462 +
9463 +#ifdef CONFIG_PM
9464 + static unsigned long standby_reg_tcon;
9465 + static unsigned long standby_reg_tcfg0;
9466 + static unsigned long standby_reg_tcfg1;
9467 +#endif
9468 +
9469 +int s3c2410_pwm_disable(struct s3c2410_pwm *pwm)
9470 +{
9471 + unsigned long tcon;
9472 +
9473 + /* stop timer */
9474 + tcon = __raw_readl(S3C2410_TCON);
9475 + tcon &= 0xffffff00;
9476 + __raw_writel(tcon, S3C2410_TCON);
9477 +
9478 + clk_disable(pwm->pclk);
9479 + clk_put(pwm->pclk);
9480 +
9481 + return 0;
9482 +}
9483 +EXPORT_SYMBOL_GPL(s3c2410_pwm_disable);
9484 +
9485 +int s3c2410_pwm_init(struct s3c2410_pwm *pwm)
9486 +{
9487 + pwm->pclk = clk_get(NULL, "timers");
9488 + if (IS_ERR(pwm->pclk))
9489 + return PTR_ERR(pwm->pclk);
9490 +
9491 + clk_enable(pwm->pclk);
9492 + pwm->pclk_rate = clk_get_rate(pwm->pclk);
9493 + return 0;
9494 +}
9495 +EXPORT_SYMBOL_GPL(s3c2410_pwm_init);
9496 +
9497 +int s3c2410_pwm_enable(struct s3c2410_pwm *pwm)
9498 +{
9499 + unsigned long tcfg0, tcfg1, tcnt, tcmp;
9500 +
9501 + /* control registers bits */
9502 + tcfg1 = __raw_readl(S3C2410_TCFG1);
9503 + tcfg0 = __raw_readl(S3C2410_TCFG0);
9504 +
9505 + /* divider & scaler slection */
9506 + switch (pwm->timerid) {
9507 + case PWM0:
9508 + tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
9509 + tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
9510 + break;
9511 + case PWM1:
9512 + tcfg1 &= ~S3C2410_TCFG1_MUX1_MASK;
9513 + tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
9514 + break;
9515 + case PWM2:
9516 + tcfg1 &= ~S3C2410_TCFG1_MUX2_MASK;
9517 + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
9518 + break;
9519 + case PWM3:
9520 + tcfg1 &= ~S3C2410_TCFG1_MUX3_MASK;
9521 + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
9522 + break;
9523 + case PWM4:
9524 + /* timer four is not capable of doing PWM */
9525 + break;
9526 + default:
9527 + clk_disable(pwm->pclk);
9528 + clk_put(pwm->pclk);
9529 + return -1;
9530 + }
9531 +
9532 + /* divider & scaler values */
9533 + tcfg1 |= pwm->divider;
9534 + __raw_writel(tcfg1, S3C2410_TCFG1);
9535 +
9536 + switch (pwm->timerid) {
9537 + case PWM0:
9538 + case PWM1:
9539 + tcfg0 |= pwm->prescaler;
9540 + __raw_writel(tcfg0, S3C2410_TCFG0);
9541 + break;
9542 + default:
9543 + if ((tcfg0 | pwm->prescaler) != tcfg0) {
9544 + printk(KERN_WARNING "not changing prescaler of PWM %u,"
9545 + " since it's shared with timer4 (clock tick)\n",
9546 + pwm->timerid);
9547 + }
9548 + break;
9549 + }
9550 +
9551 + /* timer count and compare buffer initial values */
9552 + tcnt = pwm->counter;
9553 + tcmp = pwm->comparer;
9554 +
9555 + __raw_writel(tcnt, S3C2410_TCNTB(pwm->timerid));
9556 + __raw_writel(tcmp, S3C2410_TCMPB(pwm->timerid));
9557 +
9558 + /* ensure timer is stopped */
9559 + s3c2410_pwm_stop(pwm);
9560 +
9561 + return 0;
9562 +}
9563 +EXPORT_SYMBOL_GPL(s3c2410_pwm_enable);
9564 +
9565 +int s3c2410_pwm_start(struct s3c2410_pwm *pwm)
9566 +{
9567 + unsigned long tcon;
9568 +
9569 + tcon = __raw_readl(S3C2410_TCON);
9570 +
9571 + switch (pwm->timerid) {
9572 + case PWM0:
9573 + tcon |= S3C2410_TCON_T0START;
9574 + tcon &= ~S3C2410_TCON_T0MANUALUPD;
9575 + break;
9576 + case PWM1:
9577 + tcon |= S3C2410_TCON_T1START;
9578 + tcon &= ~S3C2410_TCON_T1MANUALUPD;
9579 + break;
9580 + case PWM2:
9581 + tcon |= S3C2410_TCON_T2START;
9582 + tcon &= ~S3C2410_TCON_T2MANUALUPD;
9583 + break;
9584 + case PWM3:
9585 + tcon |= S3C2410_TCON_T3START;
9586 + tcon &= ~S3C2410_TCON_T3MANUALUPD;
9587 + break;
9588 + case PWM4:
9589 + /* timer four is not capable of doing PWM */
9590 + default:
9591 + return -ENODEV;
9592 + }
9593 +
9594 + __raw_writel(tcon, S3C2410_TCON);
9595 +
9596 + return 0;
9597 +}
9598 +EXPORT_SYMBOL_GPL(s3c2410_pwm_start);
9599 +
9600 +int s3c2410_pwm_stop(struct s3c2410_pwm *pwm)
9601 +{
9602 + unsigned long tcon;
9603 +
9604 + tcon = __raw_readl(S3C2410_TCON);
9605 +
9606 + switch (pwm->timerid) {
9607 + case PWM0:
9608 + tcon &= ~0x00000000;
9609 + tcon |= S3C2410_TCON_T0RELOAD;
9610 + tcon |= S3C2410_TCON_T0MANUALUPD;
9611 + break;
9612 + case PWM1:
9613 + tcon &= ~0x00000080;
9614 + tcon |= S3C2410_TCON_T1RELOAD;
9615 + tcon |= S3C2410_TCON_T1MANUALUPD;
9616 + break;
9617 + case PWM2:
9618 + tcon &= ~0x00000800;
9619 + tcon |= S3C2410_TCON_T2RELOAD;
9620 + tcon |= S3C2410_TCON_T2MANUALUPD;
9621 + break;
9622 + case PWM3:
9623 + tcon &= ~0x00008000;
9624 + tcon |= S3C2410_TCON_T3RELOAD;
9625 + tcon |= S3C2410_TCON_T3MANUALUPD;
9626 + break;
9627 + case PWM4:
9628 + /* timer four is not capable of doing PWM */
9629 + default:
9630 + return -ENODEV;
9631 + }
9632 +
9633 + __raw_writel(tcon, S3C2410_TCON);
9634 +
9635 + return 0;
9636 +}
9637 +EXPORT_SYMBOL_GPL(s3c2410_pwm_stop);
9638 +
9639 +int s3c2410_pwm_duty_cycle(int reg_value, struct s3c2410_pwm *pwm)
9640 +{
9641 + __raw_writel(reg_value, S3C2410_TCMPB(pwm->timerid));
9642 +
9643 + return 0;
9644 +}
9645 +EXPORT_SYMBOL_GPL(s3c2410_pwm_duty_cycle);
9646 +
9647 +int s3c2410_pwm_dumpregs(void)
9648 +{
9649 + printk(KERN_INFO "TCON: %08lx, TCFG0: %08lx, TCFG1: %08lx\n",
9650 + (unsigned long) __raw_readl(S3C2410_TCON),
9651 + (unsigned long) __raw_readl(S3C2410_TCFG0),
9652 + (unsigned long) __raw_readl(S3C2410_TCFG1));
9653 +
9654 + return 0;
9655 +}
9656 +EXPORT_SYMBOL_GPL(s3c2410_pwm_dumpregs);
9657 +
9658 +static int __init s3c24xx_pwm_probe(struct platform_device *pdev)
9659 +{
9660 + struct s3c24xx_pwm_platform_data *pdata = pdev->dev.platform_data;
9661 +
9662 + dev_info(&pdev->dev, "s3c24xx_pwm is registered \n");
9663 +
9664 + /* if platform was interested, give him a chance to register
9665 + * platform devices that switch power with us as the parent
9666 + * at registration time -- ensures suspend / resume ordering
9667 + */
9668 + if (pdata)
9669 + if (pdata->attach_child_devices)
9670 + (pdata->attach_child_devices)(&pdev->dev);
9671 +
9672 + return 0;
9673 +}
9674 +
9675 +#ifdef CONFIG_PM
9676 +static int s3c24xx_pwm_suspend(struct platform_device *pdev, pm_message_t state)
9677 +{
9678 + /* PWM config should be kept in suspending */
9679 + standby_reg_tcon = __raw_readl(S3C2410_TCON);
9680 + standby_reg_tcfg0 = __raw_readl(S3C2410_TCFG0);
9681 + standby_reg_tcfg1 = __raw_readl(S3C2410_TCFG1);
9682 +
9683 + return 0;
9684 +}
9685 +
9686 +static int s3c24xx_pwm_resume(struct platform_device *pdev)
9687 +{
9688 + __raw_writel(standby_reg_tcon, S3C2410_TCON);
9689 + __raw_writel(standby_reg_tcfg0, S3C2410_TCFG0);
9690 + __raw_writel(standby_reg_tcfg1, S3C2410_TCFG1);
9691 +
9692 + return 0;
9693 +}
9694 +#else
9695 +#define s3c24xx_pwm_suspend NULL
9696 +#define s3c24xx_pwm_resume NULL
9697 +#endif
9698 +
9699 +static struct platform_driver s3c24xx_pwm_driver = {
9700 + .driver = {
9701 + .name = "s3c24xx_pwm",
9702 + .owner = THIS_MODULE,
9703 + },
9704 + .probe = s3c24xx_pwm_probe,
9705 + .suspend = s3c24xx_pwm_suspend,
9706 + .resume = s3c24xx_pwm_resume,
9707 +};
9708 +
9709 +static int __init s3c24xx_pwm_init(void)
9710 +{
9711 + return platform_driver_register(&s3c24xx_pwm_driver);
9712 +}
9713 +
9714 +static void __exit s3c24xx_pwm_exit(void)
9715 +{
9716 +}
9717 +
9718 +MODULE_AUTHOR("Javi Roman <javiroman@kernel-labs.org>");
9719 +MODULE_LICENSE("GPL");
9720 +
9721 +module_init(s3c24xx_pwm_init);
9722 +module_exit(s3c24xx_pwm_exit);
9723 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/time.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/time.c
9724 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c/time.c 2009-05-10 22:05:04.000000000 +0200
9725 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c/time.c 2009-05-10 22:27:59.000000000 +0200
9726 @@ -97,7 +97,7 @@
9727 * IRQs are disabled before entering here from do_gettimeofday()
9728 */
9729
9730 -static unsigned long s3c2410_gettimeoffset (void)
9731 +unsigned long s3c2410_gettimeoffset (void)
9732 {
9733 unsigned long tdone;
9734 unsigned long tval;
9735 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/clock-dclk.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/clock-dclk.c
9736 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/clock-dclk.c 2009-05-10 22:05:03.000000000 +0200
9737 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/clock-dclk.c 2009-05-10 22:27:59.000000000 +0200
9738 @@ -18,6 +18,7 @@
9739
9740 #include <mach/regs-clock.h>
9741 #include <mach/regs-gpio.h>
9742 +#include <mach/hardware.h>
9743
9744 #include <plat/clock.h>
9745 #include <plat/cpu.h>
9746 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/common-smdk.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/common-smdk.c
9747 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/common-smdk.c 2009-05-10 22:05:03.000000000 +0200
9748 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/common-smdk.c 2009-05-10 22:27:59.000000000 +0200
9749 @@ -201,5 +201,5 @@
9750
9751 platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
9752
9753 - s3c2410_pm_init();
9754 + s3c_pm_init();
9755 }
9756 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/cpu.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/cpu.c
9757 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/cpu.c 2009-05-10 22:05:03.000000000 +0200
9758 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/cpu.c 2009-05-10 22:27:59.000000000 +0200
9759 @@ -61,6 +61,7 @@
9760 static const char name_s3c2412[] = "S3C2412";
9761 static const char name_s3c2440[] = "S3C2440";
9762 static const char name_s3c2442[] = "S3C2442";
9763 +static const char name_s3c2442b[] = "S3C2442B";
9764 static const char name_s3c2443[] = "S3C2443";
9765 static const char name_s3c2410a[] = "S3C2410A";
9766 static const char name_s3c2440a[] = "S3C2440A";
9767 @@ -112,6 +113,15 @@
9768 .name = name_s3c2442
9769 },
9770 {
9771 + .idcode = 0x32440aab,
9772 + .idmask = 0xffffffff,
9773 + .map_io = s3c244x_map_io,
9774 + .init_clocks = s3c244x_init_clocks,
9775 + .init_uarts = s3c244x_init_uarts,
9776 + .init = s3c2442_init,
9777 + .name = name_s3c2442b
9778 + },
9779 + {
9780 .idcode = 0x32412001,
9781 .idmask = 0xffffffff,
9782 .map_io = s3c2412_map_io,
9783 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/devs.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/devs.c
9784 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/devs.c 2009-05-10 22:05:03.000000000 +0200
9785 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/devs.c 2009-05-10 22:27:59.000000000 +0200
9786 @@ -26,6 +26,8 @@
9787 #include <asm/mach/irq.h>
9788 #include <mach/fb.h>
9789 #include <mach/hardware.h>
9790 +#include <mach/ts.h>
9791 +#include <asm/io.h>
9792 #include <asm/irq.h>
9793
9794 #include <plat/regs-serial.h>
9795 @@ -136,36 +138,6 @@
9796 struct platform_device *s3c24xx_uart_devs[4] = {
9797 };
9798
9799 -/* USB Host Controller */
9800 -
9801 -static struct resource s3c_usb_resource[] = {
9802 - [0] = {
9803 - .start = S3C24XX_PA_USBHOST,
9804 - .end = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
9805 - .flags = IORESOURCE_MEM,
9806 - },
9807 - [1] = {
9808 - .start = IRQ_USBH,
9809 - .end = IRQ_USBH,
9810 - .flags = IORESOURCE_IRQ,
9811 - }
9812 -};
9813 -
9814 -static u64 s3c_device_usb_dmamask = 0xffffffffUL;
9815 -
9816 -struct platform_device s3c_device_usb = {
9817 - .name = "s3c2410-ohci",
9818 - .id = -1,
9819 - .num_resources = ARRAY_SIZE(s3c_usb_resource),
9820 - .resource = s3c_usb_resource,
9821 - .dev = {
9822 - .dma_mask = &s3c_device_usb_dmamask,
9823 - .coherent_dma_mask = 0xffffffffUL
9824 - }
9825 -};
9826 -
9827 -EXPORT_SYMBOL(s3c_device_usb);
9828 -
9829 /* LCD Controller */
9830
9831 static struct resource s3c_lcd_resource[] = {
9832 @@ -229,6 +201,24 @@
9833
9834 EXPORT_SYMBOL(s3c_device_nand);
9835
9836 +/* Touchscreen */
9837 +struct platform_device s3c_device_ts = {
9838 + .name = "s3c2410-ts",
9839 + .id = -1,
9840 +};
9841 +
9842 +EXPORT_SYMBOL(s3c_device_ts);
9843 +
9844 +static struct s3c2410_ts_mach_info s3c2410ts_info;
9845 +
9846 +void set_s3c2410ts_info(const struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
9847 +{
9848 + memcpy(&s3c2410ts_info, hard_s3c2410ts_info,
9849 + sizeof(struct s3c2410_ts_mach_info));
9850 + s3c_device_ts.dev.platform_data = &s3c2410ts_info;
9851 +}
9852 +EXPORT_SYMBOL(set_s3c2410ts_info);
9853 +
9854 /* USB Device (Gadget)*/
9855
9856 static struct resource s3c_usbgadget_resource[] = {
9857 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/dma.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/dma.c
9858 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/dma.c 2009-05-10 22:05:03.000000000 +0200
9859 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/dma.c 2009-05-10 22:27:59.000000000 +0200
9860 @@ -31,10 +31,11 @@
9861 #include <asm/irq.h>
9862 #include <mach/hardware.h>
9863 #include <mach/dma.h>
9864 -
9865 #include <mach/map.h>
9866
9867 -#include <plat/dma.h>
9868 +#include <plat/dma-core.h>
9869 +#include <plat/regs-dma.h>
9870 +#include <plat/dma-plat.h>
9871
9872 /* io map for dma */
9873 static void __iomem *dma_base;
9874 @@ -44,8 +45,6 @@
9875
9876 static struct s3c24xx_dma_selection dma_sel;
9877
9878 -/* dma channel state information */
9879 -struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
9880
9881 /* debugging functions */
9882
9883 @@ -135,21 +134,6 @@
9884 #define dbg_showchan(chan) do { } while(0)
9885 #endif /* CONFIG_S3C2410_DMA_DEBUG */
9886
9887 -static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
9888 -
9889 -/* lookup_dma_channel
9890 - *
9891 - * change the dma channel number given into a real dma channel id
9892 -*/
9893 -
9894 -static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
9895 -{
9896 - if (channel & DMACH_LOW_LEVEL)
9897 - return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
9898 - else
9899 - return dma_chan_map[channel];
9900 -}
9901 -
9902 /* s3c2410_dma_stats_timeout
9903 *
9904 * Update DMA stats from timeout info
9905 @@ -214,8 +198,6 @@
9906 return 0;
9907 }
9908
9909 -
9910 -
9911 /* s3c2410_dma_loadbuffer
9912 *
9913 * load a buffer, and update the channel state
9914 @@ -453,7 +435,7 @@
9915 int s3c2410_dma_enqueue(unsigned int channel, void *id,
9916 dma_addr_t data, int size)
9917 {
9918 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
9919 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
9920 struct s3c2410_dma_buf *buf;
9921 unsigned long flags;
9922
9923 @@ -804,7 +786,7 @@
9924
9925 int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
9926 {
9927 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
9928 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
9929 unsigned long flags;
9930
9931 if (chan == NULL)
9932 @@ -836,7 +818,7 @@
9933 chan->irq_claimed = 0;
9934
9935 if (!(channel & DMACH_LOW_LEVEL))
9936 - dma_chan_map[channel] = NULL;
9937 + s3c_dma_chan_map[channel] = NULL;
9938
9939 local_irq_restore(flags);
9940
9941 @@ -995,7 +977,7 @@
9942 int
9943 s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
9944 {
9945 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
9946 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
9947
9948 if (chan == NULL)
9949 return -EINVAL;
9950 @@ -1038,14 +1020,13 @@
9951 /* s3c2410_dma_config
9952 *
9953 * xfersize: size of unit in bytes (1,2,4)
9954 - * dcon: base value of the DCONx register
9955 */
9956
9957 int s3c2410_dma_config(unsigned int channel,
9958 - int xferunit,
9959 - int dcon)
9960 + int xferunit)
9961 {
9962 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
9963 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
9964 + unsigned int dcon;
9965
9966 pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
9967 __func__, channel, xferunit, dcon);
9968 @@ -1055,10 +1036,33 @@
9969
9970 pr_debug("%s: Initial dcon is %08x\n", __func__, dcon);
9971
9972 - dcon |= chan->dcon & dma_sel.dcon_mask;
9973 + dcon = chan->dcon & dma_sel.dcon_mask;
9974
9975 pr_debug("%s: New dcon is %08x\n", __func__, dcon);
9976
9977 + switch (chan->req_ch) {
9978 + case DMACH_I2S_IN:
9979 + case DMACH_I2S_OUT:
9980 + case DMACH_PCM_IN:
9981 + case DMACH_PCM_OUT:
9982 + case DMACH_MIC_IN:
9983 + default:
9984 + dcon |= S3C2410_DCON_HANDSHAKE;
9985 + dcon |= S3C2410_DCON_SYNC_PCLK;
9986 + break;
9987 +
9988 + case DMACH_SDI:
9989 + /* note, ensure if need HANDSHAKE or not */
9990 + dcon |= S3C2410_DCON_SYNC_PCLK;
9991 + break;
9992 +
9993 + case DMACH_XD0:
9994 + case DMACH_XD1:
9995 + dcon |= S3C2410_DCON_HANDSHAKE;
9996 + dcon |= S3C2410_DCON_SYNC_HCLK;
9997 + break;
9998 + }
9999 +
10000 switch (xferunit) {
10001 case 1:
10002 dcon |= S3C2410_DCON_BYTE;
10003 @@ -1089,10 +1093,10 @@
10004 }
10005
10006 EXPORT_SYMBOL(s3c2410_dma_config);
10007 -
10008 +#if 0 /* moved to plat-s3c? */
10009 int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
10010 {
10011 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
10012 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
10013
10014 if (chan == NULL)
10015 return -EINVAL;
10016 @@ -1105,43 +1109,7 @@
10017 }
10018
10019 EXPORT_SYMBOL(s3c2410_dma_setflags);
10020 -
10021 -
10022 -/* do we need to protect the settings of the fields from
10023 - * irq?
10024 -*/
10025 -
10026 -int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
10027 -{
10028 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
10029 -
10030 - if (chan == NULL)
10031 - return -EINVAL;
10032 -
10033 - pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
10034 -
10035 - chan->op_fn = rtn;
10036 -
10037 - return 0;
10038 -}
10039 -
10040 -EXPORT_SYMBOL(s3c2410_dma_set_opfn);
10041 -
10042 -int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
10043 -{
10044 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
10045 -
10046 - if (chan == NULL)
10047 - return -EINVAL;
10048 -
10049 - pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
10050 -
10051 - chan->callback_fn = rtn;
10052 -
10053 - return 0;
10054 -}
10055 -
10056 -EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
10057 +#endif
10058
10059 /* s3c2410_dma_devconfig
10060 *
10061 @@ -1150,29 +1118,38 @@
10062 * source: S3C2410_DMASRC_HW: source is hardware
10063 * S3C2410_DMASRC_MEM: source is memory
10064 *
10065 - * hwcfg: the value for xxxSTCn register,
10066 - * bit 0: 0=increment pointer, 1=leave pointer
10067 - * bit 1: 0=source is AHB, 1=source is APB
10068 - *
10069 * devaddr: physical address of the source
10070 */
10071
10072 int s3c2410_dma_devconfig(int channel,
10073 enum s3c2410_dmasrc source,
10074 - int hwcfg,
10075 unsigned long devaddr)
10076 {
10077 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
10078 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
10079 + unsigned int hwcfg;
10080
10081 if (chan == NULL)
10082 return -EINVAL;
10083
10084 - pr_debug("%s: source=%d, hwcfg=%08x, devaddr=%08lx\n",
10085 - __func__, (int)source, hwcfg, devaddr);
10086 + pr_debug("%s: source=%d, devaddr=%08lx\n",
10087 + __func__, (int)source, devaddr);
10088
10089 chan->source = source;
10090 chan->dev_addr = devaddr;
10091 - chan->hw_cfg = hwcfg;
10092 +
10093 + switch (chan->req_ch) {
10094 + case DMACH_XD0:
10095 + case DMACH_XD1:
10096 + hwcfg = 0; /* AHB */
10097 + break;
10098 +
10099 + default:
10100 + hwcfg = S3C2410_DISRCC_APB;
10101 + }
10102 +
10103 + /* always assume our peripheral desintation is a fixed
10104 + * address in memory. */
10105 + hwcfg |= S3C2410_DISRCC_INC;
10106
10107 switch (source) {
10108 case S3C2410_DMASRC_HW:
10109 @@ -1219,7 +1196,7 @@
10110
10111 int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dst)
10112 {
10113 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
10114 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
10115
10116 if (chan == NULL)
10117 return -EINVAL;
10118 @@ -1278,8 +1255,8 @@
10119
10120 printk(KERN_INFO "dma%d: restoring configuration\n", cp->number);
10121
10122 - s3c2410_dma_config(no, cp->xfer_unit, cp->dcon);
10123 - s3c2410_dma_devconfig(no, cp->source, cp->hw_cfg, cp->dev_addr);
10124 + s3c2410_dma_config(no, cp->xfer_unit);
10125 + s3c2410_dma_devconfig(no, cp->source, cp->dev_addr);
10126
10127 /* re-select the dma source for this channel */
10128
10129 @@ -1476,7 +1453,8 @@
10130 found:
10131 dmach = &s3c2410_chans[ch];
10132 dmach->map = ch_map;
10133 - dma_chan_map[channel] = dmach;
10134 + dmach->req_ch = channel;
10135 + s3c_dma_chan_map[channel] = dmach;
10136
10137 /* select the channel */
10138
10139 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/gpio.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/gpio.c
10140 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/gpio.c 2009-05-10 22:05:03.000000000 +0200
10141 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/gpio.c 2009-05-10 22:27:59.000000000 +0200
10142 @@ -32,6 +32,7 @@
10143 #include <asm/irq.h>
10144
10145 #include <mach/regs-gpio.h>
10146 +#include <mach/regs-gpioj.h>
10147
10148 void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
10149 {
10150 @@ -215,3 +216,423 @@
10151 }
10152
10153 EXPORT_SYMBOL(s3c2410_gpio_irq2pin);
10154 +
10155 +static void pretty_dump(u32 cfg, u32 state, u32 pull,
10156 + const char ** function_names_2,
10157 + const char ** function_names_3,
10158 + const char * prefix,
10159 + int count)
10160 +{
10161 + int n;
10162 + const char *tag_type = NULL,
10163 + *tag_state = NULL,
10164 + *tag_pulldown = NULL,
10165 + * level0 = "0",
10166 + * level1 = "1";
10167 +
10168 + for (n = 0; n < count; n++) {
10169 + switch ((cfg >> (2 * n)) & 3) {
10170 + case 0:
10171 + tag_type = "input ";
10172 + break;
10173 + case 1:
10174 + tag_type = "OUTPUT ";
10175 + break;
10176 + case 2:
10177 + if (function_names_2) {
10178 + if (function_names_2[n])
10179 + tag_type = function_names_2[n];
10180 + else
10181 + tag_type = "*** ILLEGAL CFG (2) *** ";
10182 + } else
10183 + tag_type = "(function) ";
10184 + break;
10185 + default:
10186 + if (function_names_3) {
10187 + if (function_names_3[n])
10188 + tag_type = function_names_3[n];
10189 + else
10190 + tag_type = "*** ILLEGAL CFG (3) *** ";
10191 + } else
10192 + tag_type = "(function) ";
10193 + break;
10194 + }
10195 + if ((state >> n) & 1)
10196 + tag_state = level1;
10197 + else
10198 + tag_state = level0;
10199 +
10200 + if (((pull >> n) & 1))
10201 + tag_pulldown = "";
10202 + else
10203 + tag_pulldown = "(pulldown)";
10204 +
10205 + printk(KERN_INFO"%s%02d: %s %s %s\n", prefix, n, tag_type,
10206 + tag_state, tag_pulldown);
10207 + }
10208 + printk(KERN_INFO"\n");
10209 +}
10210 +
10211 +static void pretty_dump_a(u32 cfg, u32 state,
10212 + const char ** function_names,
10213 + const char * prefix,
10214 + int count)
10215 +{
10216 + int n;
10217 + const char *tag_type = NULL,
10218 + *tag_state = NULL,
10219 + * level0 = "0",
10220 + * level1 = "1";
10221 +
10222 + for (n = 0; n < count; n++) {
10223 + switch ((cfg >> n) & 1) {
10224 + case 0:
10225 + tag_type = "OUTPUT ";
10226 + break;
10227 + default:
10228 + if (function_names) {
10229 + if (function_names[n])
10230 + tag_type = function_names[n];
10231 + else
10232 + tag_type = "*** ILLEGAL CFG *** ";
10233 + } else
10234 + tag_type = "(function) ";
10235 + break;
10236 + }
10237 + if ((state >> n) & 1)
10238 + tag_state = level1;
10239 + else
10240 + tag_state = level0;
10241 +
10242 + printk(KERN_INFO"%s%02d: %s %s\n", prefix, n, tag_type,
10243 + tag_state);
10244 + }
10245 + printk(KERN_INFO"\n");
10246 +}
10247 +
10248 +static const char * funcs_a[] = {
10249 + "ADDR0 ",
10250 + "ADDR16 ",
10251 + "ADDR17 ",
10252 + "ADDR18 ",
10253 + "ADDR19 ",
10254 + "ADDR20 ",
10255 + "ADDR21 ",
10256 + "ADDR22 ",
10257 + "ADDR23 ",
10258 + "ADDR24 ",
10259 + "ADDR25 ",
10260 + "ADDR26 ",
10261 + "nGCS[1] ",
10262 + "nGCS[2] ",
10263 + "nGCS[3] ",
10264 + "nGCS[4] ",
10265 + "nGCS[5] ",
10266 + "CLE ",
10267 + "ALE ",
10268 + "nFWE ",
10269 + "nFRE ",
10270 + "nRSTOUT ",
10271 + "nFCE ",
10272 + NULL,
10273 + NULL
10274 +};
10275 +
10276 +
10277 +static const char * funcs_b2[] = {
10278 + "TOUT0 ",
10279 + "TOUT1 ",
10280 + "TOUT2 ",
10281 + "TOUT3 ",
10282 + "TCLK[0] ",
10283 + "nXBACK ",
10284 + "nXBREQ ",
10285 + "nXDACK1 ",
10286 + "nXDREQ1 ",
10287 + "nXDACK0 ",
10288 + "nXDREQ0 ",
10289 +};
10290 +static const char * funcs_b3[] = {
10291 + NULL,
10292 + NULL,
10293 + NULL,
10294 + NULL,
10295 + NULL,
10296 + NULL,
10297 + NULL,
10298 + NULL,
10299 + NULL,
10300 + NULL,
10301 + NULL,
10302 +};
10303 +
10304 +static const char * funcs_c2[] = {
10305 + "LEND ",
10306 + "VCLK ",
10307 + "VLINE ",
10308 + "VFRAME ",
10309 + "VM ",
10310 + "LCD_LPCOE ",
10311 + "LCD_LPCREV ",
10312 + "LCD_LPCREVB",
10313 + "VD[0] ",
10314 + "VD[1] ",
10315 + "VD[2] ",
10316 + "VD[3] ",
10317 + "VD[4] ",
10318 + "VD[5] ",
10319 + "VD[6] ",
10320 + "VD[7] ",
10321 +};
10322 +static const char * funcs_c3[] = {
10323 + NULL,
10324 + NULL,
10325 + NULL,
10326 + NULL,
10327 + "I2SSDI ",
10328 + NULL,
10329 + NULL,
10330 + NULL,
10331 + NULL,
10332 + NULL,
10333 + NULL,
10334 + NULL,
10335 + NULL,
10336 + NULL,
10337 + NULL,
10338 + NULL,
10339 +};
10340 +
10341 +static const char * funcs_d2[] = {
10342 + "VD[8] ",
10343 + "VD[9] ",
10344 + "VD[10] ",
10345 + "VD[11] ",
10346 + "VD[12] ",
10347 + "VD[13] ",
10348 + "VD[14] ",
10349 + "VD[15] ",
10350 + "VD[16] ",
10351 + "VD[17] ",
10352 + "VD[18] ",
10353 + "VD[19] ",
10354 + "VD[20] ",
10355 + "VD[21] ",
10356 + "VD[22] ",
10357 + "VD[23] ",
10358 +};
10359 +static const char * funcs_d3[] = {
10360 + "nSPICS1 ",
10361 + "SPICLK1 ",
10362 + NULL,
10363 + NULL,
10364 + NULL,
10365 + NULL,
10366 + NULL,
10367 + NULL,
10368 + "SPIMISO1 ",
10369 + "SPIMOSI1 ",
10370 + "SPICLK1 ",
10371 + NULL,
10372 + NULL,
10373 + NULL,
10374 + "nSS1 ",
10375 + "nSS0 ",
10376 +};
10377 +
10378 +static const char * funcs_e2[] = {
10379 + "I2SLRCK ",
10380 + "I2SSCLK ",
10381 + "CDCLK ",
10382 + "I2SDI ",
10383 + "I2SDO ",
10384 + "SDCLK ",
10385 + "SDCMD ",
10386 + "SDDAT0 ",
10387 + "SDDAT1 ",
10388 + "SDDAT2 ",
10389 + "SDDAT3 ",
10390 + "SPIMISO0 ",
10391 + "SPIMOSI0 ",
10392 + "SPICLK0 ",
10393 + "IICSCL ",
10394 + "IICSDA ",
10395 +};
10396 +static const char * funcs_e3[] = {
10397 + NULL,
10398 + NULL,
10399 + NULL,
10400 + NULL,
10401 + NULL,
10402 + NULL,
10403 + NULL,
10404 + NULL,
10405 + NULL,
10406 + NULL,
10407 + NULL,
10408 + NULL,
10409 + NULL,
10410 + NULL,
10411 + NULL,
10412 + NULL,
10413 +};
10414 +
10415 +static const char * funcs_f2[] = {
10416 + "EINT[0] ",
10417 + "EINT[1] ",
10418 + "EINT[2] ",
10419 + "EINT[3] ",
10420 + "EINT[4] ",
10421 + "EINT[5] ",
10422 + "EINT[6] ",
10423 + "EINT[7] ",
10424 +};
10425 +static const char * funcs_f3[] = {
10426 + NULL,
10427 + NULL,
10428 + NULL,
10429 + NULL,
10430 + NULL,
10431 + NULL,
10432 + NULL,
10433 + NULL,
10434 +};
10435 +
10436 +
10437 +static const char * funcs_g2[] = {
10438 + "EINT[8] ",
10439 + "EINT[9] ",
10440 + "EINT[10] ",
10441 + "EINT[11] ",
10442 + "EINT[12] ",
10443 + "EINT[13] ",
10444 + "EINT[14] ",
10445 + "EINT[15] ",
10446 + "EINT[16] ",
10447 + "EINT[17] ",
10448 + "EINT[18] ",
10449 + "EINT[19] ",
10450 + "EINT[20] ",
10451 + "EINT[21] ",
10452 + "EINT[22] ",
10453 + "EINT[23] ",
10454 +};
10455 +static const char * funcs_g3[] = {
10456 + NULL,
10457 + NULL,
10458 + "nSS0 ",
10459 + "nSS1 ",
10460 + "LCD_PWRDN ",
10461 + "SPIMISO1 ",
10462 + "SPIMOSI1 ",
10463 + "SPICLK1 ",
10464 + NULL,
10465 + "nRTS1 ",
10466 + "nCTS1 ",
10467 + "TCLK[1] ",
10468 + "nSPICS0 ",
10469 + NULL,
10470 + NULL,
10471 + NULL,
10472 +};
10473 +
10474 +static const char * funcs_h2[] = {
10475 + "nCTS0 ",
10476 + "nRTS0 ",
10477 + "TXD[0] ",
10478 + "RXD[0] ",
10479 + "TXD[1] ",
10480 + "RXD[1] ",
10481 + "TXD[2] ",
10482 + "RXD[2] ",
10483 + "UEXTCLK ",
10484 + "CLKOUT0 ",
10485 + "CLKOUT1 ",
10486 +};
10487 +static const char * funcs_h3[] = {
10488 + NULL,
10489 + NULL,
10490 + NULL,
10491 + NULL,
10492 + NULL,
10493 + NULL,
10494 + "nRTS1 ",
10495 + "nCTS1 ",
10496 + NULL,
10497 + "nSPICS0 ",
10498 + NULL,
10499 +};
10500 +
10501 +static const char * funcs_j2[] = {
10502 + "CAMDATA[0] ",
10503 + "CAMDATA[1] ",
10504 + "CAMDATA[2] ",
10505 + "CAMDATA[3] ",
10506 + "CAMDATA[4] ",
10507 + "CAMDATA[5] ",
10508 + "CAMDATA[6] ",
10509 + "CAMDATA[7] ",
10510 + "CAMPCLK ",
10511 + "CAMVSYNC ",
10512 + "CAMHREF ",
10513 + "CAMCLKOUT ",
10514 + "CAMRESET ",
10515 +};
10516 +static const char * funcs_j3[] = {
10517 + NULL,
10518 + NULL,
10519 + NULL,
10520 + NULL,
10521 + NULL,
10522 + NULL,
10523 + NULL,
10524 + NULL,
10525 + NULL,
10526 + NULL,
10527 + NULL,
10528 + NULL,
10529 + NULL,
10530 +};
10531 +
10532 +/* used to dump GPIO states at suspend */
10533 +void s3c24xx_dump_gpio_states(void)
10534 +{
10535 + pretty_dump_a(__raw_readl(S3C2410_GPACON),
10536 + __raw_readl(S3C2410_GPADAT),
10537 + funcs_a, "GPA", 25);
10538 + pretty_dump(__raw_readl(S3C2410_GPBCON),
10539 + __raw_readl(S3C2410_GPBDAT),
10540 + __raw_readl(S3C2410_GPBUP),
10541 + funcs_b2, funcs_b3, "GPB", 11);
10542 + pretty_dump(__raw_readl(S3C2410_GPCCON),
10543 + __raw_readl(S3C2410_GPCDAT),
10544 + __raw_readl(S3C2410_GPCUP),
10545 + funcs_c2, funcs_c3, "GPC", 16);
10546 + pretty_dump(__raw_readl(S3C2410_GPDCON),
10547 + __raw_readl(S3C2410_GPDDAT),
10548 + __raw_readl(S3C2410_GPDUP),
10549 + funcs_d2, funcs_d3, "GPD", 16);
10550 + pretty_dump(__raw_readl(S3C2410_GPECON),
10551 + __raw_readl(S3C2410_GPEDAT),
10552 + __raw_readl(S3C2410_GPEUP),
10553 + funcs_e2, funcs_e3, "GPE", 16);
10554 + pretty_dump(__raw_readl(S3C2410_GPFCON),
10555 + __raw_readl(S3C2410_GPFDAT),
10556 + __raw_readl(S3C2410_GPFUP),
10557 + funcs_f2, funcs_f3, "GPF", 8);
10558 + pretty_dump(__raw_readl(S3C2410_GPGCON),
10559 + __raw_readl(S3C2410_GPGDAT),
10560 + __raw_readl(S3C2410_GPGUP),
10561 + funcs_g2, funcs_g3, "GPG", 16);
10562 + pretty_dump(__raw_readl(S3C2410_GPHCON),
10563 + __raw_readl(S3C2410_GPHDAT),
10564 + __raw_readl(S3C2410_GPHUP),
10565 + funcs_h2, funcs_h3, "GPH", 11);
10566 + pretty_dump(__raw_readl(S3C2440_GPJCON),
10567 + __raw_readl(S3C2440_GPJDAT),
10568 + __raw_readl(S3C2440_GPJUP),
10569 + funcs_j2, funcs_j3, "GPJ", 13);
10570 +
10571 +}
10572 +EXPORT_SYMBOL(s3c24xx_dump_gpio_states);
10573 +
10574 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/gpiolib.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/gpiolib.c
10575 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/gpiolib.c 2009-05-10 22:05:03.000000000 +0200
10576 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/gpiolib.c 2009-05-10 22:27:59.000000000 +0200
10577 @@ -22,6 +22,7 @@
10578 #include <plat/gpio-core.h>
10579 #include <mach/hardware.h>
10580 #include <asm/irq.h>
10581 +#include <plat/pm.h>
10582
10583 #include <mach/regs-gpio.h>
10584
10585 @@ -78,6 +79,7 @@
10586 struct s3c_gpio_chip s3c24xx_gpios[] = {
10587 [0] = {
10588 .base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
10589 + .pm = __gpio_pm(&s3c_gpio_pm_1bit),
10590 .chip = {
10591 .base = S3C2410_GPA0,
10592 .owner = THIS_MODULE,
10593 @@ -89,6 +91,7 @@
10594 },
10595 [1] = {
10596 .base = S3C24XX_GPIO_BASE(S3C2410_GPB0),
10597 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10598 .chip = {
10599 .base = S3C2410_GPB0,
10600 .owner = THIS_MODULE,
10601 @@ -98,6 +101,7 @@
10602 },
10603 [2] = {
10604 .base = S3C24XX_GPIO_BASE(S3C2410_GPC0),
10605 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10606 .chip = {
10607 .base = S3C2410_GPC0,
10608 .owner = THIS_MODULE,
10609 @@ -107,6 +111,7 @@
10610 },
10611 [3] = {
10612 .base = S3C24XX_GPIO_BASE(S3C2410_GPD0),
10613 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10614 .chip = {
10615 .base = S3C2410_GPD0,
10616 .owner = THIS_MODULE,
10617 @@ -116,6 +121,7 @@
10618 },
10619 [4] = {
10620 .base = S3C24XX_GPIO_BASE(S3C2410_GPE0),
10621 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10622 .chip = {
10623 .base = S3C2410_GPE0,
10624 .label = "GPIOE",
10625 @@ -125,6 +131,7 @@
10626 },
10627 [5] = {
10628 .base = S3C24XX_GPIO_BASE(S3C2410_GPF0),
10629 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10630 .chip = {
10631 .base = S3C2410_GPF0,
10632 .owner = THIS_MODULE,
10633 @@ -135,12 +142,23 @@
10634 },
10635 [6] = {
10636 .base = S3C24XX_GPIO_BASE(S3C2410_GPG0),
10637 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10638 .chip = {
10639 .base = S3C2410_GPG0,
10640 .owner = THIS_MODULE,
10641 .label = "GPIOG",
10642 - .ngpio = 10,
10643 .to_irq = s3c24xx_gpiolib_bankg_toirq,
10644 + .ngpio = 16,
10645 + },
10646 + },
10647 + [7] = {
10648 + .base = S3C24XX_GPIO_BASE(S3C2410_GPH0),
10649 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10650 + .chip = {
10651 + .base = S3C2410_GPH0,
10652 + .owner = THIS_MODULE,
10653 + .label = "GPIOH",
10654 + .ngpio = 11,
10655 },
10656 },
10657 };
10658 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/gta02_pm_wlan.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/gta02_pm_wlan.c
10659 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/gta02_pm_wlan.c 1970-01-01 01:00:00.000000000 +0100
10660 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/gta02_pm_wlan.c 2009-05-10 22:27:59.000000000 +0200
10661 @@ -0,0 +1,222 @@
10662 +/*
10663 + * GTA02 WLAN power management
10664 + *
10665 + * (C) 2008, 2009 by Openmoko Inc.
10666 + * Author: Andy Green <andy@openmoko.com>
10667 + * All rights reserved.
10668 + *
10669 + * This program is free software; you can redistribute it and/or modify
10670 + * it under the terms of the GNU General Public License version 2 as
10671 + * published by the Free Software Foundation
10672 + *
10673 + */
10674 +
10675 +#include <linux/module.h>
10676 +#include <linux/init.h>
10677 +#include <linux/kernel.h>
10678 +#include <linux/mutex.h>
10679 +#include <linux/platform_device.h>
10680 +
10681 +#include <mach/hardware.h>
10682 +#include <asm/mach-types.h>
10683 +#include <asm/plat-s3c24xx/neo1973.h>
10684 +
10685 +#include <mach/gta02.h>
10686 +#include <mach/gta02-pm-wlan.h>
10687 +#include <mach/regs-gpio.h>
10688 +#include <mach/regs-gpioj.h>
10689 +
10690 +#include <linux/delay.h>
10691 +#include <linux/rfkill.h>
10692 +
10693 +
10694 +/* ----- Module hardware reset ("power") ----------------------------------- */
10695 +
10696 +
10697 +void gta02_wlan_reset(int assert_reset)
10698 +{
10699 + if (assert_reset) {
10700 + s3c2410_gpio_setpin(GTA02_GPIO_nWLAN_RESET, 0);
10701 + msleep(200); /* probably excessive but we don't have specs */
10702 + } else {
10703 + s3c2410_gpio_setpin(GTA02_GPIO_nWLAN_RESET, 1);
10704 + }
10705 +}
10706 +
10707 +#ifdef CONFIG_PM
10708 +static int gta02_wlan_suspend(struct platform_device *pdev, pm_message_t state)
10709 +{
10710 + dev_dbg(&pdev->dev, "suspending\n");
10711 +
10712 + return 0;
10713 +}
10714 +
10715 +static int gta02_wlan_resume(struct platform_device *pdev)
10716 +{
10717 + dev_dbg(&pdev->dev, "resuming\n");
10718 +
10719 + return 0;
10720 +}
10721 +#else
10722 +#define gta02_wlan_suspend NULL
10723 +#define gta02_wlan_resume NULL
10724 +#endif
10725 +
10726 +
10727 +/* ----- rfkill ------------------------------------------------------------ */
10728 +
10729 +/*
10730 + * S3C MCI handles suspend/resume through device removal/insertion. In order to
10731 + * preserve rfkill state, as required in clause 7 of section 3.1 in rfkill.txt,
10732 + * we therefore need to maintain rfkill state outside the driver.
10733 + *
10734 + * This platform driver is as good a place as any other.
10735 + */
10736 +
10737 +static int (*gta02_wlan_rfkill_cb)(void *user, int on);
10738 +static void *gta02_wlan_rfkill_user;
10739 +static DEFINE_MUTEX(gta02_wlan_rfkill_lock);
10740 +static int gta02_wlan_rfkill_on;
10741 +
10742 +
10743 +/*
10744 + * gta02_wlan_query_rfkill_lock is used to obtain the rfkill state before the
10745 + * driver is ready to process rfkill callbacks. To prevent the state from
10746 + * changing until the driver has completed its initialization, we grab and hold
10747 + * the rfkill lock.
10748 + *
10749 + * A call to gta02_wlan_query_rfkill_lock must be followed by either
10750 + * - a call to gta02_wlan_set_rfkill_cb, to complete the setup, or
10751 + * - a call to gta02_wlan_query_rfkill_unlock to abort the setup process.
10752 + */
10753 +
10754 +int gta02_wlan_query_rfkill_lock(void)
10755 +{
10756 + mutex_lock(&gta02_wlan_rfkill_lock);
10757 + return gta02_wlan_rfkill_on;
10758 +}
10759 +EXPORT_SYMBOL_GPL(gta02_wlan_query_rfkill_lock);
10760 +
10761 +void gta02_wlan_query_rfkill_unlock(void)
10762 +{
10763 + mutex_unlock(&gta02_wlan_rfkill_lock);
10764 +}
10765 +EXPORT_SYMBOL_GPL(gta02_wlan_query_rfkill_unlock);
10766 +
10767 +
10768 +void gta02_wlan_set_rfkill_cb(int (*cb)(void *user, int on), void *user)
10769 +{
10770 + BUG_ON(!mutex_is_locked(&gta02_wlan_rfkill_lock));
10771 + BUG_ON(gta02_wlan_rfkill_cb);
10772 + gta02_wlan_rfkill_cb = cb;
10773 + gta02_wlan_rfkill_user = user;
10774 + mutex_unlock(&gta02_wlan_rfkill_lock);
10775 +}
10776 +EXPORT_SYMBOL_GPL(gta02_wlan_set_rfkill_cb);
10777 +
10778 +void gta02_wlan_clear_rfkill_cb(void)
10779 +{
10780 + mutex_lock(&gta02_wlan_rfkill_lock);
10781 + BUG_ON(!gta02_wlan_rfkill_cb);
10782 + gta02_wlan_rfkill_cb = NULL;
10783 + mutex_unlock(&gta02_wlan_rfkill_lock);
10784 +}
10785 +EXPORT_SYMBOL_GPL(gta02_wlan_clear_rfkill_cb);
10786 +
10787 +static int gta02_wlan_toggle_radio(void *data, enum rfkill_state state)
10788 +{
10789 + struct device *dev = data;
10790 + int on = state == RFKILL_STATE_UNBLOCKED;
10791 + int res = 0;
10792 +
10793 + dev_dbg(dev, "gta02_wlan_toggle_radio: state %d (%p)\n",
10794 + state, gta02_wlan_rfkill_cb);
10795 + mutex_lock(&gta02_wlan_rfkill_lock);
10796 + if (gta02_wlan_rfkill_cb)
10797 + res = gta02_wlan_rfkill_cb(gta02_wlan_rfkill_user, on);
10798 + if (!res)
10799 + gta02_wlan_rfkill_on = on;
10800 + mutex_unlock(&gta02_wlan_rfkill_lock);
10801 + return res;
10802 +}
10803 +
10804 +
10805 +/* ----- Initialization/removal -------------------------------------------- */
10806 +
10807 +
10808 +static int __init gta02_wlan_probe(struct platform_device *pdev)
10809 +{
10810 + /* default-on for now */
10811 + const int default_state = 1;
10812 + struct rfkill *rfkill;
10813 + int error;
10814 +
10815 + if (!machine_is_neo1973_gta02())
10816 + return -EINVAL;
10817 +
10818 + dev_info(&pdev->dev, "starting\n");
10819 +
10820 + s3c2410_gpio_cfgpin(GTA02_GPIO_nWLAN_RESET, S3C2410_GPIO_OUTPUT);
10821 + gta02_wlan_reset(1);
10822 + gta02_wlan_reset(0);
10823 +
10824 + rfkill = rfkill_allocate(&pdev->dev, RFKILL_TYPE_WLAN);
10825 + rfkill->name = "ar6000";
10826 + rfkill->data = &pdev->dev;
10827 + rfkill->state = default_state ? RFKILL_STATE_ON : RFKILL_STATE_OFF;
10828 + /*
10829 + * If the WLAN driver somehow managed to get activated before we're
10830 + * ready, the driver is now in an unknown state, which isn't something
10831 + * we're prepared to handle. This can't happen, so just fail hard.
10832 + */
10833 + BUG_ON(gta02_wlan_rfkill_cb);
10834 + gta02_wlan_rfkill_on = default_state;
10835 + rfkill->toggle_radio = gta02_wlan_toggle_radio;
10836 +
10837 + error = rfkill_register(rfkill);
10838 + if (error) {
10839 + rfkill_free(rfkill);
10840 + return error;
10841 + }
10842 +
10843 + dev_set_drvdata(&pdev->dev, rfkill);
10844 +
10845 + return 0;
10846 +}
10847 +
10848 +static int gta02_wlan_remove(struct platform_device *pdev)
10849 +{
10850 + struct rfkill *rfkill = dev_get_drvdata(&pdev->dev);
10851 +
10852 + rfkill_unregister(rfkill);
10853 + rfkill_free(rfkill);
10854 +
10855 + return 0;
10856 +}
10857 +
10858 +static struct platform_driver gta02_wlan_driver = {
10859 + .probe = gta02_wlan_probe,
10860 + .remove = gta02_wlan_remove,
10861 + .suspend = gta02_wlan_suspend,
10862 + .resume = gta02_wlan_resume,
10863 + .driver = {
10864 + .name = "gta02-pm-wlan",
10865 + },
10866 +};
10867 +
10868 +static int __devinit gta02_wlan_init(void)
10869 +{
10870 + return platform_driver_register(&gta02_wlan_driver);
10871 +}
10872 +
10873 +static void gta02_wlan_exit(void)
10874 +{
10875 + platform_driver_unregister(&gta02_wlan_driver);
10876 +}
10877 +
10878 +module_init(gta02_wlan_init);
10879 +module_exit(gta02_wlan_exit);
10880 +
10881 +MODULE_LICENSE("GPL");
10882 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
10883 +MODULE_DESCRIPTION("Openmoko GTA02 WLAN power management");
10884 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/dma.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/dma.h
10885 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/dma.h 2009-05-10 22:05:03.000000000 +0200
10886 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/dma.h 1970-01-01 01:00:00.000000000 +0100
10887 @@ -1,82 +0,0 @@
10888 -/* linux/include/asm-arm/plat-s3c24xx/dma.h
10889 - *
10890 - * Copyright (C) 2006 Simtec Electronics
10891 - * Ben Dooks <ben@simtec.co.uk>
10892 - *
10893 - * Samsung S3C24XX DMA support
10894 - *
10895 - * This program is free software; you can redistribute it and/or modify
10896 - * it under the terms of the GNU General Public License version 2 as
10897 - * published by the Free Software Foundation.
10898 -*/
10899 -
10900 -extern struct sysdev_class dma_sysclass;
10901 -extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
10902 -
10903 -#define DMA_CH_VALID (1<<31)
10904 -#define DMA_CH_NEVER (1<<30)
10905 -
10906 -struct s3c24xx_dma_addr {
10907 - unsigned long from;
10908 - unsigned long to;
10909 -};
10910 -
10911 -/* struct s3c24xx_dma_map
10912 - *
10913 - * this holds the mapping information for the channel selected
10914 - * to be connected to the specified device
10915 -*/
10916 -
10917 -struct s3c24xx_dma_map {
10918 - const char *name;
10919 - struct s3c24xx_dma_addr hw_addr;
10920 -
10921 - unsigned long channels[S3C2410_DMA_CHANNELS];
10922 - unsigned long channels_rx[S3C2410_DMA_CHANNELS];
10923 -};
10924 -
10925 -struct s3c24xx_dma_selection {
10926 - struct s3c24xx_dma_map *map;
10927 - unsigned long map_size;
10928 - unsigned long dcon_mask;
10929 -
10930 - void (*select)(struct s3c2410_dma_chan *chan,
10931 - struct s3c24xx_dma_map *map);
10932 -
10933 - void (*direction)(struct s3c2410_dma_chan *chan,
10934 - struct s3c24xx_dma_map *map,
10935 - enum s3c2410_dmasrc dir);
10936 -};
10937 -
10938 -extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
10939 -
10940 -/* struct s3c24xx_dma_order_ch
10941 - *
10942 - * channel map for one of the `enum dma_ch` dma channels. the list
10943 - * entry contains a set of low-level channel numbers, orred with
10944 - * DMA_CH_VALID, which are checked in the order in the array.
10945 -*/
10946 -
10947 -struct s3c24xx_dma_order_ch {
10948 - unsigned int list[S3C2410_DMA_CHANNELS]; /* list of channels */
10949 - unsigned int flags; /* flags */
10950 -};
10951 -
10952 -/* struct s3c24xx_dma_order
10953 - *
10954 - * information provided by either the core or the board to give the
10955 - * dma system a hint on how to allocate channels
10956 -*/
10957 -
10958 -struct s3c24xx_dma_order {
10959 - struct s3c24xx_dma_order_ch channels[DMACH_MAX];
10960 -};
10961 -
10962 -extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
10963 -
10964 -/* DMA init code, called from the cpu support code */
10965 -
10966 -extern int s3c2410_dma_init(void);
10967 -
10968 -extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
10969 - unsigned int stride);
10970 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/dma-plat.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
10971 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/dma-plat.h 1970-01-01 01:00:00.000000000 +0100
10972 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/dma-plat.h 2009-05-10 22:27:59.000000000 +0200
10973 @@ -0,0 +1,84 @@
10974 +/* linux/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
10975 + *
10976 + * Copyright (C) 2006 Simtec Electronics
10977 + * Ben Dooks <ben@simtec.co.uk>
10978 + *
10979 + * Samsung S3C24XX DMA support
10980 + *
10981 + * This program is free software; you can redistribute it and/or modify
10982 + * it under the terms of the GNU General Public License version 2 as
10983 + * published by the Free Software Foundation.
10984 +*/
10985 +
10986 +#include <plat/dma-core.h>
10987 +
10988 +extern struct sysdev_class dma_sysclass;
10989 +extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
10990 +
10991 +#define DMA_CH_VALID (1<<31)
10992 +#define DMA_CH_NEVER (1<<30)
10993 +
10994 +struct s3c24xx_dma_addr {
10995 + unsigned long from;
10996 + unsigned long to;
10997 +};
10998 +
10999 +/* struct s3c24xx_dma_map
11000 + *
11001 + * this holds the mapping information for the channel selected
11002 + * to be connected to the specified device
11003 +*/
11004 +
11005 +struct s3c24xx_dma_map {
11006 + const char *name;
11007 + struct s3c24xx_dma_addr hw_addr;
11008 +
11009 + unsigned long channels[S3C_DMA_CHANNELS];
11010 + unsigned long channels_rx[S3C_DMA_CHANNELS];
11011 +};
11012 +
11013 +struct s3c24xx_dma_selection {
11014 + struct s3c24xx_dma_map *map;
11015 + unsigned long map_size;
11016 + unsigned long dcon_mask;
11017 +
11018 + void (*select)(struct s3c2410_dma_chan *chan,
11019 + struct s3c24xx_dma_map *map);
11020 +
11021 + void (*direction)(struct s3c2410_dma_chan *chan,
11022 + struct s3c24xx_dma_map *map,
11023 + enum s3c2410_dmasrc dir);
11024 +};
11025 +
11026 +extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
11027 +
11028 +/* struct s3c24xx_dma_order_ch
11029 + *
11030 + * channel map for one of the `enum dma_ch` dma channels. the list
11031 + * entry contains a set of low-level channel numbers, orred with
11032 + * DMA_CH_VALID, which are checked in the order in the array.
11033 +*/
11034 +
11035 +struct s3c24xx_dma_order_ch {
11036 + unsigned int list[S3C_DMA_CHANNELS]; /* list of channels */
11037 + unsigned int flags; /* flags */
11038 +};
11039 +
11040 +/* struct s3c24xx_dma_order
11041 + *
11042 + * information provided by either the core or the board to give the
11043 + * dma system a hint on how to allocate channels
11044 +*/
11045 +
11046 +struct s3c24xx_dma_order {
11047 + struct s3c24xx_dma_order_ch channels[DMACH_MAX];
11048 +};
11049 +
11050 +extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
11051 +
11052 +/* DMA init code, called from the cpu support code */
11053 +
11054 +extern int s3c2410_dma_init(void);
11055 +
11056 +extern int s3c24xx_dma_init(unsigned int channels, unsigned int irq,
11057 + unsigned int stride);
11058 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/irq.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/irq.h
11059 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/irq.h 2009-05-10 22:05:03.000000000 +0200
11060 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/irq.h 2009-05-10 22:27:59.000000000 +0200
11061 @@ -10,6 +10,13 @@
11062 * published by the Free Software Foundation.
11063 */
11064
11065 +#include <linux/io.h>
11066 +
11067 +#include <mach/irqs.h>
11068 +#include <mach/hardware.h>
11069 +#include <mach/regs-irq.h>
11070 +#include <mach/regs-gpio.h>
11071 +
11072 #define irqdbf(x...)
11073 #define irqdbf2(x...)
11074
11075 @@ -25,8 +32,15 @@
11076 {
11077 unsigned long mask;
11078 unsigned long submask;
11079 +#ifdef CONFIG_S3C2440_C_FIQ
11080 + unsigned long flags;
11081 +#endif
11082
11083 submask = __raw_readl(S3C2410_INTSUBMSK);
11084 +#ifdef CONFIG_S3C2440_C_FIQ
11085 + local_save_flags(flags);
11086 + local_fiq_disable();
11087 +#endif
11088 mask = __raw_readl(S3C2410_INTMSK);
11089
11090 submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
11091 @@ -39,6 +53,9 @@
11092
11093 /* write back masks */
11094 __raw_writel(submask, S3C2410_INTSUBMSK);
11095 +#ifdef CONFIG_S3C2440_C_FIQ
11096 + local_irq_restore(flags);
11097 +#endif
11098
11099 }
11100
11101 @@ -47,8 +64,15 @@
11102 {
11103 unsigned long mask;
11104 unsigned long submask;
11105 +#ifdef CONFIG_S3C2440_C_FIQ
11106 + unsigned long flags;
11107 +#endif
11108
11109 submask = __raw_readl(S3C2410_INTSUBMSK);
11110 +#ifdef CONFIG_S3C2440_C_FIQ
11111 + local_save_flags(flags);
11112 + local_fiq_disable();
11113 +#endif
11114 mask = __raw_readl(S3C2410_INTMSK);
11115
11116 submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
11117 @@ -57,6 +81,9 @@
11118 /* write back masks */
11119 __raw_writel(submask, S3C2410_INTSUBMSK);
11120 __raw_writel(mask, S3C2410_INTMSK);
11121 +#ifdef CONFIG_S3C2440_C_FIQ
11122 + local_irq_restore(flags);
11123 +#endif
11124 }
11125
11126
11127 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/map.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/map.h
11128 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/map.h 2009-05-10 22:05:03.000000000 +0200
11129 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/map.h 2009-05-10 22:27:59.000000000 +0200
11130 @@ -31,6 +31,8 @@
11131 #define S3C24XX_SZ_UART SZ_1M
11132 #define S3C_UART_OFFSET (0x4000)
11133
11134 +#define S3C_VA_UARTx(uart) (S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
11135 +
11136 /* Timers */
11137 #define S3C24XX_VA_TIMER S3C_VA_TIMER
11138 #define S3C2410_PA_TIMER (0x51000000)
11139 @@ -56,7 +58,6 @@
11140 #define S3C24XX_SZ_SPI SZ_1M
11141 #define S3C24XX_SZ_SDI SZ_1M
11142 #define S3C24XX_SZ_NAND SZ_1M
11143 -#define S3C24XX_SZ_USBHOST SZ_1M
11144
11145 /* GPIO ports */
11146
11147 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/pm-core.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/pm-core.h
11148 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/pm-core.h 1970-01-01 01:00:00.000000000 +0100
11149 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/pm-core.h 2009-05-10 22:27:59.000000000 +0200
11150 @@ -0,0 +1,64 @@
11151 +/* linux/arch/arm/plat-s3c24xx/include/plat/pll.h
11152 + *
11153 + * Copyright 2008 Simtec Electronics
11154 + * Ben Dooks <ben@simtec.co.uk>
11155 + * http://armlinux.simtec.co.uk/
11156 + *
11157 + * S3C24xx - PM core support for arch/arm/plat-s3c/pm.c
11158 + *
11159 + * This program is free software; you can redistribute it and/or modify
11160 + * it under the terms of the GNU General Public License version 2 as
11161 + * published by the Free Software Foundation.
11162 + */
11163 +
11164 +static inline void s3c_pm_debug_init_uart(void)
11165 +{
11166 + unsigned long tmp = __raw_readl(S3C2410_CLKCON);
11167 +
11168 + /* re-start uart clocks */
11169 + tmp |= S3C2410_CLKCON_UART0;
11170 + tmp |= S3C2410_CLKCON_UART1;
11171 + tmp |= S3C2410_CLKCON_UART2;
11172 +
11173 + __raw_writel(tmp, S3C2410_CLKCON);
11174 + udelay(10);
11175 +}
11176 +
11177 +static inline void s3c_pm_arch_prepare_irqs(void)
11178 +{
11179 + __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
11180 + __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
11181 +
11182 + /* ack any outstanding external interrupts before we go to sleep */
11183 +
11184 + __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
11185 + __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
11186 + __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
11187 +
11188 +}
11189 +
11190 +static inline void s3c_pm_arch_stop_clocks(void)
11191 +{
11192 + __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
11193 +}
11194 +
11195 +static void s3c_pm_show_resume_irqs(int start, unsigned long which,
11196 + unsigned long mask);
11197 +
11198 +static inline void s3c_pm_arch_show_resume_irqs(void)
11199 +{
11200 + S3C_PMDBG("post sleep: IRQs 0x%08x, 0x%08x\n",
11201 + __raw_readl(S3C2410_SRCPND),
11202 + __raw_readl(S3C2410_EINTPEND));
11203 +
11204 + s3c_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
11205 + s3c_irqwake_intmask);
11206 +
11207 + s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
11208 + s3c_irqwake_eintmask);
11209 +}
11210 +
11211 +static inline void s3c_pm_arch_update_uart(void __iomem *regs,
11212 + struct pm_uart_save *save)
11213 +{
11214 +}
11215 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/pm.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/pm.h
11216 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/pm.h 2009-05-10 22:05:03.000000000 +0200
11217 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/pm.h 1970-01-01 01:00:00.000000000 +0100
11218 @@ -1,73 +0,0 @@
11219 -/* linux/include/asm-arm/plat-s3c24xx/pm.h
11220 - *
11221 - * Copyright (c) 2004 Simtec Electronics
11222 - * Written by Ben Dooks, <ben@simtec.co.uk>
11223 - *
11224 - * This program is free software; you can redistribute it and/or modify
11225 - * it under the terms of the GNU General Public License version 2 as
11226 - * published by the Free Software Foundation.
11227 -*/
11228 -
11229 -/* s3c2410_pm_init
11230 - *
11231 - * called from board at initialisation time to setup the power
11232 - * management
11233 -*/
11234 -
11235 -#ifdef CONFIG_PM
11236 -
11237 -extern __init int s3c2410_pm_init(void);
11238 -
11239 -#else
11240 -
11241 -static inline int s3c2410_pm_init(void)
11242 -{
11243 - return 0;
11244 -}
11245 -#endif
11246 -
11247 -/* configuration for the IRQ mask over sleep */
11248 -extern unsigned long s3c_irqwake_intmask;
11249 -extern unsigned long s3c_irqwake_eintmask;
11250 -
11251 -/* IRQ masks for IRQs allowed to go to sleep (see irq.c) */
11252 -extern unsigned long s3c_irqwake_intallow;
11253 -extern unsigned long s3c_irqwake_eintallow;
11254 -
11255 -/* per-cpu sleep functions */
11256 -
11257 -extern void (*pm_cpu_prep)(void);
11258 -extern void (*pm_cpu_sleep)(void);
11259 -
11260 -/* Flags for PM Control */
11261 -
11262 -extern unsigned long s3c_pm_flags;
11263 -
11264 -/* from sleep.S */
11265 -
11266 -extern int s3c2410_cpu_save(unsigned long *saveblk);
11267 -extern void s3c2410_cpu_suspend(void);
11268 -extern void s3c2410_cpu_resume(void);
11269 -
11270 -extern unsigned long s3c2410_sleep_save_phys;
11271 -
11272 -/* sleep save info */
11273 -
11274 -struct sleep_save {
11275 - void __iomem *reg;
11276 - unsigned long val;
11277 -};
11278 -
11279 -#define SAVE_ITEM(x) \
11280 - { .reg = (x) }
11281 -
11282 -extern void s3c2410_pm_do_save(struct sleep_save *ptr, int count);
11283 -extern void s3c2410_pm_do_restore(struct sleep_save *ptr, int count);
11284 -
11285 -#ifdef CONFIG_PM
11286 -extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
11287 -extern int s3c24xx_irq_resume(struct sys_device *dev);
11288 -#else
11289 -#define s3c24xx_irq_suspend NULL
11290 -#define s3c24xx_irq_resume NULL
11291 -#endif
11292 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/regs-dma.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/regs-dma.h
11293 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/regs-dma.h 1970-01-01 01:00:00.000000000 +0100
11294 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/regs-dma.h 2009-05-10 22:27:59.000000000 +0200
11295 @@ -0,0 +1,145 @@
11296 +/* arch/arm/mach-s3c2410/include/mach/dma.h
11297 + *
11298 + * Copyright (C) 2003,2004,2006 Simtec Electronics
11299 + * Ben Dooks <ben@simtec.co.uk>
11300 + *
11301 + * Samsung S3C24XX DMA support
11302 + *
11303 + * This program is free software; you can redistribute it and/or modify
11304 + * it under the terms of the GNU General Public License version 2 as
11305 + * published by the Free Software Foundation.
11306 +*/
11307 +
11308 +/* DMA Register definitions */
11309 +
11310 +#define S3C2410_DMA_DISRC (0x00)
11311 +#define S3C2410_DMA_DISRCC (0x04)
11312 +#define S3C2410_DMA_DIDST (0x08)
11313 +#define S3C2410_DMA_DIDSTC (0x0C)
11314 +#define S3C2410_DMA_DCON (0x10)
11315 +#define S3C2410_DMA_DSTAT (0x14)
11316 +#define S3C2410_DMA_DCSRC (0x18)
11317 +#define S3C2410_DMA_DCDST (0x1C)
11318 +#define S3C2410_DMA_DMASKTRIG (0x20)
11319 +#define S3C2412_DMA_DMAREQSEL (0x24)
11320 +#define S3C2443_DMA_DMAREQSEL (0x24)
11321 +
11322 +#define S3C2410_DISRCC_INC (1<<0)
11323 +#define S3C2410_DISRCC_APB (1<<1)
11324 +
11325 +#define S3C2410_DMASKTRIG_STOP (1<<2)
11326 +#define S3C2410_DMASKTRIG_ON (1<<1)
11327 +#define S3C2410_DMASKTRIG_SWTRIG (1<<0)
11328 +
11329 +#define S3C2410_DCON_DEMAND (0<<31)
11330 +#define S3C2410_DCON_HANDSHAKE (1<<31)
11331 +#define S3C2410_DCON_SYNC_PCLK (0<<30)
11332 +#define S3C2410_DCON_SYNC_HCLK (1<<30)
11333 +
11334 +#define S3C2410_DCON_INTREQ (1<<29)
11335 +
11336 +#define S3C2410_DCON_CH0_XDREQ0 (0<<24)
11337 +#define S3C2410_DCON_CH0_UART0 (1<<24)
11338 +#define S3C2410_DCON_CH0_SDI (2<<24)
11339 +#define S3C2410_DCON_CH0_TIMER (3<<24)
11340 +#define S3C2410_DCON_CH0_USBEP1 (4<<24)
11341 +
11342 +#define S3C2410_DCON_CH1_XDREQ1 (0<<24)
11343 +#define S3C2410_DCON_CH1_UART1 (1<<24)
11344 +#define S3C2410_DCON_CH1_I2SSDI (2<<24)
11345 +#define S3C2410_DCON_CH1_SPI (3<<24)
11346 +#define S3C2410_DCON_CH1_USBEP2 (4<<24)
11347 +
11348 +#define S3C2410_DCON_CH2_I2SSDO (0<<24)
11349 +#define S3C2410_DCON_CH2_I2SSDI (1<<24)
11350 +#define S3C2410_DCON_CH2_SDI (2<<24)
11351 +#define S3C2410_DCON_CH2_TIMER (3<<24)
11352 +#define S3C2410_DCON_CH2_USBEP3 (4<<24)
11353 +
11354 +#define S3C2410_DCON_CH3_UART2 (0<<24)
11355 +#define S3C2410_DCON_CH3_SDI (1<<24)
11356 +#define S3C2410_DCON_CH3_SPI (2<<24)
11357 +#define S3C2410_DCON_CH3_TIMER (3<<24)
11358 +#define S3C2410_DCON_CH3_USBEP4 (4<<24)
11359 +
11360 +#define S3C2410_DCON_SRCSHIFT (24)
11361 +#define S3C2410_DCON_SRCMASK (7<<24)
11362 +
11363 +#define S3C2410_DCON_BYTE (0<<20)
11364 +#define S3C2410_DCON_HALFWORD (1<<20)
11365 +#define S3C2410_DCON_WORD (2<<20)
11366 +
11367 +#define S3C2410_DCON_AUTORELOAD (0<<22)
11368 +#define S3C2410_DCON_NORELOAD (1<<22)
11369 +#define S3C2410_DCON_HWTRIG (1<<23)
11370 +
11371 +#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
11372 +#define S3C2440_DIDSTC_CHKINT (1<<2)
11373 +
11374 +#define S3C2440_DCON_CH0_I2SSDO (5<<24)
11375 +#define S3C2440_DCON_CH0_PCMIN (6<<24)
11376 +
11377 +#define S3C2440_DCON_CH1_PCMOUT (5<<24)
11378 +#define S3C2440_DCON_CH1_SDI (6<<24)
11379 +
11380 +#define S3C2440_DCON_CH2_PCMIN (5<<24)
11381 +#define S3C2440_DCON_CH2_MICIN (6<<24)
11382 +
11383 +#define S3C2440_DCON_CH3_MICIN (5<<24)
11384 +#define S3C2440_DCON_CH3_PCMOUT (6<<24)
11385 +#endif
11386 +
11387 +#ifdef CONFIG_CPU_S3C2412
11388 +
11389 +#define S3C2412_DMAREQSEL_SRC(x) ((x)<<1)
11390 +
11391 +#define S3C2412_DMAREQSEL_HW (1)
11392 +
11393 +#define S3C2412_DMAREQSEL_SPI0TX S3C2412_DMAREQSEL_SRC(0)
11394 +#define S3C2412_DMAREQSEL_SPI0RX S3C2412_DMAREQSEL_SRC(1)
11395 +#define S3C2412_DMAREQSEL_SPI1TX S3C2412_DMAREQSEL_SRC(2)
11396 +#define S3C2412_DMAREQSEL_SPI1RX S3C2412_DMAREQSEL_SRC(3)
11397 +#define S3C2412_DMAREQSEL_I2STX S3C2412_DMAREQSEL_SRC(4)
11398 +#define S3C2412_DMAREQSEL_I2SRX S3C2412_DMAREQSEL_SRC(5)
11399 +#define S3C2412_DMAREQSEL_TIMER S3C2412_DMAREQSEL_SRC(9)
11400 +#define S3C2412_DMAREQSEL_SDI S3C2412_DMAREQSEL_SRC(10)
11401 +#define S3C2412_DMAREQSEL_USBEP1 S3C2412_DMAREQSEL_SRC(13)
11402 +#define S3C2412_DMAREQSEL_USBEP2 S3C2412_DMAREQSEL_SRC(14)
11403 +#define S3C2412_DMAREQSEL_USBEP3 S3C2412_DMAREQSEL_SRC(15)
11404 +#define S3C2412_DMAREQSEL_USBEP4 S3C2412_DMAREQSEL_SRC(16)
11405 +#define S3C2412_DMAREQSEL_XDREQ0 S3C2412_DMAREQSEL_SRC(17)
11406 +#define S3C2412_DMAREQSEL_XDREQ1 S3C2412_DMAREQSEL_SRC(18)
11407 +#define S3C2412_DMAREQSEL_UART0_0 S3C2412_DMAREQSEL_SRC(19)
11408 +#define S3C2412_DMAREQSEL_UART0_1 S3C2412_DMAREQSEL_SRC(20)
11409 +#define S3C2412_DMAREQSEL_UART1_0 S3C2412_DMAREQSEL_SRC(21)
11410 +#define S3C2412_DMAREQSEL_UART1_1 S3C2412_DMAREQSEL_SRC(22)
11411 +#define S3C2412_DMAREQSEL_UART2_0 S3C2412_DMAREQSEL_SRC(23)
11412 +#define S3C2412_DMAREQSEL_UART2_1 S3C2412_DMAREQSEL_SRC(24)
11413 +
11414 +#endif
11415 +
11416 +#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1)
11417 +
11418 +#define S3C2443_DMAREQSEL_HW (1)
11419 +
11420 +#define S3C2443_DMAREQSEL_SPI0TX S3C2443_DMAREQSEL_SRC(0)
11421 +#define S3C2443_DMAREQSEL_SPI0RX S3C2443_DMAREQSEL_SRC(1)
11422 +#define S3C2443_DMAREQSEL_SPI1TX S3C2443_DMAREQSEL_SRC(2)
11423 +#define S3C2443_DMAREQSEL_SPI1RX S3C2443_DMAREQSEL_SRC(3)
11424 +#define S3C2443_DMAREQSEL_I2STX S3C2443_DMAREQSEL_SRC(4)
11425 +#define S3C2443_DMAREQSEL_I2SRX S3C2443_DMAREQSEL_SRC(5)
11426 +#define S3C2443_DMAREQSEL_TIMER S3C2443_DMAREQSEL_SRC(9)
11427 +#define S3C2443_DMAREQSEL_SDI S3C2443_DMAREQSEL_SRC(10)
11428 +#define S3C2443_DMAREQSEL_XDREQ0 S3C2443_DMAREQSEL_SRC(17)
11429 +#define S3C2443_DMAREQSEL_XDREQ1 S3C2443_DMAREQSEL_SRC(18)
11430 +#define S3C2443_DMAREQSEL_UART0_0 S3C2443_DMAREQSEL_SRC(19)
11431 +#define S3C2443_DMAREQSEL_UART0_1 S3C2443_DMAREQSEL_SRC(20)
11432 +#define S3C2443_DMAREQSEL_UART1_0 S3C2443_DMAREQSEL_SRC(21)
11433 +#define S3C2443_DMAREQSEL_UART1_1 S3C2443_DMAREQSEL_SRC(22)
11434 +#define S3C2443_DMAREQSEL_UART2_0 S3C2443_DMAREQSEL_SRC(23)
11435 +#define S3C2443_DMAREQSEL_UART2_1 S3C2443_DMAREQSEL_SRC(24)
11436 +#define S3C2443_DMAREQSEL_UART3_0 S3C2443_DMAREQSEL_SRC(25)
11437 +#define S3C2443_DMAREQSEL_UART3_1 S3C2443_DMAREQSEL_SRC(26)
11438 +#define S3C2443_DMAREQSEL_PCMOUT S3C2443_DMAREQSEL_SRC(27)
11439 +#define S3C2443_DMAREQSEL_PCMIN S3C2443_DMAREQSEL_SRC(28)
11440 +#define S3C2443_DMAREQSEL_MICIN S3C2443_DMAREQSEL_SRC(29)
11441 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/regs-iis.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/regs-iis.h
11442 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/include/plat/regs-iis.h 1970-01-01 01:00:00.000000000 +0100
11443 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/include/plat/regs-iis.h 2009-05-10 22:27:59.000000000 +0200
11444 @@ -0,0 +1,77 @@
11445 +/* arch/arm/mach-s3c2410/include/mach/regs-iis.h
11446 + *
11447 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
11448 + * http://www.simtec.co.uk/products/SWLINUX/
11449 + *
11450 + * This program is free software; you can redistribute it and/or modify
11451 + * it under the terms of the GNU General Public License version 2 as
11452 + * published by the Free Software Foundation.
11453 + *
11454 + * S3C2410 IIS register definition
11455 +*/
11456 +
11457 +#ifndef __ASM_ARCH_REGS_IIS_H
11458 +#define __ASM_ARCH_REGS_IIS_H
11459 +
11460 +#define S3C2410_IISCON (0x00)
11461 +
11462 +#define S3C2410_IISCON_LRINDEX (1<<8)
11463 +#define S3C2410_IISCON_TXFIFORDY (1<<7)
11464 +#define S3C2410_IISCON_RXFIFORDY (1<<6)
11465 +#define S3C2410_IISCON_TXDMAEN (1<<5)
11466 +#define S3C2410_IISCON_RXDMAEN (1<<4)
11467 +#define S3C2410_IISCON_TXIDLE (1<<3)
11468 +#define S3C2410_IISCON_RXIDLE (1<<2)
11469 +#define S3C2410_IISCON_PSCEN (1<<1)
11470 +#define S3C2410_IISCON_IISEN (1<<0)
11471 +
11472 +#define S3C2410_IISMOD (0x04)
11473 +
11474 +#define S3C2440_IISMOD_MPLL (1<<9)
11475 +#define S3C2410_IISMOD_SLAVE (1<<8)
11476 +#define S3C2410_IISMOD_NOXFER (0<<6)
11477 +#define S3C2410_IISMOD_RXMODE (1<<6)
11478 +#define S3C2410_IISMOD_TXMODE (2<<6)
11479 +#define S3C2410_IISMOD_TXRXMODE (3<<6)
11480 +#define S3C2410_IISMOD_LR_LLOW (0<<5)
11481 +#define S3C2410_IISMOD_LR_RLOW (1<<5)
11482 +#define S3C2410_IISMOD_IIS (0<<4)
11483 +#define S3C2410_IISMOD_MSB (1<<4)
11484 +#define S3C2410_IISMOD_8BIT (0<<3)
11485 +#define S3C2410_IISMOD_16BIT (1<<3)
11486 +#define S3C2410_IISMOD_BITMASK (1<<3)
11487 +#define S3C2410_IISMOD_256FS (0<<2)
11488 +#define S3C2410_IISMOD_384FS (1<<2)
11489 +#define S3C2410_IISMOD_16FS (0<<0)
11490 +#define S3C2410_IISMOD_32FS (1<<0)
11491 +#define S3C2410_IISMOD_48FS (2<<0)
11492 +#define S3C2410_IISMOD_FS_MASK (3<<0)
11493 +
11494 +#define S3C2410_IISPSR (0x08)
11495 +#define S3C2410_IISPSR_INTMASK (31<<5)
11496 +#define S3C2410_IISPSR_INTSHIFT (5)
11497 +#define S3C2410_IISPSR_EXTMASK (31<<0)
11498 +#define S3C2410_IISPSR_EXTSHFIT (0)
11499 +
11500 +#define S3C2410_IISFCON (0x0c)
11501 +
11502 +#define S3C2410_IISFCON_TXDMA (1<<15)
11503 +#define S3C2410_IISFCON_RXDMA (1<<14)
11504 +#define S3C2410_IISFCON_TXENABLE (1<<13)
11505 +#define S3C2410_IISFCON_RXENABLE (1<<12)
11506 +#define S3C2410_IISFCON_TXMASK (0x3f << 6)
11507 +#define S3C2410_IISFCON_TXSHIFT (6)
11508 +#define S3C2410_IISFCON_RXMASK (0x3f)
11509 +#define S3C2410_IISFCON_RXSHIFT (0)
11510 +
11511 +#define S3C2400_IISFCON_TXDMA (1<<11)
11512 +#define S3C2400_IISFCON_RXDMA (1<<10)
11513 +#define S3C2400_IISFCON_TXENABLE (1<<9)
11514 +#define S3C2400_IISFCON_RXENABLE (1<<8)
11515 +#define S3C2400_IISFCON_TXMASK (0x07 << 4)
11516 +#define S3C2400_IISFCON_TXSHIFT (4)
11517 +#define S3C2400_IISFCON_RXMASK (0x07)
11518 +#define S3C2400_IISFCON_RXSHIFT (0)
11519 +
11520 +#define S3C2410_IISFIFO (0x10)
11521 +#endif /* __ASM_ARCH_REGS_IIS_H */
11522 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/irq.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/irq.c
11523 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/irq.c 2009-05-10 22:05:03.000000000 +0200
11524 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/irq.c 2009-05-10 22:27:59.000000000 +0200
11525 @@ -1,6 +1,6 @@
11526 /* linux/arch/arm/plat-s3c24xx/irq.c
11527 *
11528 - * Copyright (c) 2003,2004 Simtec Electronics
11529 + * Copyright (c) 2003,2004 Simtec Electronics
11530 * Ben Dooks <ben@simtec.co.uk>
11531 *
11532 * This program is free software; you can redistribute it and/or modify
11533 @@ -16,38 +16,6 @@
11534 * You should have received a copy of the GNU General Public License
11535 * along with this program; if not, write to the Free Software
11536 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
11537 - *
11538 - * Changelog:
11539 - *
11540 - * 22-Jul-2004 Ben Dooks <ben@simtec.co.uk>
11541 - * Fixed compile warnings
11542 - *
11543 - * 22-Jul-2004 Roc Wu <cooloney@yahoo.com.cn>
11544 - * Fixed s3c_extirq_type
11545 - *
11546 - * 21-Jul-2004 Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
11547 - * Addition of ADC/TC demux
11548 - *
11549 - * 04-Oct-2004 Klaus Fetscher <k.fetscher@fetron.de>
11550 - * Fix for set_irq_type() on low EINT numbers
11551 - *
11552 - * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
11553 - * Tidy up KF's patch and sort out new release
11554 - *
11555 - * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
11556 - * Add support for power management controls
11557 - *
11558 - * 04-Nov-2004 Ben Dooks
11559 - * Fix standard IRQ wake for EINT0..4 and RTC
11560 - *
11561 - * 22-Feb-2005 Ben Dooks
11562 - * Fixed edge-triggering on ADC IRQ
11563 - *
11564 - * 28-Jun-2005 Ben Dooks
11565 - * Mark IRQ_LCD valid
11566 - *
11567 - * 25-Jul-2005 Ben Dooks
11568 - * Split the S3C2440 IRQ code to separate file
11569 */
11570
11571 #include <linux/init.h>
11572 @@ -55,11 +23,8 @@
11573 #include <linux/interrupt.h>
11574 #include <linux/ioport.h>
11575 #include <linux/sysdev.h>
11576 -#include <linux/io.h>
11577
11578 -#include <mach/hardware.h>
11579 #include <asm/irq.h>
11580 -
11581 #include <asm/mach/irq.h>
11582
11583 #include <plat/regs-irqtype.h>
11584 @@ -70,76 +35,24 @@
11585 #include <plat/pm.h>
11586 #include <plat/irq.h>
11587
11588 -/* wakeup irq control */
11589 -
11590 -#ifdef CONFIG_PM
11591 -
11592 -/* state for IRQs over sleep */
11593 -
11594 -/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
11595 - *
11596 - * set bit to 1 in allow bitfield to enable the wakeup settings on it
11597 -*/
11598 -
11599 -unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
11600 -unsigned long s3c_irqwake_intmask = 0xffffffffL;
11601 -unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
11602 -unsigned long s3c_irqwake_eintmask = 0xffffffffL;
11603 -
11604 -int
11605 -s3c_irq_wake(unsigned int irqno, unsigned int state)
11606 -{
11607 - unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
11608 -
11609 - if (!(s3c_irqwake_intallow & irqbit))
11610 - return -ENOENT;
11611 -
11612 - printk(KERN_INFO "wake %s for irq %d\n",
11613 - state ? "enabled" : "disabled", irqno);
11614 -
11615 - if (!state)
11616 - s3c_irqwake_intmask |= irqbit;
11617 - else
11618 - s3c_irqwake_intmask &= ~irqbit;
11619 -
11620 - return 0;
11621 -}
11622 -
11623 -static int
11624 -s3c_irqext_wake(unsigned int irqno, unsigned int state)
11625 -{
11626 - unsigned long bit = 1L << (irqno - EXTINT_OFF);
11627 -
11628 - if (!(s3c_irqwake_eintallow & bit))
11629 - return -ENOENT;
11630 -
11631 - printk(KERN_INFO "wake %s for irq %d\n",
11632 - state ? "enabled" : "disabled", irqno);
11633 -
11634 - if (!state)
11635 - s3c_irqwake_eintmask |= bit;
11636 - else
11637 - s3c_irqwake_eintmask &= ~bit;
11638 -
11639 - return 0;
11640 -}
11641 -
11642 -#else
11643 -#define s3c_irqext_wake NULL
11644 -#define s3c_irq_wake NULL
11645 -#endif
11646 -
11647 -
11648 static void
11649 s3c_irq_mask(unsigned int irqno)
11650 {
11651 unsigned long mask;
11652 -
11653 +#ifdef CONFIG_S3C2440_C_FIQ
11654 + unsigned long flags;
11655 +#endif
11656 irqno -= IRQ_EINT0;
11657 -
11658 +#ifdef CONFIG_S3C2440_C_FIQ
11659 + local_save_flags(flags);
11660 + local_fiq_disable();
11661 +#endif
11662 mask = __raw_readl(S3C2410_INTMSK);
11663 mask |= 1UL << irqno;
11664 __raw_writel(mask, S3C2410_INTMSK);
11665 +#ifdef CONFIG_S3C2440_C_FIQ
11666 + local_irq_restore(flags);
11667 +#endif
11668 }
11669
11670 static inline void
11671 @@ -156,9 +69,19 @@
11672 {
11673 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
11674 unsigned long mask;
11675 +#ifdef CONFIG_S3C2440_C_FIQ
11676 + unsigned long flags;
11677 +#endif
11678
11679 +#ifdef CONFIG_S3C2440_C_FIQ
11680 + local_save_flags(flags);
11681 + local_fiq_disable();
11682 +#endif
11683 mask = __raw_readl(S3C2410_INTMSK);
11684 __raw_writel(mask|bitval, S3C2410_INTMSK);
11685 +#ifdef CONFIG_S3C2440_C_FIQ
11686 + local_irq_restore(flags);
11687 +#endif
11688
11689 __raw_writel(bitval, S3C2410_SRCPND);
11690 __raw_writel(bitval, S3C2410_INTPND);
11691 @@ -169,15 +92,25 @@
11692 s3c_irq_unmask(unsigned int irqno)
11693 {
11694 unsigned long mask;
11695 +#ifdef CONFIG_S3C2440_C_FIQ
11696 + unsigned long flags;
11697 +#endif
11698
11699 if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
11700 irqdbf2("s3c_irq_unmask %d\n", irqno);
11701
11702 irqno -= IRQ_EINT0;
11703
11704 +#ifdef CONFIG_S3C2440_C_FIQ
11705 + local_save_flags(flags);
11706 + local_fiq_disable();
11707 +#endif
11708 mask = __raw_readl(S3C2410_INTMSK);
11709 mask &= ~(1UL << irqno);
11710 __raw_writel(mask, S3C2410_INTMSK);
11711 +#ifdef CONFIG_S3C2440_C_FIQ
11712 + local_irq_restore(flags);
11713 +#endif
11714 }
11715
11716 struct irq_chip s3c_irq_level_chip = {
11717 @@ -590,59 +523,6 @@
11718 }
11719 }
11720
11721 -#ifdef CONFIG_PM
11722 -
11723 -static struct sleep_save irq_save[] = {
11724 - SAVE_ITEM(S3C2410_INTMSK),
11725 - SAVE_ITEM(S3C2410_INTSUBMSK),
11726 -};
11727 -
11728 -/* the extint values move between the s3c2410/s3c2440 and the s3c2412
11729 - * so we use an array to hold them, and to calculate the address of
11730 - * the register at run-time
11731 -*/
11732 -
11733 -static unsigned long save_extint[3];
11734 -static unsigned long save_eintflt[4];
11735 -static unsigned long save_eintmask;
11736 -
11737 -int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
11738 -{
11739 - unsigned int i;
11740 -
11741 - for (i = 0; i < ARRAY_SIZE(save_extint); i++)
11742 - save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
11743 -
11744 - for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
11745 - save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
11746 -
11747 - s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
11748 - save_eintmask = __raw_readl(S3C24XX_EINTMASK);
11749 -
11750 - return 0;
11751 -}
11752 -
11753 -int s3c24xx_irq_resume(struct sys_device *dev)
11754 -{
11755 - unsigned int i;
11756 -
11757 - for (i = 0; i < ARRAY_SIZE(save_extint); i++)
11758 - __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
11759 -
11760 - for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
11761 - __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
11762 -
11763 - s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
11764 - __raw_writel(save_eintmask, S3C24XX_EINTMASK);
11765 -
11766 - return 0;
11767 -}
11768 -
11769 -#else
11770 -#define s3c24xx_irq_suspend NULL
11771 -#define s3c24xx_irq_resume NULL
11772 -#endif
11773 -
11774 /* s3c24xx_init_irq
11775 *
11776 * Initialise S3C2410 IRQ system
11777 @@ -673,26 +553,26 @@
11778
11779 last = 0;
11780 for (i = 0; i < 4; i++) {
11781 - pend = __raw_readl(S3C2410_INTPND);
11782 + pend = __raw_readl(S3C2410_SUBSRCPND);
11783
11784 if (pend == 0 || pend == last)
11785 break;
11786
11787 - __raw_writel(pend, S3C2410_SRCPND);
11788 - __raw_writel(pend, S3C2410_INTPND);
11789 - printk("irq: clearing pending status %08x\n", (int)pend);
11790 + printk("irq: clearing subpending status %08x\n", (int)pend);
11791 + __raw_writel(pend, S3C2410_SUBSRCPND);
11792 last = pend;
11793 }
11794
11795 last = 0;
11796 for (i = 0; i < 4; i++) {
11797 - pend = __raw_readl(S3C2410_SUBSRCPND);
11798 + pend = __raw_readl(S3C2410_INTPND);
11799
11800 if (pend == 0 || pend == last)
11801 break;
11802
11803 - printk("irq: clearing subpending status %08x\n", (int)pend);
11804 - __raw_writel(pend, S3C2410_SUBSRCPND);
11805 + __raw_writel(pend, S3C2410_SRCPND);
11806 + __raw_writel(pend, S3C2410_INTPND);
11807 + printk("irq: clearing pending status %08x\n", (int)pend);
11808 last = pend;
11809 }
11810
11811 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/irq-pm.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/irq-pm.c
11812 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/irq-pm.c 1970-01-01 01:00:00.000000000 +0100
11813 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/irq-pm.c 2009-05-10 22:27:59.000000000 +0200
11814 @@ -0,0 +1,118 @@
11815 +/* linux/arch/arm/plat-s3c24xx/irq-om.c
11816 + *
11817 + * Copyright (c) 2003,2004 Simtec Electronics
11818 + * Ben Dooks <ben@simtec.co.uk>
11819 + * http://armlinux.simtec.co.uk/
11820 + *
11821 + * S3C24XX - IRQ PM code
11822 + *
11823 + * This program is free software; you can redistribute it and/or modify
11824 + * it under the terms of the GNU General Public License version 2 as
11825 + * published by the Free Software Foundation.
11826 + */
11827 +
11828 +#include <linux/init.h>
11829 +#include <linux/module.h>
11830 +#include <linux/interrupt.h>
11831 +#include <linux/sysdev.h>
11832 +#include <linux/irq.h>
11833 +
11834 +#include <plat/cpu.h>
11835 +#include <plat/pm.h>
11836 +#include <plat/irq.h>
11837 +
11838 +/* state for IRQs over sleep */
11839 +
11840 +/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
11841 + *
11842 + * set bit to 1 in allow bitfield to enable the wakeup settings on it
11843 +*/
11844 +
11845 +unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
11846 +unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
11847 +
11848 +int s3c_irq_wake(unsigned int irqno, unsigned int state)
11849 +{
11850 + unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
11851 +
11852 + if (!(s3c_irqwake_intallow & irqbit))
11853 + return -ENOENT;
11854 +
11855 + printk(KERN_INFO "wake %s for irq %d\n",
11856 + state ? "enabled" : "disabled", irqno);
11857 +
11858 + if (!state)
11859 + s3c_irqwake_intmask |= irqbit;
11860 + else
11861 + s3c_irqwake_intmask &= ~irqbit;
11862 +
11863 + return 0;
11864 +}
11865 +
11866 +static struct sleep_save irq_save[] = {
11867 + SAVE_ITEM(S3C2410_INTMSK),
11868 + SAVE_ITEM(S3C2410_INTSUBMSK),
11869 +};
11870 +
11871 +/* the extint values move between the s3c2410/s3c2440 and the s3c2412
11872 + * so we use an array to hold them, and to calculate the address of
11873 + * the register at run-time
11874 +*/
11875 +
11876 +static unsigned long save_extint[3];
11877 +static unsigned long save_eintflt[4];
11878 +static unsigned long save_eintmask;
11879 +
11880 +int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
11881 +{
11882 + unsigned int i;
11883 +
11884 + for (i = 0; i < ARRAY_SIZE(save_extint); i++)
11885 + save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
11886 +
11887 + for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
11888 + save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
11889 +
11890 + s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
11891 + save_eintmask = __raw_readl(S3C24XX_EINTMASK);
11892 +
11893 + return 0;
11894 +}
11895 +
11896 +int s3c24xx_irq_resume(struct sys_device *dev)
11897 +{
11898 + unsigned int i, irq;
11899 + unsigned long eintpnd;
11900 + struct irq_desc *desc;
11901 +
11902 + for (i = 0; i < ARRAY_SIZE(save_extint); i++)
11903 + __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
11904 +
11905 + for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
11906 + __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
11907 +
11908 + s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
11909 + __raw_writel(save_eintmask, S3C24XX_EINTMASK);
11910 +
11911 + /*
11912 + * ACK those interrupts which are now masked and pending.
11913 + * Level interrupts if not ACKed here, create an interrupt storm
11914 + * because they are not handled at all.
11915 + */
11916 +
11917 + eintpnd = __raw_readl(S3C24XX_EINTPEND);
11918 +
11919 + eintpnd &= save_eintmask;
11920 + eintpnd &= ~0xff; /* ignore lower irqs */
11921 +
11922 + while (eintpnd) {
11923 + irq = __ffs(eintpnd);
11924 + eintpnd &= ~(1 << irq);
11925 +
11926 + irq += (IRQ_EINT4 - 4);
11927 + desc = irq_to_desc(irq);
11928 + desc->chip->ack(irq);
11929 + }
11930 +
11931 + return 0;
11932 +}
11933 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/Kconfig linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/Kconfig
11934 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/Kconfig 2009-05-10 22:05:03.000000000 +0200
11935 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/Kconfig 2009-05-10 22:27:59.000000000 +0200
11936 @@ -10,6 +10,7 @@
11937 default y
11938 select NO_IOPORT
11939 select ARCH_REQUIRE_GPIOLIB
11940 + select S3C_GPIO_TRACK
11941 help
11942 Base platform code for any Samsung S3C24XX device
11943
11944 @@ -30,7 +31,7 @@
11945
11946 config CPU_S3C244X
11947 bool
11948 - depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
11949 + default y if CPU_S3C2440 || CPU_S3C2442
11950 help
11951 Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
11952
11953 @@ -71,6 +72,7 @@
11954 config S3C2410_DMA
11955 bool "S3C2410 DMA support"
11956 depends on ARCH_S3C2410
11957 + select S3C_DMA
11958 help
11959 S3C2410 DMA support. This is needed for drivers like sound which
11960 use the S3C2410's DMA system to move data to and from the
11961 @@ -111,4 +113,12 @@
11962 help
11963 Common machine code for SMDK2410 and SMDK2440
11964
11965 +config MACH_NEO1973
11966 + bool
11967 + select RFKILL
11968 + select SERIAL_SAMSUNG
11969 + select SERIAL_SAMSUNG_CONSOLE
11970 + help
11971 + Common machine code for Neo1973 hardware
11972 +
11973 endif
11974 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/Makefile linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/Makefile
11975 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/Makefile 2009-05-10 22:05:03.000000000 +0200
11976 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/Makefile 2009-05-10 22:27:59.000000000 +0200
11977 @@ -27,6 +27,7 @@
11978 obj-$(CONFIG_CPU_S3C244X) += s3c244x-clock.o
11979 obj-$(CONFIG_PM_SIMTEC) += pm-simtec.o
11980 obj-$(CONFIG_PM) += pm.o
11981 +obj-$(CONFIG_PM) += irq-pm.o
11982 obj-$(CONFIG_PM) += sleep.o
11983 obj-$(CONFIG_HAVE_PWM) += pwm.o
11984 obj-$(CONFIG_S3C2410_CLOCK) += s3c2410-clock.o
11985 @@ -44,3 +45,9 @@
11986 # machine common support
11987
11988 obj-$(CONFIG_MACH_SMDK) += common-smdk.o
11989 +obj-$(CONFIG_MACH_NEO1973) += \
11990 + neo1973_pm_gsm.o \
11991 + neo1973_pm_gps.o \
11992 + neo1973_pm_bt.o \
11993 + gta02_pm_wlan.o \
11994 + neo1973_shadow.o
11995 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_pm_bt.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
11996 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_pm_bt.c 1970-01-01 01:00:00.000000000 +0100
11997 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_pm_bt.c 2009-05-10 22:27:59.000000000 +0200
11998 @@ -0,0 +1,339 @@
11999 +/*
12000 + * Bluetooth PM code for the FIC Neo1973 GSM Phone
12001 + *
12002 + * (C) 2007 by Openmoko Inc.
12003 + * Author: Harald Welte <laforge@openmoko.org>
12004 + * All rights reserved.
12005 + *
12006 + * This program is free software; you can redistribute it and/or modify
12007 + * it under the terms of the GNU General Public License version 2 as
12008 + * published by the Free Software Foundation
12009 + *
12010 + */
12011 +
12012 +#include <linux/module.h>
12013 +#include <linux/init.h>
12014 +#include <linux/kernel.h>
12015 +#include <linux/platform_device.h>
12016 +#include <linux/rfkill.h>
12017 +#include <linux/err.h>
12018 +
12019 +#include <mach/hardware.h>
12020 +#include <asm/mach-types.h>
12021 +#include <asm/plat-s3c24xx/neo1973.h>
12022 +
12023 +/* For GTA01 */
12024 +#include <mach/gta01.h>
12025 +#include <linux/pcf50606.h>
12026 +
12027 +/* For GTA02 */
12028 +#include <mach/gta02.h>
12029 +#include <linux/mfd/pcf50633/gpio.h>
12030 +
12031 +#include <linux/regulator/consumer.h>
12032 +
12033 +#define DRVMSG "FIC Neo1973 Bluetooth Power Management"
12034 +
12035 +struct gta01_pm_bt_data {
12036 + struct regulator *regulator;
12037 + struct rfkill *rfkill;
12038 + int pre_resume_state;
12039 +};
12040 +
12041 +static ssize_t bt_read(struct device *dev, struct device_attribute *attr,
12042 + char *buf)
12043 +{
12044 + int ret = 0;
12045 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev);
12046 +
12047 + if (!strcmp(attr->attr.name, "power_on")) {
12048 + if (machine_is_neo1973_gta01()) {
12049 + ret = regulator_is_enabled(bt_data->regulator);
12050 + } else if (machine_is_neo1973_gta02()) {
12051 + if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN))
12052 + ret = 1;
12053 + }
12054 + } else if (!strcmp(attr->attr.name, "reset")) {
12055 + if (machine_is_neo1973_gta01()) {
12056 + if (s3c2410_gpio_getpin(GTA01_GPIO_BT_EN) == 0)
12057 + ret = 1;
12058 + } else if (machine_is_neo1973_gta02()) {
12059 + if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN) == 0)
12060 + ret = 1;
12061 + }
12062 + }
12063 +
12064 + if (!ret) {
12065 + return strlcpy(buf, "0\n", 3);
12066 + } else {
12067 + return strlcpy(buf, "1\n", 3);
12068 + }
12069 +}
12070 +
12071 +static void __gta02_pm_bt_toggle_radio(struct device *dev, unsigned int on)
12072 +{
12073 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev);
12074 +
12075 + dev_info(dev, "__gta02_pm_bt_toggle_radio %d\n", on);
12076 +
12077 + if (machine_is_neo1973_gta02()) {
12078 +
12079 + bt_data = dev_get_drvdata(dev);
12080 +
12081 + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, !on);
12082 +
12083 + if (on) {
12084 + if (!regulator_is_enabled(bt_data->regulator))
12085 + regulator_enable(bt_data->regulator);
12086 + } else {
12087 + if (regulator_is_enabled(bt_data->regulator))
12088 + regulator_disable(bt_data->regulator);
12089 + }
12090 +
12091 + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on);
12092 + }
12093 +}
12094 +
12095 +
12096 +static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state)
12097 +{
12098 + struct device *dev = data;
12099 + unsigned long on = (state == RFKILL_STATE_ON);
12100 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev);
12101 +
12102 + if (machine_is_neo1973_gta01()) {
12103 + /* if we are powering up, assert reset, then power,
12104 + * then release reset */
12105 + if (on) {
12106 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, 0);
12107 + if (!regulator_is_enabled(bt_data->regulator))
12108 + regulator_enable(bt_data->regulator);
12109 + } else {
12110 + if (regulator_is_enabled(bt_data->regulator))
12111 + regulator_disable(bt_data->regulator);
12112 + }
12113 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, on);
12114 + } else if (machine_is_neo1973_gta02())
12115 + __gta02_pm_bt_toggle_radio(dev, on);
12116 +
12117 + return 0;
12118 +}
12119 +
12120 +static ssize_t bt_write(struct device *dev, struct device_attribute *attr,
12121 + const char *buf, size_t count)
12122 +{
12123 + unsigned long on = simple_strtoul(buf, NULL, 10);
12124 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev);
12125 +
12126 + if (!strcmp(attr->attr.name, "power_on")) {
12127 + enum rfkill_state state = on ? RFKILL_STATE_ON : RFKILL_STATE_OFF;
12128 + bt_rfkill_toggle_radio(dev, state);
12129 + bt_data->rfkill->state = state;
12130 +
12131 + if (machine_is_neo1973_gta01()) {
12132 + /* if we are powering up, assert reset, then power,
12133 + * then release reset */
12134 + if (on) {
12135 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, 0);
12136 + if (!regulator_is_enabled(bt_data->regulator))
12137 + regulator_enable(bt_data->regulator);
12138 + } else {
12139 + if (regulator_is_enabled(bt_data->regulator))
12140 + regulator_disable(bt_data->regulator);
12141 + }
12142 +
12143 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, on);
12144 + } else if (machine_is_neo1973_gta02())
12145 + __gta02_pm_bt_toggle_radio(dev, on);
12146 +
12147 + } else if (!strcmp(attr->attr.name, "reset")) {
12148 + /* reset is low-active, so we need to invert */
12149 + if (machine_is_neo1973_gta01()) {
12150 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, on ? 0 : 1);
12151 + } else if (machine_is_neo1973_gta02()) {
12152 + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on ? 0 : 1);
12153 + }
12154 + }
12155 +
12156 + return count;
12157 +}
12158 +
12159 +static DEVICE_ATTR(power_on, 0644, bt_read, bt_write);
12160 +static DEVICE_ATTR(reset, 0644, bt_read, bt_write);
12161 +
12162 +#ifdef CONFIG_PM
12163 +static int gta01_bt_suspend(struct platform_device *pdev, pm_message_t state)
12164 +{
12165 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev);
12166 +
12167 + dev_dbg(&pdev->dev, DRVMSG ": suspending\n");
12168 +
12169 + if (machine_is_neo1973_gta01()) {
12170 + if (regulator_is_enabled(bt_data->regulator))
12171 + regulator_disable(bt_data->regulator);
12172 + } else if (machine_is_neo1973_gta02()) {
12173 + bt_data->pre_resume_state =
12174 + s3c2410_gpio_getpin(GTA02_GPIO_BT_EN);
12175 + __gta02_pm_bt_toggle_radio(&pdev->dev, 0);
12176 + }
12177 +
12178 + return 0;
12179 +}
12180 +
12181 +static int gta01_bt_resume(struct platform_device *pdev)
12182 +{
12183 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev);
12184 + dev_dbg(&pdev->dev, DRVMSG ": resuming\n");
12185 +
12186 + if (machine_is_neo1973_gta02()) {
12187 + __gta02_pm_bt_toggle_radio(&pdev->dev,
12188 + bt_data->pre_resume_state);
12189 + }
12190 +
12191 + return 0;
12192 +}
12193 +#else
12194 +#define gta01_bt_suspend NULL
12195 +#define gta01_bt_resume NULL
12196 +#endif
12197 +
12198 +static struct attribute *gta01_bt_sysfs_entries[] = {
12199 + &dev_attr_power_on.attr,
12200 + &dev_attr_reset.attr,
12201 + NULL
12202 +};
12203 +
12204 +static struct attribute_group gta01_bt_attr_group = {
12205 + .name = NULL,
12206 + .attrs = gta01_bt_sysfs_entries,
12207 +};
12208 +
12209 +static int __init gta01_bt_probe(struct platform_device *pdev)
12210 +{
12211 + struct rfkill *rfkill;
12212 + struct regulator *regulator;
12213 + struct gta01_pm_bt_data *bt_data;
12214 + int ret;
12215 +
12216 + dev_info(&pdev->dev, DRVMSG ": starting\n");
12217 +
12218 + bt_data = kzalloc(sizeof(*bt_data), GFP_KERNEL);
12219 + dev_set_drvdata(&pdev->dev, bt_data);
12220 +
12221 + if (machine_is_neo1973_gta01()) {
12222 + /* we make sure that the voltage is off */
12223 + regulator = regulator_get(&pdev->dev, "BT_3V1");
12224 + if (IS_ERR(regulator))
12225 + return -ENODEV;
12226 +
12227 + bt_data->regulator = regulator;
12228 +
12229 + /* this tests the true physical state of the regulator... */
12230 + if (regulator_is_enabled(regulator)) {
12231 + /*
12232 + * but these only operate on the logical state of the
12233 + * regulator... so we need to logicaly "adopt" it on
12234 + * to turn it off
12235 + */
12236 + regulator_enable(regulator);
12237 + regulator_disable(regulator);
12238 + }
12239 +
12240 + /* we pull reset to low to make sure that the chip doesn't
12241 + * drain power through the reset line */
12242 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, 0);
12243 + } else if (machine_is_neo1973_gta02()) {
12244 + regulator = regulator_get(&pdev->dev, "BT_3V2");
12245 + if (IS_ERR(regulator))
12246 + return -ENODEV;
12247 +
12248 + bt_data->regulator = regulator;
12249 +
12250 + /* this tests the true physical state of the regulator... */
12251 + if (regulator_is_enabled(regulator)) {
12252 + /*
12253 + * but these only operate on the logical state of the
12254 + * regulator... so we need to logicaly "adopt" it on
12255 + * to turn it off
12256 + */
12257 + regulator_enable(regulator);
12258 + regulator_disable(regulator);
12259 + }
12260 +
12261 + /* we pull reset to low to make sure that the chip doesn't
12262 + * drain power through the reset line */
12263 + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, 0);
12264 + }
12265 +
12266 + rfkill = rfkill_allocate(&pdev->dev, RFKILL_TYPE_BLUETOOTH);
12267 +
12268 + rfkill->name = pdev->name;
12269 + rfkill->data = &pdev->dev;
12270 + rfkill->state = RFKILL_STATE_OFF;
12271 + rfkill->toggle_radio = bt_rfkill_toggle_radio;
12272 +
12273 + ret = rfkill_register(rfkill);
12274 + if (ret) {
12275 + dev_err(&pdev->dev, "Failed to register rfkill\n");
12276 + return ret;
12277 + }
12278 +
12279 + bt_data->rfkill = rfkill;
12280 +
12281 + return sysfs_create_group(&pdev->dev.kobj, &gta01_bt_attr_group);
12282 +}
12283 +
12284 +static int gta01_bt_remove(struct platform_device *pdev)
12285 +{
12286 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev);
12287 + struct regulator *regulator;
12288 +
12289 + sysfs_remove_group(&pdev->dev.kobj, &gta01_bt_attr_group);
12290 +
12291 + if (bt_data->rfkill) {
12292 + rfkill_unregister(bt_data->rfkill);
12293 + rfkill_free(bt_data->rfkill);
12294 + }
12295 +
12296 + if (!bt_data || !bt_data->regulator)
12297 + return 0;
12298 +
12299 + regulator = bt_data->regulator;
12300 +
12301 + /* Make sure regulator is disabled before calling regulator_put */
12302 + if (regulator_is_enabled(regulator))
12303 + regulator_disable(regulator);
12304 +
12305 + regulator_put(regulator);
12306 +
12307 + kfree(bt_data);
12308 +
12309 + return 0;
12310 +}
12311 +
12312 +static struct platform_driver gta01_bt_driver = {
12313 + .probe = gta01_bt_probe,
12314 + .remove = gta01_bt_remove,
12315 + .suspend = gta01_bt_suspend,
12316 + .resume = gta01_bt_resume,
12317 + .driver = {
12318 + .name = "neo1973-pm-bt",
12319 + },
12320 +};
12321 +
12322 +static int __devinit gta01_bt_init(void)
12323 +{
12324 + return platform_driver_register(&gta01_bt_driver);
12325 +}
12326 +
12327 +static void gta01_bt_exit(void)
12328 +{
12329 + platform_driver_unregister(&gta01_bt_driver);
12330 +}
12331 +
12332 +module_init(gta01_bt_init);
12333 +module_exit(gta01_bt_exit);
12334 +
12335 +MODULE_LICENSE("GPL");
12336 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
12337 +MODULE_DESCRIPTION(DRVMSG);
12338 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_pm_gps.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
12339 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_pm_gps.c 1970-01-01 01:00:00.000000000 +0100
12340 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_pm_gps.c 2009-05-10 22:27:59.000000000 +0200
12341 @@ -0,0 +1,803 @@
12342 +/*
12343 + * GPS Power Management code for the FIC Neo1973 GSM Phone
12344 + *
12345 + * (C) 2007-2009 by Openmoko Inc.
12346 + * Author: Harald Welte <laforge@openmoko.org>
12347 + * All rights reserved.
12348 + *
12349 + * This program is free software; you can redistribute it and/or modify
12350 + * it under the terms of the GNU General Public License version 2 as
12351 + * published by the Free Software Foundation
12352 + *
12353 + */
12354 +
12355 +#include <linux/module.h>
12356 +#include <linux/init.h>
12357 +#include <linux/kernel.h>
12358 +#include <linux/delay.h>
12359 +#include <linux/platform_device.h>
12360 +
12361 +#include <mach/hardware.h>
12362 +#include <mach/cpu.h>
12363 +
12364 +#include <asm/mach-types.h>
12365 +
12366 +#include <asm/plat-s3c24xx/neo1973.h>
12367 +
12368 +/* For GTA01 */
12369 +#include <mach/gta01.h>
12370 +#include <linux/mfd/pcf50606/core.h>
12371 +#include <linux/mfd/pcf50606/gpo.h>
12372 +
12373 +/* For GTA02 */
12374 +#include <mach/gta02.h>
12375 +#include <linux/mfd/pcf50633/core.h>
12376 +#include <linux/mfd/pcf50633/pmic.h>
12377 +
12378 +#include <linux/regulator/consumer.h>
12379 +#include <linux/err.h>
12380 +
12381 +enum gta01_pm_gps_supplies {
12382 +
12383 + /* GTA01 */
12384 + GTA01_GPS_REG_2V8,
12385 + GTA01_GPS_REG_3V,
12386 + GTA01_GPS_REG_3V3,
12387 + GTA01_GPS_REG_1V5,
12388 + GTA01_GPS_REG_2V5,
12389 +
12390 + /* GTA02 */
12391 + GTA02_GPS_REG_RF_3V,
12392 +
12393 + /* Always last */
12394 + GTA01_GPS_NUM_REG
12395 +};
12396 +
12397 +struct neo1973_pm_gps_data {
12398 +#ifdef CONFIG_PM
12399 + int keep_on_in_suspend;
12400 +#endif
12401 + int power_was_on; /* For GTA02 only */
12402 + int regulator_state[GTA01_GPS_NUM_REG];
12403 + struct regulator *regulator[GTA01_GPS_NUM_REG];
12404 +};
12405 +
12406 +static struct neo1973_pm_gps_data neo1973_gps;
12407 +
12408 +int neo1973_pm_gps_is_on(void)
12409 +{
12410 + return neo1973_gps.power_was_on;
12411 +}
12412 +EXPORT_SYMBOL_GPL(neo1973_pm_gps_is_on);
12413 +
12414 +#ifdef CONFIG_MACH_NEO1973_GTA01
12415 +
12416 +/* This is the 2.8V supply for the RTC crystal, the mail clock crystal and
12417 + * the input to VDD_RF */
12418 +static void gps_power_2v8_set(int on)
12419 +{
12420 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V8];
12421 +
12422 + switch (S3C_SYSTEM_REV_ATAG) {
12423 + case GTA01v3_SYSTEM_REV:
12424 + case GTA01v4_SYSTEM_REV:
12425 + if (on)
12426 + regulator_enable(regulator);
12427 + else
12428 + regulator_disable(regulator);
12429 + neo1973_gps.regulator_state[GTA01_GPS_REG_2V8] = on;
12430 + break;
12431 + case GTA01Bv2_SYSTEM_REV:
12432 + s3c2410_gpio_setpin(GTA01_GPIO_GPS_EN_2V8, on);
12433 + break;
12434 + case GTA01Bv3_SYSTEM_REV:
12435 + case GTA01Bv4_SYSTEM_REV:
12436 + break;
12437 + }
12438 +}
12439 +
12440 +static int gps_power_2v8_get(void)
12441 +{
12442 + int ret = 0;
12443 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V8];
12444 +
12445 + switch (S3C_SYSTEM_REV_ATAG) {
12446 + case GTA01v3_SYSTEM_REV:
12447 + case GTA01v4_SYSTEM_REV:
12448 + ret = regulator_is_enabled(regulator);
12449 + break;
12450 + case GTA01Bv2_SYSTEM_REV:
12451 + if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_EN_2V8))
12452 + ret = 1;
12453 + break;
12454 + case GTA01Bv3_SYSTEM_REV:
12455 + case GTA01Bv4_SYSTEM_REV:
12456 + break;
12457 + }
12458 +
12459 + return ret;
12460 +}
12461 +
12462 +/* This is the 3V supply (AVDD) for the external RF frontend (LNA bias) */
12463 +static void gps_power_3v_set(int on)
12464 +{
12465 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V];
12466 +
12467 + switch (S3C_SYSTEM_REV_ATAG) {
12468 + case GTA01v3_SYSTEM_REV:
12469 + case GTA01v4_SYSTEM_REV:
12470 + if (on)
12471 + regulator_enable(regulator);
12472 + else
12473 + regulator_disable(regulator);
12474 + neo1973_gps.regulator_state[GTA01_GPS_REG_3V] = on;
12475 + break;
12476 + case GTA01Bv2_SYSTEM_REV:
12477 + case GTA01Bv3_SYSTEM_REV:
12478 + case GTA01Bv4_SYSTEM_REV:
12479 + s3c2410_gpio_setpin(GTA01_GPIO_GPS_EN_3V, on);
12480 + break;
12481 + }
12482 +}
12483 +
12484 +static int gps_power_3v_get(void)
12485 +{
12486 + int ret = 0;
12487 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V];
12488 +
12489 + switch (S3C_SYSTEM_REV_ATAG) {
12490 + case GTA01v3_SYSTEM_REV:
12491 + case GTA01v4_SYSTEM_REV:
12492 + ret = regulator_is_enabled(regulator);
12493 + break;
12494 + case GTA01Bv2_SYSTEM_REV:
12495 + case GTA01Bv3_SYSTEM_REV:
12496 + case GTA01Bv4_SYSTEM_REV:
12497 + if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_EN_3V))
12498 + ret = 1;
12499 + break;
12500 + }
12501 +
12502 + return ret;
12503 +}
12504 +
12505 +/* This is the 3.3V supply for VDD_IO and VDD_LPREG input */
12506 +static void gps_power_3v3_set(int on)
12507 +{
12508 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V3];
12509 +
12510 + switch (S3C_SYSTEM_REV_ATAG) {
12511 + case GTA01v3_SYSTEM_REV:
12512 + case GTA01v4_SYSTEM_REV:
12513 + case GTA01Bv2_SYSTEM_REV:
12514 + if (on)
12515 + regulator_enable(regulator);
12516 + else
12517 + regulator_disable(regulator);
12518 + neo1973_gps.regulator_state[GTA01_GPS_REG_3V3] = on;
12519 + break;
12520 + case GTA01Bv3_SYSTEM_REV:
12521 + case GTA01Bv4_SYSTEM_REV:
12522 + s3c2410_gpio_setpin(GTA01_GPIO_GPS_EN_3V3, on);
12523 + break;
12524 + }
12525 +}
12526 +
12527 +static int gps_power_3v3_get(void)
12528 +{
12529 + int ret = 0;
12530 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V3];
12531 +
12532 + switch (S3C_SYSTEM_REV_ATAG) {
12533 + case GTA01v3_SYSTEM_REV:
12534 + case GTA01v4_SYSTEM_REV:
12535 + case GTA01Bv2_SYSTEM_REV:
12536 + ret = regulator_is_enabled(regulator);
12537 + break;
12538 + case GTA01Bv3_SYSTEM_REV:
12539 + case GTA01Bv4_SYSTEM_REV:
12540 + if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_EN_3V3))
12541 + ret = 1;
12542 + break;
12543 + }
12544 +
12545 + return ret;
12546 +}
12547 +
12548 +/* This is the 2.5V supply for VDD_PLLREG and VDD_COREREG input */
12549 +static void gps_power_2v5_set(int on)
12550 +{
12551 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V5];
12552 +
12553 + switch (S3C_SYSTEM_REV_ATAG) {
12554 + case GTA01v3_SYSTEM_REV:
12555 + /* This is CORE_1V8 and cannot be disabled */
12556 + break;
12557 + case GTA01v4_SYSTEM_REV:
12558 + case GTA01Bv2_SYSTEM_REV:
12559 + case GTA01Bv3_SYSTEM_REV:
12560 + case GTA01Bv4_SYSTEM_REV:
12561 + if (on)
12562 + regulator_enable(regulator);
12563 + else
12564 + regulator_disable(regulator);
12565 + neo1973_gps.regulator_state[GTA01_GPS_REG_2V5] = on;
12566 + break;
12567 + }
12568 +}
12569 +
12570 +static int gps_power_2v5_get(void)
12571 +{
12572 + int ret = 0;
12573 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V5];
12574 +
12575 + switch (S3C_SYSTEM_REV_ATAG) {
12576 + case GTA01v3_SYSTEM_REV:
12577 + /* This is CORE_1V8 and cannot be disabled */
12578 + ret = 1;
12579 + break;
12580 + case GTA01v4_SYSTEM_REV:
12581 + case GTA01Bv2_SYSTEM_REV:
12582 + case GTA01Bv3_SYSTEM_REV:
12583 + case GTA01Bv4_SYSTEM_REV:
12584 + ret = regulator_is_enabled(regulator);
12585 + break;
12586 + }
12587 +
12588 + return ret;
12589 +}
12590 +
12591 +/* This is the 1.5V supply for VDD_CORE */
12592 +static void gps_power_1v5_set(int on)
12593 +{
12594 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_1V5];
12595 +
12596 + switch (S3C_SYSTEM_REV_ATAG) {
12597 + case GTA01v3_SYSTEM_REV:
12598 + case GTA01v4_SYSTEM_REV:
12599 + case GTA01Bv2_SYSTEM_REV:
12600 + /* This is switched via 2v5 */
12601 + break;
12602 + case GTA01Bv3_SYSTEM_REV:
12603 + case GTA01Bv4_SYSTEM_REV:
12604 + if (on)
12605 + regulator_enable(regulator);
12606 + else
12607 + regulator_disable(regulator);
12608 + neo1973_gps.regulator_state[GTA01_GPS_REG_1V5] = on;
12609 + break;
12610 + }
12611 +}
12612 +
12613 +static int gps_power_1v5_get(void)
12614 +{
12615 + int ret = 0;
12616 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_1V5];
12617 +
12618 + switch (S3C_SYSTEM_REV_ATAG) {
12619 + case GTA01v3_SYSTEM_REV:
12620 + case GTA01v4_SYSTEM_REV:
12621 + case GTA01Bv2_SYSTEM_REV:
12622 + /* This is switched via 2v5 */
12623 + ret = 1;
12624 + break;
12625 + case GTA01Bv3_SYSTEM_REV:
12626 + case GTA01Bv4_SYSTEM_REV:
12627 + ret = regulator_is_enabled(regulator);
12628 + break;
12629 + }
12630 +
12631 + return ret;
12632 +}
12633 +#endif
12634 +
12635 +/* This is the POWERON pin */
12636 +static void gps_pwron_set(int on)
12637 +{
12638 +
12639 + if (machine_is_neo1973_gta01())
12640 + neo1973_gpb_setpin(GTA01_GPIO_GPS_PWRON, on);
12641 +
12642 + if (machine_is_neo1973_gta02()) {
12643 + if (on) {
12644 + /* return UART pins to being UART pins */
12645 + s3c2410_gpio_cfgpin(S3C2410_GPH4, S3C2410_GPH4_TXD1);
12646 + /* remove pulldown now it won't be floating any more */
12647 + s3c2410_gpio_pullup(S3C2410_GPH5, 0);
12648 +
12649 + if (!neo1973_gps.power_was_on)
12650 + regulator_enable(neo1973_gps.regulator[
12651 + GTA02_GPS_REG_RF_3V]);
12652 + return;
12653 + }
12654 +
12655 + /*
12656 + * take care not to power unpowered GPS from UART TX
12657 + * return them to GPIO and force low
12658 + */
12659 + s3c2410_gpio_cfgpin(S3C2410_GPH4, S3C2410_GPH4_OUTP);
12660 + s3c2410_gpio_setpin(S3C2410_GPH4, 0);
12661 + /* don't let RX from unpowered GPS float */
12662 + s3c2410_gpio_pullup(S3C2410_GPH5, 1);
12663 + if (neo1973_gps.power_was_on)
12664 + regulator_disable(neo1973_gps.regulator[
12665 + GTA02_GPS_REG_RF_3V]);
12666 + }
12667 +}
12668 +
12669 +static int gps_pwron_get(void)
12670 +{
12671 + if (machine_is_neo1973_gta01())
12672 + return !!s3c2410_gpio_getpin(GTA01_GPIO_GPS_PWRON);
12673 +
12674 + if (machine_is_neo1973_gta02())
12675 + return regulator_is_enabled(neo1973_gps.regulator[GTA02_GPS_REG_RF_3V]);
12676 + return -1;
12677 +}
12678 +
12679 +
12680 +#ifdef CONFIG_MACH_NEO1973_GTA01
12681 +static void gps_rst_set(int on);
12682 +static int gps_rst_get(void);
12683 +#endif
12684 +
12685 +#ifdef CONFIG_PM
12686 +/* This is the flag for keeping gps ON during suspend */
12687 +static void gps_keep_on_in_suspend_set(int on)
12688 +{
12689 + neo1973_gps.keep_on_in_suspend = on;
12690 +}
12691 +
12692 +static int gps_keep_on_in_suspend_get(void)
12693 +{
12694 + return neo1973_gps.keep_on_in_suspend;
12695 +}
12696 +#endif
12697 +
12698 +static ssize_t power_gps_read(struct device *dev,
12699 + struct device_attribute *attr, char *buf)
12700 +{
12701 + int ret = 0;
12702 +
12703 + if (!strcmp(attr->attr.name, "power_on") ||
12704 + !strcmp(attr->attr.name, "pwron")) {
12705 + ret = gps_pwron_get();
12706 +#ifdef CONFIG_PM
12707 + } else if (!strcmp(attr->attr.name, "keep_on_in_suspend")) {
12708 + ret = gps_keep_on_in_suspend_get();
12709 +#endif
12710 +#ifdef CONFIG_MACH_NEO1973_GTA01
12711 + } else if (!strcmp(attr->attr.name, "power_avdd_3v")) {
12712 + ret = gps_power_3v_get();
12713 + } else if (!strcmp(attr->attr.name, "power_tcxo_2v8")) {
12714 + ret = gps_power_2v8_get();
12715 + } else if (!strcmp(attr->attr.name, "reset")) {
12716 + ret = gps_rst_get();
12717 + } else if (!strcmp(attr->attr.name, "power_lp_io_3v3")) {
12718 + ret = gps_power_3v3_get();
12719 + } else if (!strcmp(attr->attr.name, "power_pll_core_2v5")) {
12720 + ret = gps_power_2v5_get();
12721 + } else if (!strcmp(attr->attr.name, "power_core_1v5") ||
12722 + !strcmp(attr->attr.name, "power_vdd_core_1v5")) {
12723 + ret = gps_power_1v5_get();
12724 +#endif
12725 + }
12726 + if (ret)
12727 + return strlcpy(buf, "1\n", 3);
12728 + else
12729 + return strlcpy(buf, "0\n", 3);
12730 +}
12731 +
12732 +static ssize_t power_gps_write(struct device *dev,
12733 + struct device_attribute *attr, const char *buf,
12734 + size_t count)
12735 +{
12736 + unsigned long on = simple_strtoul(buf, NULL, 10);
12737 +
12738 + if (!strcmp(attr->attr.name, "power_on") ||
12739 + !strcmp(attr->attr.name, "pwron")) {
12740 + gps_pwron_set(on);
12741 + neo1973_gps.power_was_on = !!on;
12742 +#ifdef CONFIG_PM
12743 + } else if (!strcmp(attr->attr.name, "keep_on_in_suspend")) {
12744 + gps_keep_on_in_suspend_set(on);
12745 +#endif
12746 +#ifdef CONFIG_MACH_NEO1973_GTA01
12747 + } else if (!strcmp(attr->attr.name, "power_avdd_3v")) {
12748 + gps_power_3v_set(on);
12749 + } else if (!strcmp(attr->attr.name, "power_tcxo_2v8")) {
12750 + gps_power_2v8_set(on);
12751 + } else if (!strcmp(attr->attr.name, "reset")) {
12752 + gps_rst_set(on);
12753 + } else if (!strcmp(attr->attr.name, "power_lp_io_3v3")) {
12754 + gps_power_3v3_set(on);
12755 + } else if (!strcmp(attr->attr.name, "power_pll_core_2v5")) {
12756 + gps_power_2v5_set(on);
12757 + } else if (!strcmp(attr->attr.name, "power_core_1v5") ||
12758 + !strcmp(attr->attr.name, "power_vdd_core_1v5")) {
12759 + gps_power_1v5_set(on);
12760 +#endif
12761 + }
12762 + return count;
12763 +}
12764 +
12765 +
12766 +#ifdef CONFIG_MACH_NEO1973_GTA01
12767 +
12768 +/* This is the nRESET pin */
12769 +static void gps_rst_set(int on)
12770 +{
12771 + switch (S3C_SYSTEM_REV_ATAG) {
12772 + case GTA01v3_SYSTEM_REV:
12773 + pcf50606_gpo_set_active(gta01_pcf, PCF50606_GPO1, on);
12774 + break;
12775 + case GTA01v4_SYSTEM_REV:
12776 + case GTA01Bv2_SYSTEM_REV:
12777 + case GTA01Bv3_SYSTEM_REV:
12778 + case GTA01Bv4_SYSTEM_REV:
12779 + s3c2410_gpio_setpin(GTA01_GPIO_GPS_RESET, on);
12780 + break;
12781 + }
12782 +}
12783 +
12784 +static int gps_rst_get(void)
12785 +{
12786 + switch (S3C_SYSTEM_REV_ATAG) {
12787 + case GTA01v3_SYSTEM_REV:
12788 + return pcf50606_gpo_get_active(gta01_pcf, PCF50606_GPO1);
12789 + break;
12790 + case GTA01v4_SYSTEM_REV:
12791 + case GTA01Bv2_SYSTEM_REV:
12792 + case GTA01Bv3_SYSTEM_REV:
12793 + case GTA01Bv4_SYSTEM_REV:
12794 + if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_RESET))
12795 + return 1;
12796 + break;
12797 + }
12798 +
12799 + return 0;
12800 +}
12801 +
12802 +
12803 +static void gps_power_sequence_up(void)
12804 +{
12805 + /* According to PMB2520 Data Sheet, Rev. 2006-06-05,
12806 + * Chapter 4.2.2 */
12807 +
12808 + /* nRESET must be asserted low */
12809 + gps_rst_set(0);
12810 +
12811 + /* POWERON must be de-asserted (low) */
12812 + gps_pwron_set(0);
12813 +
12814 + /* Apply VDD_IO and VDD_LPREG_IN */
12815 + gps_power_3v3_set(1);
12816 +
12817 + /* VDD_COREREG_IN, VDD_PLLREG_IN */
12818 + gps_power_1v5_set(1);
12819 + gps_power_2v5_set(1);
12820 +
12821 + /* and VDD_RF may be applied */
12822 + gps_power_2v8_set(1);
12823 +
12824 + /* We need to enable AVDD, since in GTA01Bv3 it is
12825 + * shared with RFREG_IN */
12826 + gps_power_3v_set(1);
12827 +
12828 + msleep(3); /* Is 3ms enough? */
12829 +
12830 + /* De-asert nRESET */
12831 + gps_rst_set(1);
12832 +
12833 + /* Switch power on */
12834 + gps_pwron_set(1);
12835 +
12836 +}
12837 +
12838 +static void gps_power_sequence_down(void)
12839 +{
12840 + /* According to PMB2520 Data Sheet, Rev. 2006-06-05,
12841 + * Chapter 4.2.3.1 */
12842 + gps_pwron_set(0);
12843 +
12844 + /* Don't disable AVDD before PWRON is cleared, since
12845 + * in GTA01Bv3, AVDD and RFREG_IN are shared */
12846 + if (neo1973_gps.regulator_state[GTA01_GPS_REG_3V])
12847 + gps_power_3v_set(0);
12848 +
12849 + /* Remove VDD_COREREG_IN, VDD_PLLREG_IN and VDD_REFREG_IN */
12850 + if (neo1973_gps.regulator_state[GTA01_GPS_REG_1V5])
12851 + gps_power_1v5_set(0);
12852 + if (neo1973_gps.regulator_state[GTA01_GPS_REG_2V5])
12853 + gps_power_2v5_set(0);
12854 + if (neo1973_gps.regulator_state[GTA01_GPS_REG_2V8])
12855 + gps_power_2v8_set(0);
12856 +
12857 + /* Remove VDD_LPREG_IN and VDD_IO */
12858 + if (neo1973_gps.regulator_state[GTA01_GPS_REG_3V3])
12859 + gps_power_3v3_set(0);
12860 +
12861 +}
12862 +
12863 +static ssize_t power_sequence_read(struct device *dev,
12864 + struct device_attribute *attr,
12865 + char *buf)
12866 +{
12867 + return strlcpy(buf, "power_up power_down\n", PAGE_SIZE);
12868 +}
12869 +
12870 +static ssize_t power_sequence_write(struct device *dev,
12871 + struct device_attribute *attr,
12872 + const char *buf, size_t count)
12873 +{
12874 + dev_dbg(dev, "wrote: '%s'\n", buf);
12875 +
12876 + if (!strncmp(buf, "power_up", 8))
12877 + gps_power_sequence_up();
12878 + else if (!strncmp(buf, "power_down", 10))
12879 + gps_power_sequence_down();
12880 + else
12881 + return -EINVAL;
12882 +
12883 + return count;
12884 +}
12885 +
12886 +static DEVICE_ATTR(power_tcxo_2v8, 0644, power_gps_read, power_gps_write);
12887 +static DEVICE_ATTR(power_avdd_3v, 0644, power_gps_read, power_gps_write);
12888 +static DEVICE_ATTR(reset, 0644, power_gps_read, power_gps_write);
12889 +static DEVICE_ATTR(power_lp_io_3v3, 0644, power_gps_read, power_gps_write);
12890 +static DEVICE_ATTR(power_pll_core_2v5, 0644, power_gps_read, power_gps_write);
12891 +static DEVICE_ATTR(power_core_1v5, 0644, power_gps_read, power_gps_write);
12892 +static DEVICE_ATTR(power_vdd_core_1v5, 0644, power_gps_read, power_gps_write);
12893 +static DEVICE_ATTR(power_sequence, 0644, power_sequence_read,
12894 + power_sequence_write);
12895 +#endif
12896 +
12897 +#ifdef CONFIG_PM
12898 +static int gta01_pm_gps_suspend(struct platform_device *pdev,
12899 + pm_message_t state)
12900 +{
12901 +#ifdef CONFIG_MACH_NEO1973_GTA01
12902 + if (machine_is_neo1973_gta01())
12903 + /* FIXME */
12904 + gps_power_sequence_down();
12905 +#endif
12906 + if (machine_is_neo1973_gta02()) {
12907 + if (!neo1973_gps.keep_on_in_suspend ||
12908 + !neo1973_gps.power_was_on)
12909 + gps_pwron_set(0);
12910 + else
12911 + dev_warn(&pdev->dev, "GTA02: keeping gps ON "
12912 + "during suspend\n");
12913 + }
12914 +
12915 + return 0;
12916 +}
12917 +
12918 +static int gta01_pm_gps_resume(struct platform_device *pdev)
12919 +{
12920 +#ifdef CONFIG_MACH_NEO1973_GTA01
12921 + if (machine_is_neo1973_gta01())
12922 + if (neo1973_gps.power_was_on)
12923 + gps_power_sequence_up();
12924 +#endif
12925 + if (machine_is_neo1973_gta02())
12926 + if (!neo1973_gps.keep_on_in_suspend && neo1973_gps.power_was_on)
12927 + gps_pwron_set(1);
12928 +
12929 + return 0;
12930 +}
12931 +
12932 +static DEVICE_ATTR(keep_on_in_suspend, 0644, power_gps_read, power_gps_write);
12933 +#else
12934 +#define gta01_pm_gps_suspend NULL
12935 +#define gta01_pm_gps_resume NULL
12936 +#endif
12937 +
12938 +static DEVICE_ATTR(power_on, 0644, power_gps_read, power_gps_write);
12939 +static DEVICE_ATTR(pwron, 0644, power_gps_read, power_gps_write);
12940 +
12941 +
12942 +static struct attribute *gta01_gps_sysfs_entries[] = {
12943 + &dev_attr_power_on.attr,
12944 + &dev_attr_pwron.attr,
12945 +#ifdef CONFIG_MACH_NEO1973_GTA01
12946 + &dev_attr_power_avdd_3v.attr,
12947 + &dev_attr_reset.attr,
12948 + &dev_attr_power_lp_io_3v3.attr,
12949 + &dev_attr_power_pll_core_2v5.attr,
12950 + &dev_attr_power_sequence.attr,
12951 + NULL, /* power_core_1v5 */
12952 + NULL, /* power_vdd_core_1v5 */
12953 +#endif
12954 + NULL /* terminating entry */
12955 +};
12956 +
12957 +static struct attribute_group gta01_gps_attr_group = {
12958 + .name = NULL,
12959 + .attrs = gta01_gps_sysfs_entries,
12960 +};
12961 +
12962 +static struct attribute *gta02_gps_sysfs_entries[] = {
12963 + &dev_attr_power_on.attr,
12964 +#ifdef CONFIG_PM
12965 + &dev_attr_keep_on_in_suspend.attr,
12966 +#endif
12967 + NULL
12968 +};
12969 +
12970 +static struct attribute_group gta02_gps_attr_group = {
12971 + .name = NULL,
12972 + .attrs = gta02_gps_sysfs_entries,
12973 +};
12974 +
12975 +static int __init gta01_pm_gps_probe(struct platform_device *pdev)
12976 +{
12977 + int ret;
12978 +#ifdef CONFIG_MACH_NEO1973_GTA01
12979 + int entries = ARRAY_SIZE(gta01_gps_sysfs_entries);
12980 +#endif
12981 +
12982 + if (machine_is_neo1973_gta01()) {
12983 + s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_PWRON, S3C2410_GPIO_OUTPUT);
12984 +
12985 + switch (S3C_SYSTEM_REV_ATAG) {
12986 + case GTA01v3_SYSTEM_REV:
12987 + break;
12988 + case GTA01v4_SYSTEM_REV:
12989 + s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_RESET,
12990 + S3C2410_GPIO_OUTPUT);
12991 + break;
12992 + case GTA01Bv3_SYSTEM_REV:
12993 + case GTA01Bv4_SYSTEM_REV:
12994 + s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_3V3,
12995 + S3C2410_GPIO_OUTPUT);
12996 + /* fallthrough */
12997 + case GTA01Bv2_SYSTEM_REV:
12998 + s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_2V8,
12999 + S3C2410_GPIO_OUTPUT);
13000 + s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_EN_3V,
13001 + S3C2410_GPIO_OUTPUT);
13002 + s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_RESET,
13003 + S3C2410_GPIO_OUTPUT);
13004 + break;
13005 + default:
13006 + dev_warn(&pdev->dev, "Unknown GTA01 Revision 0x%x, "
13007 + "AGPS PM features not available!!!\n",
13008 + system_rev);
13009 + return -1;
13010 + break;
13011 + }
13012 +
13013 +#ifdef CONFIG_MACH_NEO1973_GTA01
13014 +
13015 + neo1973_gps.regulator[GTA01_GPS_REG_2V8] =
13016 + regulator_get(&pdev->dev, "GPS_2V8");
13017 + neo1973_gps.regulator[GTA01_GPS_REG_3V] =
13018 + regulator_get(&pdev->dev, "GPS_3V");
13019 + neo1973_gps.regulator[GTA01_GPS_REG_3V3] =
13020 + regulator_get(&pdev->dev, "GPS_3V3");
13021 + neo1973_gps.regulator[GTA01_GPS_REG_1V5] =
13022 + regulator_get(&pdev->dev, "GPS_1V5");
13023 + neo1973_gps.regulator[GTA01_GPS_REG_2V5] =
13024 + regulator_get(&pdev->dev, "GPS_2V5");
13025 +
13026 + gps_power_sequence_down();
13027 +
13028 + switch (S3C_SYSTEM_REV_ATAG) {
13029 + case GTA01v3_SYSTEM_REV:
13030 + case GTA01v4_SYSTEM_REV:
13031 + case GTA01Bv2_SYSTEM_REV:
13032 + gta01_gps_sysfs_entries[entries-3] =
13033 + &dev_attr_power_tcxo_2v8.attr;
13034 + break;
13035 + case GTA01Bv3_SYSTEM_REV:
13036 + case GTA01Bv4_SYSTEM_REV:
13037 + gta01_gps_sysfs_entries[entries-3] =
13038 + &dev_attr_power_core_1v5.attr;
13039 + gta01_gps_sysfs_entries[entries-2] =
13040 + &dev_attr_power_vdd_core_1v5.attr;
13041 + break;
13042 + }
13043 +#endif
13044 + ret = sysfs_create_group(&pdev->dev.kobj,
13045 + &gta01_gps_attr_group);
13046 + if (ret)
13047 + return ret;
13048 + return bus_create_device_link(&platform_bus_type,
13049 + &pdev->dev.kobj, "gta01-pm-gps.0");
13050 + }
13051 +
13052 + if (machine_is_neo1973_gta02()) {
13053 +
13054 + neo1973_gps.regulator[GTA02_GPS_REG_RF_3V] = regulator_get(
13055 + &pdev->dev, "RF_3V");
13056 + if (IS_ERR(neo1973_gps.regulator)) {
13057 + dev_err(&pdev->dev, "probe failed %ld\n",
13058 + PTR_ERR(neo1973_gps.regulator));
13059 +
13060 + return PTR_ERR(neo1973_gps.regulator);
13061 + }
13062 +
13063 + dev_info(&pdev->dev, "starting\n");
13064 +
13065 + /*
13066 + * Here we should call the code that handles the set GPS power
13067 + * off action. But, the regulator API does not allow us to
13068 + * reassert regulator state, and when we read the regulator API
13069 + * logical state, it can differ from the actual state, So
13070 + * a workaround for this is to just set the regulator off in the
13071 + * PMU directly. Because that's different from normal flow, we
13072 + * have to reproduce other things from the OFF action here too.
13073 + */
13074 +
13075 + /*
13076 + * u-boot enables LDO5 (GPS), which doesn't make sense and
13077 + * causes confusion. We therefore disable the regulator here.
13078 + */
13079 + pcf50633_reg_write(gta02_pcf, PCF50633_REG_LDO5ENA, 0);
13080 +
13081 + /*
13082 + * take care not to power unpowered GPS from UART TX
13083 + * return them to GPIO and force low
13084 + */
13085 + s3c2410_gpio_cfgpin(S3C2410_GPH4, S3C2410_GPH4_OUTP);
13086 + s3c2410_gpio_setpin(S3C2410_GPH4, 0);
13087 + /* don't let RX from unpowered GPS float */
13088 + s3c2410_gpio_pullup(S3C2410_GPH5, 1);
13089 +
13090 + return sysfs_create_group(&pdev->dev.kobj,
13091 + &gta02_gps_attr_group);
13092 + }
13093 + return -1;
13094 +}
13095 +
13096 +static int gta01_pm_gps_remove(struct platform_device *pdev)
13097 +{
13098 + if (machine_is_neo1973_gta01()) {
13099 +#ifdef CONFIG_MACH_NEO1973_GTA01
13100 + int i;
13101 +
13102 + gps_power_sequence_down();
13103 + /* Now disable all regulators */
13104 + for (i = 0; i < GTA01_GPS_NUM_REG; i++) {
13105 + regulator_put(neo1973_gps.regulator[i]);
13106 + }
13107 +#endif
13108 + bus_remove_device_link(&platform_bus_type, "gta01-pm-gps.0");
13109 + sysfs_remove_group(&pdev->dev.kobj, &gta01_gps_attr_group);
13110 + }
13111 +
13112 + if (machine_is_neo1973_gta02()) {
13113 + regulator_put(neo1973_gps.regulator[GTA02_GPS_REG_RF_3V]);
13114 + sysfs_remove_group(&pdev->dev.kobj, &gta02_gps_attr_group);
13115 + }
13116 + return 0;
13117 +}
13118 +
13119 +static struct platform_driver gta01_pm_gps_driver = {
13120 + .probe = gta01_pm_gps_probe,
13121 + .remove = gta01_pm_gps_remove,
13122 + .suspend = gta01_pm_gps_suspend,
13123 + .resume = gta01_pm_gps_resume,
13124 + .driver = {
13125 + .name = "neo1973-pm-gps",
13126 + },
13127 +};
13128 +
13129 +static int __devinit gta01_pm_gps_init(void)
13130 +{
13131 + return platform_driver_register(&gta01_pm_gps_driver);
13132 +}
13133 +
13134 +static void gta01_pm_gps_exit(void)
13135 +{
13136 + platform_driver_unregister(&gta01_pm_gps_driver);
13137 +}
13138 +
13139 +module_init(gta01_pm_gps_init);
13140 +module_exit(gta01_pm_gps_exit);
13141 +
13142 +MODULE_LICENSE("GPL");
13143 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
13144 +MODULE_DESCRIPTION("FIC Neo1973 GPS Power Management");
13145 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_pm_gps.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_pm_gps.h
13146 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_pm_gps.h 1970-01-01 01:00:00.000000000 +0100
13147 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_pm_gps.h 2009-05-10 22:27:59.000000000 +0200
13148 @@ -0,0 +1 @@
13149 +extern int neo1973_pm_gps_is_on(void);
13150 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c
13151 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c 1970-01-01 01:00:00.000000000 +0100
13152 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c 2009-05-10 22:27:59.000000000 +0200
13153 @@ -0,0 +1,380 @@
13154 +/*
13155 + * GSM Management code for the FIC Neo1973 GSM Phone
13156 + *
13157 + * (C) 2007 by Openmoko Inc.
13158 + * Author: Harald Welte <laforge@openmoko.org>
13159 + * All rights reserved.
13160 + *
13161 + * This program is free software; you can redistribute it and/or modify
13162 + * it under the terms of the GNU General Public License version 2 as
13163 + * published by the Free Software Foundation
13164 + *
13165 + */
13166 +
13167 +#include <linux/module.h>
13168 +#include <linux/init.h>
13169 +#include <linux/kernel.h>
13170 +#include <linux/platform_device.h>
13171 +#include <linux/console.h>
13172 +#include <linux/errno.h>
13173 +#include <linux/interrupt.h>
13174 +#include <linux/delay.h>
13175 +
13176 +#include <mach/gpio.h>
13177 +#include <asm/mach-types.h>
13178 +#include <mach/gta01.h>
13179 +#include <asm/plat-s3c24xx/neo1973.h>
13180 +#include <mach/s3c24xx-serial.h>
13181 +
13182 +#include <mach/hardware.h>
13183 +#include <mach/cpu.h>
13184 +
13185 +/* For GTA02 */
13186 +#include <mach/gta02.h>
13187 +#include <linux/mfd/pcf50633/gpio.h>
13188 +#include <mach/regs-gpio.h>
13189 +#include <mach/regs-gpioj.h>
13190 +
13191 +int gta_gsm_interrupts;
13192 +EXPORT_SYMBOL(gta_gsm_interrupts);
13193 +
13194 +extern void s3c24xx_serial_console_set_silence(int);
13195 +
13196 +struct gta01pm_priv {
13197 + int gpio_ngsm_en;
13198 + int gpio_ndl_gsm;
13199 +
13200 + struct console *con;
13201 +};
13202 +
13203 +static struct gta01pm_priv gta01_gsm;
13204 +
13205 +static struct console *find_s3c24xx_console(void)
13206 +{
13207 + struct console *con;
13208 +
13209 + acquire_console_sem();
13210 +
13211 + for (con = console_drivers; con; con = con->next) {
13212 + if (!strcmp(con->name, "ttySAC"))
13213 + break;
13214 + }
13215 +
13216 + release_console_sem();
13217 +
13218 + return con;
13219 +}
13220 +
13221 +static ssize_t gsm_read(struct device *dev, struct device_attribute *attr,
13222 + char *buf)
13223 +{
13224 + if (!strcmp(attr->attr.name, "power_on")) {
13225 + if (gta01_gsm.gpio_ngsm_en) {
13226 + if (!s3c2410_gpio_getpin(gta01_gsm.gpio_ngsm_en))
13227 + goto out_1;
13228 + } else if (machine_is_neo1973_gta02())
13229 + if (pcf50633_gpio_get(gta02_pcf, PCF50633_GPIO2))
13230 + goto out_1;
13231 + } else if (!strcmp(attr->attr.name, "download")) {
13232 + if (machine_is_neo1973_gta01()) {
13233 + if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_DNLOAD))
13234 + goto out_1;
13235 + } else if (machine_is_neo1973_gta02()) {
13236 + if (!s3c2410_gpio_getpin(GTA02_GPIO_nDL_GSM))
13237 + goto out_1;
13238 + }
13239 + } else if (!strcmp(attr->attr.name, "flowcontrolled")) {
13240 + if (s3c2410_gpio_getcfg(S3C2410_GPH1) == S3C2410_GPIO_OUTPUT)
13241 + goto out_1;
13242 + }
13243 +
13244 + return strlcpy(buf, "0\n", 3);
13245 +out_1:
13246 + return strlcpy(buf, "1\n", 3);
13247 +}
13248 +
13249 +static void gsm_on_off(struct device *dev, int on)
13250 +{
13251 + if (!on) {
13252 + if (machine_is_neo1973_gta02()) {
13253 + /*
13254 + * Do not drive into powered-down GSM side
13255 + * GTA02 only, because on GTA01 maybe serial
13256 + * is used otherwise.
13257 + */
13258 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPIO_INPUT);
13259 + s3c2410_gpio_cfgpin(S3C2410_GPH2, S3C2410_GPIO_INPUT);
13260 +
13261 + pcf50633_gpio_set(gta02_pcf, PCF50633_GPIO2, 0);
13262 + }
13263 +
13264 + if (gta01_gsm.gpio_ngsm_en)
13265 + s3c2410_gpio_setpin(gta01_gsm.gpio_ngsm_en, 1);
13266 +
13267 + if (gta01_gsm.con) {
13268 + s3c24xx_serial_console_set_silence(0);
13269 + console_start(gta01_gsm.con);
13270 +
13271 + dev_dbg(dev, "powered down GTA01 GSM, enabling "
13272 + "serial console\n");
13273 + }
13274 +
13275 + return;
13276 + }
13277 +
13278 + if (gta01_gsm.con) {
13279 + dev_dbg(dev, "powering up GSM, thus "
13280 + "disconnecting serial console\n");
13281 +
13282 + console_stop(gta01_gsm.con);
13283 + s3c24xx_serial_console_set_silence(1);
13284 + }
13285 +
13286 + /* allow UART to talk to GSM side now we will power it */
13287 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_nRTS0);
13288 + s3c2410_gpio_cfgpin(S3C2410_GPH2, S3C2410_GPH2_TXD0);
13289 +
13290 + if (gta01_gsm.gpio_ngsm_en)
13291 + s3c2410_gpio_setpin(gta01_gsm.gpio_ngsm_en, 0);
13292 +
13293 + if (machine_is_neo1973_gta02())
13294 + pcf50633_gpio_set(gta02_pcf, PCF50633_GPIO2, 7);
13295 +
13296 + msleep(100);
13297 +
13298 + neo1973_gpb_setpin(GTA01_GPIO_MODEM_ON, 1);
13299 + msleep(500);
13300 + neo1973_gpb_setpin(GTA01_GPIO_MODEM_ON, 0);
13301 +
13302 + /*
13303 + * workaround for calypso firmware moko10 and earlier,
13304 + * without this it will leave IRQ line high after
13305 + * booting
13306 + */
13307 + s3c2410_gpio_setpin(S3C2410_GPH1, 1);
13308 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_OUTP);
13309 + msleep(1000);
13310 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_nRTS0);
13311 +
13312 +}
13313 +
13314 +static ssize_t gsm_write(struct device *dev, struct device_attribute *attr,
13315 + const char *buf, size_t count)
13316 +{
13317 + unsigned long on = simple_strtoul(buf, NULL, 10);
13318 +
13319 + if (!strcmp(attr->attr.name, "power_on")) {
13320 + gsm_on_off(dev, on);
13321 +
13322 + return count;
13323 + }
13324 +
13325 + if (!strcmp(attr->attr.name, "download")) {
13326 + if (machine_is_neo1973_gta01())
13327 + s3c2410_gpio_setpin(GTA01_GPIO_MODEM_DNLOAD, on);
13328 +
13329 + if (machine_is_neo1973_gta02()) {
13330 + /*
13331 + * the keyboard / buttons driver requests and enables
13332 + * the JACK_INSERT IRQ. We have to take care about
13333 + * not enabling and disabling the IRQ when it was
13334 + * already in that state or we get "unblanaced IRQ"
13335 + * kernel warnings and stack dumps. So we use the
13336 + * copy of the ndl_gsm state to figure out if we should
13337 + * enable or disable the jack interrupt
13338 + */
13339 + if (on) {
13340 + if (gta01_gsm.gpio_ndl_gsm)
13341 + disable_irq(gpio_to_irq(
13342 + GTA02_GPIO_JACK_INSERT));
13343 + } else {
13344 + if (!gta01_gsm.gpio_ndl_gsm)
13345 + enable_irq(gpio_to_irq(
13346 + GTA02_GPIO_JACK_INSERT));
13347 + }
13348 +
13349 + gta01_gsm.gpio_ndl_gsm = !on;
13350 + s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, !on);
13351 + }
13352 +
13353 + return count;
13354 + }
13355 +
13356 + if (!strcmp(attr->attr.name, "flowcontrolled")) {
13357 + if (on) {
13358 + gta_gsm_interrupts = 0;
13359 + s3c2410_gpio_setpin(S3C2410_GPH1, 1);
13360 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_OUTP);
13361 + } else
13362 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_nRTS0);
13363 + }
13364 +
13365 + return count;
13366 +}
13367 +
13368 +static DEVICE_ATTR(power_on, 0644, gsm_read, gsm_write);
13369 +static DEVICE_ATTR(reset, 0644, gsm_read, gsm_write);
13370 +static DEVICE_ATTR(download, 0644, gsm_read, gsm_write);
13371 +static DEVICE_ATTR(flowcontrolled, 0644, gsm_read, gsm_write);
13372 +
13373 +#ifdef CONFIG_PM
13374 +
13375 +static int gta01_gsm_resume(struct platform_device *pdev);
13376 +static int gta01_gsm_suspend(struct platform_device *pdev, pm_message_t state)
13377 +{
13378 + /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we
13379 + * don't need to do much here. */
13380 +
13381 + /* If flowcontrol asserted, abort if GSM already interrupted */
13382 + if (s3c2410_gpio_getcfg(S3C2410_GPH1) == S3C2410_GPIO_OUTPUT) {
13383 + if (gta_gsm_interrupts)
13384 + goto busy;
13385 + }
13386 +
13387 + /* disable DL GSM to prevent jack_insert becoming 'floating' */
13388 + if (machine_is_neo1973_gta02())
13389 + s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, 1);
13390 + return 0;
13391 +
13392 +busy:
13393 + return -EBUSY;
13394 +}
13395 +
13396 +static int
13397 +gta01_gsm_suspend_late(struct platform_device *pdev, pm_message_t state)
13398 +{
13399 + /* Last chance: abort if GSM already interrupted */
13400 + if (s3c2410_gpio_getcfg(S3C2410_GPH1) == S3C2410_GPIO_OUTPUT) {
13401 + if (gta_gsm_interrupts)
13402 + return -EBUSY;
13403 + }
13404 + return 0;
13405 +}
13406 +
13407 +static int gta01_gsm_resume(struct platform_device *pdev)
13408 +{
13409 + /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we
13410 + * don't need to do much here. */
13411 +
13412 + /* Make sure that the kernel console on the serial port is still
13413 + * disabled. FIXME: resume ordering race with serial driver! */
13414 + if (gta01_gsm.con && s3c2410_gpio_getpin(GTA01_GPIO_MODEM_ON))
13415 + console_stop(gta01_gsm.con);
13416 +
13417 + if (machine_is_neo1973_gta02())
13418 + s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, gta01_gsm.gpio_ndl_gsm);
13419 +
13420 + return 0;
13421 +}
13422 +#else
13423 +#define gta01_gsm_suspend NULL
13424 +#define gta01_gsm_suspend_late NULL
13425 +#define gta01_gsm_resume NULL
13426 +#endif /* CONFIG_PM */
13427 +
13428 +static struct attribute *gta01_gsm_sysfs_entries[] = {
13429 + &dev_attr_power_on.attr,
13430 + &dev_attr_reset.attr,
13431 + &dev_attr_download.attr,
13432 + &dev_attr_flowcontrolled.attr,
13433 + NULL
13434 +};
13435 +
13436 +static struct attribute_group gta01_gsm_attr_group = {
13437 + .name = NULL,
13438 + .attrs = gta01_gsm_sysfs_entries,
13439 +};
13440 +
13441 +static int __init gta01_gsm_probe(struct platform_device *pdev)
13442 +{
13443 + switch (S3C_SYSTEM_REV_ATAG) {
13444 + case GTA01v3_SYSTEM_REV:
13445 + gta01_gsm.gpio_ngsm_en = GTA01v3_GPIO_nGSM_EN;
13446 + break;
13447 + case GTA01v4_SYSTEM_REV:
13448 + gta01_gsm.gpio_ngsm_en = 0;
13449 + break;
13450 + case GTA01Bv2_SYSTEM_REV:
13451 + case GTA01Bv3_SYSTEM_REV:
13452 + case GTA01Bv4_SYSTEM_REV:
13453 + gta01_gsm.gpio_ngsm_en = GTA01Bv2_GPIO_nGSM_EN;
13454 + s3c2410_gpio_setpin(GTA01v3_GPIO_nGSM_EN, 0);
13455 + break;
13456 + case GTA02v1_SYSTEM_REV:
13457 + case GTA02v2_SYSTEM_REV:
13458 + case GTA02v3_SYSTEM_REV:
13459 + case GTA02v4_SYSTEM_REV:
13460 + case GTA02v5_SYSTEM_REV:
13461 + case GTA02v6_SYSTEM_REV:
13462 + gta01_gsm.gpio_ngsm_en = 0;
13463 + break;
13464 + default:
13465 + dev_warn(&pdev->dev, "Unknown Neo1973 Revision 0x%x, "
13466 + "some PM features not available!!!\n",
13467 + system_rev);
13468 + break;
13469 + }
13470 +
13471 + switch (S3C_SYSTEM_REV_ATAG) {
13472 + case GTA01v4_SYSTEM_REV:
13473 + case GTA01Bv2_SYSTEM_REV:
13474 + gta01_gsm_sysfs_entries[ARRAY_SIZE(gta01_gsm_sysfs_entries)-2] =
13475 + &dev_attr_download.attr;
13476 + break;
13477 + default:
13478 + break;
13479 + }
13480 +
13481 + if (machine_is_neo1973_gta01()) {
13482 + gta01_gsm.con = find_s3c24xx_console();
13483 + if (!gta01_gsm.con)
13484 + dev_warn(&pdev->dev,
13485 + "cannot find S3C24xx console driver\n");
13486 + } else
13487 + gta01_gsm.con = NULL;
13488 +
13489 + /* note that download initially disabled, and enforce that */
13490 + gta01_gsm.gpio_ndl_gsm = 1;
13491 + if (machine_is_neo1973_gta02())
13492 + s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, 1);
13493 +
13494 + /* GSM is to be initially off (at boot, or if this module inserted) */
13495 + gsm_on_off(&pdev->dev, 0);
13496 +
13497 + return sysfs_create_group(&pdev->dev.kobj, &gta01_gsm_attr_group);
13498 +}
13499 +
13500 +static int gta01_gsm_remove(struct platform_device *pdev)
13501 +{
13502 + sysfs_remove_group(&pdev->dev.kobj, &gta01_gsm_attr_group);
13503 +
13504 + return 0;
13505 +}
13506 +
13507 +static struct platform_driver gta01_gsm_driver = {
13508 + .probe = gta01_gsm_probe,
13509 + .remove = gta01_gsm_remove,
13510 + .suspend = gta01_gsm_suspend,
13511 + .suspend_late = gta01_gsm_suspend_late,
13512 + .resume = gta01_gsm_resume,
13513 + .driver = {
13514 + .name = "neo1973-pm-gsm",
13515 + },
13516 +};
13517 +
13518 +static int __devinit gta01_gsm_init(void)
13519 +{
13520 + return platform_driver_register(&gta01_gsm_driver);
13521 +}
13522 +
13523 +static void gta01_gsm_exit(void)
13524 +{
13525 + platform_driver_unregister(&gta01_gsm_driver);
13526 +}
13527 +
13528 +module_init(gta01_gsm_init);
13529 +module_exit(gta01_gsm_exit);
13530 +
13531 +MODULE_LICENSE("GPL");
13532 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
13533 +MODULE_DESCRIPTION("FIC Neo1973 GSM Power Management");
13534 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_shadow.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_shadow.c
13535 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/neo1973_shadow.c 1970-01-01 01:00:00.000000000 +0100
13536 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/neo1973_shadow.c 2009-05-10 22:27:59.000000000 +0200
13537 @@ -0,0 +1,88 @@
13538 +/*
13539 + * include/asm-arm/plat-s3c24xx/neo1973.h
13540 + *
13541 + * Common utility code for GTA01 and GTA02
13542 + *
13543 + * Copyright (C) 2008 by Openmoko, Inc.
13544 + * Author: Holger Hans Peter Freyther <freyther@openmoko.org>
13545 + * All rights reserved.
13546 + *
13547 + * This program is free software; you can redistribute it and/or
13548 + * modify it under the terms of the GNU General Public License as
13549 + * published by the Free Software Foundation; either version 2 of
13550 + * the License, or (at your option) any later version.
13551 + *
13552 + * This program is distributed in the hope that it will be useful,
13553 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
13554 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13555 + * GNU General Public License for more details.
13556 + *
13557 + * You should have received a copy of the GNU General Public License
13558 + * along with this program; if not, write to the Free Software
13559 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
13560 + * MA 02111-1307 USA
13561 + *
13562 + */
13563 +
13564 +#include <linux/module.h>
13565 +#include <linux/io.h>
13566 +#include <linux/irq.h>
13567 +
13568 +#include <asm/gpio.h>
13569 +#include <mach/regs-gpio.h>
13570 +#include <asm/plat-s3c24xx/neo1973.h>
13571 +
13572 +/**
13573 + * Shadow GPIO bank B handling. For the LEDs we need to keep track of the state
13574 + * in software. The s3c2410_gpio_setpin must not be used for GPIOs on bank B
13575 + */
13576 +static unsigned long gpb_mask;
13577 +static unsigned long gpb_state;
13578 +
13579 +void neo1973_gpb_add_shadow_gpio(unsigned int gpio)
13580 +{
13581 + unsigned long offset = S3C2410_GPIO_OFFSET(gpio);
13582 + unsigned long flags;
13583 +
13584 + local_irq_save(flags);
13585 + gpb_mask |= 1L << offset;
13586 + local_irq_restore(flags);
13587 +}
13588 +EXPORT_SYMBOL(neo1973_gpb_add_shadow_gpio);
13589 +
13590 +static void set_shadow_gpio(unsigned long offset, unsigned int value)
13591 +{
13592 + unsigned long state = value != 0;
13593 +
13594 + gpb_state &= ~(1L << offset);
13595 + gpb_state |= state << offset;
13596 +}
13597 +
13598 +void neo1973_gpb_setpin(unsigned int pin, unsigned to)
13599 +{
13600 + void __iomem *base = S3C24XX_GPIO_BASE(S3C2410_GPB0);
13601 + unsigned long offset = S3C2410_GPIO_OFFSET(pin);
13602 + unsigned long flags;
13603 + unsigned long dat;
13604 +
13605 + BUG_ON(base != S3C24XX_GPIO_BASE(pin));
13606 +
13607 + local_irq_save(flags);
13608 + dat = __raw_readl(base + 0x04);
13609 +
13610 + /* Add the shadow values */
13611 + dat &= ~gpb_mask;
13612 + dat |= gpb_state;
13613 +
13614 + /* Do the operation like s3c2410_gpio_setpin */
13615 + dat &= ~(1L << offset);
13616 + dat |= to << offset;
13617 +
13618 + /* Update the shadow state */
13619 + if ((1L << offset) & gpb_mask)
13620 + set_shadow_gpio(offset, to);
13621 +
13622 + __raw_writel(dat, base + 0x04);
13623 + local_irq_restore(flags);
13624 +}
13625 +EXPORT_SYMBOL(neo1973_gpb_setpin);
13626 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/pm.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/pm.c
13627 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/pm.c 2009-05-10 22:05:03.000000000 +0200
13628 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/pm.c 2009-05-10 22:27:59.000000000 +0200
13629 @@ -31,28 +31,20 @@
13630 #include <linux/errno.h>
13631 #include <linux/time.h>
13632 #include <linux/interrupt.h>
13633 -#include <linux/crc32.h>
13634 -#include <linux/ioport.h>
13635 #include <linux/serial_core.h>
13636 #include <linux/io.h>
13637
13638 -#include <asm/cacheflush.h>
13639 -#include <mach/hardware.h>
13640 -
13641 #include <plat/regs-serial.h>
13642 #include <mach/regs-clock.h>
13643 #include <mach/regs-gpio.h>
13644 #include <mach/regs-mem.h>
13645 #include <mach/regs-irq.h>
13646 +#include <mach/hardware.h>
13647
13648 #include <asm/mach/time.h>
13649
13650 #include <plat/pm.h>
13651
13652 -/* for external use */
13653 -
13654 -unsigned long s3c_pm_flags;
13655 -
13656 #define PFX "s3c24xx-pm: "
13657
13658 static struct sleep_save core_save[] = {
13659 @@ -84,364 +76,17 @@
13660 SAVE_ITEM(S3C2410_CLKSLOW),
13661 };
13662
13663 -static struct gpio_sleep {
13664 - void __iomem *base;
13665 - unsigned int gpcon;
13666 - unsigned int gpdat;
13667 - unsigned int gpup;
13668 -} gpio_save[] = {
13669 - [0] = {
13670 - .base = S3C2410_GPACON,
13671 - },
13672 - [1] = {
13673 - .base = S3C2410_GPBCON,
13674 - },
13675 - [2] = {
13676 - .base = S3C2410_GPCCON,
13677 - },
13678 - [3] = {
13679 - .base = S3C2410_GPDCON,
13680 - },
13681 - [4] = {
13682 - .base = S3C2410_GPECON,
13683 - },
13684 - [5] = {
13685 - .base = S3C2410_GPFCON,
13686 - },
13687 - [6] = {
13688 - .base = S3C2410_GPGCON,
13689 - },
13690 - [7] = {
13691 - .base = S3C2410_GPHCON,
13692 - },
13693 -};
13694 -
13695 static struct sleep_save misc_save[] = {
13696 SAVE_ITEM(S3C2410_DCLKCON),
13697 };
13698
13699 -#ifdef CONFIG_S3C2410_PM_DEBUG
13700 -
13701 -#define SAVE_UART(va) \
13702 - SAVE_ITEM((va) + S3C2410_ULCON), \
13703 - SAVE_ITEM((va) + S3C2410_UCON), \
13704 - SAVE_ITEM((va) + S3C2410_UFCON), \
13705 - SAVE_ITEM((va) + S3C2410_UMCON), \
13706 - SAVE_ITEM((va) + S3C2410_UBRDIV)
13707 -
13708 -static struct sleep_save uart_save[] = {
13709 - SAVE_UART(S3C24XX_VA_UART0),
13710 - SAVE_UART(S3C24XX_VA_UART1),
13711 -#ifndef CONFIG_CPU_S3C2400
13712 - SAVE_UART(S3C24XX_VA_UART2),
13713 -#endif
13714 -};
13715 -
13716 -/* debug
13717 - *
13718 - * we send the debug to printascii() to allow it to be seen if the
13719 - * system never wakes up from the sleep
13720 -*/
13721 -
13722 -extern void printascii(const char *);
13723 -
13724 -void pm_dbg(const char *fmt, ...)
13725 -{
13726 - va_list va;
13727 - char buff[256];
13728 -
13729 - va_start(va, fmt);
13730 - vsprintf(buff, fmt, va);
13731 - va_end(va);
13732 -
13733 - printascii(buff);
13734 -}
13735 -
13736 -static void s3c2410_pm_debug_init(void)
13737 -{
13738 - unsigned long tmp = __raw_readl(S3C2410_CLKCON);
13739 -
13740 - /* re-start uart clocks */
13741 - tmp |= S3C2410_CLKCON_UART0;
13742 - tmp |= S3C2410_CLKCON_UART1;
13743 - tmp |= S3C2410_CLKCON_UART2;
13744 -
13745 - __raw_writel(tmp, S3C2410_CLKCON);
13746 - udelay(10);
13747 -}
13748 -
13749 -#define DBG(fmt...) pm_dbg(fmt)
13750 -#else
13751 -#define DBG(fmt...) printk(KERN_DEBUG fmt)
13752 -
13753 -#define s3c2410_pm_debug_init() do { } while(0)
13754 -
13755 -static struct sleep_save uart_save[] = {};
13756 -#endif
13757 -
13758 -#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
13759 -
13760 -/* suspend checking code...
13761 - *
13762 - * this next area does a set of crc checks over all the installed
13763 - * memory, so the system can verify if the resume was ok.
13764 - *
13765 - * CONFIG_S3C2410_PM_CHECK_CHUNKSIZE defines the block-size for the CRC,
13766 - * increasing it will mean that the area corrupted will be less easy to spot,
13767 - * and reducing the size will cause the CRC save area to grow
13768 -*/
13769 -
13770 -#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
13771 -
13772 -static u32 crc_size; /* size needed for the crc block */
13773 -static u32 *crcs; /* allocated over suspend/resume */
13774 -
13775 -typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
13776 -
13777 -/* s3c2410_pm_run_res
13778 - *
13779 - * go thorugh the given resource list, and look for system ram
13780 -*/
13781 -
13782 -static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
13783 -{
13784 - while (ptr != NULL) {
13785 - if (ptr->child != NULL)
13786 - s3c2410_pm_run_res(ptr->child, fn, arg);
13787 -
13788 - if ((ptr->flags & IORESOURCE_MEM) &&
13789 - strcmp(ptr->name, "System RAM") == 0) {
13790 - DBG("Found system RAM at %08lx..%08lx\n",
13791 - ptr->start, ptr->end);
13792 - arg = (fn)(ptr, arg);
13793 - }
13794 -
13795 - ptr = ptr->sibling;
13796 - }
13797 -}
13798 -
13799 -static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
13800 -{
13801 - s3c2410_pm_run_res(&iomem_resource, fn, arg);
13802 -}
13803 -
13804 -static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
13805 -{
13806 - u32 size = (u32)(res->end - res->start)+1;
13807 -
13808 - size += CHECK_CHUNKSIZE-1;
13809 - size /= CHECK_CHUNKSIZE;
13810 -
13811 - DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
13812 -
13813 - *val += size * sizeof(u32);
13814 - return val;
13815 -}
13816 -
13817 -/* s3c2410_pm_prepare_check
13818 - *
13819 - * prepare the necessary information for creating the CRCs. This
13820 - * must be done before the final save, as it will require memory
13821 - * allocating, and thus touching bits of the kernel we do not
13822 - * know about.
13823 -*/
13824 -
13825 -static void s3c2410_pm_check_prepare(void)
13826 -{
13827 - crc_size = 0;
13828 -
13829 - s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
13830 -
13831 - DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
13832 -
13833 - crcs = kmalloc(crc_size+4, GFP_KERNEL);
13834 - if (crcs == NULL)
13835 - printk(KERN_ERR "Cannot allocated CRC save area\n");
13836 -}
13837 -
13838 -static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
13839 -{
13840 - unsigned long addr, left;
13841 -
13842 - for (addr = res->start; addr < res->end;
13843 - addr += CHECK_CHUNKSIZE) {
13844 - left = res->end - addr;
13845 -
13846 - if (left > CHECK_CHUNKSIZE)
13847 - left = CHECK_CHUNKSIZE;
13848 -
13849 - *val = crc32_le(~0, phys_to_virt(addr), left);
13850 - val++;
13851 - }
13852 -
13853 - return val;
13854 -}
13855 -
13856 -/* s3c2410_pm_check_store
13857 - *
13858 - * compute the CRC values for the memory blocks before the final
13859 - * sleep.
13860 -*/
13861 -
13862 -static void s3c2410_pm_check_store(void)
13863 -{
13864 - if (crcs != NULL)
13865 - s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
13866 -}
13867 -
13868 -/* in_region
13869 - *
13870 - * return TRUE if the area defined by ptr..ptr+size contatins the
13871 - * what..what+whatsz
13872 -*/
13873 -
13874 -static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
13875 -{
13876 - if ((what+whatsz) < ptr)
13877 - return 0;
13878 -
13879 - if (what > (ptr+size))
13880 - return 0;
13881 -
13882 - return 1;
13883 -}
13884 -
13885 -static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
13886 -{
13887 - void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
13888 - unsigned long addr;
13889 - unsigned long left;
13890 - void *ptr;
13891 - u32 calc;
13892 -
13893 - for (addr = res->start; addr < res->end;
13894 - addr += CHECK_CHUNKSIZE) {
13895 - left = res->end - addr;
13896 -
13897 - if (left > CHECK_CHUNKSIZE)
13898 - left = CHECK_CHUNKSIZE;
13899 -
13900 - ptr = phys_to_virt(addr);
13901 -
13902 - if (in_region(ptr, left, crcs, crc_size)) {
13903 - DBG("skipping %08lx, has crc block in\n", addr);
13904 - goto skip_check;
13905 - }
13906 -
13907 - if (in_region(ptr, left, save_at, 32*4 )) {
13908 - DBG("skipping %08lx, has save block in\n", addr);
13909 - goto skip_check;
13910 - }
13911 -
13912 - /* calculate and check the checksum */
13913 -
13914 - calc = crc32_le(~0, ptr, left);
13915 - if (calc != *val) {
13916 - printk(KERN_ERR PFX "Restore CRC error at "
13917 - "%08lx (%08x vs %08x)\n", addr, calc, *val);
13918 -
13919 - DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
13920 - addr, calc, *val);
13921 - }
13922 -
13923 - skip_check:
13924 - val++;
13925 - }
13926 -
13927 - return val;
13928 -}
13929 -
13930 -/* s3c2410_pm_check_restore
13931 - *
13932 - * check the CRCs after the restore event and free the memory used
13933 - * to hold them
13934 -*/
13935 -
13936 -static void s3c2410_pm_check_restore(void)
13937 -{
13938 - if (crcs != NULL) {
13939 - s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
13940 - kfree(crcs);
13941 - crcs = NULL;
13942 - }
13943 -}
13944 -
13945 -#else
13946 -
13947 -#define s3c2410_pm_check_prepare() do { } while(0)
13948 -#define s3c2410_pm_check_restore() do { } while(0)
13949 -#define s3c2410_pm_check_store() do { } while(0)
13950 -#endif
13951 -
13952 -/* helper functions to save and restore register state */
13953 -
13954 -void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
13955 -{
13956 - for (; count > 0; count--, ptr++) {
13957 - ptr->val = __raw_readl(ptr->reg);
13958 - DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
13959 - }
13960 -}
13961 -
13962 -/* s3c2410_pm_do_restore
13963 - *
13964 - * restore the system from the given list of saved registers
13965 - *
13966 - * Note, we do not use DBG() in here, as the system may not have
13967 - * restore the UARTs state yet
13968 -*/
13969 -
13970 -void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
13971 -{
13972 - for (; count > 0; count--, ptr++) {
13973 - printk(KERN_DEBUG "restore %p (restore %08lx, was %08x)\n",
13974 - ptr->reg, ptr->val, __raw_readl(ptr->reg));
13975 -
13976 - __raw_writel(ptr->val, ptr->reg);
13977 - }
13978 -}
13979 -
13980 -/* s3c2410_pm_do_restore_core
13981 - *
13982 - * similar to s3c2410_pm_do_restore_core
13983 - *
13984 - * WARNING: Do not put any debug in here that may effect memory or use
13985 - * peripherals, as things may be changing!
13986 -*/
13987 -
13988 -static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
13989 -{
13990 - for (; count > 0; count--, ptr++) {
13991 - __raw_writel(ptr->val, ptr->reg);
13992 - }
13993 -}
13994 -
13995 -/* s3c2410_pm_show_resume_irqs
13996 - *
13997 - * print any IRQs asserted at resume time (ie, we woke from)
13998 -*/
13999 -
14000 -static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
14001 - unsigned long mask)
14002 -{
14003 - int i;
14004 -
14005 - which &= ~mask;
14006 -
14007 - for (i = 0; i <= 31; i++) {
14008 - if ((which) & (1L<<i)) {
14009 - DBG("IRQ %d asserted at resume\n", start+i);
14010 - }
14011 - }
14012 -}
14013 -
14014 -/* s3c2410_pm_check_resume_pin
14015 +/* s3c_pm_check_resume_pin
14016 *
14017 * check to see if the pin is configured correctly for sleep mode, and
14018 * make any necessary adjustments if it is not
14019 */
14020
14021 -static void s3c2410_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
14022 +static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
14023 {
14024 unsigned long irqstate;
14025 unsigned long pinstate;
14026 @@ -456,21 +101,21 @@
14027
14028 if (!irqstate) {
14029 if (pinstate == S3C2410_GPIO_IRQ)
14030 - DBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
14031 + S3C_PMDBG("Leaving IRQ %d (pin %d) enabled\n", irq, pin);
14032 } else {
14033 if (pinstate == S3C2410_GPIO_IRQ) {
14034 - DBG("Disabling IRQ %d (pin %d)\n", irq, pin);
14035 + S3C_PMDBG("Disabling IRQ %d (pin %d)\n", irq, pin);
14036 s3c2410_gpio_cfgpin(pin, S3C2410_GPIO_INPUT);
14037 }
14038 }
14039 }
14040
14041 -/* s3c2410_pm_configure_extint
14042 +/* s3c_pm_configure_extint
14043 *
14044 * configure all external interrupt pins
14045 */
14046
14047 -static void s3c2410_pm_configure_extint(void)
14048 +void s3c_pm_configure_extint(void)
14049 {
14050 int pin;
14051
14052 @@ -480,336 +125,24 @@
14053 */
14054
14055 for (pin = S3C2410_GPF0; pin <= S3C2410_GPF7; pin++) {
14056 - s3c2410_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
14057 + s3c_pm_check_resume_pin(pin, pin - S3C2410_GPF0);
14058 }
14059
14060 for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
14061 - s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
14062 - }
14063 -}
14064 -
14065 -/* offsets for CON/DAT/UP registers */
14066 -
14067 -#define OFFS_CON (S3C2410_GPACON - S3C2410_GPACON)
14068 -#define OFFS_DAT (S3C2410_GPADAT - S3C2410_GPACON)
14069 -#define OFFS_UP (S3C2410_GPBUP - S3C2410_GPBCON)
14070 -
14071 -/* s3c2410_pm_save_gpios()
14072 - *
14073 - * Save the state of the GPIOs
14074 - */
14075 -
14076 -static void s3c2410_pm_save_gpios(void)
14077 -{
14078 - struct gpio_sleep *gps = gpio_save;
14079 - unsigned int gpio;
14080 -
14081 - for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
14082 - void __iomem *base = gps->base;
14083 -
14084 - gps->gpcon = __raw_readl(base + OFFS_CON);
14085 - gps->gpdat = __raw_readl(base + OFFS_DAT);
14086 -
14087 - if (gpio > 0)
14088 - gps->gpup = __raw_readl(base + OFFS_UP);
14089 -
14090 - }
14091 -}
14092 -
14093 -/* Test whether the given masked+shifted bits of an GPIO configuration
14094 - * are one of the SFN (special function) modes. */
14095 -
14096 -static inline int is_sfn(unsigned long con)
14097 -{
14098 - return (con == 2 || con == 3);
14099 -}
14100 -
14101 -/* Test if the given masked+shifted GPIO configuration is an input */
14102 -
14103 -static inline int is_in(unsigned long con)
14104 -{
14105 - return con == 0;
14106 -}
14107 -
14108 -/* Test if the given masked+shifted GPIO configuration is an output */
14109 -
14110 -static inline int is_out(unsigned long con)
14111 -{
14112 - return con == 1;
14113 -}
14114 -
14115 -/* s3c2410_pm_restore_gpio()
14116 - *
14117 - * Restore one of the GPIO banks that was saved during suspend. This is
14118 - * not as simple as once thought, due to the possibility of glitches
14119 - * from the order that the CON and DAT registers are set in.
14120 - *
14121 - * The three states the pin can be are {IN,OUT,SFN} which gives us 9
14122 - * combinations of changes to check. Three of these, if the pin stays
14123 - * in the same configuration can be discounted. This leaves us with
14124 - * the following:
14125 - *
14126 - * { IN => OUT } Change DAT first
14127 - * { IN => SFN } Change CON first
14128 - * { OUT => SFN } Change CON first, so new data will not glitch
14129 - * { OUT => IN } Change CON first, so new data will not glitch
14130 - * { SFN => IN } Change CON first
14131 - * { SFN => OUT } Change DAT first, so new data will not glitch [1]
14132 - *
14133 - * We do not currently deal with the UP registers as these control
14134 - * weak resistors, so a small delay in change should not need to bring
14135 - * these into the calculations.
14136 - *
14137 - * [1] this assumes that writing to a pin DAT whilst in SFN will set the
14138 - * state for when it is next output.
14139 - */
14140 -
14141 -static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
14142 -{
14143 - void __iomem *base = gps->base;
14144 - unsigned long gps_gpcon = gps->gpcon;
14145 - unsigned long gps_gpdat = gps->gpdat;
14146 - unsigned long old_gpcon;
14147 - unsigned long old_gpdat;
14148 - unsigned long old_gpup = 0x0;
14149 - unsigned long gpcon;
14150 - int nr;
14151 -
14152 - old_gpcon = __raw_readl(base + OFFS_CON);
14153 - old_gpdat = __raw_readl(base + OFFS_DAT);
14154 -
14155 - if (base == S3C2410_GPACON) {
14156 - /* GPACON only has one bit per control / data and no PULLUPs.
14157 - * GPACON[x] = 0 => Output, 1 => SFN */
14158 -
14159 - /* first set all SFN bits to SFN */
14160 -
14161 - gpcon = old_gpcon | gps->gpcon;
14162 - __raw_writel(gpcon, base + OFFS_CON);
14163 -
14164 - /* now set all the other bits */
14165 -
14166 - __raw_writel(gps_gpdat, base + OFFS_DAT);
14167 - __raw_writel(gps_gpcon, base + OFFS_CON);
14168 - } else {
14169 - unsigned long old, new, mask;
14170 - unsigned long change_mask = 0x0;
14171 -
14172 - old_gpup = __raw_readl(base + OFFS_UP);
14173 -
14174 - /* Create a change_mask of all the items that need to have
14175 - * their CON value changed before their DAT value, so that
14176 - * we minimise the work between the two settings.
14177 - */
14178 -
14179 - for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
14180 - old = (old_gpcon & mask) >> nr;
14181 - new = (gps_gpcon & mask) >> nr;
14182 -
14183 - /* If there is no change, then skip */
14184 -
14185 - if (old == new)
14186 - continue;
14187 -
14188 - /* If both are special function, then skip */
14189 -
14190 - if (is_sfn(old) && is_sfn(new))
14191 - continue;
14192 -
14193 - /* Change is IN => OUT, do not change now */
14194 -
14195 - if (is_in(old) && is_out(new))
14196 - continue;
14197 -
14198 - /* Change is SFN => OUT, do not change now */
14199 -
14200 - if (is_sfn(old) && is_out(new))
14201 - continue;
14202 -
14203 - /* We should now be at the case of IN=>SFN,
14204 - * OUT=>SFN, OUT=>IN, SFN=>IN. */
14205 -
14206 - change_mask |= mask;
14207 - }
14208 -
14209 - /* Write the new CON settings */
14210 -
14211 - gpcon = old_gpcon & ~change_mask;
14212 - gpcon |= gps_gpcon & change_mask;
14213 -
14214 - __raw_writel(gpcon, base + OFFS_CON);
14215 -
14216 - /* Now change any items that require DAT,CON */
14217 -
14218 - __raw_writel(gps_gpdat, base + OFFS_DAT);
14219 - __raw_writel(gps_gpcon, base + OFFS_CON);
14220 - __raw_writel(gps->gpup, base + OFFS_UP);
14221 + s3c_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
14222 }
14223 -
14224 - DBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
14225 - index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
14226 }
14227
14228
14229 -/** s3c2410_pm_restore_gpios()
14230 - *
14231 - * Restore the state of the GPIOs
14232 - */
14233 -
14234 -static void s3c2410_pm_restore_gpios(void)
14235 +void s3c_pm_restore_core(void)
14236 {
14237 - struct gpio_sleep *gps = gpio_save;
14238 - int gpio;
14239 -
14240 - for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
14241 - s3c2410_pm_restore_gpio(gpio, gps);
14242 - }
14243 + s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
14244 + s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
14245 }
14246
14247 -void (*pm_cpu_prep)(void);
14248 -void (*pm_cpu_sleep)(void);
14249 -
14250 -#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
14251 -
14252 -/* s3c2410_pm_enter
14253 - *
14254 - * central control for sleep/resume process
14255 -*/
14256 -
14257 -static int s3c2410_pm_enter(suspend_state_t state)
14258 +void s3c_pm_save_core(void)
14259 {
14260 - unsigned long regs_save[16];
14261 -
14262 - /* ensure the debug is initialised (if enabled) */
14263 -
14264 - s3c2410_pm_debug_init();
14265 -
14266 - DBG("s3c2410_pm_enter(%d)\n", state);
14267 -
14268 - if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
14269 - printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
14270 - return -EINVAL;
14271 - }
14272 -
14273 - /* check if we have anything to wake-up with... bad things seem
14274 - * to happen if you suspend with no wakeup (system will often
14275 - * require a full power-cycle)
14276 - */
14277 -
14278 - if (!any_allowed(s3c_irqwake_intmask, s3c_irqwake_intallow) &&
14279 - !any_allowed(s3c_irqwake_eintmask, s3c_irqwake_eintallow)) {
14280 - printk(KERN_ERR PFX "No sources enabled for wake-up!\n");
14281 - printk(KERN_ERR PFX "Aborting sleep\n");
14282 - return -EINVAL;
14283 - }
14284 -
14285 - /* prepare check area if configured */
14286 -
14287 - s3c2410_pm_check_prepare();
14288 -
14289 - /* store the physical address of the register recovery block */
14290 -
14291 - s3c2410_sleep_save_phys = virt_to_phys(regs_save);
14292 -
14293 - DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
14294 -
14295 - /* save all necessary core registers not covered by the drivers */
14296 -
14297 - s3c2410_pm_save_gpios();
14298 - s3c2410_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
14299 - s3c2410_pm_do_save(core_save, ARRAY_SIZE(core_save));
14300 - s3c2410_pm_do_save(uart_save, ARRAY_SIZE(uart_save));
14301 -
14302 - /* set the irq configuration for wake */
14303 -
14304 - s3c2410_pm_configure_extint();
14305 -
14306 - DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
14307 - s3c_irqwake_intmask, s3c_irqwake_eintmask);
14308 -
14309 - __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
14310 - __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
14311 -
14312 - /* ack any outstanding external interrupts before we go to sleep */
14313 -
14314 - __raw_writel(__raw_readl(S3C2410_EINTPEND), S3C2410_EINTPEND);
14315 - __raw_writel(__raw_readl(S3C2410_INTPND), S3C2410_INTPND);
14316 - __raw_writel(__raw_readl(S3C2410_SRCPND), S3C2410_SRCPND);
14317 -
14318 - /* call cpu specific preparation */
14319 -
14320 - pm_cpu_prep();
14321 -
14322 - /* flush cache back to ram */
14323 -
14324 - flush_cache_all();
14325 -
14326 - s3c2410_pm_check_store();
14327 -
14328 - /* send the cpu to sleep... */
14329 -
14330 - __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
14331 -
14332 - /* s3c2410_cpu_save will also act as our return point from when
14333 - * we resume as it saves its own register state, so use the return
14334 - * code to differentiate return from save and return from sleep */
14335 -
14336 - if (s3c2410_cpu_save(regs_save) == 0) {
14337 - flush_cache_all();
14338 - pm_cpu_sleep();
14339 - }
14340 -
14341 - /* restore the cpu state */
14342 -
14343 - cpu_init();
14344 -
14345 - /* restore the system state */
14346 -
14347 - s3c2410_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
14348 - s3c2410_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
14349 - s3c2410_pm_do_restore(uart_save, ARRAY_SIZE(uart_save));
14350 - s3c2410_pm_restore_gpios();
14351 -
14352 - s3c2410_pm_debug_init();
14353 -
14354 - /* check what irq (if any) restored the system */
14355 -
14356 - DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
14357 - __raw_readl(S3C2410_SRCPND),
14358 - __raw_readl(S3C2410_EINTPEND));
14359 -
14360 - s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
14361 - s3c_irqwake_intmask);
14362 -
14363 - s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
14364 - s3c_irqwake_eintmask);
14365 -
14366 - DBG("post sleep, preparing to return\n");
14367 -
14368 - s3c2410_pm_check_restore();
14369 -
14370 - /* ok, let's return from sleep */
14371 -
14372 - DBG("S3C2410 PM Resume (post-restore)\n");
14373 - return 0;
14374 + s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
14375 + s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
14376 }
14377
14378 -static struct platform_suspend_ops s3c2410_pm_ops = {
14379 - .enter = s3c2410_pm_enter,
14380 - .valid = suspend_valid_only_mem,
14381 -};
14382 -
14383 -/* s3c2410_pm_init
14384 - *
14385 - * Attach the power management functions. This should be called
14386 - * from the board specific initialisation if the board supports
14387 - * it.
14388 -*/
14389 -
14390 -int __init s3c2410_pm_init(void)
14391 -{
14392 - printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
14393 -
14394 - suspend_set_ops(&s3c2410_pm_ops);
14395 - return 0;
14396 -}
14397 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/pm-simtec.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/pm-simtec.c
14398 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/pm-simtec.c 2009-05-10 22:05:03.000000000 +0200
14399 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/pm-simtec.c 2009-05-10 22:27:59.000000000 +0200
14400 @@ -61,7 +61,7 @@
14401
14402 __raw_writel(gstatus4, S3C2410_GSTATUS4);
14403
14404 - return s3c2410_pm_init();
14405 + return s3c_pm_init();
14406 }
14407
14408 arch_initcall(pm_simtec_init);
14409 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/pwm-clock.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/pwm-clock.c
14410 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/pwm-clock.c 1970-01-01 01:00:00.000000000 +0100
14411 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/pwm-clock.c 2009-05-10 22:27:59.000000000 +0200
14412 @@ -0,0 +1,437 @@
14413 +/* linux/arch/arm/plat-s3c24xx/pwm-clock.c
14414 + *
14415 + * Copyright (c) 2007 Simtec Electronics
14416 + * Copyright (c) 2007, 2008 Ben Dooks
14417 + * Ben Dooks <ben-linux@fluff.org>
14418 + *
14419 + * This program is free software; you can redistribute it and/or modify
14420 + * it under the terms of the GNU General Public License as published by
14421 + * the Free Software Foundation; either version 2 of the License.
14422 +*/
14423 +
14424 +#include <linux/init.h>
14425 +#include <linux/module.h>
14426 +#include <linux/kernel.h>
14427 +#include <linux/list.h>
14428 +#include <linux/errno.h>
14429 +#include <linux/clk.h>
14430 +#include <linux/err.h>
14431 +#include <linux/io.h>
14432 +
14433 +#include <mach/hardware.h>
14434 +#include <asm/irq.h>
14435 +
14436 +#include <mach/regs-clock.h>
14437 +#include <mach/regs-gpio.h>
14438 +
14439 +#include <asm/plat-s3c24xx/clock.h>
14440 +#include <asm/plat-s3c24xx/cpu.h>
14441 +
14442 +#include <asm/plat-s3c/regs-timer.h>
14443 +
14444 +/* Each of the timers 0 through 5 go through the following
14445 + * clock tree, with the inputs depending on the timers.
14446 + *
14447 + * pclk ---- [ prescaler 0 ] -+---> timer 0
14448 + * +---> timer 1
14449 + *
14450 + * pclk ---- [ prescaler 1 ] -+---> timer 2
14451 + * +---> timer 3
14452 + * \---> timer 4
14453 + *
14454 + * Which are fed into the timers as so:
14455 + *
14456 + * prescaled 0 ---- [ div 2,4,8,16 ] ---\
14457 + * [mux] -> timer 0
14458 + * tclk 0 ------------------------------/
14459 + *
14460 + * prescaled 0 ---- [ div 2,4,8,16 ] ---\
14461 + * [mux] -> timer 1
14462 + * tclk 0 ------------------------------/
14463 + *
14464 + *
14465 + * prescaled 1 ---- [ div 2,4,8,16 ] ---\
14466 + * [mux] -> timer 2
14467 + * tclk 1 ------------------------------/
14468 + *
14469 + * prescaled 1 ---- [ div 2,4,8,16 ] ---\
14470 + * [mux] -> timer 3
14471 + * tclk 1 ------------------------------/
14472 + *
14473 + * prescaled 1 ---- [ div 2,4,8, 16 ] --\
14474 + * [mux] -> timer 4
14475 + * tclk 1 ------------------------------/
14476 + *
14477 + * Since the mux and the divider are tied together in the
14478 + * same register space, it is impossible to set the parent
14479 + * and the rate at the same time. To avoid this, we add an
14480 + * intermediate 'prescaled-and-divided' clock to select
14481 + * as the parent for the timer input clock called tdiv.
14482 + *
14483 + * prescaled clk --> pwm-tdiv ---\
14484 + * [ mux ] --> timer X
14485 + * tclk -------------------------/
14486 +*/
14487 +
14488 +static unsigned long clk_pwm_scaler_getrate(struct clk *clk)
14489 +{
14490 + unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
14491 +
14492 + if (clk->id == 1) {
14493 + tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK;
14494 + tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT;
14495 + } else {
14496 + tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK;
14497 + }
14498 +
14499 + return clk_get_rate(clk->parent) / (tcfg0 + 1);
14500 +}
14501 +
14502 +/* TODO - add set rate calls. */
14503 +
14504 +static struct clk clk_timer_scaler[] = {
14505 + [0] = {
14506 + .name = "pwm-scaler0",
14507 + .id = -1,
14508 + .get_rate = clk_pwm_scaler_getrate,
14509 + },
14510 + [1] = {
14511 + .name = "pwm-scaler1",
14512 + .id = -1,
14513 + .get_rate = clk_pwm_scaler_getrate,
14514 + },
14515 +};
14516 +
14517 +static struct clk clk_timer_tclk[] = {
14518 + [0] = {
14519 + .name = "pwm-tclk0",
14520 + .id = -1,
14521 + },
14522 + [1] = {
14523 + .name = "pwm-tclk1",
14524 + .id = -1,
14525 + },
14526 +};
14527 +
14528 +struct pwm_tdiv_clk {
14529 + struct clk clk;
14530 + unsigned int divisor;
14531 +};
14532 +
14533 +static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk)
14534 +{
14535 + return container_of(clk, struct pwm_tdiv_clk, clk);
14536 +}
14537 +
14538 +static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
14539 +{
14540 + return 1 << (1 + tcfg1);
14541 +}
14542 +
14543 +static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk)
14544 +{
14545 + unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
14546 + unsigned int divisor;
14547 +
14548 + tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
14549 + tcfg1 &= S3C2410_TCFG1_MUX_MASK;
14550 +
14551 + if (tcfg1 == S3C2410_TCFG1_MUX_TCLK)
14552 + divisor = to_tdiv(clk)->divisor;
14553 + else
14554 + divisor = tcfg_to_divisor(tcfg1);
14555 +
14556 + return clk_get_rate(clk->parent) / divisor;
14557 +}
14558 +
14559 +static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk,
14560 + unsigned long rate)
14561 +{
14562 + unsigned long parent_rate;
14563 + unsigned long divisor;
14564 +
14565 + parent_rate = clk_get_rate(clk->parent);
14566 + divisor = parent_rate / rate;
14567 +
14568 + if (divisor <= 2)
14569 + divisor = 2;
14570 + else if (divisor <= 4)
14571 + divisor = 4;
14572 + else if (divisor <= 8)
14573 + divisor = 8;
14574 + else
14575 + divisor = 16;
14576 +
14577 + return parent_rate / divisor;
14578 +}
14579 +
14580 +static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk)
14581 +{
14582 + unsigned long bits;
14583 +
14584 + switch (divclk->divisor) {
14585 + case 2:
14586 + bits = S3C2410_TCFG1_MUX_DIV2;
14587 + break;
14588 + case 4:
14589 + bits = S3C2410_TCFG1_MUX_DIV4;
14590 + break;
14591 + case 8:
14592 + bits = S3C2410_TCFG1_MUX_DIV8;
14593 + break;
14594 + case 16:
14595 + default:
14596 + bits = S3C2410_TCFG1_MUX_DIV16;
14597 + break;
14598 + }
14599 +
14600 + return bits;
14601 +}
14602 +
14603 +static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk)
14604 +{
14605 + unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
14606 + unsigned long bits = clk_pwm_tdiv_bits(divclk);
14607 + unsigned long flags;
14608 + unsigned long shift = S3C2410_TCFG1_SHIFT(divclk->clk.id);
14609 +
14610 + local_irq_save(flags);
14611 +
14612 + tcfg1 = __raw_readl(S3C2410_TCFG1);
14613 + tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
14614 + tcfg1 |= bits << shift;
14615 + __raw_writel(tcfg1, S3C2410_TCFG1);
14616 +
14617 + local_irq_restore(flags);
14618 +}
14619 +
14620 +static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate)
14621 +{
14622 + struct pwm_tdiv_clk *divclk = to_tdiv(clk);
14623 + unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
14624 + unsigned long parent_rate = clk_get_rate(clk->parent);
14625 + unsigned long divisor;
14626 +
14627 + tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
14628 + tcfg1 &= S3C2410_TCFG1_MUX_MASK;
14629 +
14630 + rate = clk_round_rate(clk, rate);
14631 + divisor = parent_rate / rate;
14632 +
14633 + if (divisor > 16)
14634 + return -EINVAL;
14635 +
14636 + divclk->divisor = divisor;
14637 +
14638 + /* Update the current MUX settings if we are currently
14639 + * selected as the clock source for this clock. */
14640 +
14641 + if (tcfg1 != S3C2410_TCFG1_MUX_TCLK)
14642 + clk_pwm_tdiv_update(divclk);
14643 +
14644 + return 0;
14645 +}
14646 +
14647 +static struct pwm_tdiv_clk clk_timer_tdiv[] = {
14648 + [0] = {
14649 + .clk = {
14650 + .name = "pwm-tdiv",
14651 + .parent = &clk_timer_scaler[0],
14652 + .get_rate = clk_pwm_tdiv_get_rate,
14653 + .set_rate = clk_pwm_tdiv_set_rate,
14654 + .round_rate = clk_pwm_tdiv_round_rate,
14655 + },
14656 + },
14657 + [1] = {
14658 + .clk = {
14659 + .name = "pwm-tdiv",
14660 + .parent = &clk_timer_scaler[0],
14661 + .get_rate = clk_pwm_tdiv_get_rate,
14662 + .set_rate = clk_pwm_tdiv_set_rate,
14663 + .round_rate = clk_pwm_tdiv_round_rate,
14664 + }
14665 + },
14666 + [2] = {
14667 + .clk = {
14668 + .name = "pwm-tdiv",
14669 + .parent = &clk_timer_scaler[1],
14670 + .get_rate = clk_pwm_tdiv_get_rate,
14671 + .set_rate = clk_pwm_tdiv_set_rate,
14672 + .round_rate = clk_pwm_tdiv_round_rate,
14673 + },
14674 + },
14675 + [3] = {
14676 + .clk = {
14677 + .name = "pwm-tdiv",
14678 + .parent = &clk_timer_scaler[1],
14679 + .get_rate = clk_pwm_tdiv_get_rate,
14680 + .set_rate = clk_pwm_tdiv_set_rate,
14681 + .round_rate = clk_pwm_tdiv_round_rate,
14682 + },
14683 + },
14684 + [4] = {
14685 + .clk = {
14686 + .name = "pwm-tdiv",
14687 + .parent = &clk_timer_scaler[1],
14688 + .get_rate = clk_pwm_tdiv_get_rate,
14689 + .set_rate = clk_pwm_tdiv_set_rate,
14690 + .round_rate = clk_pwm_tdiv_round_rate,
14691 + },
14692 + },
14693 +};
14694 +
14695 +static int __init clk_pwm_tdiv_register(unsigned int id)
14696 +{
14697 + struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id];
14698 + unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
14699 +
14700 + tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
14701 + tcfg1 &= S3C2410_TCFG1_MUX_MASK;
14702 +
14703 + divclk->clk.id = id;
14704 + divclk->divisor = tcfg_to_divisor(tcfg1);
14705 +
14706 + return s3c24xx_register_clock(&divclk->clk);
14707 +}
14708 +
14709 +static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id)
14710 +{
14711 + return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0];
14712 +}
14713 +
14714 +static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id)
14715 +{
14716 + return &clk_timer_tdiv[id].clk;
14717 +}
14718 +
14719 +static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent)
14720 +{
14721 + unsigned int id = clk->id;
14722 + unsigned long tcfg1;
14723 + unsigned long flags;
14724 + unsigned long bits;
14725 + unsigned long shift = S3C2410_TCFG1_SHIFT(id);
14726 +
14727 + if (parent == s3c24xx_pwmclk_tclk(id))
14728 + bits = S3C2410_TCFG1_MUX_TCLK << shift;
14729 + else if (parent == s3c24xx_pwmclk_tdiv(id))
14730 + bits = clk_pwm_tdiv_bits(to_tdiv(parent)) << shift;
14731 + else
14732 + return -EINVAL;
14733 +
14734 + clk->parent = parent;
14735 +
14736 + local_irq_save(flags);
14737 +
14738 + tcfg1 = __raw_readl(S3C2410_TCFG1);
14739 + tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
14740 + __raw_writel(tcfg1 | bits, S3C2410_TCFG1);
14741 +
14742 + local_irq_restore(flags);
14743 +
14744 + return 0;
14745 +}
14746 +
14747 +static struct clk clk_tin[] = {
14748 + [0] = {
14749 + .name = "pwm-tin",
14750 + .id = 0,
14751 + .set_parent = clk_pwm_tin_set_parent,
14752 + },
14753 + [1] = {
14754 + .name = "pwm-tin",
14755 + .id = 1,
14756 + .set_parent = clk_pwm_tin_set_parent,
14757 + },
14758 + [2] = {
14759 + .name = "pwm-tin",
14760 + .id = 2,
14761 + .set_parent = clk_pwm_tin_set_parent,
14762 + },
14763 + [3] = {
14764 + .name = "pwm-tin",
14765 + .id = 3,
14766 + .set_parent = clk_pwm_tin_set_parent,
14767 + },
14768 + [4] = {
14769 + .name = "pwm-tin",
14770 + .id = 4,
14771 + .set_parent = clk_pwm_tin_set_parent,
14772 + },
14773 +};
14774 +
14775 +static __init int clk_pwm_tin_register(struct clk *pwm)
14776 +{
14777 + unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
14778 + unsigned int id = pwm->id;
14779 +
14780 + struct clk *parent;
14781 + int ret;
14782 +
14783 + ret = s3c24xx_register_clock(pwm);
14784 + if (ret < 0)
14785 + return ret;
14786 +
14787 + tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
14788 + tcfg1 &= S3C2410_TCFG1_MUX_MASK;
14789 +
14790 + if (tcfg1 == S3C2410_TCFG1_MUX_TCLK)
14791 + parent = s3c24xx_pwmclk_tclk(id);
14792 + else
14793 + parent = s3c24xx_pwmclk_tdiv(id);
14794 +
14795 + return clk_set_parent(pwm, parent);
14796 +}
14797 +
14798 +static __init int s3c24xx_pwmclk_init(void)
14799 +{
14800 + struct clk *clk_timers;
14801 + unsigned int clk;
14802 + int ret;
14803 +
14804 + clk_timers = clk_get(NULL, "timers");
14805 + if (IS_ERR(clk_timers)) {
14806 + printk(KERN_ERR "%s: no parent clock\n", __func__);
14807 + return -EINVAL;
14808 + }
14809 +
14810 + for (clk = 0; clk < ARRAY_SIZE(clk_timer_scaler); clk++) {
14811 + clk_timer_scaler[clk].parent = clk_timers;
14812 + ret = s3c24xx_register_clock(&clk_timer_scaler[clk]);
14813 + if (ret < 0) {
14814 + printk(KERN_ERR "error adding pwm scaler%d clock\n", clk);
14815 + goto err;
14816 + }
14817 + }
14818 +
14819 + for (clk = 0; clk < ARRAY_SIZE(clk_timer_tclk); clk++) {
14820 + ret = s3c24xx_register_clock(&clk_timer_tclk[clk]);
14821 + if (ret < 0) {
14822 + printk(KERN_ERR "error adding pww tclk%d\n", clk);
14823 + goto err;
14824 + }
14825 + }
14826 +
14827 + for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) {
14828 + ret = clk_pwm_tdiv_register(clk);
14829 + if (ret < 0) {
14830 + printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk);
14831 + goto err;
14832 + }
14833 + }
14834 +
14835 + for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) {
14836 + ret = clk_pwm_tin_register(&clk_tin[clk]);
14837 + if (ret < 0) {
14838 + printk(KERN_ERR "error adding pwm%d tin clock\n", clk);
14839 + goto err;
14840 + }
14841 + }
14842 +
14843 + return 0;
14844 +
14845 + err:
14846 + return ret;
14847 +}
14848 +
14849 +arch_initcall(s3c24xx_pwmclk_init);
14850 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/s3c244x.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/s3c244x.c
14851 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/s3c244x.c 2009-05-10 22:05:03.000000000 +0200
14852 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/s3c244x.c 2009-05-10 22:27:59.000000000 +0200
14853 @@ -59,6 +59,8 @@
14854 s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
14855 }
14856
14857 +extern struct platform_device s3c_device_ts;
14858 +
14859 void __init s3c244x_map_io(void)
14860 {
14861 /* register our io-tables */
14862 @@ -70,6 +72,7 @@
14863 s3c_device_sdi.name = "s3c2440-sdi";
14864 s3c_device_i2c0.name = "s3c2440-i2c";
14865 s3c_device_nand.name = "s3c2440-nand";
14866 + s3c_device_ts.name = "s3c2440-ts";
14867 s3c_device_usbgadget.name = "s3c2440-usbgadget";
14868 }
14869
14870 @@ -145,13 +148,13 @@
14871
14872 static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
14873 {
14874 - s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
14875 + s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
14876 return 0;
14877 }
14878
14879 static int s3c244x_resume(struct sys_device *dev)
14880 {
14881 - s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
14882 + s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
14883 return 0;
14884 }
14885
14886 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/sleep.S linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/sleep.S
14887 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/sleep.S 2009-05-10 22:05:03.000000000 +0200
14888 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/sleep.S 2009-05-10 22:27:59.000000000 +0200
14889 @@ -41,7 +41,7 @@
14890
14891 .text
14892
14893 - /* s3c2410_cpu_save
14894 + /* s3c_cpu_save
14895 *
14896 * save enough of the CPU state to allow us to re-start
14897 * pm.c code. as we store items like the sp/lr, we will
14898 @@ -59,7 +59,7 @@
14899 * 1 => resumed from sleep
14900 */
14901
14902 -ENTRY(s3c2410_cpu_save)
14903 +ENTRY(s3c_cpu_save)
14904 stmfd sp!, { r4 - r12, lr }
14905
14906 @@ store co-processor registers
14907 @@ -84,7 +84,7 @@
14908 .ltorg
14909
14910 @@ the next bits sit in the .data segment, even though they
14911 - @@ happen to be code... the s3c2410_sleep_save_phys needs to be
14912 + @@ happen to be code... the s3c_sleep_save_phys needs to be
14913 @@ accessed by the resume code before it can restore the MMU.
14914 @@ This means that the variable has to be close enough for the
14915 @@ code to read it... since the .text segment needs to be RO,
14916 @@ -92,19 +92,19 @@
14917
14918 .data
14919
14920 - .global s3c2410_sleep_save_phys
14921 -s3c2410_sleep_save_phys:
14922 + .global s3c_sleep_save_phys
14923 +s3c_sleep_save_phys:
14924 .word 0
14925
14926
14927 /* sleep magic, to allow the bootloader to check for an valid
14928 * image to resume to. Must be the first word before the
14929 - * s3c2410_cpu_resume entry.
14930 + * s3c_cpu_resume entry.
14931 */
14932
14933 .word 0x2bedf00d
14934
14935 - /* s3c2410_cpu_resume
14936 + /* s3c_cpu_resume
14937 *
14938 * resume code entry for bootloader to call
14939 *
14940 @@ -113,7 +113,7 @@
14941 * must not write to the code segment (code is read-only)
14942 */
14943
14944 -ENTRY(s3c2410_cpu_resume)
14945 +ENTRY(s3c_cpu_resume)
14946 mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
14947 msr cpsr_c, r0
14948
14949 @@ -145,7 +145,7 @@
14950 mcr p15, 0, r1, c8, c7, 0 @@ invalidate I & D TLBs
14951 mcr p15, 0, r1, c7, c7, 0 @@ invalidate I & D caches
14952
14953 - ldr r0, s3c2410_sleep_save_phys @ address of restore block
14954 + ldr r0, s3c_sleep_save_phys @ address of restore block
14955 ldmia r0, { r4 - r13 }
14956
14957 mcr p15, 0, r4, c13, c0, 0 @ PID
14958 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/time.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/time.c
14959 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c24xx/time.c 1970-01-01 01:00:00.000000000 +0100
14960 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c24xx/time.c 2009-05-10 22:27:59.000000000 +0200
14961 @@ -0,0 +1,480 @@
14962 +/* linux/arch/arm/plat-s3c24xx/time.c
14963 + *
14964 + * Copyright (C) 2003-2005 Simtec Electronics
14965 + * Ben Dooks, <ben@simtec.co.uk>
14966 + *
14967 + * dyn_tick support by Andrzej Zaborowski based on omap_dyn_tick_timer.
14968 + *
14969 + * This program is free software; you can redistribute it and/or modify
14970 + * it under the terms of the GNU General Public License as published by
14971 + * the Free Software Foundation; either version 2 of the License, or
14972 + * (at your option) any later version.
14973 + *
14974 + * This program is distributed in the hope that it will be useful,
14975 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
14976 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14977 + * GNU General Public License for more details.
14978 + *
14979 + * You should have received a copy of the GNU General Public License
14980 + * along with this program; if not, write to the Free Software
14981 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
14982 + */
14983 +
14984 +#include <linux/kernel.h>
14985 +#include <linux/sched.h>
14986 +#include <linux/init.h>
14987 +#include <linux/interrupt.h>
14988 +#include <linux/irq.h>
14989 +#include <linux/err.h>
14990 +#include <linux/clk.h>
14991 +
14992 +#include <asm/system.h>
14993 +#include <asm/leds.h>
14994 +#include <asm/mach-types.h>
14995 +
14996 +#include <asm/io.h>
14997 +#include <asm/irq.h>
14998 +#include <mach/map.h>
14999 +#include <asm/plat-s3c/regs-timer.h>
15000 +#include <mach/regs-irq.h>
15001 +#include <asm/mach/time.h>
15002 +
15003 +#include <asm/plat-s3c24xx/clock.h>
15004 +#include <asm/plat-s3c24xx/cpu.h>
15005 +
15006 +static unsigned long timer_startval;
15007 +static unsigned long timer_usec_ticks;
15008 +static struct work_struct resume_work;
15009 +
15010 +unsigned long pclk;
15011 +struct clk *clk;
15012 +
15013 +#define TIMER_USEC_SHIFT 16
15014 +
15015 +/* we use the shifted arithmetic to work out the ratio of timer ticks
15016 + * to usecs, as often the peripheral clock is not a nice even multiple
15017 + * of 1MHz.
15018 + *
15019 + * shift of 14 and 15 are too low for the 12MHz, 16 seems to be ok
15020 + * for the current HZ value of 200 without producing overflows.
15021 + *
15022 + * Original patch by Dimitry Andric, updated by Ben Dooks
15023 +*/
15024 +
15025 +
15026 +/* timer_mask_usec_ticks
15027 + *
15028 + * given a clock and divisor, make the value to pass into timer_ticks_to_usec
15029 + * to scale the ticks into usecs
15030 +*/
15031 +
15032 +static inline unsigned long
15033 +timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)
15034 +{
15035 + unsigned long den = pclk / 1000;
15036 +
15037 + return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;
15038 +}
15039 +
15040 +/* timer_ticks_to_usec
15041 + *
15042 + * convert timer ticks to usec.
15043 +*/
15044 +
15045 +static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
15046 +{
15047 + unsigned long res;
15048 +
15049 + res = ticks * timer_usec_ticks;
15050 + res += 1 << (TIMER_USEC_SHIFT - 4); /* round up slightly */
15051 +
15052 + return res >> TIMER_USEC_SHIFT;
15053 +}
15054 +
15055 +/***
15056 + * Returns microsecond since last clock interrupt. Note that interrupts
15057 + * will have been disabled by do_gettimeoffset()
15058 + * IRQs are disabled before entering here from do_gettimeofday()
15059 + */
15060 +
15061 +#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
15062 +
15063 +unsigned long s3c2410_gettimeoffset (void)
15064 +{
15065 + unsigned long tdone;
15066 + unsigned long irqpend;
15067 + unsigned long tval;
15068 +
15069 + /* work out how many ticks have gone since last timer interrupt */
15070 +
15071 + tval = __raw_readl(S3C2410_TCNTO(4));
15072 + tdone = timer_startval - tval;
15073 +
15074 + /* check to see if there is an interrupt pending */
15075 +
15076 + irqpend = __raw_readl(S3C2410_SRCPND);
15077 + if (irqpend & SRCPND_TIMER4) {
15078 + /* re-read the timer, and try and fix up for the missed
15079 + * interrupt. Note, the interrupt may go off before the
15080 + * timer has re-loaded from wrapping.
15081 + */
15082 +
15083 + tval = __raw_readl(S3C2410_TCNTO(4));
15084 + tdone = timer_startval - tval;
15085 +
15086 + if (tval != 0)
15087 + tdone += timer_startval;
15088 + }
15089 +
15090 + return timer_ticks_to_usec(tdone);
15091 +}
15092 +
15093 +
15094 +/*
15095 + * IRQ handler for the timer
15096 + */
15097 +static irqreturn_t
15098 +s3c2410_timer_interrupt(int irq, void *dev_id)
15099 +{
15100 + timer_tick();
15101 + return IRQ_HANDLED;
15102 +}
15103 +
15104 +static struct irqaction s3c2410_timer_irq = {
15105 + .name = "S3C2410 Timer Tick",
15106 + .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
15107 + .handler = s3c2410_timer_interrupt,
15108 +};
15109 +
15110 +#define use_tclk1_12() ( \
15111 + machine_is_bast() || \
15112 + machine_is_vr1000() || \
15113 + machine_is_anubis() || \
15114 + machine_is_osiris() )
15115 +
15116 +/*
15117 + * Set up timer interrupt, and return the current time in seconds.
15118 + *
15119 + * Currently we only use timer4, as it is the only timer which has no
15120 + * other function that can be exploited externally
15121 + */
15122 +static void s3c2410_timer_setup (void)
15123 +{
15124 + unsigned long tcon;
15125 + unsigned long tcnt;
15126 + unsigned long tcfg1;
15127 + unsigned long tcfg0;
15128 +
15129 + tcnt = 0xffff; /* default value for tcnt */
15130 +
15131 + /* read the current timer configuration bits */
15132 +
15133 + tcon = __raw_readl(S3C2410_TCON);
15134 + tcfg1 = __raw_readl(S3C2410_TCFG1);
15135 + tcfg0 = __raw_readl(S3C2410_TCFG0);
15136 +
15137 + /* configure the system for whichever machine is in use */
15138 +
15139 + if (use_tclk1_12()) {
15140 + /* timer is at 12MHz, scaler is 1 */
15141 + timer_usec_ticks = timer_mask_usec_ticks(1, 12000000);
15142 + tcnt = 12000000 / HZ;
15143 +
15144 + tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
15145 + tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
15146 + } else {
15147 + /* since values around 50 to
15148 + * 70MHz are not values we can directly generate the timer
15149 + * value from, we need to pre-scale and divide before using it.
15150 + *
15151 + * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz
15152 + * (8.45 ticks per usec)
15153 + */
15154 +
15155 + /* configure clock tick */
15156 + timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
15157 + printk("timer_usec_ticks = %lu\n", timer_usec_ticks);
15158 +
15159 + tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
15160 + tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
15161 +
15162 + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
15163 + tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
15164 +
15165 + tcnt = (pclk / 6) / HZ;
15166 + }
15167 +
15168 + /* timers reload after counting zero, so reduce the count by 1 */
15169 +
15170 + tcnt--;
15171 +
15172 + printk("timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n",
15173 + tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks);
15174 +
15175 + /* check to see if timer is within 16bit range... */
15176 + if (tcnt > 0xffff) {
15177 + panic("setup_timer: HZ is too small, cannot configure timer!");
15178 + return;
15179 + }
15180 +
15181 + __raw_writel(tcfg1, S3C2410_TCFG1);
15182 + __raw_writel(tcfg0, S3C2410_TCFG0);
15183 +
15184 + timer_startval = tcnt;
15185 + __raw_writel(tcnt, S3C2410_TCNTB(4));
15186 +
15187 + /* ensure timer is stopped... */
15188 +
15189 + tcon &= ~(7<<20);
15190 + tcon |= S3C2410_TCON_T4RELOAD;
15191 + tcon |= S3C2410_TCON_T4MANUALUPD;
15192 +
15193 + __raw_writel(tcon, S3C2410_TCON);
15194 + __raw_writel(tcnt, S3C2410_TCNTB(4));
15195 + __raw_writel(tcnt, S3C2410_TCMPB(4));
15196 +
15197 + /* start the timer running */
15198 + tcon |= S3C2410_TCON_T4START;
15199 + tcon &= ~S3C2410_TCON_T4MANUALUPD;
15200 + __raw_writel(tcon, S3C2410_TCON);
15201 +
15202 + __raw_writel(__raw_readl(S3C2410_INTMSK) & (~(1UL << 14)),
15203 + S3C2410_INTMSK);
15204 +
15205 +}
15206 +
15207 +struct sys_timer s3c24xx_timer;
15208 +static void timer_resume_work(struct work_struct *work)
15209 +{
15210 + clk_enable(clk);
15211 +
15212 +#ifdef CONFIG_NO_IDLE_HZ
15213 + if (s3c24xx_timer.dyn_tick->state & DYN_TICK_ENABLED)
15214 + s3c24xx_timer.dyn_tick->enable();
15215 + else
15216 +#endif
15217 + s3c2410_timer_setup();
15218 +}
15219 +
15220 +static void __init s3c2410_timer_init (void)
15221 +{
15222 + if (!use_tclk1_12()) {
15223 + /* for the h1940 (and others), we use the pclk from the core
15224 + * to generate the timer values.
15225 + */
15226 +
15227 + /* this is used as default if no other timer can be found */
15228 + clk = clk_get(NULL, "timers");
15229 + if (IS_ERR(clk))
15230 + panic("failed to get clock for system timer");
15231 +
15232 + clk_enable(clk);
15233 +
15234 + pclk = clk_get_rate(clk);
15235 + printk("pclk = %lu\n", pclk);
15236 + }
15237 +
15238 + INIT_WORK(&resume_work, timer_resume_work);
15239 + s3c2410_timer_setup();
15240 + setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
15241 +}
15242 +
15243 +static void s3c2410_timer_resume_work(struct work_struct *work)
15244 +{
15245 + s3c2410_timer_setup();
15246 +}
15247 +
15248 +static void s3c2410_timer_resume(void)
15249 +{
15250 + static DECLARE_WORK(work, s3c2410_timer_resume_work);
15251 + int res;
15252 +
15253 + res = schedule_work(&work);
15254 + if (!res)
15255 + printk(KERN_ERR
15256 + "s3c2410_timer_resume_work already queued ???\n");
15257 +}
15258 +
15259 +#ifdef CONFIG_NO_IDLE_HZ
15260 +/*
15261 + * We'll set a constant prescaler so we don't have to bother setting it
15262 + * when reprogramming and so that we avoid costly divisions.
15263 + *
15264 + * (2 * HZ) << INPUT_FREQ_SHIFT is the desired frequency after prescaler.
15265 + * At HZ == 200, HZ * 1024 should work for PCLKs of up to ~53.5 MHz.
15266 + */
15267 +#define INPUT_FREQ_SHIFT 9
15268 +
15269 +static int ticks_last;
15270 +static int ticks_left;
15271 +static uint32_t tcnto_last;
15272 +
15273 +static inline int s3c24xx_timer_read(void)
15274 +{
15275 + uint32_t tcnto = __raw_readl(S3C2410_TCNTO(4));
15276 +
15277 + /*
15278 + * WARNING: sometimes we get called before TCNTB has been
15279 + * loaded into the counter and TCNTO then returns its previous
15280 + * value and kill us, so don't do anything before counter is
15281 + * reloaded.
15282 + */
15283 + if (unlikely(tcnto == tcnto_last))
15284 + return ticks_last;
15285 +
15286 + tcnto_last = -1;
15287 + return tcnto <<
15288 + ((__raw_readl(S3C2410_TCFG1) >> S3C2410_TCFG1_MUX4_SHIFT) & 3);
15289 +}
15290 +
15291 +static inline void s3c24xx_timer_program(int ticks)
15292 +{
15293 + uint32_t tcon = __raw_readl(S3C2410_TCON) & ~(7 << 20);
15294 + uint32_t tcfg1 = __raw_readl(S3C2410_TCFG1) & ~S3C2410_TCFG1_MUX4_MASK;
15295 +
15296 + /* Just make sure the timer is stopped. */
15297 + __raw_writel(tcon, S3C2410_TCON);
15298 +
15299 + /* TODO: add likely()ies / unlikely()ies */
15300 + if (ticks >> 18) {
15301 + ticks_last = min(ticks, 0xffff << 3);
15302 + ticks_left = ticks - ticks_last;
15303 + __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV16, S3C2410_TCFG1);
15304 + __raw_writel(ticks_last >> 3, S3C2410_TCNTB(4));
15305 + } else if (ticks >> 17) {
15306 + ticks_last = ticks;
15307 + ticks_left = 0;
15308 + __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV8, S3C2410_TCFG1);
15309 + __raw_writel(ticks_last >> 2, S3C2410_TCNTB(4));
15310 + } else if (ticks >> 16) {
15311 + ticks_last = ticks;
15312 + ticks_left = 0;
15313 + __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV4, S3C2410_TCFG1);
15314 + __raw_writel(ticks_last >> 1, S3C2410_TCNTB(4));
15315 + } else {
15316 + ticks_last = ticks;
15317 + ticks_left = 0;
15318 + __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV2, S3C2410_TCFG1);
15319 + __raw_writel(ticks_last >> 0, S3C2410_TCNTB(4));
15320 + }
15321 +
15322 + tcnto_last = __raw_readl(S3C2410_TCNTO(4));
15323 + __raw_writel(tcon | S3C2410_TCON_T4MANUALUPD,
15324 + S3C2410_TCON);
15325 + __raw_writel(tcon | S3C2410_TCON_T4START,
15326 + S3C2410_TCON);
15327 +}
15328 +
15329 +/*
15330 + * If we have already waited all the time we were supposed to wait,
15331 + * kick the timer, setting the longest allowed timeout value just
15332 + * for time-keeping.
15333 + */
15334 +static inline void s3c24xx_timer_program_idle(void)
15335 +{
15336 + s3c24xx_timer_program(0xffff << 3);
15337 +}
15338 +
15339 +static inline void s3c24xx_timer_update(int restart)
15340 +{
15341 + int ticks_cur = s3c24xx_timer_read();
15342 + int jiffies_elapsed = (ticks_last - ticks_cur) >> INPUT_FREQ_SHIFT;
15343 + int subjiffy = ticks_last - (jiffies_elapsed << INPUT_FREQ_SHIFT);
15344 +
15345 + if (restart) {
15346 + if (ticks_left >= (1 << INPUT_FREQ_SHIFT))
15347 + s3c24xx_timer_program(ticks_left);
15348 + else
15349 + s3c24xx_timer_program_idle();
15350 + ticks_last += subjiffy;
15351 + } else
15352 + ticks_last = subjiffy;
15353 +
15354 + while (jiffies_elapsed --)
15355 + timer_tick();
15356 +}
15357 +
15358 +/* Called when the timer expires. */
15359 +static irqreturn_t s3c24xx_timer_handler(int irq, void *dev_id)
15360 +{
15361 + tcnto_last = -1;
15362 + s3c24xx_timer_update(1);
15363 +
15364 + return IRQ_HANDLED;
15365 +}
15366 +
15367 +/* Called to update jiffies with time elapsed. */
15368 +static irqreturn_t s3c24xx_timer_handler_dyn_tick(int irq, void *dev_id)
15369 +{
15370 + s3c24xx_timer_update(0);
15371 +
15372 + return IRQ_HANDLED;
15373 +}
15374 +
15375 +/*
15376 + * Programs the next timer interrupt needed. Called when dynamic tick is
15377 + * enabled, and to reprogram the ticks to skip from pm_idle. The CPU goes
15378 + * to sleep directly after this.
15379 + */
15380 +static void s3c24xx_timer_reprogram_dyn_tick(unsigned long next_jiffies)
15381 +{
15382 + int subjiffy_left = ticks_last - s3c24xx_timer_read();
15383 +
15384 + s3c24xx_timer_program(max((int) next_jiffies, 1) << INPUT_FREQ_SHIFT);
15385 + ticks_last += subjiffy_left;
15386 +}
15387 +
15388 +static unsigned long s3c24xx_timer_offset_dyn_tick(void)
15389 +{
15390 + /* TODO */
15391 + return 0;
15392 +}
15393 +
15394 +static int s3c24xx_timer_enable_dyn_tick(void)
15395 +{
15396 + /* Set our constant prescaler. */
15397 + uint32_t tcfg0 = __raw_readl(S3C2410_TCFG0);
15398 + int prescaler =
15399 + max(min(256, (int) pclk / (HZ << (INPUT_FREQ_SHIFT + 1))), 1);
15400 +
15401 + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
15402 + tcfg0 |= (prescaler - 1) << S3C2410_TCFG_PRESCALER1_SHIFT;
15403 + __raw_writel(tcfg0, S3C2410_TCFG0);
15404 +
15405 + /* Override handlers. */
15406 + s3c2410_timer_irq.handler = s3c24xx_timer_handler;
15407 + s3c24xx_timer.offset = s3c24xx_timer_offset_dyn_tick;
15408 +
15409 + printk(KERN_INFO "dyn_tick enabled on s3c24xx timer 4, "
15410 + "%li Hz pclk with prescaler %i\n", pclk, prescaler);
15411 +
15412 + s3c24xx_timer_program_idle();
15413 +
15414 + return 0;
15415 +}
15416 +
15417 +static int s3c24xx_timer_disable_dyn_tick(void)
15418 +{
15419 + s3c2410_timer_irq.handler = s3c2410_timer_interrupt;
15420 + s3c24xx_timer.offset = s3c2410_gettimeoffset;
15421 + s3c2410_timer_setup();
15422 +
15423 + return 0;
15424 +}
15425 +
15426 +static struct dyn_tick_timer s3c24xx_dyn_tick_timer = {
15427 + .enable = s3c24xx_timer_enable_dyn_tick,
15428 + .disable = s3c24xx_timer_disable_dyn_tick,
15429 + .reprogram = s3c24xx_timer_reprogram_dyn_tick,
15430 + .handler = s3c24xx_timer_handler_dyn_tick,
15431 +};
15432 +#endif /* CONFIG_NO_IDLE_HZ */
15433 +
15434 +struct sys_timer s3c24xx_timer = {
15435 + .init = s3c2410_timer_init,
15436 + .offset = s3c2410_gettimeoffset,
15437 + .resume = s3c2410_timer_resume,
15438 +#ifdef CONFIG_NO_IDLE_HZ
15439 + .dyn_tick = &s3c24xx_dyn_tick_timer,
15440 +#endif
15441 +};
15442 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/clock.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/clock.c
15443 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/clock.c 2009-05-10 22:08:41.000000000 +0200
15444 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/clock.c 2009-05-10 22:27:59.000000000 +0200
15445 @@ -27,6 +27,12 @@
15446 #include <plat/devs.h>
15447 #include <plat/clock.h>
15448
15449 +struct clk clk_h2 = {
15450 + .name = "hclk2",
15451 + .id = -1,
15452 + .rate = 0,
15453 +};
15454 +
15455 struct clk clk_27m = {
15456 .name = "clk_27m",
15457 .id = -1,
15458 @@ -83,7 +89,7 @@
15459 return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
15460 }
15461
15462 -static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
15463 +int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
15464 {
15465 return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
15466 }
15467 @@ -152,6 +158,30 @@
15468 .parent = &clk_48m,
15469 .enable = s3c64xx_sclk_ctrl,
15470 .ctrlbit = S3C_CLKCON_SCLK_MMC2_48,
15471 + }, {
15472 + .name = "dma0",
15473 + .id = -1,
15474 + .parent = &clk_h,
15475 + .enable = s3c64xx_hclk_ctrl,
15476 + .ctrlbit = S3C_CLKCON_HCLK_DMA0,
15477 + }, {
15478 + .name = "dma1",
15479 + .id = -1,
15480 + .parent = &clk_h,
15481 + .enable = s3c64xx_hclk_ctrl,
15482 + .ctrlbit = S3C_CLKCON_HCLK_DMA1,
15483 + }, {
15484 + .name = "dma2",
15485 + .id = -1,
15486 + .parent = &clk_h,
15487 + .enable = s3c64xx_hclk_ctrl,
15488 + .ctrlbit = S3C_CLKCON_HCLK_SDMA0,
15489 + }, {
15490 + .name = "dma3",
15491 + .id = -1,
15492 + .parent = &clk_h,
15493 + .enable = s3c64xx_hclk_ctrl,
15494 + .ctrlbit = S3C_CLKCON_HCLK_SDMA1,
15495 },
15496 };
15497
15498 @@ -246,6 +276,7 @@
15499 &clk_epll,
15500 &clk_27m,
15501 &clk_48m,
15502 + &clk_h2,
15503 };
15504
15505 void s3c64xx_register_clocks(void)
15506 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/cpu.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/cpu.c
15507 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/cpu.c 2009-05-10 22:05:04.000000000 +0200
15508 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/cpu.c 2009-05-10 22:27:59.000000000 +0200
15509 @@ -16,6 +16,7 @@
15510 #include <linux/module.h>
15511 #include <linux/interrupt.h>
15512 #include <linux/ioport.h>
15513 +#include <linux/sysdev.h>
15514 #include <linux/serial_core.h>
15515 #include <linux/platform_device.h>
15516 #include <linux/io.h>
15517 @@ -96,9 +97,34 @@
15518 .pfn = __phys_to_pfn(S3C64XX_PA_GPIO),
15519 .length = SZ_4K,
15520 .type = MT_DEVICE,
15521 - },
15522 + }, {
15523 + .virtual = (unsigned long)S3C64XX_VA_MODEM,
15524 + .pfn = __phys_to_pfn(S3C64XX_PA_MODEM),
15525 + .length = SZ_4K,
15526 + .type = MT_DEVICE,
15527 + }, {
15528 + .virtual = (unsigned long)S3C_VA_TZIC0,
15529 + .pfn = __phys_to_pfn(S3C64XX_PA_TZIC0),
15530 + .length = SZ_4K,
15531 + .type = MT_DEVICE,
15532 + }, {
15533 + .virtual = (unsigned long)S3C_VA_TZIC1,
15534 + .pfn = __phys_to_pfn(S3C64XX_PA_TZIC1),
15535 + .length = SZ_4K,
15536 + .type = MT_DEVICE,
15537 + }
15538 };
15539
15540 +
15541 +struct sysdev_class s3c64xx_sysclass = {
15542 + .name = "s3c64xx-core",
15543 +};
15544 +
15545 +static struct sys_device s3c64xx_sysdev = {
15546 + .cls = &s3c64xx_sysclass,
15547 +};
15548 +
15549 +
15550 /* read cpu identification code */
15551
15552 void __init s3c64xx_init_io(struct map_desc *mach_desc, int size)
15553 @@ -112,3 +138,11 @@
15554 idcode = __raw_readl(S3C_VA_SYS + 0x118);
15555 s3c_init_cpu(idcode, cpu_ids, ARRAY_SIZE(cpu_ids));
15556 }
15557 +
15558 +static __init int s3c64xx_sysdev_init(void)
15559 +{
15560 + sysdev_class_register(&s3c64xx_sysclass);
15561 + return sysdev_register(&s3c64xx_sysdev);
15562 +}
15563 +
15564 +core_initcall(s3c64xx_sysdev_init);
15565 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/cpufreq.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/cpufreq.c
15566 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/cpufreq.c 1970-01-01 01:00:00.000000000 +0100
15567 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/cpufreq.c 2009-05-10 22:27:59.000000000 +0200
15568 @@ -0,0 +1,225 @@
15569 +/* linux/arch/arm/plat-s3c64xx/cpufreq.c
15570 + *
15571 + * Copyright 2009 Wolfson Microelectronics plc
15572 + *
15573 + * S3C64XX CPUfreq Support
15574 + *
15575 + * This program is free software; you can redistribute it and/or modify
15576 + * it under the terms of the GNU General Public License version 2 as
15577 + * published by the Free Software Foundation.
15578 + */
15579 +
15580 +#include <linux/kernel.h>
15581 +#include <linux/types.h>
15582 +#include <linux/init.h>
15583 +#include <linux/cpufreq.h>
15584 +#include <linux/clk.h>
15585 +#include <linux/err.h>
15586 +#include <linux/regulator/consumer.h>
15587 +
15588 +#include <mach/cpu.h>
15589 +
15590 +static struct clk *armclk;
15591 +static struct regulator *vddarm;
15592 +
15593 +struct s3c64xx_dvfs {
15594 + unsigned int vddarm_min;
15595 + unsigned int vddarm_max;
15596 +};
15597 +
15598 +static struct s3c64xx_dvfs s3c6410_dvfs_table[] = {
15599 + [0] = { 1000000, 1000000 },
15600 + [1] = { 1000000, 1050000 },
15601 + [2] = { 1050000, 1100000 },
15602 + [3] = { 1050000, 1150000 },
15603 + [4] = { 1250000, 1350000 },
15604 +};
15605 +
15606 +static struct cpufreq_frequency_table s3c6410_freq_table[] = {
15607 + { 0, 66000 },
15608 + { 0, 133000 },
15609 + { 1, 222000 },
15610 + { 1, 266000 },
15611 + { 2, 333000 },
15612 + { 2, 400000 },
15613 + { 3, 532000 },
15614 + { 3, 533000 },
15615 + { 4, 667000 },
15616 + { 0, CPUFREQ_TABLE_END },
15617 +};
15618 +
15619 +/* Data tables for current CPU and maximum index into it */
15620 +static struct cpufreq_frequency_table *s3c64xx_freq_table;
15621 +static struct s3c64xx_dvfs *s3c64xx_dvfs_table;
15622 +
15623 +static int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy)
15624 +{
15625 + if (policy->cpu != 0)
15626 + return -EINVAL;
15627 +
15628 + return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table);
15629 +}
15630 +
15631 +static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu)
15632 +{
15633 + if (cpu != 0)
15634 + return 0;
15635 +
15636 + return clk_get_rate(armclk) / 1000;
15637 +}
15638 +
15639 +static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
15640 + unsigned int target_freq,
15641 + unsigned int relation)
15642 +{
15643 + int ret = 0;
15644 + unsigned int i;
15645 + struct cpufreq_freqs freqs;
15646 + struct s3c64xx_dvfs *dvfs;
15647 +
15648 + ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table,
15649 + target_freq, relation, &i);
15650 + if (ret != 0)
15651 + return ret;
15652 +
15653 + freqs.cpu = 0;
15654 + freqs.old = clk_get_rate(armclk) / 1000;
15655 + freqs.new = s3c64xx_freq_table[i].frequency;
15656 + freqs.flags = 0;
15657 + dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].index];
15658 +
15659 + if (freqs.old == freqs.new)
15660 + return 0;
15661 +
15662 + pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
15663 +
15664 + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
15665 +
15666 +#ifdef CONFIG_REGULATOR
15667 + if (vddarm && freqs.new > freqs.old) {
15668 + ret = regulator_set_voltage(vddarm,
15669 + dvfs->vddarm_min,
15670 + dvfs->vddarm_max);
15671 + if (ret != 0) {
15672 + pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
15673 + freqs.new, ret);
15674 + goto err;
15675 + }
15676 + }
15677 +#endif
15678 +
15679 + ret = clk_set_rate(armclk, freqs.new * 1000);
15680 + if (ret < 0) {
15681 + pr_err("cpufreq: Failed to set rate %dkHz: %d\n",
15682 + freqs.new, ret);
15683 + goto err;
15684 + }
15685 +
15686 +#ifdef CONFIG_REGULATOR
15687 + if (vddarm && freqs.new < freqs.old) {
15688 + ret = regulator_set_voltage(vddarm,
15689 + dvfs->vddarm_min,
15690 + dvfs->vddarm_max);
15691 + if (ret != 0) {
15692 + pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
15693 + freqs.new, ret);
15694 + goto err_clk;
15695 + }
15696 + }
15697 +#endif
15698 +
15699 + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
15700 +
15701 + pr_debug("cpufreq: Set actual frequency %lukHz\n",
15702 + clk_get_rate(armclk) / 1000);
15703 +
15704 + return 0;
15705 +
15706 +err_clk:
15707 + if (clk_set_rate(armclk, freqs.old * 1000) < 0)
15708 + pr_err("Failed to restore original clock rate\n");
15709 +err:
15710 + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
15711 +
15712 + return ret;
15713 +}
15714 +
15715 +
15716 +static int __init s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
15717 +{
15718 + int ret;
15719 + struct cpufreq_frequency_table *freq;;
15720 +
15721 + if (policy->cpu != 0)
15722 + return -EINVAL;
15723 +
15724 + if (cpu_is_s3c6410()) {
15725 + s3c64xx_freq_table = s3c6410_freq_table;
15726 + s3c64xx_dvfs_table = s3c6410_dvfs_table;
15727 + }
15728 +
15729 + if (s3c64xx_freq_table == NULL) {
15730 + pr_err("cpufreq: No frequency information for this CPU\n");
15731 + return -ENODEV;
15732 + }
15733 +
15734 + armclk = clk_get(NULL, "armclk");
15735 + if (IS_ERR(armclk)) {
15736 + pr_err("cpufreq: Unable to obtain ARMCLK: %ld\n",
15737 + PTR_ERR(armclk));
15738 + return PTR_ERR(armclk);
15739 + }
15740 +
15741 +#ifdef CONFIG_REGULATOR
15742 + vddarm = regulator_get(NULL, "vddarm");
15743 + if (IS_ERR(vddarm)) {
15744 + ret = PTR_ERR(vddarm);
15745 + pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret);
15746 + pr_err("cpufreq: Only frequency scaling available\n");
15747 + vddarm = NULL;
15748 + }
15749 +#endif
15750 +
15751 + /* Check for frequencies we can generate */
15752 + freq = s3c64xx_freq_table;
15753 + while (freq->frequency != CPUFREQ_TABLE_END) {
15754 + unsigned long r;
15755 +
15756 + r = clk_round_rate(armclk, freq->frequency * 1000);
15757 + r /= 1000;
15758 +
15759 + if (r != freq->frequency)
15760 + freq->frequency = CPUFREQ_ENTRY_INVALID;
15761 +
15762 + freq++;
15763 + }
15764 +
15765 + policy->cur = clk_get_rate(armclk) / 1000;
15766 + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
15767 +
15768 + ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
15769 + if (ret == 0)
15770 + return ret;
15771 +
15772 + pr_err("cpufreq: Failed to configure frequency table: %d\n", ret);
15773 +
15774 + regulator_put(vddarm);
15775 + clk_put(armclk);
15776 + return ret;
15777 +}
15778 +
15779 +static struct cpufreq_driver s3c64xx_cpufreq_driver = {
15780 + .owner = THIS_MODULE,
15781 + .flags = 0,
15782 + .verify = s3c64xx_cpufreq_verify_speed,
15783 + .target = s3c64xx_cpufreq_set_target,
15784 + .get = s3c64xx_cpufreq_get_speed,
15785 + .init = s3c64xx_cpufreq_driver_init,
15786 + .name = "s3c64xx",
15787 +};
15788 +
15789 +static int __init s3c64xx_cpufreq_init(void)
15790 +{
15791 + return cpufreq_register_driver(&s3c64xx_cpufreq_driver);
15792 +}
15793 +module_init(s3c64xx_cpufreq_init);
15794 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/dev-usbgadget.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/dev-usbgadget.c
15795 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/dev-usbgadget.c 1970-01-01 01:00:00.000000000 +0100
15796 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/dev-usbgadget.c 2009-05-10 22:27:59.000000000 +0200
15797 @@ -0,0 +1,32 @@
15798 +/* Base S3C64XX usbgadget resource and device definitions */
15799 +
15800 +#include <linux/kernel.h>
15801 +#include <linux/interrupt.h>
15802 +#include <linux/platform_device.h>
15803 +#include <linux/ioport.h>
15804 +
15805 +#include <mach/map.h>
15806 +#include <plat/map-base.h>
15807 +#include <plat/devs.h>
15808 +#include <plat/irqs.h>
15809 +
15810 +static struct resource s3c_usbgadget_resource[] = {
15811 + [0] = {
15812 + .start = S3C64XX_PA_OTG,
15813 + .end = S3C64XX_PA_OTG + 0x200000 - 1,
15814 + .flags = IORESOURCE_MEM,
15815 + },
15816 + [1] = {
15817 + .start = IRQ_OTG,
15818 + .end = IRQ_OTG,
15819 + .flags = IORESOURCE_IRQ,
15820 + }
15821 +};
15822 +
15823 +struct platform_device s3c_device_usbgadget = {
15824 + .name = "s3c-otg-usbgadget",
15825 + .id = -1,
15826 + .num_resources = ARRAY_SIZE(s3c_usbgadget_resource),
15827 + .resource = s3c_usbgadget_resource,
15828 +};
15829 +EXPORT_SYMBOL(s3c_device_usbgadget);
15830 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/dma.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/dma.c
15831 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/dma.c 1970-01-01 01:00:00.000000000 +0100
15832 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/dma.c 2009-05-10 22:27:59.000000000 +0200
15833 @@ -0,0 +1,728 @@
15834 +/* linux/arch/arm/plat-s3c64xx/dma.c
15835 + *
15836 + * Copyright 2009 Openmoko, Inc.
15837 + * Copyright 2009 Simtec Electronics
15838 + * Ben Dooks <ben@simtec.co.uk>
15839 + * http://armlinux.simtec.co.uk/
15840 + *
15841 + * S3C64XX DMA core
15842 + *
15843 + * This program is free software; you can redistribute it and/or modify
15844 + * it under the terms of the GNU General Public License version 2 as
15845 + * published by the Free Software Foundation.
15846 +*/
15847 +
15848 +#include <linux/kernel.h>
15849 +#include <linux/module.h>
15850 +#include <linux/interrupt.h>
15851 +#include <linux/dmapool.h>
15852 +#include <linux/sysdev.h>
15853 +#include <linux/errno.h>
15854 +#include <linux/delay.h>
15855 +#include <linux/clk.h>
15856 +#include <linux/err.h>
15857 +#include <linux/io.h>
15858 +
15859 +#include <mach/dma.h>
15860 +#include <mach/irqs.h>
15861 +
15862 +#include <plat/dma-plat.h>
15863 +
15864 +#include <plat/pl080.h>
15865 +#include <mach/map.h>
15866 +#include <plat/regs-sys.h>
15867 +
15868 +#define DEBUG
15869 +
15870 +#undef pr_debug
15871 +#define pr_debug(x...) printk(x)
15872 +
15873 +/* dma channel state information */
15874 +
15875 +
15876 +struct s3c64xx_dmac {
15877 + struct sys_device sysdev;
15878 + struct clk *clk;
15879 + void __iomem *regs;
15880 + struct s3c2410_dma_chan *channels;
15881 + enum dma_ch chanbase;
15882 +};
15883 +
15884 +/* pool to provide LLI buffers */
15885 +static struct dma_pool *dma_pool;
15886 +
15887 +/* Debug configuration and code */
15888 +
15889 +static unsigned char debug_show_buffs = 0;
15890 +
15891 +static void dbg_showchan(struct s3c2410_dma_chan *chan)
15892 +{
15893 + pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n",
15894 + chan->number,
15895 + readl(chan->regs + PL080_CH_SRC_ADDR),
15896 + readl(chan->regs + PL080_CH_DST_ADDR),
15897 + readl(chan->regs + PL080_CH_LLI),
15898 + readl(chan->regs + PL080_CH_CONTROL),
15899 + readl(chan->regs + PL080S_CH_CONTROL2),
15900 + readl(chan->regs + PL080S_CH_CONFIG));
15901 +}
15902 +
15903 +static void show_lli(struct pl080_lli *lli)
15904 +{
15905 + pr_debug("LLI[%p] %08x->%08x, NL %08x C %08x,%08x\n",
15906 + lli, lli->src_addr, lli->dst_addr, lli->next_lli,
15907 + lli->control0, lli->control1);
15908 +}
15909 +
15910 +static void dbg_showbuffs(struct s3c2410_dma_chan *chan)
15911 +{
15912 + struct s3c64xx_dma_buff *ptr;
15913 + struct s3c64xx_dma_buff *end;
15914 +
15915 + pr_debug("DMA%d: buffs next %p, curr %p, end %p\n",
15916 + chan->number, chan->next, chan->curr, chan->end);
15917 +
15918 + ptr = chan->next;
15919 + end = chan->end;
15920 +
15921 + if (debug_show_buffs) {
15922 + for (; ptr != NULL; ptr = ptr->next) {
15923 + pr_debug("DMA%d: %08x ",
15924 + chan->number, ptr->lli_dma);
15925 + show_lli(ptr->lli);
15926 + }
15927 + }
15928 +}
15929 +
15930 +/* End of Debug */
15931 +
15932 +static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel)
15933 +{
15934 + struct s3c2410_dma_chan *chan;
15935 + unsigned int start, offs;
15936 +
15937 + start = 0;
15938 +
15939 + if (channel >= DMACH_PCM1_TX)
15940 + start = 8;
15941 +
15942 + for (offs = 0; offs < 8; offs++) {
15943 + chan = &s3c2410_chans[start + offs];
15944 + if (!chan->in_use)
15945 + goto found;
15946 + }
15947 +
15948 + return NULL;
15949 +
15950 +found:
15951 + s3c_dma_chan_map[channel] = chan;
15952 + return chan;
15953 +}
15954 +
15955 +int s3c2410_dma_config(unsigned int channel, int xferunit)
15956 +{
15957 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
15958 +
15959 + if (chan == NULL)
15960 + return -EINVAL;
15961 +
15962 + switch (xferunit) {
15963 + case 1:
15964 + chan->hw_width = 0;
15965 + break;
15966 + case 2:
15967 + chan->hw_width = 1;
15968 + break;
15969 + case 4:
15970 + chan->hw_width = 2;
15971 + break;
15972 + default:
15973 + printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit);
15974 + return -EINVAL;
15975 + }
15976 +
15977 + return 0;
15978 +}
15979 +EXPORT_SYMBOL(s3c2410_dma_config);
15980 +
15981 +static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
15982 + struct pl080_lli *lli,
15983 + dma_addr_t data, int size)
15984 +{
15985 + dma_addr_t src, dst;
15986 + u32 control0, control1;
15987 +
15988 + switch (chan->source) {
15989 + case S3C2410_DMASRC_HW:
15990 + src = chan->dev_addr;
15991 + dst = data;
15992 + control0 = PL080_CONTROL_SRC_AHB2;
15993 + control0 |= (u32)chan->hw_width << PL080_CONTROL_SWIDTH_SHIFT;
15994 + control0 |= 2 << PL080_CONTROL_DWIDTH_SHIFT;
15995 + control0 |= PL080_CONTROL_DST_INCR;
15996 + break;
15997 +
15998 + case S3C2410_DMASRC_MEM:
15999 + src = data;
16000 + dst = chan->dev_addr;
16001 + control0 = PL080_CONTROL_DST_AHB2;
16002 + control0 |= (u32)chan->hw_width << PL080_CONTROL_DWIDTH_SHIFT;
16003 + control0 |= 2 << PL080_CONTROL_SWIDTH_SHIFT;
16004 + control0 |= PL080_CONTROL_SRC_INCR;
16005 + break;
16006 + default:
16007 + BUG();
16008 + }
16009 +
16010 + /* todo - burst control */
16011 +
16012 + control1 = size / 4; /* TODO - calculate */
16013 + control0 |= PL080_CONTROL_PROT_SYS; /* always in priv. mode */
16014 + control0 |= PL080_CONTROL_TC_IRQ_EN; /* always fire IRQ */
16015 +
16016 + lli->src_addr = src;
16017 + lli->dst_addr = dst;
16018 + lli->next_lli = 0;
16019 + lli->control0 = control0;
16020 + lli->control1 = control1;
16021 +}
16022 +
16023 +static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
16024 + struct pl080_lli *lli)
16025 +{
16026 + void __iomem *regs = chan->regs;
16027 +
16028 + pr_debug("%s: LLI %p => regs\n", __func__, lli);
16029 + show_lli(lli);
16030 +
16031 + writel(lli->src_addr, regs + PL080_CH_SRC_ADDR);
16032 + writel(lli->dst_addr, regs + PL080_CH_DST_ADDR);
16033 + writel(lli->next_lli, regs + PL080_CH_LLI);
16034 + writel(lli->control0, regs + PL080_CH_CONTROL);
16035 + writel(lli->control1, regs + PL080S_CH_CONTROL2);
16036 +}
16037 +
16038 +static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
16039 +{
16040 + struct s3c64xx_dmac *dmac = chan->dmac;
16041 + u32 config;
16042 + u32 bit = chan->bit;
16043 +
16044 + dbg_showchan(chan);
16045 +
16046 + pr_debug("%s: clearing interrupts\n", __func__);
16047 +
16048 + /* clear interrupts */
16049 + writel(bit, dmac->regs + PL080_TC_CLEAR);
16050 + writel(bit, dmac->regs + PL080_ERR_CLEAR);
16051 +
16052 + pr_debug("%s: starting channel\n", __func__);
16053 +
16054 + config = readl(chan->regs + PL080S_CH_CONFIG);
16055 + config |= PL080_CONFIG_ENABLE;
16056 +
16057 + pr_debug("%s: writing config %08x\n", __func__, config);
16058 + writel(config, chan->regs + PL080S_CH_CONFIG);
16059 +
16060 + return 0;
16061 +}
16062 +
16063 +static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
16064 +{
16065 + u32 config;
16066 + int timeout;
16067 +
16068 + pr_debug("%s: stopping channel\n", __func__);
16069 +
16070 + dbg_showchan(chan);
16071 +
16072 + config = readl(chan->regs + PL080S_CH_CONFIG);
16073 + config |= PL080_CONFIG_HALT;
16074 + writel(config, chan->regs + PL080S_CH_CONFIG);
16075 +
16076 + timeout = 1000;
16077 + do {
16078 + config = readl(chan->regs + PL080S_CH_CONFIG);
16079 + pr_debug("%s: %d - config %08x\n", __func__, timeout, config);
16080 + if (config & PL080_CONFIG_ACTIVE)
16081 + udelay(100);
16082 + else
16083 + break;
16084 + } while (--timeout > 0);
16085 +
16086 + if (config & PL080_CONFIG_ACTIVE) {
16087 + printk(KERN_ERR "%s: channel still active\n", __func__);
16088 + return -EFAULT;
16089 + }
16090 +
16091 + config = readl(chan->regs + PL080S_CH_CONFIG);
16092 + config &= ~PL080_CONFIG_ENABLE;
16093 + writel(config, chan->regs + PL080S_CH_CONFIG);
16094 +
16095 + return 0;
16096 +}
16097 +
16098 +static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
16099 + struct s3c64xx_dma_buff *buf,
16100 + enum s3c2410_dma_buffresult result)
16101 +{
16102 + if (chan->callback_fn != NULL)
16103 + (chan->callback_fn)(chan, buf->pw, 0, result);
16104 +}
16105 +
16106 +static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
16107 +{
16108 + dma_pool_free(dma_pool, buff->lli, buff->lli_dma);
16109 + kfree(buff);
16110 +}
16111 +
16112 +static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
16113 +{
16114 + struct s3c64xx_dma_buff *buff, *next;
16115 + u32 config;
16116 +
16117 + dbg_showchan(chan);
16118 +
16119 + pr_debug("%s: flushing channel\n", __func__);
16120 +
16121 + config = readl(chan->regs + PL080S_CH_CONFIG);
16122 + config &= ~PL080_CONFIG_ENABLE;
16123 + writel(config, chan->regs + PL080S_CH_CONFIG);
16124 +
16125 + /* dump all the buffers associated with this channel */
16126 +
16127 + for (buff = chan->curr; buff != NULL; buff = next) {
16128 + next = buff->next;
16129 + pr_debug("%s: buff %p (next %p)\n", __func__, buff, buff->next);
16130 +
16131 + s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT);
16132 + s3c64xx_dma_freebuff(buff);
16133 + }
16134 +
16135 + chan->curr = chan->next = chan->end = NULL;
16136 +
16137 + return 0;
16138 +}
16139 +
16140 +int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
16141 +{
16142 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
16143 +
16144 + WARN_ON(!chan);
16145 + if (!chan)
16146 + return -EINVAL;
16147 +
16148 + switch (op) {
16149 + case S3C2410_DMAOP_START:
16150 + return s3c64xx_dma_start(chan);
16151 +
16152 + case S3C2410_DMAOP_STOP:
16153 + return s3c64xx_dma_stop(chan);
16154 +
16155 + case S3C2410_DMAOP_FLUSH:
16156 + return s3c64xx_dma_flush(chan);
16157 +
16158 + /* belive PAUSE/RESUME are no-ops */
16159 + case S3C2410_DMAOP_PAUSE:
16160 + case S3C2410_DMAOP_RESUME:
16161 + case S3C2410_DMAOP_STARTED:
16162 + case S3C2410_DMAOP_TIMEOUT:
16163 + return 0;
16164 + }
16165 +
16166 + return -ENOENT;
16167 +}
16168 +EXPORT_SYMBOL(s3c2410_dma_ctrl);
16169 +
16170 +/* s3c2410_dma_enque
16171 + *
16172 + */
16173 +
16174 +int s3c2410_dma_enqueue(unsigned int channel, void *id,
16175 + dma_addr_t data, int size)
16176 +{
16177 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
16178 + struct s3c64xx_dma_buff *next;
16179 + struct s3c64xx_dma_buff *buff;
16180 + struct pl080_lli *lli;
16181 + int ret;
16182 +
16183 + WARN_ON(!chan);
16184 + if (!chan)
16185 + return -EINVAL;
16186 +
16187 + buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_KERNEL);
16188 + if (!buff) {
16189 + printk(KERN_ERR "%s: no memory for buffer\n", __func__);
16190 + return -ENOMEM;
16191 + }
16192 +
16193 + lli = dma_pool_alloc(dma_pool, GFP_KERNEL, &buff->lli_dma);
16194 + if (!lli) {
16195 + printk(KERN_ERR "%s: no memory for lli\n", __func__);
16196 + ret = -ENOMEM;
16197 + goto err_buff;
16198 + }
16199 +
16200 + pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n",
16201 + __func__, buff, data, lli, (u32)buff->lli_dma, size);
16202 +
16203 + buff->lli = lli;
16204 + buff->pw = id;
16205 +
16206 + s3c64xx_dma_fill_lli(chan, lli, data, size);
16207 +
16208 + if ((next = chan->next) != NULL) {
16209 + struct s3c64xx_dma_buff *end = chan->end;
16210 + struct pl080_lli *endlli = end->lli;
16211 +
16212 + pr_debug("enquing onto channel\n");
16213 +
16214 + end->next = buff;
16215 + endlli->next_lli = buff->lli_dma;
16216 +
16217 + if (chan->flags & S3C2410_DMAF_CIRCULAR) {
16218 + struct s3c64xx_dma_buff *curr = chan->curr;
16219 + lli->next_lli = curr->lli_dma;
16220 + }
16221 +
16222 + if (next == chan->curr) {
16223 + writel(buff->lli_dma, chan->regs + PL080_CH_LLI);
16224 + chan->next = buff;
16225 + }
16226 +
16227 + show_lli(endlli);
16228 + chan->end = buff;
16229 + } else {
16230 + pr_debug("enquing onto empty channel\n");
16231 +
16232 + chan->curr = buff;
16233 + chan->next = buff;
16234 + chan->end = buff;
16235 +
16236 + s3c64xx_lli_to_regs(chan, lli);
16237 + }
16238 +
16239 + show_lli(lli);
16240 +
16241 + dbg_showchan(chan);
16242 + dbg_showbuffs(chan);
16243 + return 0;
16244 +
16245 +err_buff:
16246 + kfree(buff);
16247 + return ret;
16248 +}
16249 +
16250 +EXPORT_SYMBOL(s3c2410_dma_enqueue);
16251 +
16252 +
16253 +int s3c2410_dma_devconfig(int channel,
16254 + enum s3c2410_dmasrc source,
16255 + unsigned long devaddr)
16256 +{
16257 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
16258 + u32 peripheral;
16259 + u32 config = 0;
16260 +
16261 + printk("%s: channel %d, source %d, dev %08lx, chan %p\n",
16262 + __func__, channel, source, devaddr, chan);
16263 +
16264 + WARN_ON(!chan);
16265 + if (!chan)
16266 + return -EINVAL;
16267 +
16268 + peripheral = (chan->peripheral & 0xf);
16269 + chan->source = source;
16270 + chan->dev_addr = devaddr;
16271 +
16272 + pr_debug("%s: peripheral %d\n", __func__, peripheral);
16273 +
16274 + switch (source) {
16275 + case S3C2410_DMASRC_HW:
16276 + config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
16277 + config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
16278 + break;
16279 + case S3C2410_DMASRC_MEM:
16280 + config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
16281 + config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
16282 + break;
16283 + default:
16284 + printk(KERN_ERR "%s: bad source\n", __func__);
16285 + return -EINVAL;
16286 + }
16287 +
16288 + /* allow TC and ERR interrupts */
16289 + config |= PL080_CONFIG_TC_IRQ_MASK;
16290 + config |= PL080_CONFIG_ERR_IRQ_MASK;
16291 +
16292 + pr_debug("%s: config %08x\n", __func__, config);
16293 +
16294 + writel(config, chan->regs + PL080S_CH_CONFIG);
16295 +
16296 + return 0;
16297 +}
16298 +EXPORT_SYMBOL(s3c2410_dma_devconfig);
16299 +
16300 +
16301 +int s3c2410_dma_getposition(unsigned int channel,
16302 + dma_addr_t *src, dma_addr_t *dst)
16303 +{
16304 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
16305 +
16306 + WARN_ON(!chan);
16307 + if (!chan)
16308 + return -EINVAL;
16309 +
16310 + if (src != NULL)
16311 + *src = readl(chan->regs + PL080_CH_SRC_ADDR);
16312 +
16313 + if (dst != NULL)
16314 + *dst = readl(chan->regs + PL080_CH_DST_ADDR);
16315 +
16316 + return 0;
16317 +}
16318 +EXPORT_SYMBOL(s3c2410_dma_getposition);
16319 +
16320 +/* s3c2410_request_dma
16321 + *
16322 + * get control of an dma channel
16323 +*/
16324 +
16325 +int s3c2410_dma_request(unsigned int channel,
16326 + struct s3c2410_dma_client *client,
16327 + void *dev)
16328 +{
16329 + struct s3c2410_dma_chan *chan;
16330 + unsigned long flags;
16331 +
16332 + pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
16333 + channel, client->name, dev);
16334 +
16335 + local_irq_save(flags);
16336 +
16337 + chan = s3c64xx_dma_map_channel(channel);
16338 + if (chan == NULL) {
16339 + local_irq_restore(flags);
16340 + return -EBUSY;
16341 + }
16342 +
16343 + dbg_showchan(chan);
16344 +
16345 + chan->client = client;
16346 + chan->in_use = 1;
16347 + chan->peripheral = channel;
16348 +
16349 + local_irq_restore(flags);
16350 +
16351 + /* need to setup */
16352 +
16353 + pr_debug("%s: channel initialised, %p\n", __func__, chan);
16354 +
16355 + return chan->number | DMACH_LOW_LEVEL;
16356 +}
16357 +
16358 +EXPORT_SYMBOL(s3c2410_dma_request);
16359 +
16360 +/* s3c2410_dma_free
16361 + *
16362 + * release the given channel back to the system, will stop and flush
16363 + * any outstanding transfers, and ensure the channel is ready for the
16364 + * next claimant.
16365 + *
16366 + * Note, although a warning is currently printed if the freeing client
16367 + * info is not the same as the registrant's client info, the free is still
16368 + * allowed to go through.
16369 +*/
16370 +
16371 +int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
16372 +{
16373 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
16374 + unsigned long flags;
16375 +
16376 + if (chan == NULL)
16377 + return -EINVAL;
16378 +
16379 + local_irq_save(flags);
16380 +
16381 + if (chan->client != client) {
16382 + printk(KERN_WARNING "dma%d: possible free from different client (channel %p, passed %p)\n",
16383 + channel, chan->client, client);
16384 + }
16385 +
16386 + /* sort out stopping and freeing the channel */
16387 +
16388 +
16389 + chan->client = NULL;
16390 + chan->in_use = 0;
16391 +
16392 + if (!(channel & DMACH_LOW_LEVEL))
16393 + s3c_dma_chan_map[channel] = NULL;
16394 +
16395 + local_irq_restore(flags);
16396 +
16397 + return 0;
16398 +}
16399 +
16400 +EXPORT_SYMBOL(s3c2410_dma_free);
16401 +
16402 +
16403 +static void s3c64xx_dma_tcirq(struct s3c64xx_dmac *dmac, int offs)
16404 +{
16405 + struct s3c2410_dma_chan *chan = dmac->channels + offs;
16406 +
16407 + /* note, we currently do not bother to work out which buffer
16408 + * or buffers have been completed since the last tc-irq. */
16409 +
16410 + if (chan->callback_fn)
16411 + (chan->callback_fn)(chan, chan->curr->pw, 0, S3C2410_RES_OK);
16412 +}
16413 +
16414 +static void s3c64xx_dma_errirq(struct s3c64xx_dmac *dmac, int offs)
16415 +{
16416 + printk(KERN_DEBUG "%s: offs %d\n", __func__, offs);
16417 +}
16418 +
16419 +static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
16420 +{
16421 + struct s3c64xx_dmac *dmac = pw;
16422 + u32 tcstat, errstat;
16423 + u32 bit;
16424 + int offs;
16425 +
16426 + tcstat = readl(dmac->regs + PL080_TC_STATUS);
16427 + errstat = readl(dmac->regs + PL080_ERR_STATUS);
16428 +
16429 + for (offs = 0, bit = 1; offs < 8; offs++, bit <<= 1) {
16430 + if (tcstat & bit) {
16431 + writel(bit, dmac->regs + PL080_TC_CLEAR);
16432 + s3c64xx_dma_tcirq(dmac, offs);
16433 + }
16434 +
16435 + if (errstat & bit) {
16436 + s3c64xx_dma_errirq(dmac, offs);
16437 + writel(bit, dmac->regs + PL080_ERR_CLEAR);
16438 + }
16439 + }
16440 +
16441 + return IRQ_HANDLED;
16442 +}
16443 +
16444 +static struct sysdev_class dma_sysclass = {
16445 + .name = "s3c64xx-dma",
16446 +};
16447 +
16448 +static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
16449 + int irq, unsigned int base)
16450 +{
16451 + struct s3c2410_dma_chan *chptr = &s3c2410_chans[chno];
16452 + struct s3c64xx_dmac *dmac;
16453 + char clkname[16];
16454 + void __iomem *regs;
16455 + void __iomem *regptr;
16456 + int err, ch;
16457 +
16458 + dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL);
16459 + if (!dmac) {
16460 + printk(KERN_ERR "%s: failed to alloc mem\n", __func__);
16461 + return -ENOMEM;
16462 + }
16463 +
16464 + dmac->sysdev.id = chno / 8;
16465 + dmac->sysdev.cls = &dma_sysclass;
16466 +
16467 + err = sysdev_register(&dmac->sysdev);
16468 + if (err) {
16469 + printk(KERN_ERR "%s: failed to register sysdevice\n", __func__);
16470 + goto err_alloc;
16471 + }
16472 +
16473 + regs = ioremap(base, 0x200);
16474 + if (!regs) {
16475 + printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
16476 + err = -ENXIO;
16477 + goto err_dev;
16478 + }
16479 +
16480 + snprintf(clkname, sizeof(clkname), "dma%d", dmac->sysdev.id);
16481 +
16482 + dmac->clk = clk_get(NULL, clkname);
16483 + if (IS_ERR(dmac->clk)) {
16484 + printk(KERN_ERR "%s: failed to get clock %s\n", __func__, clkname);
16485 + err = PTR_ERR(dmac->clk);
16486 + goto err_map;
16487 + }
16488 +
16489 + clk_enable(dmac->clk);
16490 +
16491 + dmac->regs = regs;
16492 + dmac->chanbase = chbase;
16493 + dmac->channels = chptr;
16494 +
16495 + err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac);
16496 + if (err < 0) {
16497 + printk(KERN_ERR "%s: failed to get irq\n", __func__);
16498 + goto err_clk;
16499 + }
16500 +
16501 + regptr = regs + PL080_Cx_BASE(0);
16502 +
16503 + for (ch = 0; ch < 8; ch++, chno++, chptr++) {
16504 + printk(KERN_INFO "%s: registering DMA %d (%p)\n",
16505 + __func__, chno, regptr);
16506 +
16507 + chptr->bit = 1 << ch;
16508 + chptr->number = chno;
16509 + chptr->dmac = dmac;
16510 + chptr->regs = regptr;
16511 + regptr += PL008_Cx_STRIDE;
16512 + }
16513 +
16514 + /* for the moment, permanently enable the controller */
16515 + writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
16516 +
16517 + printk(KERN_INFO "PL080: IRQ %d, at %p\n", irq, regs);
16518 +
16519 + return 0;
16520 +
16521 +err_clk:
16522 + clk_disable(dmac->clk);
16523 + clk_put(dmac->clk);
16524 +err_map:
16525 + iounmap(regs);
16526 +err_dev:
16527 + sysdev_unregister(&dmac->sysdev);
16528 +err_alloc:
16529 + kfree(dmac);
16530 + return err;
16531 +}
16532 +
16533 +static int __init s3c64xx_dma_init(void)
16534 +{
16535 + int ret;
16536 +
16537 + printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
16538 +
16539 + dma_pool = dma_pool_create("DMA-LLI", NULL, 32, 16, 0);
16540 + if (!dma_pool) {
16541 + printk(KERN_ERR "%s: failed to create pool\n", __func__);
16542 + return -ENOMEM;
16543 + }
16544 +
16545 + ret = sysdev_class_register(&dma_sysclass);
16546 + if (ret) {
16547 + printk(KERN_ERR "%s: failed to create sysclass\n", __func__);
16548 + return -ENOMEM;
16549 + }
16550 +
16551 + /* Set all DMA configuration to be DMA, not SDMA */
16552 + writel(0xffffff, S3C_SYSREG(0x110));
16553 +
16554 + /* Register standard DMA controlers */
16555 + s3c64xx_dma_init1(0, DMACH_UART0, IRQ_DMA0, 0x75000000);
16556 + s3c64xx_dma_init1(8, DMACH_PCM1_TX, IRQ_DMA1, 0x75100000);
16557 +
16558 + return 0;
16559 +}
16560 +
16561 +arch_initcall(s3c64xx_dma_init);
16562 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/dma-fake.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/dma-fake.c
16563 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/dma-fake.c 1970-01-01 01:00:00.000000000 +0100
16564 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/dma-fake.c 2009-05-10 22:27:59.000000000 +0200
16565 @@ -0,0 +1,36 @@
16566 +/* linux/arch/arm/plat-s3c64xx/dma.c
16567 + *
16568 + * Copyright 2009 Simtec Electronics
16569 + * Ben Dooks <ben@simtec.co.uk>
16570 + *
16571 + * S3C64XX DMA core - fake
16572 + *
16573 + * http://armlinux.simtec.co.uk/
16574 + *
16575 + * This program is free software; you can redistribute it and/or modify
16576 + * it under the terms of the GNU General Public License version 2 as
16577 + * published by the Free Software Foundation.
16578 +*/
16579 +
16580 +#include <linux/module.h>
16581 +#include <linux/init.h>
16582 +#include <linux/sched.h>
16583 +#include <linux/spinlock.h>
16584 +#include <linux/interrupt.h>
16585 +#include <linux/sysdev.h>
16586 +#include <linux/slab.h>
16587 +#include <linux/errno.h>
16588 +#include <linux/io.h>
16589 +
16590 +#include <asm/system.h>
16591 +#include <asm/irq.h>
16592 +#include <mach/hardware.h>
16593 +#include <mach/dma.h>
16594 +
16595 +
16596 +int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
16597 +{
16598 + return 0;
16599 +}
16600 +
16601 +EXPORT_SYMBOL(s3c2410_dma_ctrl);
16602 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/gpiolib.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/gpiolib.c
16603 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/gpiolib.c 2009-05-10 22:08:41.000000000 +0200
16604 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/gpiolib.c 2009-05-10 22:27:59.000000000 +0200
16605 @@ -18,6 +18,7 @@
16606
16607 #include <mach/map.h>
16608 #include <mach/gpio.h>
16609 +#include <mach/irqs.h>
16610 #include <mach/gpio-core.h>
16611
16612 #include <plat/gpio-cfg.h>
16613 @@ -321,6 +322,11 @@
16614 .get_pull = s3c_gpio_getpull_updown,
16615 };
16616
16617 +static int s3c_gpiolib_bankn_toirq(struct gpio_chip *chip, unsigned offset)
16618 +{
16619 + return S3C_EINT(0) + offset;
16620 +}
16621 +
16622 static struct s3c_gpio_chip gpio_2bit[] = {
16623 {
16624 .base = S3C64XX_GPF_BASE,
16625 @@ -353,6 +359,7 @@
16626 .base = S3C64XX_GPN(0),
16627 .ngpio = S3C64XX_GPIO_N_NR,
16628 .label = "GPN",
16629 + .to_irq = s3c_gpiolib_bankn_toirq,
16630 },
16631 }, {
16632 .base = S3C64XX_GPO_BASE,
16633 @@ -385,12 +392,19 @@
16634 {
16635 chip->chip.direction_input = s3c64xx_gpiolib_4bit_input;
16636 chip->chip.direction_output = s3c64xx_gpiolib_4bit_output;
16637 + chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
16638 }
16639
16640 static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
16641 {
16642 chip->chip.direction_input = s3c64xx_gpiolib_4bit2_input;
16643 chip->chip.direction_output = s3c64xx_gpiolib_4bit2_output;
16644 + chip->pm = __gpio_pm(&s3c_gpio_pm_4bit);
16645 +}
16646 +
16647 +static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
16648 +{
16649 + chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
16650 }
16651
16652 static __init void s3c64xx_gpiolib_add(struct s3c_gpio_chip *chips,
16653 @@ -412,7 +426,8 @@
16654 s3c64xx_gpiolib_add(gpio_4bit2, ARRAY_SIZE(gpio_4bit2),
16655 s3c64xx_gpiolib_add_4bit2);
16656
16657 - s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit), NULL);
16658 + s3c64xx_gpiolib_add(gpio_2bit, ARRAY_SIZE(gpio_2bit),
16659 + s3c64xx_gpiolib_add_2bit);
16660
16661 return 0;
16662 }
16663 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/dma-plat.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/dma-plat.h
16664 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/dma-plat.h 1970-01-01 01:00:00.000000000 +0100
16665 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/dma-plat.h 2009-05-10 22:27:59.000000000 +0200
16666 @@ -0,0 +1,70 @@
16667 +/* linux/arch/arm/plat-s3c64xx/include/plat/dma-plat.h
16668 + *
16669 + * Copyright 2009 Openmoko, Inc.
16670 + * Copyright 2009 Simtec Electronics
16671 + * Ben Dooks <ben@simtec.co.uk>
16672 + * http://armlinux.simtec.co.uk/
16673 + *
16674 + * S3C64XX DMA core
16675 + *
16676 + * This program is free software; you can redistribute it and/or modify
16677 + * it under the terms of the GNU General Public License version 2 as
16678 + * published by the Free Software Foundation.
16679 +*/
16680 +
16681 +#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
16682 +
16683 +struct s3c64xx_dma_buff;
16684 +
16685 +/** s3c64xx_dma_buff - S3C64XX DMA buffer descriptor
16686 + * @next: Pointer to next buffer in queue or ring.
16687 + * @pw: Client provided identifier
16688 + * @lli: Pointer to hardware descriptor this buffer is associated with.
16689 + * @lli_dma: Hardare address of the descriptor.
16690 + */
16691 +struct s3c64xx_dma_buff {
16692 + struct s3c64xx_dma_buff *next;
16693 +
16694 + void *pw;
16695 + struct pl080_lli *lli;
16696 + dma_addr_t lli_dma;
16697 +};
16698 +
16699 +struct s3c64xx_dmac;
16700 +
16701 +struct s3c2410_dma_chan {
16702 + unsigned char number; /* number of this dma channel */
16703 + unsigned char in_use; /* channel allocated */
16704 + unsigned char bit; /* bit for enable/disable/etc */
16705 + unsigned char hw_width;
16706 + unsigned char peripheral;
16707 +
16708 + unsigned int flags;
16709 + enum s3c2410_dmasrc source;
16710 +
16711 +
16712 + dma_addr_t dev_addr;
16713 +
16714 + struct s3c2410_dma_client *client;
16715 + struct s3c64xx_dmac *dmac; /* pointer to controller */
16716 +
16717 + void __iomem *regs;
16718 +
16719 + /* cdriver callbacks */
16720 + s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */
16721 + s3c2410_dma_opfn_t op_fn; /* channel op callback */
16722 +
16723 + /* buffer list and information */
16724 + struct s3c64xx_dma_buff *curr; /* current dma buffer */
16725 + struct s3c64xx_dma_buff *next; /* next buffer to load */
16726 + struct s3c64xx_dma_buff *end; /* end of queue */
16727 +
16728 + /* note, when channel is running in circular mode, curr is the
16729 + * first buffer enqueued, end is the last and curr is where the
16730 + * last buffer-done event is set-at. The buffers are not freed
16731 + * and the last buffer hardware descriptor points back to the
16732 + * first.
16733 + */
16734 +};
16735 +
16736 +#include <plat/dma-core.h>
16737 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/irqs.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/irqs.h
16738 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/irqs.h 2009-05-10 22:08:41.000000000 +0200
16739 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/irqs.h 2009-05-10 22:27:59.000000000 +0200
16740 @@ -148,6 +148,7 @@
16741 /* compatibility for device defines */
16742
16743 #define IRQ_IIC1 IRQ_S3C6410_IIC1
16744 +#define IRQ_USBH IRQ_UHOST
16745
16746 /* Since the IRQ_EINT(x) are a linear mapping on current s3c64xx series
16747 * we just defined them as an IRQ_EINT(x) macro from S3C_IRQ_EINT_BASE
16748 @@ -157,6 +158,7 @@
16749
16750 #define S3C_EINT(x) ((x) + S3C_IRQ_EINT_BASE)
16751 #define IRQ_EINT(x) S3C_EINT(x)
16752 +#define IRQ_EINT_BIT(x) ((x) - S3C_EINT(0))
16753
16754 /* Next the external interrupt groups. These are similar to the IRQ_EINT(x)
16755 * that they are sourced from the GPIO pins but with a different scheme for
16756 @@ -197,5 +199,6 @@
16757
16758 #define NR_IRQS (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR + 1)
16759
16760 +#define FIQ_START S3C_IRQ(0)
16761 #endif /* __ASM_PLAT_S3C64XX_IRQS_H */
16762
16763 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/pl080.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/pl080.h
16764 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/pl080.h 1970-01-01 01:00:00.000000000 +0100
16765 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/pl080.h 2009-05-10 22:27:59.000000000 +0200
16766 @@ -0,0 +1,110 @@
16767 +/* arch/arm/include/asm/hardware/pl080.h
16768 + *
16769 + * Copyright 2008 Openmoko, Inc.
16770 + * Copyright 2008 Simtec Electronics
16771 + * http://armlinux.simtec.co.uk/
16772 + * Ben Dooks <ben@simtec.co.uk>
16773 + *
16774 + * ARM PrimeCell PL080 DMA controller
16775 + *
16776 + * This program is free software; you can redistribute it and/or modify
16777 + * it under the terms of the GNU General Public License version 2 as
16778 + * published by the Free Software Foundation.
16779 +*/
16780 +
16781 +/* Note, there are some Samsung updates to this controller block which
16782 + * make it not entierly compatible with the PL080 specification from
16783 + * ARM. When in doubt, check the Samsung documentation first.
16784 + *
16785 + * The Samsung defines are PL080S, and add an extra controll register,
16786 + * the ability to move more than 2^11 counts of data and some extra
16787 + * OneNAND features.
16788 +*/
16789 +
16790 +#define PL080_INT_STATUS (0x00)
16791 +#define PL080_TC_STATUS (0x04)
16792 +#define PL080_TC_CLEAR (0x08)
16793 +#define PL080_ERR_STATUS (0x0C)
16794 +#define PL080_ERR_CLEAR (0x10)
16795 +#define PL080_RAW_TC_STATUS (0x14)
16796 +#define PL080_RAW_ERR_STATUS (0x18)
16797 +#define PL080_EN_CHAN (0x1c)
16798 +#define PL080_SOFT_BREQ (0x20)
16799 +#define PL080_SOFT_SREQ (0x24)
16800 +#define PL080_SOFT_LBREQ (0x28)
16801 +#define PL080_SOFT_LSREQ (0x2C)
16802 +
16803 +#define PL080_CONFIG (0x30)
16804 +#define PL080_CONFIG_M2_BE (1 << 2)
16805 +#define PL080_CONFIG_M1_BE (1 << 1)
16806 +#define PL080_CONFIG_ENABLE (1 << 0)
16807 +
16808 +#define PL080_SYNC (0x34)
16809 +
16810 +/* Per channel configuration registers */
16811 +
16812 +#define PL008_Cx_STRIDE (0x20)
16813 +#define PL080_Cx_BASE(x) ((0x100 + (x * 0x20)))
16814 +#define PL080_Cx_SRC_ADDR(x) ((0x100 + (x * 0x20)))
16815 +#define PL080_Cx_DST_ADDR(x) ((0x104 + (x * 0x20)))
16816 +#define PL080_Cx_LLI(x) ((0x108 + (x * 0x20)))
16817 +#define PL080_Cx_CONTROL(x) ((0x10C + (x * 0x20)))
16818 +#define PL080_Cx_CONFIG(x) ((0x110 + (x * 0x20)))
16819 +#define PL080S_Cx_CONTROL2(x) ((0x110 + (x * 0x20)))
16820 +#define PL080S_Cx_CONFIG(x) ((0x114 + (x * 0x20)))
16821 +
16822 +#define PL080_CH_SRC_ADDR (0x00)
16823 +#define PL080_CH_DST_ADDR (0x04)
16824 +#define PL080_CH_LLI (0x08)
16825 +#define PL080_CH_CONTROL (0x0C)
16826 +#define PL080_CH_CONFIG (0x10)
16827 +#define PL080S_CH_CONTROL2 (0x10)
16828 +#define PL080S_CH_CONFIG (0x14)
16829 +
16830 +#define PL080_LLI_ADDR_MASK (0x3fffffff << 2)
16831 +#define PL080_LLI_ADDR_SHIFT (2)
16832 +#define PL080_LLI_LM_AHB2 (1 << 0)
16833 +
16834 +#define PL080_CONTROL_TC_IRQ_EN (1 << 31)
16835 +#define PL080_CONTROL_PROT_MASK (0x7 << 28)
16836 +#define PL080_CONTROL_PROT_SHIFT (28)
16837 +#define PL080_CONTROL_PROT_SYS (1 << 28)
16838 +#define PL080_CONTROL_DST_INCR (1 << 27)
16839 +#define PL080_CONTROL_SRC_INCR (1 << 26)
16840 +#define PL080_CONTROL_DST_AHB2 (1 << 25)
16841 +#define PL080_CONTROL_SRC_AHB2 (1 << 24)
16842 +#define PL080_CONTROL_DWIDTH_MASK (0x7 << 21)
16843 +#define PL080_CONTROL_DWIDTH_SHIFT (21)
16844 +#define PL080_CONTROL_SWIDTH_MASK (0x7 << 18)
16845 +#define PL080_CONTROL_SWIDTH_SHIFT (18)
16846 +#define PL080_CONTROL_DB_SIZE_MASK (0x7 << 15)
16847 +#define PL080_CONTROL_DB_SIZE_SHIFT (15)
16848 +#define PL080_CONTROL_SB_SIZE_MASK (0x7 << 12)
16849 +#define PL080_CONTROL_SB_SIZE_SHIFT (12)
16850 +#define PL080_CONTROL_TRANSFER_SIZE_MASK (0xfff << 0)
16851 +#define PL080_CONTROL_TRANSFER_SIZE_SHIFT (0)
16852 +
16853 +#define PL080_CONFIG_HALT (1 << 18)
16854 +#define PL080_CONFIG_ACTIVE (1 << 17)
16855 +#define PL080_CONFIG_LOCK (1 << 16)
16856 +#define PL080_CONFIG_TC_IRQ_MASK (1 << 15)
16857 +#define PL080_CONFIG_ERR_IRQ_MASK (1 << 14)
16858 +#define PL080_CONFIG_FLOW_CONTROL_MASK (0x7 << 11)
16859 +#define PL080_CONFIG_FLOW_CONTROL_SHIFT (11)
16860 +#define PL080_CONFIG_DST_SEL_MASK (0xf << 6)
16861 +#define PL080_CONFIG_DST_SEL_SHIFT (6)
16862 +#define PL080_CONFIG_SRC_SEL_MASK (0xf << 1)
16863 +#define PL080_CONFIG_SRC_SEL_SHIFT (1)
16864 +#define PL080_CONFIG_ENABLE (1 << 0)
16865 +
16866 +
16867 +/* DMA linked list chain structure */
16868 +
16869 +struct pl080_lli {
16870 + u32 src_addr;
16871 + u32 dst_addr;
16872 + u32 next_lli;
16873 + u32 control0;
16874 + u32 control1;
16875 +};
16876 +
16877 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/pm-core.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/pm-core.h
16878 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/pm-core.h 1970-01-01 01:00:00.000000000 +0100
16879 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/pm-core.h 2009-05-10 22:27:59.000000000 +0200
16880 @@ -0,0 +1,106 @@
16881 +/* linux/arch/arm/plat-s3c64xx/include/plat/pm-core.h
16882 + *
16883 + * Copyright 2008 Openmoko, Inc.
16884 + * Copyright 2008 Simtec Electronics
16885 + * Ben Dooks <ben@simtec.co.uk>
16886 + * http://armlinux.simtec.co.uk/
16887 + *
16888 + * S3C64XX - PM core support for arch/arm/plat-s3c/pm.c
16889 + *
16890 + * This program is free software; you can redistribute it and/or modify
16891 + * it under the terms of the GNU General Public License version 2 as
16892 + * published by the Free Software Foundation.
16893 + */
16894 +
16895 +#include <plat/regs-gpio.h>
16896 +
16897 +static inline void s3c_pm_debug_init_uart(void)
16898 +{
16899 + u32 tmp = __raw_readl(S3C_PCLK_GATE);
16900 +
16901 + /* As a note, since the S3C64XX UARTs generally have multiple
16902 + * clock sources, we simply enable PCLK at the moment and hope
16903 + * that the resume settings for the UART are suitable for the
16904 + * use with PCLK.
16905 + */
16906 +
16907 + tmp |= S3C_CLKCON_PCLK_UART0;
16908 + tmp |= S3C_CLKCON_PCLK_UART1;
16909 + tmp |= S3C_CLKCON_PCLK_UART2;
16910 + tmp |= S3C_CLKCON_PCLK_UART3;
16911 +
16912 + __raw_writel(tmp, S3C_PCLK_GATE);
16913 + udelay(10);
16914 +}
16915 +
16916 +static inline void s3c_pm_arch_clear_vic(void __iomem *base)
16917 +{
16918 + __raw_writel(~0, base + VIC_INT_ENABLE_CLEAR);
16919 + __raw_writel(~0, base + VIC_INT_SOFT_CLEAR);
16920 +}
16921 +
16922 +static inline void s3c_pm_arch_prepare_irqs(void)
16923 +{
16924 + /* shutdown the VICs */
16925 + s3c_pm_arch_clear_vic(S3C_VA_VIC0);
16926 + s3c_pm_arch_clear_vic(S3C_VA_VIC1);
16927 +
16928 + /* clear any pending EINT0 interrupts */
16929 + __raw_writel(__raw_readl(S3C64XX_EINT0PEND), S3C64XX_EINT0PEND);
16930 +}
16931 +
16932 +static inline void s3c_pm_arch_stop_clocks(void)
16933 +{
16934 +}
16935 +
16936 +static inline void s3c_pm_arch_show_resume_irqs(void)
16937 +{
16938 +}
16939 +
16940 +/* make these defines, we currently do not have any need to change
16941 + * the IRQ wake controls depending on the CPU we are running on */
16942 +
16943 +#define s3c_irqwake_eintallow ((1 << 28) - 1)
16944 +#define s3c_irqwake_intallow (0)
16945 +
16946 +static inline void s3c_pm_arch_update_uart(void __iomem *regs,
16947 + struct pm_uart_save *save)
16948 +{
16949 + u32 ucon = __raw_readl(regs + S3C2410_UCON);
16950 + u32 ucon_clk = ucon & S3C6400_UCON_CLKMASK;
16951 + u32 save_clk = save->ucon & S3C6400_UCON_CLKMASK;
16952 + u32 new_ucon;
16953 + u32 delta;
16954 +
16955 + /* S3C64XX UART blocks only support level interrupts, so ensure that
16956 + * when we restore unused UART blocks we force the level interrupt
16957 + * settigs. */
16958 + save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
16959 +
16960 + /* We have a constraint on changing the clock type of the UART
16961 + * between UCLKx and PCLK, so ensure that when we restore UCON
16962 + * that the CLK field is correctly modified if the bootloader
16963 + * has changed anything.
16964 + */
16965 + if (ucon_clk != save_clk) {
16966 + new_ucon = save->ucon;
16967 + delta = ucon_clk ^ save_clk;
16968 +
16969 + /* change from UCLKx => wrong PCLK,
16970 + * either UCLK can be tested for by a bit-test
16971 + * with UCLK0 */
16972 + if (ucon_clk & S3C6400_UCON_UCLK0 &&
16973 + !(save_clk & S3C6400_UCON_UCLK0) &&
16974 + delta & S3C6400_UCON_PCLK2) {
16975 + new_ucon &= ~S3C6400_UCON_UCLK0;
16976 + } else if (delta == S3C6400_UCON_PCLK2) {
16977 + /* as an precaution, don't change from
16978 + * PCLK2 => PCLK or vice-versa */
16979 + new_ucon ^= S3C6400_UCON_PCLK2;
16980 + }
16981 +
16982 + S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
16983 + ucon, new_ucon, save->ucon);
16984 + save->ucon = new_ucon;
16985 + }
16986 +}
16987 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-camif.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-camif.h
16988 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-camif.h 1970-01-01 01:00:00.000000000 +0100
16989 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-camif.h 2009-05-10 22:27:59.000000000 +0200
16990 @@ -0,0 +1,460 @@
16991 +/* arch/arm/plat-s3c64xx/include/plat/regs-camif.h
16992 + *
16993 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
16994 + * http://www.simtec.co.uk/products/SWLINUX/
16995 + *
16996 + * This program is free software; you can redistribute it and/or modify
16997 + * it under the terms of the GNU General Public License version 2 as
16998 + * published by the Free Software Foundation.
16999 +*/
17000 +
17001 +
17002 +#ifndef ___ASM_ARCH_REGS_CAMIF_H
17003 +#define ___ASM_ARCH_REGS_CAMIF_H
17004 +
17005 +#define S3C_CAMIFREG(x) (x)
17006 +
17007 +/*************************************************************************
17008 + * Macro part
17009 + ************************************************************************/
17010 +#define S3C_CISRCFMT_SOURCEHSIZE(x) ((x) << 16)
17011 +#define S3C_CISRCFMT_GET_SOURCEHSIZE(x) (((x) >> 16) & 0x1FFFF)
17012 +#define S3C_CISRCFMT_SOURCEVSIZE(x) ((x) << 0)
17013 +#define S3C_CISRCFMT_GET_SOURCEVSIZE(x) (((x) >> 0) & 0x1FFF)
17014 +
17015 +#define S3C_CIWDOFST_WINHOROFST(x) ((x) << 16)
17016 +#define S3C_CIWDOFST_GET_WINHOROFST(x) (((x) >> 16) & 0x7FF)
17017 +#define S3C_CIWDOFST_WINVEROFST(x) ((x) << 0)
17018 +#define S3C_CIWDOFST_GET_WINVEROFST(x) (((x) >> 0) & 0x7FF)
17019 +
17020 +#define S3C_CIDOWSFT2_WINHOROFST2(x) ((x) << 16)
17021 +#define S3C_CIDOWSFT2_GET_WINHOROFST2(x) (((x) >> 16) & 0x7FF)
17022 +#define S3C_CIDOWSFT2_WINVEROFST2(x) ((x) << 0)
17023 +#define S3C_CIDOWSFT2_GET_WINVEROFST2(x) (((x) >> 0) & 0x7FF)
17024 +
17025 +#define S3C_CICOTRGFMT_TARGETHSIZE_CO(x) ((x) << 16)
17026 +#define S3C_CICOTRGFMT_GET_TARGETHSIZE_CO(x) (((x) >> 16) & 0x1FFF)
17027 +
17028 +#define S3C_CICOTRGFMT_TARGETVSIZE_CO(x) ((x) << 0)
17029 +#define S3C_CICOTRGFMT_GET_TARGETVSIZE_CO(x) (((x) >> 0) & 0x1FFF)
17030 +
17031 +#define S3C_CICOCTRL_YBURST1_CO(x) ((x) << 19)
17032 +#define S3C_CICOCTRL_YBURST2_CO(x) ((x) << 14)
17033 +#define S3C_CICOCTRL_CBURST1_CO(x) ((x) << 9)
17034 +#define S3C_CICOCTRL_CBURST2_CO(x) ((x) << 4)
17035 +
17036 +#define S3C_CICOSCPRERATIO_SHFACTOR_CO(x) ((x) << 28)
17037 +#define S3C_CICOSCPRERATIO_GET_SHFACTOR_CO(x) (((x) >> 28) & 0x7F)
17038 +#define S3C_CICOSCPRERATIO_PREHORRATIO_CO(x) ((x) << 16)
17039 +#define S3C_CICOSCPRERATIO_GET_PREHORRATIO_CO(x) (((x) >> 16) & 0x7F)
17040 +#define S3C_CICOSCPRERATIO_PREVERRATIO_CO(x) ((x) << 0)
17041 +#define S3C_CICOSCPRERATIO_GET_PREVERRATIO_CO(x) (((x) >> 0) & 0x7F)
17042 +
17043 +#define S3C_CICOSCPREDST_PREDSTWIDTH_CO(x) ((x) << 16)
17044 +#define S3C_CICOSCPREDST_GET_PREDSTWIDTH_CO(x) (((x) >> 16) & 0x7FF)
17045 +#define S3C_CICOSCPREDST_PREDSTHEIGHT_CO(x) ((x) << 0)
17046 +#define S3C_CICOSCPREDST_GET_PREDSTHEIGHT_CO(x) (((x) >> 0) & 0x7FF)
17047 +
17048 +#define S3C_CICOSCCTRL_MAINHORRATIO_CO(x) ((x) << 16)
17049 +#define S3C_CICOSCCTRL_GET_MAINHORRATIO_CO(x) (((x) >> 16) & 0x1FF)
17050 +#define S3C_CICOSCCTRL_MAINVERRATIO_CO(x) ((x) << 0)
17051 +
17052 +#define S3C_CICOSTATUS_FRAMECNT_CO(x) ((x) << 26)
17053 +#define S3C_CICOSTATUS_GET_FRAMECNT_CO(x) (((x) >> 26) & 0x3)
17054 +
17055 +#define S3C_CIPRTRGFMT_TARGETHSIZE_PR(x) ((x) << 16)
17056 +#define S3C_CIPRTRGFMT_GET_TARGETHSIZE_PR(x) (((x) >> 16) & 0x1FFF)
17057 +
17058 +#define S3C_CIPRTRGFMT_GET_ROT90_PR(x) (((x) >> 13) & 0x1)
17059 +
17060 +#define S3C_CIPRTRGFMT_TARGETVSIZE_PR(x) ((x) << 0)
17061 +#define S3C_CIPRTRGFMT_GET_TARGETVSIZE_PR(x) (((x) >> 0) & 0x1FFF)
17062 +
17063 +#define S3C_CIPRSCPRERATIO_SHFACTOR_PR(x) ((x) << 28)
17064 +#define S3C_CIPRSCPRERATIO_GET_SHFACTOR_PR(x) (((x) >> 28) & 0xF)
17065 +#define S3C_CIPRSCPRERATIO_PREHORRATIO_PR(x) ((x) << 16)
17066 +#define S3C_CIPRSCPRERATIO_GET_PREHORRATIO_PR(x) (((x) >> 16) & 0x7F)
17067 +#define S3C_CIPRSCPRERATIO_PREVERRATIO_PR(x) ((x) << 0)
17068 +#define S3C_CIPRSCPRERATIO_GET_PREVERRATIO_PR(x) (((x) >> 0) & 0x7F)
17069 +
17070 +#define S3C_CIPRSCPREDST_PREDSTWIDTH_PR(x) ((x) << 16)
17071 +#define S3C_CIPRSCPREDST_GET_PREDSTWIDTH_PR(x) (((x) >> 16) & 0xFFF)
17072 +#define S3C_CIPRSCPREDST_PREDSTHEIGHT_PR(x) ((x) << 0)
17073 +#define S3C_CIPRSCPREDST_GET_PREDSTHEIGHT_PR(x) (((x) >> 0) & 0xFFF)
17074 +
17075 +#define S3C_CIPRSCCTRL_MAINHORRATIO_PR(x) ((x) << 16)
17076 +#define S3C_CIPRSCCTRL_GET_MAINHORRATIO_PR(x) (((x) >> 16) && 0x1FF)
17077 +#define S3C_CIPRSCCTRL_MAINVERRATIO_PR(x) ((x) << 0)
17078 +#define S3C_CIPRSCCTRL_GET_MAINVERRATIO_PR(x) (((x) >> 0) && 0x1FF)
17079 +
17080 +/*************************************************************************
17081 + * Bit definition part
17082 + ************************************************************************/
17083 +/* Windows Offset Register */
17084 +#define S3C_CIWDOFST_WINOFSEN (1 << 31)
17085 +#define S3C_CIWDOFST_CLROVCOFIY (1 << 30)
17086 +#define S3C_CIWDOFST_CLROVRLB_CO (1 << 29)
17087 +#define S3C_CIWDOFST_CLROVRLB_PR (1 << 28)
17088 +#define S3C_CIWDOFST_CLROVPRFIY (1 << 27)
17089 +#define S3C_CIWDOFST_CLROVCOFICB (1 << 15)
17090 +#define S3C_CIWDOFST_CLROVCOFICR (1 << 14)
17091 +#define S3C_CIWDOFST_CLROVPRFICB (1 << 13)
17092 +#define S3C_CIWDOFST_CLROVPRFICR (1 << 12)
17093 +
17094 +/* Global Control Register */
17095 +#define S3C_CIGCTRL_SWRST (1 << 31)
17096 +#define S3C_CIGCTRL_CAMRST (1 << 30)
17097 +
17098 +#if defined (CONFIG_CPU_S3C6400) || defined (CONFIG_CPU_S3C6410)
17099 +#define S3C_CIGCTRL_IRQ_LEVEL (1 << 20)
17100 +#endif
17101 +
17102 +#define S3C_CIGCTRL_TESTPATTERN_VER_INC (3 << 27)
17103 +#define S3C_CIGCTRL_TESTPATTERN_HOR_INC (2 << 27)
17104 +#define S3C_CIGCTRL_TESTPATTERN_COLOR_BAR (1 << 27)
17105 +#define S3C_CIGCTRL_TESTPATTERN_NORMAL (0 << 27)
17106 +
17107 +#define S3C_CIGCTRL_INVPOLPCLK (1 << 26)
17108 +#define S3C_CIGCTRL_INVPOLVSYNC (1 << 25)
17109 +#define S3C_CIGCTRL_INVPOLHREF (1 << 24)
17110 +#define S3C_CIGCTRL_IRQ_OVFEN (1 << 22)
17111 +#define S3C_CIGCTRL_HREF_MASK (1 << 21)
17112 +#define S3C_CIGCTRL_IRQ_LEVEL (1 << 20)
17113 +#define S3C_CIGCTRL_IRQ_CLR_C (1 << 19)
17114 +#define S3C_CIGCTRL_IRQ_CLR_P (1 << 18)
17115 +
17116 +/* Codec Target Format Register */
17117 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
17118 +#define S3C_CICOTRGFMT_IN422_422 (1 << 31)
17119 +#define S3C_CICOTRGFMT_IN422_420 (0 << 31)
17120 +#define S3C_CICOTRGFMT_OUT422_422 (1 << 30)
17121 +#define S3C_CICOTRGFMT_OUT422_420 (0 << 30)
17122 +
17123 +#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
17124 +#define S3C_CICOTRGFMT_OUTFORMAT_RGBOUT (3 << 29)
17125 +#define S3C_CICOTRGFMT_OUTFORMAT_YCBCR422OUTINTERLEAVE (2 << 29)
17126 +#define S3C_CICOTRGFMT_OUTFORMAT_YCBCR422OUT (1 << 29)
17127 +#define S3C_CICOTRGFMT_OUTFORMAT_YCBCR420OUT (0 << 29)
17128 +#endif
17129 +
17130 +#define S3C_CICOTRGFMT_INTERLEAVE_ON (1 << 29)
17131 +#define S3C_CICOTRGFMT_INTERLEAVE_OFF (0 << 29)
17132 +
17133 +#define S3C_CICOTRGFMT_FLIP_180 (3 << 14)
17134 +#define S3C_CICOTRGFMT_FLIP_Y_MIRROR (2 << 14)
17135 +#define S3C_CICOTRGFMT_FLIP_X_MIRROR (1 << 14)
17136 +#define S3C_CICOTRGFMT_FLIP_NORMAL (0 << 14)
17137 +
17138 +/* Codec DMA Control Register */
17139 +#define S3C_CICOCTRL_LASTIRQEN (1 << 2)
17140 +#define S3C_CICOCTRL_ORDER422_CRYCBY (3 << 0)
17141 +#define S3C_CICOCTRL_ORDER422_CBYCRY (2 << 0)
17142 +#define S3C_CICOCTRL_ORDER422_YCRYCB (1 << 0)
17143 +#define S3C_CICOCTRL_ORDER422_YCBYCR (0 << 0)
17144 +
17145 +/* Codec Main-Scaler Control Register */
17146 +#define S3C_CICOSCCTRL_SCALERBYPASS_CO (1 << 31)
17147 +#define S3C_CICOSCCTRL_SCALEUP_H (1 << 30)
17148 +#define S3C_CICOSCCTRL_SCALEUP_V (1 << 29)
17149 +
17150 +#define S3C_CICOSCCTRL_CSCR2Y_WIDE (1 << 28)
17151 +#define S3C_CICOSCCTRL_CSCR2Y_NARROW (0 << 28)
17152 +
17153 +#define S3C_CICOSCCTRL_CSCY2R_WIDE (1 << 27)
17154 +#define S3C_CICOSCCTRL_CSCY2R_NARROW (0 << 27)
17155 +
17156 +#define S3C_CICOSCCTRL_LCDPATHEN_FIFO (1 << 26)
17157 +#define S3C_CICOSCCTRL_LCDPATHEN_DMA (0 << 26)
17158 +
17159 +#define S3C_CICOSCCTRL_INTERLACE_INTERLACE (1 << 25)
17160 +#define S3C_CICOSCCTRL_INTERLACE_PROGRESSIVE (0 << 25)
17161 +
17162 +#define S3C_CICOSCCTRL_COSCALERSTART (1 << 15)
17163 +
17164 +#define S3C_CICOSCCTRL_INRGB_FMT_RGB888 (2 << 13)
17165 +#define S3C_CICOSCCTRL_INRGB_FMT_RGB666 (1 << 13)
17166 +#define S3C_CICOSCCTRL_INRGB_FMT_RGB565 (0 << 13)
17167 +
17168 +#define S3C_CICOSCCTRL_OUTRGB_FMT_RGB888 (2 << 11)
17169 +#define S3C_CICOSCCTRL_OUTRGB_FMT_RGB666 (1 << 11)
17170 +#define S3C_CICOSCCTRL_OUTRGB_FMT_RGB565 (0 << 11)
17171 +
17172 +#define S3C_CICOSCCTRL_EXTRGB_EXTENSION (1 << 10)
17173 +#define S3C_CICOSCCTRL_EXTRGB_NORMAL (0 << 10)
17174 +
17175 +/* Codec Status Register */
17176 +#define S3C_CICOSTATUS_OVFIY_CO (1 << 31)
17177 +#define S3C_CICOSTATUS_OVFICB_CO (1 << 30)
17178 +#define S3C_CICOSTATUS_OVFICR_CO (1 << 29)
17179 +#define S3C_CICOSTATUS_VSYNC (1 << 28)
17180 +#define S3C_CICOSTATUS_WINOFSTEN_CO (1 << 25)
17181 +#define S3C_CICOSTATUS_IMGCPTEN_CAMIF (1 << 22)
17182 +#define S3C_CICOSTATUS_IMGCPTEN_COSC (1 << 21)
17183 +#define S3C_CICOSTATUS_VSYNC_A (1 << 20)
17184 +#define S3C_CICOSTATUS_VSYNC_B (1 << 19)
17185 +#define S3C_CICOSTATUS_OVRLB_CO (1 << 18)
17186 +#define S3C_CICOSTATUS_FRAMEEND_CO (1 << 17)
17187 +
17188 +/* Preview Target Format Register */
17189 +#define S3C_CIPRTRGFMT_FLIPMD_180ROT (3 << 14)
17190 +#define S3C_CIPRTRGFMT_FLIPMD_YMIRROR (2 << 14)
17191 +#define S3C_CIPRTRGFMT_FLIPMD_XMIRROR (1 << 14)
17192 +#define S3C_CIPRTRGFMT_FLIPMD_NORMAL (0 << 14)
17193 +
17194 +#define S3C_CIPRTRGFMT_ROT90_ROTATE (1 << 13)
17195 +#define S3C_CIPRTRGFMT_ROT90_BYPASS (0 << 13)
17196 +
17197 +/* Preview DMA Control Register */
17198 +#define S3C_CIPRCTRL_LASTIRQEN_ENABLE (1 << 2)
17199 +#define S3C_CIPRCTRL_LASTIRQEN_NORMAL (0 << 2)
17200 +
17201 +#define S3C_CIPRCTRL_ORDER422_CRYCBY (3 << 0)
17202 +#define S3C_CIPRCTRL_ORDER422_CBYCRY (2 << 0)
17203 +#define S3C_CIPRCTRL_ORDER422_YCRYCB (1 << 0)
17204 +#define S3C_CIPRCTRL_ORDER422_YCBYCR (0 << 0)
17205 +
17206 +/* Preview Main-Scaler Control Register */
17207 +#define S3C_CIPRSCCTRL_SAMPLE_PR (1 << 31)
17208 +
17209 +#define S3C_CIPRSCCTRL_RGBFORMAT_24 (1 << 30)
17210 +#define S3C_CIPRSCCTRL_RGBFORMAT_16 (0 << 30)
17211 +
17212 +#define S3C_CIPRSCCTRL_START (1 << 15)
17213 +
17214 +#define S3C_CIPRSCCTRL_INRGB_FMT_PR_RGB888 (2 << 13)
17215 +#define S3C_CIPRSCCTRL_INRGB_FMT_PR_RGB666 (1 << 13)
17216 +#define S3C_CIPRSCCTRL_INRGB_FMT_PR_RGB565 (0 << 13)
17217 +
17218 +#define S3C_CIPRSCCTRL_OUTRGB_FMT_PR_RGB888 (2 << 11)
17219 +#define S3C_CIPRSCCTRL_OUTRGB_FMT_PR_RGB666 (1 << 11)
17220 +#define S3C_CIPRSCCTRL_OUTRGB_FMT_PR_RGB565 (0 << 11)
17221 +
17222 +/* Preview Status Register */
17223 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
17224 +#define S3C_CIPRSTATUS_OVFICB_PR (1 << 31)
17225 +#define S3C_CIPRSTATUS_OVFICR_PR (1 << 30)
17226 +
17227 +#elif defined CONFIG_CPU_S3C6400 || defined CONFIG_CPU_S3C6410
17228 +#define S3C_CIPRSTATUS_OVFIY_PR (1 << 31)
17229 +#define S3C_CIPRSTATUS_OVFICB_PR (1 << 30)
17230 +#define S3C_CIPRSTATUS_OVFICR_PR (1 << 29)
17231 +#endif
17232 +
17233 +/* Image Capture Enable Register */
17234 +#define S3C_CIIMGCPT_IMGCPTEN (1 << 31)
17235 +#define S3C_CIIMGCPT_IMGCPTEN_COSC (1 << 30)
17236 +#define S3C_CIIMGCPT_IMGCPTEN_PRSC (1 << 29)
17237 +
17238 +#define S3C_CIIMGCPT_CPT_CODMA_SEL_RGB (1 << 26)
17239 +#define S3C_CIIMGCPT_CPT_CODMA_SEL_YUV (0 << 26)
17240 +
17241 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
17242 +#define S3C_CIIMGCPT_CPT_CODMA_RGBFMT_24 (1 << 25)
17243 +#define S3C_CIIMGCPT_CPT_CODMA_RGBFMT_16 (0 << 25)
17244 +#define S3C_CIIMGCPT_CPT_CODMA_ENABLE (1 << 24)
17245 +#define S3C_CIIMGCPT_CPT_CODMA_DISABLE (0 << 24)
17246 +#define S3C_CIIMGCPT_CPT_CODMA_MOD_CNT (1 << 18)
17247 +#define S3C_CIIMGCPT_CPT_CODMA_MOD_EN (0 << 18)
17248 +
17249 +#elif defined CONFIG_CPU_S3C6400 || defined CONFIG_CPU_S3C6410
17250 +#define S3C_CIIMGCPT_CPT_FREN_CO_ENABLE (1 << 25)
17251 +#define S3C_CIIMGCPT_CPT_FREN_CO_DISABLE (0 << 25)
17252 +#define S3C_CIIMGCPT_CPT_FREN_PR_ENABLE (1 << 24)
17253 +#define S3C_CIIMGCPT_CPT_FREN_PR_DISABLE (0 << 24)
17254 +#define S3C_CIIMGCPT_CPT_FRMOD_CNT (1 << 18)
17255 +#define S3C_CIIMGCPT_CPT_FRMOD_EN (0 << 18)
17256 +#endif
17257 +
17258 +/* Image Effects Register */
17259 +#define S3C_CIIMGEFF_IE_ON_PR_ENABLE (1 << 31)
17260 +#define S3C_CIIMGEFF_IE_ON_PR_DISABLE (0 << 31)
17261 +
17262 +#define S3C_CIIMGEFF_IE_ON_CO_ENABLE (1 << 30)
17263 +#define S3C_CIIMGEFF_IE_ON_CO_DISABLE (0 << 30)
17264 +
17265 +#define S3C_CIIMGEFF_IE_AFTER_SC_BEFORE (0 << 29)
17266 +#define S3C_CIIMGEFF_IE_AFTER_SC_AFTER (1 << 29)
17267 +
17268 +#define S3C_CIIMGEFF_FIN_SILHOUETTE (5 << 26)
17269 +#define S3C_CIIMGEFF_FIN_EMBOSSING (4 << 26)
17270 +#define S3C_CIIMGEFF_FIN_ARTFREEZE (3 << 26)
17271 +#define S3C_CIIMGEFF_FIN_NEGATIVE (2 << 26)
17272 +#define S3C_CIIMGEFF_FIN_ARBITRARY (1 << 26)
17273 +#define S3C_CIIMGEFF_FIN_BYPASS (0 << 26)
17274 +
17275 +/* MSDMA for Codec Source Image Width Register */
17276 +#define S3C_MSCOWIDTH_AUTOLOAD_ENABLE (1 << 31)
17277 +#define S3C_MSCOWIDTH_AUTOLOAD_DISABLE (0 << 31)
17278 +
17279 +#define S3C_MSCOWIDTH_ADDR_CH_ENABLE (1 << 30)
17280 +#define S3C_MSCOWIDTH_ADDR_CH_DISABLE (0 << 30)
17281 +
17282 +/* MSDMA Control Register */
17283 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
17284 +#define S3C_CIMSCTRL_INTERLEAVE_MS_INTERLEAVE (1 << 5)
17285 +#define S3C_CIMSCTRL_INTERLEAVE_MS_NONINTERLEAVE (0 << 5)
17286 +#define S3C_CIMSCTRL_ORDER422_MS_CRYCBY (3 << 3)
17287 +#define S3C_CIMSCTRL_ORDER422_MS_CBYCRY (2 << 3)
17288 +#define S3C_CIMSCTRL_ORDER422_MS_YCRYCB (1 << 3)
17289 +#define S3C_CIMSCTRL_ORDER422_MS_YCBYCR (0 << 3)
17290 +#define S3C_CIMSCTRL_SEL_DMA_CAM_MEMORY (1 << 2)
17291 +#define S3C_CIMSCTRL_SEL_DMA_CAM_EXTCAM (0 << 2)
17292 +#define S3C_CIMSCTRL_SRC420_MS_420 (1 << 1)
17293 +#define S3C_CIMSCTRL_SRC420_MS_422 (0 << 1)
17294 +#define S3C_CIMSCTRL_ENVID_MS_SET (1 << 0)
17295 +
17296 +#elif defined CONFIG_CPU_S3C6400 || defined CONFIG_CPU_S3C6410
17297 +#define S3C_MSCOCTRL_BC_SEL_FRAME (0 << 10)
17298 +#define S3C_MSCOCTRL_BC_SEL_FIELD (1 << 10)
17299 +#define S3C_MSCOCTRL_BUFFER_INI_0 (0 << 8)
17300 +#define S3C_MSCOCTRL_BUFFER_INI_1 (1 << 8)
17301 +#define S3C_MSCOCTRL_TRG_MODE_SOFT (0 << 7)
17302 +#define S3C_MSCOCTRL_TRG_MODE_HARD (1 << 7)
17303 +#define S3C_MSCOCTRL_ORDER422_M_C_YCBYCR (0 << 4)
17304 +#define S3C_MSCOCTRL_ORDER422_M_C_YCRYCB (1 << 4)
17305 +#define S3C_MSCOCTRL_ORDER422_M_C_CBYCRY (2 << 4)
17306 +#define S3C_MSCOCTRL_ORDER422_M_C_CRYCBY (3 << 4)
17307 +#define S3C_MSCOCTRL_SEL_DMA_CAM_C_EXTCAM (0 << 3)
17308 +#define S3C_MSCOCTRL_SEL_DMA_CAM_C_MEMORY (1 << 3)
17309 +#define S3C_MSCOCTRL_INFORMAT_M_C_420 (0 << 1)
17310 +#define S3C_MSCOCTRL_INFORMAT_M_C_422 (1 << 1)
17311 +#define S3C_MSCOCTRL_INFORMAT_M_C_422_INT (2 << 1)
17312 +#define S3C_MSCOCTRL_INFORMAT_M_C_RGB (3 << 1)
17313 +#define S3C_MSCOCTRL_ENVID_M_C_SET (1 << 0)
17314 +#define S3C_MSPRCTRL_BC_SEL_FIELD (0 << 10)
17315 +#define S3C_MSPRCTRL_BC_SEL_FRAME (1 << 10)
17316 +#define S3C_MSPRCTRL_BUFFER_INI_0 (0 << 8)
17317 +#define S3C_MSPRCTRL_BUFFER_INI_1 (1 << 8)
17318 +#define S3C_MSPRCTRL_TRG_MODE_SOFT (0 << 7)
17319 +#define S3C_MSPRCTRL_TRG_MODE_HARD (1 << 7)
17320 +#define S3C_MSPRCTRL_ORDER422_M_P_YCBYCR (0 << 4)
17321 +#define S3C_MSPRCTRL_ORDER422_M_P_YCRYCB (1 << 4)
17322 +#define S3C_MSPRCTRL_ORDER422_M_P_CBYCRY (2 << 4)
17323 +#define S3C_MSPRCTRL_ORDER422_M_P_CRYCBY (3 << 4)
17324 +#define S3C_MSPRCTRL_SEL_DMA_CAM_P_EXTCAM (0 << 3)
17325 +#define S3C_MSPRCTRL_SEL_DMA_CAM_P_MEMORY (1 << 3)
17326 +#define S3C_MSPRCTRL_INFORMAT_M_P_420 (0 << 1)
17327 +#define S3C_MSPRCTRL_INFORMAT_M_P_422 (1 << 1)
17328 +#define S3C_MSPRCTRL_INFORMAT_M_P_422_INT (2 << 1)
17329 +#define S3C_MSPRCTRL_INFORMAT_M_P_RGB (3 << 1)
17330 +#define S3C_MSPRCTRL_ENVID_M_P_SET (1 << 0)
17331 +#endif
17332 +
17333 +/*************************************************************************
17334 + * Register part
17335 + ************************************************************************/
17336 +#define S3C_CICOYSA(__x) S3C_CAMIFREG(0x18 + (__x) * 4)
17337 +#define S3C_CICOCBSA(__x) S3C_CAMIFREG(0x28 + (__x) * 4)
17338 +#define S3C_CICOCRSA(__x) S3C_CAMIFREG(0x38 + (__x) * 4)
17339 +#define S3C_CIPRCLRSA(__x) S3C_CAMIFREG(0x6C + (__x) * 4)
17340 +#define S3C_CIPRYSA(__x) S3C_CAMIFREG(0x6C + (__x) * 4)
17341 +#define S3C_CIPRCBSA(__x) S3C_CAMIFREG(0x7C + (__x) * 4)
17342 +#define S3C_CIPRCRSA(__x) S3C_CAMIFREG(0x8C + (__x) * 4)
17343 +
17344 +#define S3C_CISRCFMT S3C_CAMIFREG(0x00)
17345 +#define S3C_CIWDOFST S3C_CAMIFREG(0x04)
17346 +#define S3C_CIGCTRL S3C_CAMIFREG(0x08)
17347 +#define S3C_CIDOWSFT2 S3C_CAMIFREG(0x14)
17348 +#define S3C_CICOYSA1 S3C_CAMIFREG(0x18)
17349 +#define S3C_CICOYSA2 S3C_CAMIFREG(0x1C)
17350 +#define S3C_CICOYSA3 S3C_CAMIFREG(0x20)
17351 +#define S3C_CICOYSA4 S3C_CAMIFREG(0x24)
17352 +#define S3C_CICOCBSA1 S3C_CAMIFREG(0x28)
17353 +#define S3C_CICOCBSA2 S3C_CAMIFREG(0x2C)
17354 +#define S3C_CICOCBSA3 S3C_CAMIFREG(0x30)
17355 +#define S3C_CICOCBSA4 S3C_CAMIFREG(0x34)
17356 +#define S3C_CICOCRSA1 S3C_CAMIFREG(0x38)
17357 +#define S3C_CICOCRSA2 S3C_CAMIFREG(0x3C)
17358 +#define S3C_CICOCRSA3 S3C_CAMIFREG(0x40)
17359 +#define S3C_CICOCRSA4 S3C_CAMIFREG(0x44)
17360 +#define S3C_CICOTRGFMT S3C_CAMIFREG(0x48) /* CODEC target format */
17361 +#define S3C_CICOCTRL S3C_CAMIFREG(0x4C) /* CODEC DMA control register */
17362 +#define S3C_CICOSCPRERATIO S3C_CAMIFREG(0x50) /* CODEC pre-scaler control register 1 */
17363 +#define S3C_CICOSCPREDST S3C_CAMIFREG(0x54) /* CODEC pre-scaler control register 2 */
17364 +#define S3C_CICOSCCTRL S3C_CAMIFREG(0x58) /* CODEC main-scaler control */
17365 +#define S3C_CICOTAREA S3C_CAMIFREG(0x5C) /* CODEC DMA target area register */
17366 +#define S3C_CICOSTATUS S3C_CAMIFREG(0x64) /* CODEC status register */
17367 +
17368 +#if defined (CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
17369 +#define S3C_CIPRCLRSA1 S3C_CAMIFREG(0x6C) /* RGB 1st frame start address for preview DMA */
17370 +#define S3C_CIPRCLRSA2 S3C_CAMIFREG(0x70) /* RGB 2nd frame start address for preview DMA */
17371 +#define S3C_CIPRCLRSA3 S3C_CAMIFREG(0x74) /* RGB 3rd frame start address for preview DMA */
17372 +#define S3C_CIPRCLRSA4 S3C_CAMIFREG(0x78) /* RGB 4th frame start address for preview DMA */
17373 +#define S3C_CIPRTRGFMT S3C_CAMIFREG(0x7C) /* PREVIEW target format register */
17374 +#define S3C_CIPRCTRL S3C_CAMIFREG(0x80) /* PREVIEW DMA control register */
17375 +#define S3C_CIPRSCPRERATIO S3C_CAMIFREG(0x84) /* PREVIEW pre-scaler control register 1 */
17376 +#define S3C_CIPRSCPREDST S3C_CAMIFREG(0x88) /* PREVIEW pre-scaler control register 2 */
17377 +#define S3C_CIPRSCCTRL S3C_CAMIFREG(0x8C) /* PREVIEW main-scaler control register */
17378 +#define S3C_CIPRTAREA S3C_CAMIFREG(0x90) /* PREVIEW DMA target area register */
17379 +#define S3C_CIPRSTATUS S3C_CAMIFREG(0x98) /* PREVIEW status register */
17380 +#define S3C_CIIMGCPT S3C_CAMIFREG(0xA0) /* image capture enable register */
17381 +#define S3C_CICOCPTSEQ S3C_CAMIFREG(0xA4) /* CODEC capture sequence register */
17382 +#define S3C_CICOSCOS S3C_CAMIFREG(0xA8) /* CODEC scan line offset register */
17383 +#define S3C_CIIMGEFF S3C_CAMIFREG(0xB0) /* image effect register */
17384 +#define S3C_CIMSYSA S3C_CAMIFREG(0xB4) /* MSDMA Y start address register */
17385 +#define S3C_CIMSCBSA S3C_CAMIFREG(0xB8) /* MSDMA CB start address register */
17386 +#define S3C_CIMSCRSA S3C_CAMIFREG(0xBC) /* MSDMA CR start address register */
17387 +#define S3C_CIMSYEND S3C_CAMIFREG(0xC0) /* MSDMA Y end address register */
17388 +#define S3C_CIMSCBEND S3C_CAMIFREG(0xC4) /* MSDMA CB end address register */
17389 +#define S3C_CIMSCREND S3C_CAMIFREG(0xC8) /* MSDMA CR end address register */
17390 +#define S3C_CIMSYOFF S3C_CAMIFREG(0xCC) /* MSDMA Y offset register */
17391 +#define S3C_CIMSCBOFF S3C_CAMIFREG(0xD0) /* MSDMA CB offset register */
17392 +#define S3C_CIMSCROFF S3C_CAMIFREG(0xD4) /* MSDMA CR offset register */
17393 +#define S3C_CIMSWIDTH S3C_CAMIFREG(0xD8) /* MSDMA source image width register */
17394 +#define S3C_CIMSCTRL S3C_CAMIFREG(0xDC) /* MSDMA control register */
17395 +
17396 +#elif defined CONFIG_CPU_S3C6400 || defined CONFIG_CPU_S3C6410
17397 +#define S3C_CIPRYSA1 S3C_CAMIFREG(0x6C) /* 1st frame start address for preview DMA */
17398 +#define S3C_CIPRYSA2 S3C_CAMIFREG(0x70) /* 2nd frame start address for preview DMA */
17399 +#define S3C_CIPRYSA3 S3C_CAMIFREG(0x74) /* 3rd frame start address for preview DMA */
17400 +#define S3C_CIPRYSA4 S3C_CAMIFREG(0x78) /* 4th frame start address for preview DMA */
17401 +#define S3C_CIPRCBSA1 S3C_CAMIFREG(0x7C) /* 1st frame start address for preview DMA */
17402 +#define S3C_CIPRCBSA2 S3C_CAMIFREG(0x80) /* 2nd frame start address for preview DMA */
17403 +#define S3C_CIPRCBSA3 S3C_CAMIFREG(0x84) /* 3rd frame start address for preview DMA */
17404 +#define S3C_CIPRCBSA4 S3C_CAMIFREG(0x88) /* 4th frame start address for preview DMA */
17405 +#define S3C_CIPRCRSA1 S3C_CAMIFREG(0x8C) /* 1st frame start address for preview DMA */
17406 +#define S3C_CIPRCRSA2 S3C_CAMIFREG(0x90) /* 2nd frame start address for preview DMA */
17407 +#define S3C_CIPRCRSA3 S3C_CAMIFREG(0x94) /* 3rd frame start address for preview DMA */
17408 +#define S3C_CIPRCRSA4 S3C_CAMIFREG(0x98) /* 4th frame start address for preview DMA */
17409 +#define S3C_CIPRTRGFMT S3C_CAMIFREG(0x9C) /* PREVIEW target format register */
17410 +#define S3C_CIPRCTRL S3C_CAMIFREG(0xA0) /* PREVIEW DMA control register */
17411 +#define S3C_CIPRSCPRERATIO S3C_CAMIFREG(0xA4) /* PREVIEW pre-scaler control register 1 */
17412 +#define S3C_CIPRSCPREDST S3C_CAMIFREG(0xA8) /* PREVIEW pre-scaler control register 2 */
17413 +#define S3C_CIPRSCCTRL S3C_CAMIFREG(0xAC) /* PREVIEW main-scaler control register */
17414 +#define S3C_CIPRTAREA S3C_CAMIFREG(0xB0) /* PREVIEW DMA target area register */
17415 +#define S3C_CIPRSTATUS S3C_CAMIFREG(0xB8) /* PREVIEW status register */
17416 +#define S3C_CIIMGCPT S3C_CAMIFREG(0xC0) /* image capture enable register */
17417 +#define S3C_CICOCPTSEQ S3C_CAMIFREG(0xC4) /* CODEC capture sequence register */
17418 +#define S3C_CIIMGEFF S3C_CAMIFREG(0xD0) /* image effect register */
17419 +#define S3C_MSCOY0SA S3C_CAMIFREG(0xD4) /* MSDMA for CODEC Y start address register */
17420 +#define S3C_MSCOCB0SA S3C_CAMIFREG(0xD8) /* MSDMA for CODEC CB start address register */
17421 +#define S3C_MSCOCR0SA S3C_CAMIFREG(0xDC) /* MSDMA for CODEC CR start address register */
17422 +#define S3C_MSCOY0END S3C_CAMIFREG(0xE0) /* MSDMA for CODEC Y end address register */
17423 +#define S3C_MSCOCB0END S3C_CAMIFREG(0xE4) /* MSDMA for CODEC CB end address register */
17424 +#define S3C_MSCOCR0END S3C_CAMIFREG(0xE8) /* MSDMA for CODEC CR end address register */
17425 +#define S3C_MSCOYOFF S3C_CAMIFREG(0xEC) /* MSDMA for CODEC Y offset register */
17426 +#define S3C_MSCOCBOFF S3C_CAMIFREG(0xF0) /* MSDMA for CODEC CB offset register */
17427 +#define S3C_MSCOCROFF S3C_CAMIFREG(0xF4) /* MSDMA for CODEC CR offset register */
17428 +#define S3C_MSCOWIDTH S3C_CAMIFREG(0xF8) /* MSDMA for CODEC source image width register */
17429 +#define S3C_MSCOCTRL S3C_CAMIFREG(0xFC) /* MSDMA for CODEC control register */
17430 +#define S3C_MSPRY0SA S3C_CAMIFREG(0x100) /* MSDMA for PREVIEW Y0 start address register */
17431 +#define S3C_MSPRCB0SA S3C_CAMIFREG(0x104) /* MSDMA for PREVIEW CB0 start address register */
17432 +#define S3C_MSPRCR0SA S3C_CAMIFREG(0x108) /* MSDMA for PREVIEW CR0 start address register */
17433 +#define S3C_MSPRY0END S3C_CAMIFREG(0x10C) /* MSDMA for PREVIEW Y0 end address register */
17434 +#define S3C_MSPRCB0END S3C_CAMIFREG(0x110) /* MSDMA for PREVIEW CB0 end address register */
17435 +#define S3C_MSPRCR0END S3C_CAMIFREG(0x114) /* MSDMA for PREVIEW CR0 end address register */
17436 +#define S3C_MSPRYOFF S3C_CAMIFREG(0x118) /* MSDMA for PREVIEW Y offset register */
17437 +#define S3C_MSPRCBOFF S3C_CAMIFREG(0x11C) /* MSDMA for PREVIEW CB offset register */
17438 +#define S3C_MSPRCROFF S3C_CAMIFREG(0x120) /* MSDMA for PREVIEW CR offset register */
17439 +#define S3C_MSPRWIDTH S3C_CAMIFREG(0x124) /* MSDMA for PREVIEW source image width register */
17440 +#define S3C_CIMSCTRL S3C_CAMIFREG(0x128) /* MSDMA for PREVIEW control register */
17441 +#define S3C_CICOSCOSY S3C_CAMIFREG(0x12C) /* CODEC scan line Y offset register */
17442 +#define S3C_CICOSCOSCB S3C_CAMIFREG(0x130) /* CODEC scan line CB offset register */
17443 +#define S3C_CICOSCOSCR S3C_CAMIFREG(0x134) /* CODEC scan line CR offset register */
17444 +#define S3C_CIPRSCOSY S3C_CAMIFREG(0x138) /* PREVIEW scan line Y offset register */
17445 +#define S3C_CIPRSCOSCB S3C_CAMIFREG(0x13C) /* PREVIEW scan line CB offset register */
17446 +#define S3C_CIPRSCOSCR S3C_CAMIFREG(0x140) /* PREVIEW scan line CR offset register */
17447 +#endif
17448 +
17449 +#endif /* ___ASM_ARCH_REGS_CAMIF_H */
17450 +
17451 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-clock.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-clock.h
17452 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-clock.h 2009-05-10 22:05:04.000000000 +0200
17453 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-clock.h 2009-05-10 22:27:59.000000000 +0200
17454 @@ -32,6 +32,7 @@
17455 #define S3C_HCLK_GATE S3C_CLKREG(0x30)
17456 #define S3C_PCLK_GATE S3C_CLKREG(0x34)
17457 #define S3C_SCLK_GATE S3C_CLKREG(0x38)
17458 +#define S3C_MEM0_GATE S3C_CLKREG(0x3C)
17459
17460 /* CLKDIV0 */
17461 #define S3C6400_CLKDIV0_MFC_MASK (0xf << 28)
17462 @@ -88,10 +89,10 @@
17463
17464 /* HCLK GATE Registers */
17465 #define S3C_CLKCON_HCLK_BUS (1<<30)
17466 -#define S3C_CLKCON_HCLK_SECUR (1<<29)
17467 -#define S3C_CLKCON_HCLK_SDMA1 (1<<28)
17468 -#define S3C_CLKCON_HCLK_SDMA2 (1<<27)
17469 -#define S3C_CLKCON_HCLK_UHOST (1<<26)
17470 +#define S3C_CLKCON_HCLK_UHOST (1<<29)
17471 +#define S3C_CLKCON_HCLK_SECUR (1<<28)
17472 +#define S3C_CLKCON_HCLK_SDMA1 (1<<27)
17473 +#define S3C_CLKCON_HCLK_SDMA0 (1<<26)
17474 #define S3C_CLKCON_HCLK_IROM (1<<25)
17475 #define S3C_CLKCON_HCLK_DDR1 (1<<24)
17476 #define S3C_CLKCON_HCLK_DDR0 (1<<23)
17477 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h
17478 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h 2009-05-10 22:05:04.000000000 +0200
17479 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-gpio.h 2009-05-10 22:27:59.000000000 +0200
17480 @@ -13,23 +13,175 @@
17481
17482 /* Base addresses for each of the banks */
17483
17484 -#define S3C64XX_GPA_BASE (S3C64XX_VA_GPIO + 0x0000)
17485 -#define S3C64XX_GPB_BASE (S3C64XX_VA_GPIO + 0x0020)
17486 -#define S3C64XX_GPC_BASE (S3C64XX_VA_GPIO + 0x0040)
17487 -#define S3C64XX_GPD_BASE (S3C64XX_VA_GPIO + 0x0060)
17488 -#define S3C64XX_GPE_BASE (S3C64XX_VA_GPIO + 0x0080)
17489 -#define S3C64XX_GPF_BASE (S3C64XX_VA_GPIO + 0x00A0)
17490 -#define S3C64XX_GPG_BASE (S3C64XX_VA_GPIO + 0x00C0)
17491 -#define S3C64XX_GPH_BASE (S3C64XX_VA_GPIO + 0x00E0)
17492 -#define S3C64XX_GPI_BASE (S3C64XX_VA_GPIO + 0x0100)
17493 -#define S3C64XX_GPJ_BASE (S3C64XX_VA_GPIO + 0x0120)
17494 -#define S3C64XX_GPK_BASE (S3C64XX_VA_GPIO + 0x0800)
17495 -#define S3C64XX_GPL_BASE (S3C64XX_VA_GPIO + 0x0810)
17496 -#define S3C64XX_GPM_BASE (S3C64XX_VA_GPIO + 0x0820)
17497 -#define S3C64XX_GPN_BASE (S3C64XX_VA_GPIO + 0x0830)
17498 -#define S3C64XX_GPO_BASE (S3C64XX_VA_GPIO + 0x0140)
17499 -#define S3C64XX_GPP_BASE (S3C64XX_VA_GPIO + 0x0160)
17500 -#define S3C64XX_GPQ_BASE (S3C64XX_VA_GPIO + 0x0180)
17501 +#define S3C64XX_GPIOREG(reg) (S3C64XX_VA_GPIO + (reg))
17502 +
17503 +#define S3C64XX_GPA_BASE S3C64XX_GPIOREG(0x0000)
17504 +#define S3C64XX_GPB_BASE S3C64XX_GPIOREG(0x0020)
17505 +#define S3C64XX_GPC_BASE S3C64XX_GPIOREG(0x0040)
17506 +#define S3C64XX_GPD_BASE S3C64XX_GPIOREG(0x0060)
17507 +#define S3C64XX_GPE_BASE S3C64XX_GPIOREG(0x0080)
17508 +#define S3C64XX_GPF_BASE S3C64XX_GPIOREG(0x00A0)
17509 +#define S3C64XX_GPG_BASE S3C64XX_GPIOREG(0x00C0)
17510 +#define S3C64XX_GPH_BASE S3C64XX_GPIOREG(0x00E0)
17511 +#define S3C64XX_GPI_BASE S3C64XX_GPIOREG(0x0100)
17512 +#define S3C64XX_GPJ_BASE S3C64XX_GPIOREG(0x0120)
17513 +#define S3C64XX_GPK_BASE S3C64XX_GPIOREG(0x0800)
17514 +#define S3C64XX_GPL_BASE S3C64XX_GPIOREG(0x0810)
17515 +#define S3C64XX_GPM_BASE S3C64XX_GPIOREG(0x0820)
17516 +#define S3C64XX_GPN_BASE S3C64XX_GPIOREG(0x0830)
17517 +#define S3C64XX_GPO_BASE S3C64XX_GPIOREG(0x0140)
17518 +#define S3C64XX_GPP_BASE S3C64XX_GPIOREG(0x0160)
17519 +#define S3C64XX_GPQ_BASE S3C64XX_GPIOREG(0x0180)
17520 +
17521 +/* SPCON */
17522 +
17523 +#define S3C64XX_SPCON S3C64XX_GPIOREG(0x1A0)
17524 +
17525 +#define S3C64XX_SPCON_DRVCON_CAM_MASK (0x3 << 30)
17526 +#define S3C64XX_SPCON_DRVCON_CAM_SHIFT (30)
17527 +#define S3C64XX_SPCON_DRVCON_CAM_2mA (0x0 << 30)
17528 +#define S3C64XX_SPCON_DRVCON_CAM_4mA (0x1 << 30)
17529 +#define S3C64XX_SPCON_DRVCON_CAM_7mA (0x2 << 30)
17530 +#define S3C64XX_SPCON_DRVCON_CAM_9mA (0x3 << 30)
17531 +
17532 +#define S3C64XX_SPCON_DRVCON_HSSPI_MASK (0x3 << 28)
17533 +#define S3C64XX_SPCON_DRVCON_HSSPI_SHIFT (28)
17534 +#define S3C64XX_SPCON_DRVCON_HSSPI_2mA (0x0 << 28)
17535 +#define S3C64XX_SPCON_DRVCON_HSSPI_4mA (0x1 << 28)
17536 +#define S3C64XX_SPCON_DRVCON_HSSPI_7mA (0x2 << 28)
17537 +#define S3C64XX_SPCON_DRVCON_HSSPI_9mA (0x3 << 28)
17538 +
17539 +#define S3C64XX_SPCON_DRVCON_HSMMC_MASK (0x3 << 26)
17540 +#define S3C64XX_SPCON_DRVCON_HSMMC_SHIFT (26)
17541 +#define S3C64XX_SPCON_DRVCON_HSMMC_2mA (0x0 << 26)
17542 +#define S3C64XX_SPCON_DRVCON_HSMMC_4mA (0x1 << 26)
17543 +#define S3C64XX_SPCON_DRVCON_HSMMC_7mA (0x2 << 26)
17544 +#define S3C64XX_SPCON_DRVCON_HSMMC_9mA (0x3 << 26)
17545 +
17546 +#define S3C64XX_SPCON_DRVCON_LCD_MASK (0x3 << 24)
17547 +#define S3C64XX_SPCON_DRVCON_LCD_SHIFT (24)
17548 +#define S3C64XX_SPCON_DRVCON_LCD_2mA (0x0 << 24)
17549 +#define S3C64XX_SPCON_DRVCON_LCD_4mA (0x1 << 24)
17550 +#define S3C64XX_SPCON_DRVCON_LCD_7mA (0x2 << 24)
17551 +#define S3C64XX_SPCON_DRVCON_LCD_9mA (0x3 << 24)
17552 +
17553 +#define S3C64XX_SPCON_DRVCON_MODEM_MASK (0x3 << 22)
17554 +#define S3C64XX_SPCON_DRVCON_MODEM_SHIFT (22)
17555 +#define S3C64XX_SPCON_DRVCON_MODEM_2mA (0x0 << 22)
17556 +#define S3C64XX_SPCON_DRVCON_MODEM_4mA (0x1 << 22)
17557 +#define S3C64XX_SPCON_DRVCON_MODEM_7mA (0x2 << 22)
17558 +#define S3C64XX_SPCON_DRVCON_MODEM_9mA (0x3 << 22)
17559 +
17560 +#define S3C64XX_SPCON_nRSTOUT_OEN (1 << 21)
17561 +
17562 +#define S3C64XX_SPCON_DRVCON_SPICLK1_MASK (0x3 << 18)
17563 +#define S3C64XX_SPCON_DRVCON_SPICLK1_SHIFT (18)
17564 +#define S3C64XX_SPCON_DRVCON_SPICLK1_2mA (0x0 << 18)
17565 +#define S3C64XX_SPCON_DRVCON_SPICLK1_4mA (0x1 << 18)
17566 +#define S3C64XX_SPCON_DRVCON_SPICLK1_7mA (0x2 << 18)
17567 +#define S3C64XX_SPCON_DRVCON_SPICLK1_9mA (0x3 << 18)
17568 +
17569 +#define S3C64XX_SPCON_MEM1_DQS_PUD_MASK (0x3 << 16)
17570 +#define S3C64XX_SPCON_MEM1_DQS_PUD_SHIFT (16)
17571 +#define S3C64XX_SPCON_MEM1_DQS_PUD_DISABLED (0x0 << 16)
17572 +#define S3C64XX_SPCON_MEM1_DQS_PUD_DOWN (0x1 << 16)
17573 +#define S3C64XX_SPCON_MEM1_DQS_PUD_UP (0x2 << 16)
17574 +
17575 +#define S3C64XX_SPCON_MEM1_D_PUD1_MASK (0x3 << 14)
17576 +#define S3C64XX_SPCON_MEM1_D_PUD1_SHIFT (14)
17577 +#define S3C64XX_SPCON_MEM1_D_PUD1_DISABLED (0x0 << 14)
17578 +#define S3C64XX_SPCON_MEM1_D_PUD1_DOWN (0x1 << 14)
17579 +#define S3C64XX_SPCON_MEM1_D_PUD1_UP (0x2 << 14)
17580 +
17581 +#define S3C64XX_SPCON_MEM1_D_PUD0_MASK (0x3 << 12)
17582 +#define S3C64XX_SPCON_MEM1_D_PUD0_SHIFT (12)
17583 +#define S3C64XX_SPCON_MEM1_D_PUD0_DISABLED (0x0 << 12)
17584 +#define S3C64XX_SPCON_MEM1_D_PUD0_DOWN (0x1 << 12)
17585 +#define S3C64XX_SPCON_MEM1_D_PUD0_UP (0x2 << 12)
17586 +
17587 +#define S3C64XX_SPCON_MEM0_D_PUD_MASK (0x3 << 8)
17588 +#define S3C64XX_SPCON_MEM0_D_PUD_SHIFT (8)
17589 +#define S3C64XX_SPCON_MEM0_D_PUD_DISABLED (0x0 << 8)
17590 +#define S3C64XX_SPCON_MEM0_D_PUD_DOWN (0x1 << 8)
17591 +#define S3C64XX_SPCON_MEM0_D_PUD_UP (0x2 << 8)
17592 +
17593 +#define S3C64XX_SPCON_USBH_DMPD (1 << 7)
17594 +#define S3C64XX_SPCON_USBH_DPPD (1 << 6)
17595 +#define S3C64XX_SPCON_USBH_PUSW2 (1 << 5)
17596 +#define S3C64XX_SPCON_USBH_PUSW1 (1 << 4)
17597 +#define S3C64XX_SPCON_USBH_SUSPND (1 << 3)
17598 +
17599 +#define S3C64XX_SPCON_LCD_SEL_MASK (0x3 << 0)
17600 +#define S3C64XX_SPCON_LCD_SEL_SHIFT (0)
17601 +#define S3C64XX_SPCON_LCD_SEL_HOST (0x0 << 0)
17602 +#define S3C64XX_SPCON_LCD_SEL_RGB (0x1 << 0)
17603 +#define S3C64XX_SPCON_LCD_SEL_606_656 (0x2 << 0)
17604 +
17605 +
17606 +/* External interrupt registers */
17607 +
17608 +#define S3C64XX_EINT12CON S3C64XX_GPIOREG(0x200)
17609 +#define S3C64XX_EINT34CON S3C64XX_GPIOREG(0x204)
17610 +#define S3C64XX_EINT56CON S3C64XX_GPIOREG(0x208)
17611 +#define S3C64XX_EINT78CON S3C64XX_GPIOREG(0x20C)
17612 +#define S3C64XX_EINT9CON S3C64XX_GPIOREG(0x210)
17613 +
17614 +#define S3C64XX_EINT12FLTCON S3C64XX_GPIOREG(0x220)
17615 +#define S3C64XX_EINT34FLTCON S3C64XX_GPIOREG(0x224)
17616 +#define S3C64XX_EINT56FLTCON S3C64XX_GPIOREG(0x228)
17617 +#define S3C64XX_EINT78FLTCON S3C64XX_GPIOREG(0x22C)
17618 +#define S3C64XX_EINT9FLTCON S3C64XX_GPIOREG(0x230)
17619 +
17620 +#define S3C64XX_EINT12MASK S3C64XX_GPIOREG(0x240)
17621 +#define S3C64XX_EINT34MASK S3C64XX_GPIOREG(0x244)
17622 +#define S3C64XX_EINT56MASK S3C64XX_GPIOREG(0x248)
17623 +#define S3C64XX_EINT78MASK S3C64XX_GPIOREG(0x24C)
17624 +#define S3C64XX_EINT9MASK S3C64XX_GPIOREG(0x250)
17625 +
17626 +#define S3C64XX_EINT12PEND S3C64XX_GPIOREG(0x260)
17627 +#define S3C64XX_EINT34PEND S3C64XX_GPIOREG(0x264)
17628 +#define S3C64XX_EINT56PEND S3C64XX_GPIOREG(0x268)
17629 +#define S3C64XX_EINT78PEND S3C64XX_GPIOREG(0x26C)
17630 +#define S3C64XX_EINT9PEND S3C64XX_GPIOREG(0x270)
17631 +
17632 +#define S3C64XX_PRIORITY S3C64XX_GPIOREG(0x280)
17633 +#define S3C64XX_PRIORITY_ARB(x) (1 << (x))
17634 +
17635 +#define S3C64XX_SERVICE S3C64XX_GPIOREG(0x284)
17636 +#define S3C64XX_SERVICEPEND S3C64XX_GPIOREG(0x288)
17637 +
17638 +#define S3C64XX_EINT0CON0 S3C64XX_GPIOREG(0x900)
17639 +#define S3C64XX_EINT0CON1 S3C64XX_GPIOREG(0x904)
17640 +#define S3C64XX_EINT0FLTCON0 S3C64XX_GPIOREG(0x910)
17641 +#define S3C64XX_EINT0FLTCON1 S3C64XX_GPIOREG(0x914)
17642 +#define S3C64XX_EINT0FLTCON2 S3C64XX_GPIOREG(0x918)
17643 +#define S3C64XX_EINT0FLTCON3 S3C64XX_GPIOREG(0x91C)
17644 +
17645 +#define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920)
17646 +#define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924)
17647 +
17648 +/* GPIO sleep configuration */
17649 +
17650 +#define S3C64XX_SPCONSLP S3C64XX_GPIOREG(0x880)
17651 +
17652 +#define S3C64XX_SPCONSLP_TDO_PULLDOWN (1 << 14)
17653 +#define S3C64XX_SPCONSLP_CKE1INIT (1 << 5)
17654 +
17655 +#define S3C64XX_SPCONSLP_RSTOUT_MASK (0x3 << 12)
17656 +#define S3C64XX_SPCONSLP_RSTOUT_OUT0 (0x0 << 12)
17657 +#define S3C64XX_SPCONSLP_RSTOUT_OUT1 (0x1 << 12)
17658 +#define S3C64XX_SPCONSLP_RSTOUT_HIZ (0x2 << 12)
17659 +
17660 +#define S3C64XX_SPCONSLP_KPCOL_MASK (0x3 << 0)
17661 +#define S3C64XX_SPCONSLP_KPCOL_OUT0 (0x0 << 0)
17662 +#define S3C64XX_SPCONSLP_KPCOL_OUT1 (0x1 << 0)
17663 +#define S3C64XX_SPCONSLP_KPCOL_INP (0x2 << 0)
17664 +
17665 +
17666 +#define S3C64XX_SLPEN S3C64XX_GPIOREG(0x930)
17667 +
17668 +#define S3C64XX_SLPEN_USE_xSLP (1 << 0)
17669 +#define S3C64XX_SLPEN_CFG_BYSLPEN (1 << 1)
17670
17671 #endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_H */
17672
17673 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h
17674 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h 1970-01-01 01:00:00.000000000 +0100
17675 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-gpio-memport.h 2009-05-10 22:27:59.000000000 +0200
17676 @@ -0,0 +1,25 @@
17677 +/* linux/arch/arm/plat-s3c64xx/include/mach/regs-gpio-memport.h
17678 + *
17679 + * Copyright 2008 Openmoko, Inc.
17680 + * Copyright 2008 Simtec Electronics
17681 + * Ben Dooks <ben@simtec.co.uk>
17682 + * http://armlinux.simtec.co.uk/
17683 + *
17684 + * S3C64XX - GPIO memory port register definitions
17685 + */
17686 +
17687 +#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H
17688 +#define __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H __FILE__
17689 +
17690 +#define S3C64XX_MEM0CONSTOP S3C64XX_GPIOREG(0x1B0)
17691 +#define S3C64XX_MEM1CONSTOP S3C64XX_GPIOREG(0x1B4)
17692 +
17693 +#define S3C64XX_MEM0CONSLP0 S3C64XX_GPIOREG(0x1C0)
17694 +#define S3C64XX_MEM0CONSLP1 S3C64XX_GPIOREG(0x1C4)
17695 +#define S3C64XX_MEM1CONSLP S3C64XX_GPIOREG(0x1C8)
17696 +
17697 +#define S3C64XX_MEM0DRVCON S3C64XX_GPIOREG(0x1D0)
17698 +#define S3C64XX_MEM1DRVCON S3C64XX_GPIOREG(0x1D4)
17699 +
17700 +#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H */
17701 +
17702 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-modem.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-modem.h
17703 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-modem.h 1970-01-01 01:00:00.000000000 +0100
17704 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-modem.h 2009-05-10 22:27:59.000000000 +0200
17705 @@ -0,0 +1,31 @@
17706 +/* arch/arm/plat-s3c64xx/include/plat/regs-modem.h
17707 + *
17708 + * Copyright 2008 Openmoko, Inc.
17709 + * Copyright 2008 Simtec Electronics
17710 + * http://armlinux.simtec.co.uk/
17711 + * Ben Dooks <ben@simtec.co.uk>
17712 + *
17713 + * S3C64XX - modem block registers
17714 + *
17715 + * This program is free software; you can redistribute it and/or modify
17716 + * it under the terms of the GNU General Public License version 2 as
17717 + * published by the Free Software Foundation.
17718 +*/
17719 +
17720 +#ifndef __PLAT_S3C64XX_REGS_MODEM_H
17721 +#define __PLAT_S3C64XX_REGS_MODEM_H __FILE__
17722 +
17723 +#define S3C64XX_MODEMREG(x) (S3C64XX_VA_MODEM + (x))
17724 +
17725 +#define S3C64XX_MODEM_INT2AP S3C64XX_MODEMREG(0x0)
17726 +#define S3C64XX_MODEM_INT2MODEM S3C64XX_MODEMREG(0x4)
17727 +#define S3C64XX_MODEM_MIFCON S3C64XX_MODEMREG(0x8)
17728 +#define S3C64XX_MODEM_MIFPCON S3C64XX_MODEMREG(0xC)
17729 +#define S3C64XX_MODEM_INTCLR S3C64XX_MODEMREG(0x10)
17730 +#define S3C64XX_MODEM_DMA_TXADDR S3C64XX_MODEMREG(0x14)
17731 +#define S3C64XX_MODEM_DMA_RXADDR S3C64XX_MODEMREG(0x18)
17732 +
17733 +#define MIFPCON_INT2M_LEVEL (1 << 4)
17734 +#define MIFPCON_LCD_BYPASS (1 << 3)
17735 +
17736 +#endif /* __PLAT_S3C64XX_REGS_MODEM_H */
17737 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
17738 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h 1970-01-01 01:00:00.000000000 +0100
17739 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h 2009-05-10 22:27:59.000000000 +0200
17740 @@ -0,0 +1,116 @@
17741 +/* arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
17742 + *
17743 + * Copyright 2008 Openmoko, Inc.
17744 + * Copyright 2008 Simtec Electronics
17745 + * http://armlinux.simtec.co.uk/
17746 + * Ben Dooks <ben@simtec.co.uk>
17747 + *
17748 + * S3C64XX - syscon power and sleep control registers
17749 + *
17750 + * This program is free software; you can redistribute it and/or modify
17751 + * it under the terms of the GNU General Public License version 2 as
17752 + * published by the Free Software Foundation.
17753 +*/
17754 +
17755 +#ifndef __PLAT_S3C64XX_REGS_SYSCON_POWER_H
17756 +#define __PLAT_S3C64XX_REGS_SYSCON_POWER_H __FILE__
17757 +
17758 +#define S3C64XX_PWR_CFG S3C_SYSREG(0x804)
17759 +
17760 +#define S3C64XX_PWRCFG_OSC_OTG_DISABLE (1 << 17)
17761 +#define S3C64XX_PWRCFG_MMC2_DISABLE (1 << 16)
17762 +#define S3C64XX_PWRCFG_MMC1_DISABLE (1 << 15)
17763 +#define S3C64XX_PWRCFG_MMC0_DISABLE (1 << 14)
17764 +#define S3C64XX_PWRCFG_HSI_DISABLE (1 << 13)
17765 +#define S3C64XX_PWRCFG_TS_DISABLE (1 << 12)
17766 +#define S3C64XX_PWRCFG_RTC_TICK_DISABLE (1 << 11)
17767 +#define S3C64XX_PWRCFG_RTC_ALARM_DISABLE (1 << 10)
17768 +#define S3C64XX_PWRCFG_MSM_DISABLE (1 << 9)
17769 +#define S3C64XX_PWRCFG_KEY_DISABLE (1 << 8)
17770 +#define S3C64XX_PWRCFG_BATF_DISABLE (1 << 7)
17771 +
17772 +#define S3C64XX_PWRCFG_CFG_WFI_MASK (0x3 << 5)
17773 +#define S3C64XX_PWRCFG_CFG_WFI_SHIFT (5)
17774 +#define S3C64XX_PWRCFG_CFG_WFI_IGNORE (0x0 << 5)
17775 +#define S3C64XX_PWRCFG_CFG_WFI_IDLE (0x1 << 5)
17776 +#define S3C64XX_PWRCFG_CFG_WFI_STOP (0x2 << 5)
17777 +#define S3C64XX_PWRCFG_CFG_WFI_SLEEP (0x3 << 5)
17778 +
17779 +#define S3C64XX_PWRCFG_CFG_BATFLT_MASK (0x3 << 3)
17780 +#define S3C64XX_PWRCFG_CFG_BATFLT_SHIFT (3)
17781 +#define S3C64XX_PWRCFG_CFG_BATFLT_IGNORE (0x0 << 3)
17782 +#define S3C64XX_PWRCFG_CFG_BATFLT_IRQ (0x1 << 3)
17783 +#define S3C64XX_PWRCFG_CFG_BATFLT_SLEEP (0x3 << 3)
17784 +
17785 +#define S3C64XX_PWRCFG_CFG_BAT_WAKE (1 << 2)
17786 +#define S3C64XX_PWRCFG_OSC27_EN (1 << 0)
17787 +
17788 +#define S3C64XX_EINT_MASK S3C_SYSREG(0x808)
17789 +
17790 +#define S3C64XX_NORMAL_CFG S3C_SYSREG(0x810)
17791 +
17792 +#define S3C64XX_NORMALCFG_IROM_ON (1 << 30)
17793 +#define S3C64XX_NORMALCFG_DOMAIN_ETM_ON (1 << 16)
17794 +#define S3C64XX_NORMALCFG_DOMAIN_S_ON (1 << 15)
17795 +#define S3C64XX_NORMALCFG_DOMAIN_F_ON (1 << 14)
17796 +#define S3C64XX_NORMALCFG_DOMAIN_P_ON (1 << 13)
17797 +#define S3C64XX_NORMALCFG_DOMAIN_I_ON (1 << 12)
17798 +#define S3C64XX_NORMALCFG_DOMAIN_G_ON (1 << 10)
17799 +#define S3C64XX_NORMALCFG_DOMAIN_V_ON (1 << 9)
17800 +
17801 +#define S3C64XX_STOP_CFG S3C_SYSREG(0x814)
17802 +
17803 +#define S3C64XX_STOPCFG_MEMORY_ARM_ON (1 << 29)
17804 +#define S3C64XX_STOPCFG_TOP_MEMORY_ON (1 << 20)
17805 +#define S3C64XX_STOPCFG_ARM_LOGIC_ON (1 << 17)
17806 +#define S3C64XX_STOPCFG_TOP_LOGIC_ON (1 << 8)
17807 +#define S3C64XX_STOPCFG_OSC_EN (1 << 0)
17808 +
17809 +#define S3C64XX_SLEEP_CFG S3C_SYSREG(0x818)
17810 +
17811 +#define S3C64XX_SLEEPCFG_OSC_EN (1 << 0)
17812 +
17813 +#define S3C64XX_STOP_MEM_CFG S3C_SYSREG(0x81c)
17814 +
17815 +#define S3C64XX_STOPMEMCFG_MODEMIF_RETAIN (1 << 6)
17816 +#define S3C64XX_STOPMEMCFG_HOSTIF_RETAIN (1 << 5)
17817 +#define S3C64XX_STOPMEMCFG_OTG_RETAIN (1 << 4)
17818 +#define S3C64XX_STOPMEMCFG_HSMCC_RETAIN (1 << 3)
17819 +#define S3C64XX_STOPMEMCFG_IROM_RETAIN (1 << 2)
17820 +#define S3C64XX_STOPMEMCFG_IRDA_RETAIN (1 << 1)
17821 +#define S3C64XX_STOPMEMCFG_NFCON_RETAIN (1 << 0)
17822 +
17823 +#define S3C64XX_OSC_STABLE S3C_SYSREG(0x824)
17824 +#define S3C64XX_PWR_STABLE S3C_SYSREG(0x828)
17825 +
17826 +#define S3C64XX_WAKEUP_STAT S3C_SYSREG(0x908)
17827 +
17828 +#define S3C64XX_WAKEUPSTAT_MMC2 (1 << 11)
17829 +#define S3C64XX_WAKEUPSTAT_MMC1 (1 << 10)
17830 +#define S3C64XX_WAKEUPSTAT_MMC0 (1 << 9)
17831 +#define S3C64XX_WAKEUPSTAT_HSI (1 << 8)
17832 +#define S3C64XX_WAKEUPSTAT_BATFLT (1 << 6)
17833 +#define S3C64XX_WAKEUPSTAT_MSM (1 << 5)
17834 +#define S3C64XX_WAKEUPSTAT_KEY (1 << 4)
17835 +#define S3C64XX_WAKEUPSTAT_TS (1 << 3)
17836 +#define S3C64XX_WAKEUPSTAT_RTC_TICK (1 << 2)
17837 +#define S3C64XX_WAKEUPSTAT_RTC_ALARM (1 << 1)
17838 +#define S3C64XX_WAKEUPSTAT_EINT (1 << 0)
17839 +
17840 +#define S3C64XX_BLK_PWR_STAT S3C_SYSREG(0x90c)
17841 +
17842 +#define S3C64XX_BLKPWRSTAT_G (1 << 7)
17843 +#define S3C64XX_BLKPWRSTAT_ETM (1 << 6)
17844 +#define S3C64XX_BLKPWRSTAT_S (1 << 5)
17845 +#define S3C64XX_BLKPWRSTAT_F (1 << 4)
17846 +#define S3C64XX_BLKPWRSTAT_P (1 << 3)
17847 +#define S3C64XX_BLKPWRSTAT_I (1 << 2)
17848 +#define S3C64XX_BLKPWRSTAT_V (1 << 1)
17849 +#define S3C64XX_BLKPWRSTAT_TOP (1 << 0)
17850 +
17851 +#define S3C64XX_INFORM0 S3C_SYSREG(0xA00)
17852 +#define S3C64XX_INFORM1 S3C_SYSREG(0xA04)
17853 +#define S3C64XX_INFORM2 S3C_SYSREG(0xA08)
17854 +#define S3C64XX_INFORM3 S3C_SYSREG(0xA0C)
17855 +
17856 +#endif /* __PLAT_S3C64XX_REGS_SYSCON_POWER_H */
17857 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-sys.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-sys.h
17858 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/regs-sys.h 2009-05-10 22:05:04.000000000 +0200
17859 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/regs-sys.h 2009-05-10 22:27:59.000000000 +0200
17860 @@ -17,6 +17,10 @@
17861
17862 #define S3C_SYSREG(x) (S3C_VA_SYS + (x))
17863
17864 +#define S3C64XX_AHB_CON0 S3C_SYSREG(0x100)
17865 +#define S3C64XX_AHB_CON1 S3C_SYSREG(0x104)
17866 +#define S3C64XX_AHB_CON2 S3C_SYSREG(0x108)
17867 +
17868 #define S3C64XX_OTHERS S3C_SYSREG(0x900)
17869
17870 #define S3C64XX_OTHERS_USBMASK (1 << 16)
17871 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/tzic-sp890.h linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/tzic-sp890.h
17872 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/include/plat/tzic-sp890.h 1970-01-01 01:00:00.000000000 +0100
17873 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/include/plat/tzic-sp890.h 2009-05-10 22:27:59.000000000 +0200
17874 @@ -0,0 +1,21 @@
17875 +#ifndef __S3C64XX_TZIC_SP890_H__
17876 +#define __S3C64XX_TZIC_SP890_H__
17877 +
17878 +
17879 +#define S3C64XX_VA_TZIC0_FIQ_STATUS (S3C_VA_TZIC0 + SP890_TZIC_FIQSTATUS)
17880 +#define S3C64XX_VA_TZIC0_RAWINTR (S3C_VA_TZIC0 + SP890_TZIC_RAWINTR)
17881 +#define S3C64XX_VA_TZIC0_INTSELECT (S3C_VA_TZIC0 + SP890_TZIC_INTSELECT)
17882 +#define S3C64XX_VA_TZIC0_FIQENABLE (S3C_VA_TZIC0 + SP890_TZIC_FIQENABLE)
17883 +#define S3C64XX_VA_TZIC0_FIQENCLEAR (S3C_VA_TZIC0 + SP890_TZIC_FIQENCLEAR)
17884 +#define S3C64XX_VA_TZIC0_FIQBYPASS (S3C_VA_TZIC0 + SP890_TZIC_FIQBYPASS)
17885 +#define S3C64XX_VA_TZIC0_FPROTECTION (S3C_VA_TZIC0 + SP890_TZIC_PROTECTION)
17886 +#define S3C64XX_VA_TZIC0_LOCK (S3C_VA_TZIC0 + SP890_TZIC_LOCK)
17887 +#define S3C64XX_VA_TZIC0_LOCKSTATUS (S3C_VA_TZIC0 + SP890_TZIC_LOCKSTATUS)
17888 +#define S3C64XX_VA_TZIC0_ITCR (S3C_VA_TZIC0 + SP890_TZIC_ITCR)
17889 +#define S3C64XX_VA_TZIC0_ITIP1 (S3C_VA_TZIC0 + SP890_TZIC_ITIP1)
17890 +#define S3C64XX_VA_TZIC0_ITIP2 (S3C_VA_TZIC0 + SP890_TZIC_ITIP2)
17891 +#define S3C64XX_VA_TZIC0_ITOP1 (S3C_VA_TZIC0 + SP890_TZIC_ITOP1)
17892 +#define S3C64XX_VA_TZIC0_ITOP2 (S3C_VA_TZIC0 + SP890_TZIC_ITOP2)
17893 +#define S3C64XX_VA_TZIC0_PERIPHIDO (S3C_VA_TZIC0 + SP890_TZIC_PERIPHIDO)
17894 +
17895 +#endif
17896 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/irq.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/irq.c
17897 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/irq.c 2009-05-10 22:08:41.000000000 +0200
17898 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/irq.c 2009-05-10 22:27:59.000000000 +0200
17899 @@ -14,12 +14,14 @@
17900
17901 #include <linux/kernel.h>
17902 #include <linux/interrupt.h>
17903 +#include <linux/serial_core.h>
17904 #include <linux/irq.h>
17905 #include <linux/io.h>
17906
17907 #include <asm/hardware/vic.h>
17908
17909 #include <mach/map.h>
17910 +#include <plat/regs-serial.h>
17911 #include <plat/regs-timer.h>
17912 #include <plat/cpu.h>
17913
17914 @@ -135,9 +137,6 @@
17915 }
17916
17917 /* UART interrupt registers, not worth adding to seperate include header */
17918 -#define S3C64XX_UINTP 0x30
17919 -#define S3C64XX_UINTSP 0x34
17920 -#define S3C64XX_UINTM 0x38
17921
17922 static void s3c_irq_uart_mask(unsigned int irq)
17923 {
17924 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/irq-eint.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/irq-eint.c
17925 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/irq-eint.c 2009-05-10 22:08:41.000000000 +0200
17926 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/irq-eint.c 2009-05-10 22:27:59.000000000 +0200
17927 @@ -14,29 +14,20 @@
17928
17929 #include <linux/kernel.h>
17930 #include <linux/interrupt.h>
17931 +#include <linux/gpio.h>
17932 #include <linux/irq.h>
17933 #include <linux/io.h>
17934 +#include <linux/gpio.h>
17935
17936 #include <asm/hardware/vic.h>
17937
17938 #include <plat/regs-irqtype.h>
17939 +#include <plat/regs-gpio.h>
17940 +#include <plat/gpio-cfg.h>
17941
17942 #include <mach/map.h>
17943 #include <plat/cpu.h>
17944 -
17945 -/* GPIO is 0x7F008xxx, */
17946 -#define S3C64XX_GPIOREG(x) (S3C64XX_VA_GPIO + (x))
17947 -
17948 -#define S3C64XX_EINT0CON0 S3C64XX_GPIOREG(0x900)
17949 -#define S3C64XX_EINT0CON1 S3C64XX_GPIOREG(0x904)
17950 -#define S3C64XX_EINT0FLTCON0 S3C64XX_GPIOREG(0x910)
17951 -#define S3C64XX_EINT0FLTCON1 S3C64XX_GPIOREG(0x914)
17952 -#define S3C64XX_EINT0FLTCON2 S3C64XX_GPIOREG(0x918)
17953 -#define S3C64XX_EINT0FLTCON3 S3C64XX_GPIOREG(0x91C)
17954 -
17955 -#define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920)
17956 -#define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924)
17957 -
17958 +#include <plat/pm.h>
17959
17960 #define eint_offset(irq) ((irq) - IRQ_EINT(0))
17961 #define eint_irq_to_bit(irq) (1 << eint_offset(irq))
17962 @@ -55,7 +46,7 @@
17963 u32 mask;
17964
17965 mask = __raw_readl(S3C64XX_EINT0MASK);
17966 - mask |= eint_irq_to_bit(irq);
17967 + mask &= ~eint_irq_to_bit(irq);
17968 __raw_writel(mask, S3C64XX_EINT0MASK);
17969 }
17970
17971 @@ -74,6 +65,7 @@
17972 static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
17973 {
17974 int offs = eint_offset(irq);
17975 + int pin;
17976 int shift;
17977 u32 ctrl, mask;
17978 u32 newvalue = 0;
17979 @@ -125,6 +117,14 @@
17980 ctrl |= newvalue << shift;
17981 __raw_writel(ctrl, reg);
17982
17983 + /* set the GPIO pin appropriately */
17984 +
17985 + if (offs < 23)
17986 + pin = S3C64XX_GPN(offs);
17987 + else
17988 + pin = S3C64XX_GPM(offs - 23);
17989 +
17990 + s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(2));
17991 return 0;
17992 }
17993
17994 @@ -135,6 +135,7 @@
17995 .mask_ack = s3c_irq_eint_maskack,
17996 .ack = s3c_irq_eint_ack,
17997 .set_type = s3c_irq_eint_set_type,
17998 + .set_wake = s3c_irqext_wake,
17999 };
18000
18001 /* s3c_irq_demux_eint
18002 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/irq-pm.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/irq-pm.c
18003 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/irq-pm.c 1970-01-01 01:00:00.000000000 +0100
18004 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/irq-pm.c 2009-05-10 22:27:59.000000000 +0200
18005 @@ -0,0 +1,173 @@
18006 +/* arch/arm/plat-s3c64xx/irq-pm.c
18007 + *
18008 + * Copyright 2008 Openmoko, Inc.
18009 + * Copyright 2008 Simtec Electronics
18010 + * Ben Dooks <ben@simtec.co.uk>
18011 + * http://armlinux.simtec.co.uk/
18012 + *
18013 + * S3C64XX - Interrupt handling Power Management
18014 + *
18015 + * This program is free software; you can redistribute it and/or modify
18016 + * it under the terms of the GNU General Public License version 2 as
18017 + * published by the Free Software Foundation.
18018 + */
18019 +
18020 +#include <linux/kernel.h>
18021 +#include <linux/sysdev.h>
18022 +#include <linux/interrupt.h>
18023 +#include <linux/serial_core.h>
18024 +#include <linux/irq.h>
18025 +#include <linux/io.h>
18026 +
18027 +#include <asm/hardware/vic.h>
18028 +
18029 +#include <mach/map.h>
18030 +
18031 +#include <plat/regs-serial.h>
18032 +#include <plat/regs-timer.h>
18033 +#include <plat/regs-gpio.h>
18034 +#include <plat/cpu.h>
18035 +#include <plat/pm.h>
18036 +
18037 +/* We handled all the IRQ types in this code, to save having to make several
18038 + * small files to handle each different type separately. Having the EINT_GRP
18039 + * code here shouldn't be as much bloat as the IRQ table space needed when
18040 + * they are enabled. The added benefit is we ensure that these registers are
18041 + * in the same state as we suspended.
18042 + */
18043 +
18044 +static struct sleep_save irq_save[] = {
18045 + SAVE_ITEM(S3C64XX_PRIORITY),
18046 + SAVE_ITEM(S3C64XX_EINT0CON0),
18047 + SAVE_ITEM(S3C64XX_EINT0CON1),
18048 + SAVE_ITEM(S3C64XX_EINT0FLTCON0),
18049 + SAVE_ITEM(S3C64XX_EINT0FLTCON1),
18050 + SAVE_ITEM(S3C64XX_EINT0FLTCON2),
18051 + SAVE_ITEM(S3C64XX_EINT0FLTCON3),
18052 + SAVE_ITEM(S3C64XX_EINT0MASK),
18053 + SAVE_ITEM(S3C64XX_TINT_CSTAT),
18054 +};
18055 +
18056 +static struct irq_grp_save {
18057 + u32 fltcon;
18058 + u32 con;
18059 + u32 mask;
18060 +} eint_grp_save[5];
18061 +
18062 +struct irq_vic_save {
18063 + u32 int_select;
18064 + u32 int_enable;
18065 + u32 soft_int;
18066 + u32 protect;
18067 + u32 vect_addr[32];
18068 + u32 vect_cntl[32];
18069 +};
18070 +
18071 +static struct irq_vic_save irq_pm_vic0_save;
18072 +static struct irq_vic_save irq_pm_vic1_save;
18073 +
18074 +static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
18075 +
18076 +static void s3c64xx_vic_save(void __iomem *base, struct irq_vic_save *save)
18077 +{
18078 + int v;
18079 +
18080 + save->int_select = readl(base + VIC_INT_SELECT);
18081 + save->int_enable = readl(base + VIC_INT_ENABLE);
18082 + save->soft_int = readl(base + VIC_INT_SOFT);
18083 + save->protect = readl(base + VIC_PROTECT);
18084 +
18085 + S3C_PMDBG("%s: select=%08x, enable=%08x, protect=%08x\n", __func__,
18086 + save->int_select, save->int_enable, save->protect);
18087 +
18088 + for (v = 0; v < ARRAY_SIZE(save->vect_addr); v++) {
18089 + save->vect_addr[v] = readl(base + VIC_VECT_ADDR0 + (v * 4));
18090 + save->vect_cntl[v] = readl(base + VIC_VECT_CNTL0 + (v * 4));
18091 + }
18092 +}
18093 +
18094 +static void s3c64xx_vic_restore(void __iomem *base, struct irq_vic_save *save)
18095 +{
18096 + int v;
18097 +
18098 + writel(save->int_select, base + VIC_INT_SELECT);
18099 + writel(save->protect, base + VIC_PROTECT);
18100 +
18101 + /* set the enabled ints and then clear the non-enabled */
18102 + writel(save->int_enable, base + VIC_INT_ENABLE);
18103 + writel(~save->int_enable, base + VIC_INT_ENABLE_CLEAR);
18104 +
18105 + /* and the same for the soft-int register */
18106 +
18107 + writel(save->soft_int, base + VIC_INT_SOFT);
18108 + writel(~save->soft_int, base + VIC_INT_SOFT_CLEAR);
18109 +
18110 + S3C_PMDBG("%s: vic int_enable=%08x\n", __func__, readl(base + VIC_INT_ENABLE));
18111 +
18112 + for (v = 0; v < ARRAY_SIZE(save->vect_addr); v++) {
18113 + writel(save->vect_addr[v], base + VIC_VECT_ADDR0 + (v * 4));
18114 + writel(save->vect_cntl[v], base + VIC_VECT_CNTL0 + (v * 4));
18115 + }
18116 +}
18117 +
18118 +static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
18119 +{
18120 + struct irq_grp_save *grp = eint_grp_save;
18121 + int i;
18122 +
18123 + S3C_PMDBG("%s: suspending IRQs\n", __func__);
18124 +
18125 + s3c64xx_vic_save(S3C_VA_VIC0, &irq_pm_vic0_save);
18126 + s3c64xx_vic_save(S3C_VA_VIC1, &irq_pm_vic1_save);
18127 +
18128 + s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
18129 +
18130 + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
18131 + irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
18132 +
18133 + for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
18134 + grp->con = __raw_readl(S3C64XX_EINT12CON + (i * 4));
18135 + grp->mask = __raw_readl(S3C64XX_EINT12MASK + (i * 4));
18136 + grp->fltcon = __raw_readl(S3C64XX_EINT12FLTCON + (i * 4));
18137 + }
18138 +
18139 + return 0;
18140 +}
18141 +
18142 +static int s3c64xx_irq_pm_resume(struct sys_device *dev)
18143 +{
18144 + struct irq_grp_save *grp = eint_grp_save;
18145 + int i;
18146 +
18147 + S3C_PMDBG("%s: resuming IRQs\n", __func__);
18148 +
18149 + s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
18150 +
18151 + s3c64xx_vic_restore(S3C_VA_VIC0, &irq_pm_vic0_save);
18152 + s3c64xx_vic_restore(S3C_VA_VIC1, &irq_pm_vic1_save);
18153 +
18154 + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
18155 + __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
18156 +
18157 + for (i = 0; i < ARRAY_SIZE(eint_grp_save); i++, grp++) {
18158 + __raw_writel(grp->con, S3C64XX_EINT12CON + (i * 4));
18159 + __raw_writel(grp->mask, S3C64XX_EINT12MASK + (i * 4));
18160 + __raw_writel(grp->fltcon, S3C64XX_EINT12FLTCON + (i * 4));
18161 + }
18162 +
18163 + S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
18164 + return 0;
18165 +}
18166 +
18167 +static struct sysdev_driver s3c64xx_irq_driver = {
18168 + .suspend = s3c64xx_irq_pm_suspend,
18169 + .resume = s3c64xx_irq_pm_resume,
18170 +};
18171 +
18172 +static int __init s3c64xx_irq_pm_init(void)
18173 +{
18174 + return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
18175 +}
18176 +
18177 +arch_initcall(s3c64xx_irq_pm_init);
18178 +
18179 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/Kconfig linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/Kconfig
18180 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/Kconfig 2009-05-10 22:05:04.000000000 +0200
18181 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/Kconfig 2009-05-10 22:27:59.000000000 +0200
18182 @@ -19,6 +19,8 @@
18183 select S3C_GPIO_PULL_UPDOWN
18184 select S3C_GPIO_CFG_S3C24XX
18185 select S3C_GPIO_CFG_S3C64XX
18186 + select USB_ARCH_HAS_OHCI
18187 + select S3C64XX_SETUP_USBOTG
18188 help
18189 Base platform code for any Samsung S3C64XX device
18190
18191 @@ -38,6 +40,10 @@
18192 Common clock support code for the S3C6400 that is shared
18193 by other CPUs in the series, such as the S3C6410.
18194
18195 +config S3C64XX_DMA
18196 + bool "S3C64XX DMA"
18197 + select S3C_DMA
18198 +
18199 # platform specific device setup
18200
18201 config S3C64XX_SETUP_I2C0
18202 @@ -59,4 +65,10 @@
18203 help
18204 Common setup code for S3C64XX with an 24bpp RGB display helper.
18205
18206 +config S3C64XX_SETUP_USBOTG
18207 + bool
18208 + help
18209 + Common setup code for S3C64XX with USB OTG
18210 +
18211 +
18212 endif
18213 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/Makefile linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/Makefile
18214 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/Makefile 2009-05-10 22:05:04.000000000 +0200
18215 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/Makefile 2009-05-10 22:27:59.000000000 +0200
18216 @@ -24,8 +24,22 @@
18217 obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o
18218 obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o
18219
18220 +# DMA support
18221 +
18222 +obj-$(CONFIG_S3C64XX_DMA) += dma.o
18223 +
18224 +# PM support
18225 +
18226 +obj-$(CONFIG_PM) += pm.o
18227 +obj-$(CONFIG_PM) += sleep.o
18228 +obj-$(CONFIG_PM) += irq-pm.o
18229 +
18230 +obj-$(CONFIG_CPU_FREQ_S3C64XX) += cpufreq.o
18231 +
18232 # Device setup
18233
18234 obj-$(CONFIG_S3C64XX_SETUP_I2C0) += setup-i2c0.o
18235 obj-$(CONFIG_S3C64XX_SETUP_I2C1) += setup-i2c1.o
18236 obj-$(CONFIG_S3C64XX_SETUP_FB_24BPP) += setup-fb-24bpp.o
18237 +obj-$(CONFIG_S3C64XX_SETUP_USBOTG) += dev-usbgadget.o
18238 +
18239 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/pm.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/pm.c
18240 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/pm.c 1970-01-01 01:00:00.000000000 +0100
18241 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/pm.c 2009-05-10 22:27:59.000000000 +0200
18242 @@ -0,0 +1,177 @@
18243 +/* linux/arch/arm/plat-s3c64xx/pm.c
18244 + *
18245 + * Copyright 2008 Openmoko, Inc.
18246 + * Copyright 2008 Simtec Electronics
18247 + * Ben Dooks <ben@simtec.co.uk>
18248 + * http://armlinux.simtec.co.uk/
18249 + *
18250 + * S3C64XX CPU PM support.
18251 + *
18252 + * This program is free software; you can redistribute it and/or modify
18253 + * it under the terms of the GNU General Public License version 2 as
18254 + * published by the Free Software Foundation.
18255 +*/
18256 +
18257 +#include <linux/init.h>
18258 +#include <linux/suspend.h>
18259 +#include <linux/serial_core.h>
18260 +#include <linux/io.h>
18261 +
18262 +#include <mach/map.h>
18263 +
18264 +#include <plat/pm.h>
18265 +#include <plat/regs-sys.h>
18266 +#include <plat/regs-gpio.h>
18267 +#include <plat/regs-clock.h>
18268 +#include <plat/regs-modem.h>
18269 +#include <plat/regs-syscon-power.h>
18270 +#include <plat/regs-gpio-memport.h>
18271 +
18272 +#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
18273 +#include <plat/gpio-bank-n.h>
18274 +
18275 +void s3c_pm_debug_smdkled(u32 set, u32 clear)
18276 +{
18277 + unsigned long flags;
18278 + u32 reg;
18279 +
18280 + local_irq_save(flags);
18281 + reg = __raw_readl(S3C64XX_GPNCON);
18282 + reg &= ~(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) |
18283 + S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15));
18284 + reg |= S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) |
18285 + S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15);
18286 + __raw_writel(reg, S3C64XX_GPNCON);
18287 +
18288 + reg = __raw_readl(S3C64XX_GPNDAT);
18289 + reg &= ~(clear << 12);
18290 + reg |= set << 12;
18291 + __raw_writel(reg, S3C64XX_GPNDAT);
18292 +
18293 + local_irq_restore(flags);
18294 +}
18295 +#endif
18296 +
18297 +static struct sleep_save core_save[] = {
18298 + SAVE_ITEM(S3C_APLL_LOCK),
18299 + SAVE_ITEM(S3C_MPLL_LOCK),
18300 + SAVE_ITEM(S3C_EPLL_LOCK),
18301 + SAVE_ITEM(S3C_CLK_SRC),
18302 + SAVE_ITEM(S3C_CLK_DIV0),
18303 + SAVE_ITEM(S3C_CLK_DIV1),
18304 + SAVE_ITEM(S3C_CLK_DIV2),
18305 + SAVE_ITEM(S3C_CLK_OUT),
18306 + SAVE_ITEM(S3C_HCLK_GATE),
18307 + SAVE_ITEM(S3C_PCLK_GATE),
18308 + SAVE_ITEM(S3C_SCLK_GATE),
18309 + SAVE_ITEM(S3C_MEM0_GATE),
18310 +
18311 + SAVE_ITEM(S3C_EPLL_CON1),
18312 + SAVE_ITEM(S3C_EPLL_CON0),
18313 +
18314 + SAVE_ITEM(S3C64XX_MEM0DRVCON),
18315 + SAVE_ITEM(S3C64XX_MEM1DRVCON),
18316 +
18317 +#ifndef CONFIG_CPU_FREQ
18318 + SAVE_ITEM(S3C_APLL_CON),
18319 + SAVE_ITEM(S3C_MPLL_CON),
18320 +#endif
18321 +};
18322 +
18323 +static struct sleep_save misc_save[] = {
18324 + SAVE_ITEM(S3C64XX_AHB_CON0),
18325 + SAVE_ITEM(S3C64XX_AHB_CON1),
18326 + SAVE_ITEM(S3C64XX_AHB_CON2),
18327 +
18328 + SAVE_ITEM(S3C64XX_MODEM_MIFPCON),
18329 + SAVE_ITEM(S3C64XX_SPCON),
18330 +
18331 + SAVE_ITEM(S3C64XX_MEM0CONSTOP),
18332 + SAVE_ITEM(S3C64XX_MEM1CONSTOP),
18333 + SAVE_ITEM(S3C64XX_MEM0CONSLP0),
18334 + SAVE_ITEM(S3C64XX_MEM0CONSLP1),
18335 + SAVE_ITEM(S3C64XX_MEM1CONSLP),
18336 +};
18337 +
18338 +void s3c_pm_configure_extint(void)
18339 +{
18340 + __raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
18341 +}
18342 +
18343 +void s3c_pm_restore_core(void)
18344 +{
18345 + __raw_writel(0, S3C64XX_EINT_MASK);
18346 +
18347 + s3c_pm_debug_smdkled(1 << 2, 0);
18348 +
18349 + s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
18350 + s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
18351 +}
18352 +
18353 +void s3c_pm_save_core(void)
18354 +{
18355 + s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
18356 + s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
18357 +}
18358 +
18359 +/* since both s3c6400 and s3c6410 share the same sleep pm calls, we
18360 + * put the per-cpu code in here until any new cpu comes along and changes
18361 + * this.
18362 + */
18363 +
18364 +#include <plat/regs-gpio.h>
18365 +
18366 +static void s3c64xx_cpu_suspend(void)
18367 +{
18368 + unsigned long tmp;
18369 +
18370 + /* set our standby method to sleep */
18371 +
18372 + tmp = __raw_readl(S3C64XX_PWR_CFG);
18373 + tmp &= ~S3C64XX_PWRCFG_CFG_WFI_MASK;
18374 + tmp |= S3C64XX_PWRCFG_CFG_WFI_SLEEP;
18375 + __raw_writel(tmp, S3C64XX_PWR_CFG);
18376 +
18377 + /* clear any old wakeup */
18378 +
18379 + __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT),
18380 + S3C64XX_WAKEUP_STAT);
18381 +
18382 + /* set the LED state to 0110 over sleep */
18383 + s3c_pm_debug_smdkled(3 << 1, 0xf);
18384 +
18385 + /* issue the standby signal into the pm unit. Note, we
18386 + * issue a write-buffer drain just in case */
18387 +
18388 + tmp = 0;
18389 +
18390 + asm("b 1f\n\t"
18391 + ".align 5\n\t"
18392 + "1:\n\t"
18393 + "mcr p15, 0, %0, c7, c10, 5\n\t"
18394 + "mcr p15, 0, %0, c7, c10, 4\n\t"
18395 + "mcr p15, 0, %0, c7, c0, 4" :: "r" (tmp));
18396 +
18397 + /* we should never get past here */
18398 +
18399 + panic("sleep resumed to originator?");
18400 +}
18401 +
18402 +static void s3c64xx_pm_prepare(void)
18403 +{
18404 + /* store address of resume. */
18405 + __raw_writel(virt_to_phys(s3c_cpu_resume), S3C64XX_INFORM0);
18406 +
18407 + /* ensure previous wakeup state is cleared before sleeping */
18408 + __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT), S3C64XX_WAKEUP_STAT);
18409 +}
18410 +
18411 +static int s3c64xx_pm_init(void)
18412 +{
18413 + pm_cpu_prep = s3c64xx_pm_prepare;
18414 + pm_cpu_sleep = s3c64xx_cpu_suspend;
18415 + pm_uart_udivslot = 1;
18416 + return 0;
18417 +}
18418 +
18419 +arch_initcall(s3c64xx_pm_init);
18420 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/s3c6400-clock.c linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/s3c6400-clock.c
18421 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/s3c6400-clock.c 2009-05-10 22:08:41.000000000 +0200
18422 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/s3c6400-clock.c 2009-05-10 22:27:59.000000000 +0200
18423 @@ -24,6 +24,7 @@
18424
18425 #include <mach/hardware.h>
18426 #include <mach/map.h>
18427 +#include <mach/cpu.h>
18428
18429 #include <plat/cpu-freq.h>
18430
18431 @@ -88,6 +89,80 @@
18432 .sources = &clk_src_apll,
18433 };
18434
18435 +static u32 clk_arm_div_mask(void)
18436 +{
18437 + if (cpu_is_s3c6400())
18438 + return S3C6400_CLKDIV0_ARM_MASK;
18439 +
18440 + if (cpu_is_s3c6410())
18441 + return S3C6410_CLKDIV0_ARM_MASK;
18442 +
18443 + return 0;
18444 +}
18445 +
18446 +static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
18447 +{
18448 + unsigned long rate = clk_get_rate(clk->parent);
18449 + u32 val;
18450 +
18451 + val = __raw_readl(S3C_CLK_DIV0);
18452 + val &= clk_arm_div_mask();
18453 +
18454 + return rate / (val + 1);
18455 +}
18456 +
18457 +static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
18458 + unsigned long rate)
18459 +{
18460 + unsigned long parent = clk_get_rate(clk->parent);
18461 + int div;
18462 + int max = clk_arm_div_mask() + 1;
18463 +
18464 + if (parent < rate)
18465 + return parent;
18466 +
18467 + div = parent / rate;
18468 +
18469 + if (div < 1)
18470 + div = 1;
18471 + if (div > max)
18472 + div = max;
18473 +
18474 + return parent / div;
18475 +}
18476 +
18477 +static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
18478 +{
18479 + unsigned int div;
18480 + u32 val;
18481 + unsigned long flags;
18482 +
18483 + div = (clk_get_rate(clk->parent) / rate) - 1;
18484 +
18485 + if (div > clk_arm_div_mask())
18486 + return -EINVAL;
18487 +
18488 + local_irq_save(flags);
18489 +
18490 + val = __raw_readl(S3C_CLK_DIV0);
18491 + val &= ~clk_arm_div_mask();
18492 + val |= div;
18493 +
18494 + __raw_writel(val, S3C_CLK_DIV0);
18495 + local_irq_restore(flags);
18496 +
18497 + return 0;
18498 +}
18499 +
18500 +static struct clk clk_arm = {
18501 + .name = "armclk",
18502 + .id = -1,
18503 + .parent = &clk_mout_apll.clk,
18504 + .round_rate = &s3c64xx_clk_arm_round_rate,
18505 + .get_rate = s3c64xx_clk_arm_get_rate,
18506 + .set_rate = s3c64xx_clk_arm_set_rate,
18507 +};
18508 +
18509 struct clk clk_fout_epll = {
18510 .name = "fout_epll",
18511 .id = -1,
18512 @@ -239,10 +314,12 @@
18513
18514 rate = clk_round_rate(clk, rate);
18515 div = clk_get_rate(clk->parent) / rate;
18516 + if (div > 16)
18517 + return -EINVAL;
18518
18519 val = __raw_readl(reg);
18520 - val &= ~sclk->mask;
18521 - val |= (rate - 1) << sclk->shift;
18522 + val &= ~(0xf << sclk->divider_shift);
18523 + val |= (div - 1) << sclk->divider_shift;
18524 __raw_writel(val, reg);
18525
18526 return 0;
18527 @@ -282,7 +359,7 @@
18528 if (rate > parent_rate)
18529 rate = parent_rate;
18530 else {
18531 - div = rate / parent_rate;
18532 + div = parent_rate / rate;
18533
18534 if (div == 0)
18535 div = 1;
18536 @@ -351,7 +428,7 @@
18537
18538 static struct clksrc_clk clk_usbhost = {
18539 .clk = {
18540 - .name = "usb-host-bus",
18541 + .name = "usb-bus-host",
18542 .id = -1,
18543 .ctrlbit = S3C_CLKCON_SCLK_UHOST,
18544 .enable = s3c64xx_sclk_ctrl,
18545 @@ -518,6 +595,55 @@
18546 .reg_divider = S3C_CLK_DIV2,
18547 };
18548
18549 +static struct clk *clkset_camera_list[] = {
18550 + &clk_h2,
18551 +};
18552 +
18553 +static struct clk_sources clkset_camera = {
18554 + .sources = clkset_camera_list,
18555 + .nr_sources = ARRAY_SIZE(clkset_camera_list),
18556 +};
18557 +
18558 +static struct clksrc_clk clk_camera = {
18559 + .clk = {
18560 + .name = "camera",
18561 + .id = -1,
18562 + .ctrlbit = S3C_CLKCON_SCLK_CAM,
18563 + .enable = s3c64xx_sclk_ctrl,
18564 + .set_parent = s3c64xx_setparent_clksrc,
18565 + .get_rate = s3c64xx_getrate_clksrc,
18566 + .set_rate = s3c64xx_setrate_clksrc,
18567 + .round_rate = s3c64xx_roundrate_clksrc,
18568 + },
18569 + .shift = 0,
18570 + .mask = 0,
18571 + .sources = &clkset_camera,
18572 + .divider_shift = S3C6400_CLKDIV0_CAM_SHIFT,
18573 + .reg_divider = S3C_CLK_DIV0,
18574 +};
18575 +
18576 +static struct clk *clkset_camif_list[] = {
18577 + &clk_h,
18578 +};
18579 +
18580 +static struct clk_sources clkset_camif = {
18581 + .sources = clkset_camif_list,
18582 + .nr_sources = ARRAY_SIZE(clkset_camif_list),
18583 +};
18584 +
18585 +static struct clksrc_clk clk_camif = {
18586 + .clk = {
18587 + .name = "camif",
18588 + .id = -1,
18589 + .ctrlbit = S3C_CLKCON_HCLK_CAMIF,
18590 + .enable = s3c64xx_hclk_ctrl,
18591 + .set_parent = s3c64xx_setparent_clksrc,
18592 + },
18593 + .shift = 0,
18594 + .mask = 0,
18595 + .sources = &clkset_camif,
18596 +};
18597 +
18598 /* Clock initialisation code */
18599
18600 static struct clksrc_clk *init_parents[] = {
18601 @@ -534,6 +660,8 @@
18602 &clk_audio0,
18603 &clk_audio1,
18604 &clk_irda,
18605 + &clk_camif,
18606 + &clk_camera,
18607 };
18608
18609 static void __init_or_cpufreq s3c6400_set_clksrc(struct clksrc_clk *clk)
18610 @@ -606,6 +734,7 @@
18611 clk_fout_epll.rate = epll;
18612 clk_fout_apll.rate = apll;
18613
18614 + clk_h2.rate = hclk2;
18615 clk_h.rate = hclk;
18616 clk_p.rate = pclk;
18617 clk_f.rate = fclk;
18618 @@ -633,6 +762,9 @@
18619 &clk_audio0.clk,
18620 &clk_audio1.clk,
18621 &clk_irda.clk,
18622 + &clk_camera.clk,
18623 + &clk_camif.clk,
18624 + &clk_arm,
18625 };
18626
18627 void __init s3c6400_register_clocks(void)
18628 @@ -650,6 +782,5 @@
18629 }
18630 }
18631
18632 - clk_mpll.parent = &clk_mout_mpll.clk;
18633 clk_epll.parent = &clk_mout_epll.clk;
18634 }
18635 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/sleep.S linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/sleep.S
18636 --- linux-2.6.29-rc3.owrt/arch/arm/plat-s3c64xx/sleep.S 1970-01-01 01:00:00.000000000 +0100
18637 +++ linux-2.6.29-rc3.owrt.om/arch/arm/plat-s3c64xx/sleep.S 2009-05-10 22:27:59.000000000 +0200
18638 @@ -0,0 +1,143 @@
18639 +/* linux/0arch/arm/plat-s3c64xx/sleep.S
18640 + *
18641 + * Copyright 2008 Openmoko, Inc.
18642 + * Copyright 2008 Simtec Electronics
18643 + * Ben Dooks <ben@simtec.co.uk>
18644 + * http://armlinux.simtec.co.uk/
18645 + *
18646 + * S3C64XX CPU sleep code
18647 + *
18648 + * This program is free software; you can redistribute it and/or modify
18649 + * it under the terms of the GNU General Public License version 2 as
18650 + * published by the Free Software Foundation.
18651 +*/
18652 +
18653 +#include <linux/linkage.h>
18654 +#include <asm/assembler.h>
18655 +#include <mach/map.h>
18656 +
18657 +#undef S3C64XX_VA_GPIO
18658 +#define S3C64XX_VA_GPIO (0x0)
18659 +
18660 +#include <plat/regs-gpio.h>
18661 +#include <plat/gpio-bank-n.h>
18662 +
18663 +#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))
18664 +
18665 + .text
18666 +
18667 + /* s3c_cpu_save
18668 + *
18669 + * Save enough processor state to allow the restart of the pm.c
18670 + * code after resume.
18671 + *
18672 + * entry:
18673 + * r0 = pointer to the save block
18674 + * exit:
18675 + * r0 = exit code: 1 => stored data
18676 + * 0 => resumed from sleep
18677 + */
18678 +
18679 +ENTRY(s3c_cpu_save)
18680 + stmfd sp!, { r4 - r12, lr }
18681 +
18682 + mrc p15, 0, r4, c13, c0, 0 @ FCSE/PID
18683 + mrc p15, 0, r5, c3, c0, 0 @ Domain ID
18684 + mrc p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
18685 + mrc p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
18686 + mrc p15, 0, r8, c2, c0, 2 @ Translation Table Control
18687 + mrc p15, 0, r9, c1, c0, 0 @ Control register
18688 + mrc p15, 0, r10, c1, c0, 1 @ Auxiliary control register
18689 + mrc p15, 0, r11, c1, c0, 2 @ Co-processor access controls
18690 +
18691 + stmia r0, { r4 - r13 } @ Save CP registers and SP
18692 + mov r0, #0
18693 + ldmfd sp, { r4 - r12, pc } @ return, not disturbing SP
18694 +
18695 + @@ return to the caller, after the MMU is turned on.
18696 + @@ restore the last bits of the stack and return.
18697 +resume_with_mmu:
18698 + mov r0, #1
18699 + ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save
18700 +
18701 + .data
18702 +
18703 + /* the next bit is code, but it requires easy access to the
18704 + * s3c_sleep_save_phys data before the MMU is switched on, so
18705 + * we store the code that needs this variable in the .data where
18706 + * the value can be written to (the .text segment is RO).
18707 + */
18708 +
18709 + .global s3c_sleep_save_phys
18710 +s3c_sleep_save_phys:
18711 + .word 0
18712 +
18713 + /* Sleep magic, the word before the resume entry point so that the
18714 + * bootloader can check for a resumeable image. */
18715 +
18716 + .word 0x2bedf00d
18717 +
18718 + /* s3c_cpu_reusme
18719 + *
18720 + * This is the entry point, stored by whatever method the bootloader
18721 + * requires to get the kernel runnign again. This code expects to be
18722 + * entered with no caches live and the MMU disabled. It will then
18723 + * restore the MMU and other basic CP registers saved and restart
18724 + * the kernel C code to finish the resume code.
18725 + */
18726 +
18727 +ENTRY(s3c_cpu_resume)
18728 + msr cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
18729 + ldr r2, =LL_UART /* for debug */
18730 +
18731 +#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
18732 + /* Initialise the GPIO state if we are debugging via the SMDK LEDs,
18733 + * as the uboot version supplied resets these to inputs during the
18734 + * resume checks.
18735 + */
18736 +
18737 + ldr r3, =S3C64XX_PA_GPIO
18738 + ldr r0, [ r3, #S3C64XX_GPNCON ]
18739 + bic r0, r0, #(S3C64XX_GPN_CONMASK(12) | S3C64XX_GPN_CONMASK(13) | \
18740 + S3C64XX_GPN_CONMASK(14) | S3C64XX_GPN_CONMASK(15))
18741 + orr r0, r0, #(S3C64XX_GPN_OUTPUT(12) | S3C64XX_GPN_OUTPUT(13) | \
18742 + S3C64XX_GPN_OUTPUT(14) | S3C64XX_GPN_OUTPUT(15))
18743 + str r0, [ r3, #S3C64XX_GPNCON ]
18744 +
18745 + ldr r0, [ r3, #S3C64XX_GPNDAT ]
18746 + bic r0, r0, #0xf << 12 @ GPN12..15
18747 + orr r0, r0, #1 << 15 @ GPN15
18748 + str r0, [ r3, #S3C64XX_GPNDAT ]
18749 +#endif
18750 +
18751 + /* __v6_setup from arch/arm/mm/proc-v6.S, ensure that the caches
18752 + * are thoroughly cleaned just in case the bootloader didn't do it
18753 + * for us. */
18754 + mov r0, #0
18755 + mcr p15, 0, r0, c7, c14, 0 @ clean+invalidate D cache
18756 + mcr p15, 0, r0, c7, c5, 0 @ invalidate I cache
18757 + mcr p15, 0, r0, c7, c15, 0 @ clean+invalidate cache
18758 + mcr p15, 0, r0, c7, c10, 4 @ drain write buffer
18759 + @@mcr p15, 0, r0, c8, c7, 0 @ invalidate I + D TLBs
18760 + @@mcr p15, 0, r0, c7, c7, 0 @ Invalidate I + D caches
18761 +
18762 + ldr r0, s3c_sleep_save_phys
18763 + ldmia r0, { r4 - r13 }
18764 +
18765 + mcr p15, 0, r4, c13, c0, 0 @ FCSE/PID
18766 + mcr p15, 0, r5, c3, c0, 0 @ Domain ID
18767 + mcr p15, 0, r6, c2, c0, 0 @ Translation Table BASE0
18768 + mcr p15, 0, r7, c2, c0, 1 @ Translation Table BASE1
18769 + mcr p15, 0, r8, c2, c0, 2 @ Translation Table Control
18770 + mcr p15, 0, r10, c1, c0, 1 @ Auxiliary control register
18771 +
18772 + mov r0, #0 @ restore copro access controls
18773 + mcr p15, 0, r11, c1, c0, 2 @ Co-processor access controls
18774 + mcr p15, 0, r0, c7, c5, 4
18775 +
18776 + ldr r2, =resume_with_mmu
18777 + mcr p15, 0, r9, c1, c0, 0 /* turn mmu back on */
18778 + nop
18779 + mov pc, r2 /* jump back */
18780 +
18781 + .end
18782 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/arch/arm/tools/mach-types linux-2.6.29-rc3.owrt.om/arch/arm/tools/mach-types
18783 --- linux-2.6.29-rc3.owrt/arch/arm/tools/mach-types 2009-05-10 22:08:41.000000000 +0200
18784 +++ linux-2.6.29-rc3.owrt.om/arch/arm/tools/mach-types 2009-05-10 22:27:59.000000000 +0200
18785 @@ -1994,3 +1994,5 @@
18786 blaze MACH_BLAZE BLAZE 2004
18787 linkstation_ls_hgl MACH_LINKSTATION_LS_HGL LINKSTATION_LS_HGL 2005
18788 htcvenus MACH_HTCVENUS HTCVENUS 2006
18789 +om_3d7k MACH_OM_3D7K OM_3D7K 2120
18790 +
18791 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/build linux-2.6.29-rc3.owrt.om/build
18792 --- linux-2.6.29-rc3.owrt/build 1970-01-01 01:00:00.000000000 +0100
18793 +++ linux-2.6.29-rc3.owrt.om/build 2009-05-10 22:27:59.000000000 +0200
18794 @@ -0,0 +1,128 @@
18795 +#!/bin/sh
18796 +#
18797 +# Kernel building helper script (C)2008 Openmoko, Inc
18798 +# Andy Green <andy@openmoko.org>
18799 +#
18800 +# Licensed under GPLv3 or later
18801 +#
18802 +#
18803 +# you need to run this from the top level source dir, but it creates all
18804 +# object files into a subdir given in the first argument, eg
18805 +#
18806 +# ./build GTA02
18807 +#
18808 +# this radically speeds up swapping between build contexts. Note the config
18809 +# for each build lives in the subdir.
18810 +
18811 +PARALLEL=16
18812 +
18813 +if [ -z "$1" ] ; then
18814 + echo "Specify the build subdir, eg, GTA02 which contains the .config"
18815 + echo "and will hold the object files"
18816 + exit 1
18817 +fi
18818 +
18819 +mkdir -p $1
18820 +
18821 +if [ -z "$CROSS_COMPILE" ]; then
18822 + export CROSS_COMPILE=/usr/local/openmoko/arm/bin/arm-angstrom-linux-gnueabi-
18823 +fi
18824 +make O=$1 ARCH=arm silentoldconfig
18825 +
18826 +#
18827 +# figure out what we are building
18828 +#
18829 +
18830 +PRODUCT=
18831 +
18832 +if [ ! -z "`grep CONFIG_MACH_NEO1973_GTA01=y $1/.config`" ] ; then
18833 + START=30008000
18834 + PRODUCT=GTA01
18835 +fi
18836 +
18837 +if [ ! -z "`grep CONFIG_MACH_NEO1973_GTA02=y $1/.config`" ] ; then
18838 + START=30008000
18839 + PRODUCT=GTA02
18840 +fi
18841 +
18842 +if [ ! -z "`grep CONFIG_MACH_OM_3D7K=y $1/.config`" ] ; then
18843 + START=50008000
18844 + PRODUCT=OM_3D7K
18845 +fi
18846 +
18847 +if [ ! -z "`grep CONFIG_MACH_SMDK6410=y $1/.config`" ] ; then
18848 + START=50008000
18849 + PRODUCT=SMDK6410
18850 +fi
18851 +
18852 +if [ ! -z "`grep CONFIG_MACH_M800=y $1/.config`" ] ; then
18853 + START=30008000
18854 + PRODUCT=M800
18855 +fi
18856 +
18857 +if [ -z "$PRODUCT" ] ; then
18858 + echo "Unable to figure out what we are building from the config"
18859 + exit 1
18860 +fi
18861 +
18862 +#
18863 +# check that we are in a valid branch
18864 +#
18865 +
18866 +if git branch | head -n1 | grep -q "* (no branch)"; then
18867 + cat <<EOF 1>&2
18868 +There is no branch in the local copy of the repository right now!
18869 +Hint: type git-branch, make sure you are in a valid branch and then try again
18870 +EOF
18871 + exit 1
18872 +fi;
18873 +
18874 +#
18875 +# get the branch and head hash for the version we are building to
18876 +# allow source tracability
18877 +#
18878 +
18879 +VERSION=
18880 +if [ -d .git ] ; then
18881 + HEAD=`git show --pretty=oneline | head -n1 | cut -d' ' -f1 | cut -b1-16`
18882 + BRANCH=`git branch | grep ^\* | cut -d' ' -f2 | sed s/-hist//g`
18883 + VERSION=-$PRODUCT\_$BRANCH
18884 +fi
18885 +
18886 +
18887 +echo $MKIMAGECMD
18888 +
18889 +#
18890 +# actually make it
18891 +#
18892 +
18893 +if make -j$PARALLEL O=$1 ARCH=arm CONFIG_DEBUG_SECTION_MISMATCH=y EXTRAVERSION=$VERSION; then
18894 +
18895 + #
18896 + # if the build is happy, postprocess it by strip and with U-Boot header wrapper
18897 + # you can get mkimage from U-Boot or Qi build
18898 + #
18899 +
18900 + ${CROSS_COMPILE}objcopy -O binary -R .note -R .comment -S $1/arch/arm/boot/compressed/vmlinux $1/linux.bin
18901 + mkimage -A arm -O linux -T kernel -C none -a $START -e $START -n "OM $PRODUCT $BRANCH""_$HEAD" -d $1/linux.bin $1/uImage-$PRODUCT.bin
18902 +
18903 + # we can see if it is an "moredrivers" build by looking for USB Eth gadget
18904 + # if it is then keep a stamped copy of last build
18905 +
18906 + if [ ! -z "`grep CONFIG_USB_USBNET=y $1/.config`" ] ; then
18907 + rm -f $1/uImage-moredrivers-$PRODUCT*.bin $1/modules-$PRODUCT*.tar.gz
18908 + cp $1/uImage-$PRODUCT.bin $1/uImage-moredrivers$VERSION-$HEAD.bin
18909 + rm -rf $1/staging
18910 + mkdir -p $1/staging
18911 + if [ ! -z "$2" ] ; then
18912 + make O=$1 ARCH=arm modules_install INSTALL_MOD_PATH=staging
18913 + cd $1/staging
18914 + tar czf ../modules$VERSION-$HEAD.tar.gz .
18915 + cd ../..
18916 + fi
18917 + fi
18918 + exit 0
18919 +else
18920 + exit 1
18921 +fi
18922 +
18923 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/dfu-kern linux-2.6.29-rc3.owrt.om/dfu-kern
18924 --- linux-2.6.29-rc3.owrt/dfu-kern 1970-01-01 01:00:00.000000000 +0100
18925 +++ linux-2.6.29-rc3.owrt.om/dfu-kern 2009-05-10 22:27:59.000000000 +0200
18926 @@ -0,0 +1,16 @@
18927 +#!/bin/bash
18928 +
18929 +if [ -z "$1" ] ; then
18930 + echo "Usage: $0 <DEVICE> eg, $0 GTA02"
18931 + exit 1
18932 +fi
18933 +
18934 +NAME=`echo $1 | cut -d'-' -f1`
18935 +
18936 +../../dfu-util/src/dfu-util -a 3 -d 0x1d50:0x5119 -D $1/uImage-$NAME.bin
18937 +if [ $? -eq 1 ] ; then
18938 +../../dfu-util/src/dfu-util -a 3 -d 0x1d50:0x5120 -D $1/uImage-$NAME.bin
18939 +../../dfu-util/src/dfu-util -a 3 -d 0x1d50:0x5119 -D $1/uImage-$NAME.bin
18940 +fi
18941 +
18942 +
18943 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/Documentation/arm/Samsung-S3C24XX/Suspend.txt linux-2.6.29-rc3.owrt.om/Documentation/arm/Samsung-S3C24XX/Suspend.txt
18944 --- linux-2.6.29-rc3.owrt/Documentation/arm/Samsung-S3C24XX/Suspend.txt 2009-05-10 22:05:01.000000000 +0200
18945 +++ linux-2.6.29-rc3.owrt.om/Documentation/arm/Samsung-S3C24XX/Suspend.txt 2009-05-10 22:27:59.000000000 +0200
18946 @@ -40,13 +40,13 @@
18947 Machine Support
18948 ---------------
18949
18950 - The machine specific functions must call the s3c2410_pm_init() function
18951 + The machine specific functions must call the s3c_pm_init() function
18952 to say that its bootloader is capable of resuming. This can be as
18953 simple as adding the following to the machine's definition:
18954
18955 - INITMACHINE(s3c2410_pm_init)
18956 + INITMACHINE(s3c_pm_init)
18957
18958 - A board can do its own setup before calling s3c2410_pm_init, if it
18959 + A board can do its own setup before calling s3c_pm_init, if it
18960 needs to setup anything else for power management support.
18961
18962 There is currently no support for over-riding the default method of
18963 @@ -74,7 +74,7 @@
18964
18965 enable_irq_wake(IRQ_EINT0);
18966
18967 - s3c2410_pm_init();
18968 + s3c_pm_init();
18969 }
18970
18971
18972 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ar6000_drv.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ar6000_drv.c
18973 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ar6000_drv.c 1970-01-01 01:00:00.000000000 +0100
18974 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ar6000_drv.c 2009-05-10 22:27:59.000000000 +0200
18975 @@ -0,0 +1,3128 @@
18976 +/*
18977 + *
18978 + * Copyright (c) 2004-2007 Atheros Communications Inc.
18979 + * All rights reserved.
18980 + *
18981 + *
18982 + * This program is free software; you can redistribute it and/or modify
18983 + * it under the terms of the GNU General Public License version 2 as
18984 + * published by the Free Software Foundation;
18985 + *
18986 + * Software distributed under the License is distributed on an "AS
18987 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
18988 + * implied. See the License for the specific language governing
18989 + * rights and limitations under the License.
18990 + *
18991 + *
18992 + *
18993 + */
18994 +
18995 +/*
18996 + * This driver is a pseudo ethernet driver to access the Atheros AR6000
18997 + * WLAN Device
18998 + */
18999 +static const char athId[] __attribute__ ((unused)) = "$Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/ar6000_drv.c#2 $";
19000 +
19001 +#include "ar6000_drv.h"
19002 +#include "htc.h"
19003 +
19004 +MODULE_LICENSE("GPL and additional rights");
19005 +
19006 +#ifndef REORG_APTC_HEURISTICS
19007 +#undef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19008 +#endif /* REORG_APTC_HEURISTICS */
19009 +
19010 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19011 +#define APTC_TRAFFIC_SAMPLING_INTERVAL 100 /* msec */
19012 +#define APTC_UPPER_THROUGHPUT_THRESHOLD 3000 /* Kbps */
19013 +#define APTC_LOWER_THROUGHPUT_THRESHOLD 2000 /* Kbps */
19014 +
19015 +typedef struct aptc_traffic_record {
19016 + A_BOOL timerScheduled;
19017 + struct timeval samplingTS;
19018 + unsigned long bytesReceived;
19019 + unsigned long bytesTransmitted;
19020 +} APTC_TRAFFIC_RECORD;
19021 +
19022 +A_TIMER aptcTimer;
19023 +APTC_TRAFFIC_RECORD aptcTR;
19024 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19025 +
19026 +int bmienable = 0;
19027 +unsigned int bypasswmi = 0;
19028 +unsigned int debuglevel = 0;
19029 +int tspecCompliance = 1;
19030 +unsigned int busspeedlow = 0;
19031 +unsigned int onebitmode = 0;
19032 +unsigned int skipflash = 0;
19033 +unsigned int wmitimeout = 2;
19034 +unsigned int wlanNodeCaching = 1;
19035 +unsigned int enableuartprint = 0;
19036 +unsigned int logWmiRawMsgs = 0;
19037 +unsigned int enabletimerwar = 0;
19038 +unsigned int mbox_yield_limit = 99;
19039 +int reduce_credit_dribble = 1 + HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF;
19040 +int allow_trace_signal = 0;
19041 +#ifdef CONFIG_HOST_TCMD_SUPPORT
19042 +unsigned int testmode =0;
19043 +#endif
19044 +
19045 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
19046 +module_param(bmienable, int, 0644);
19047 +module_param(bypasswmi, int, 0644);
19048 +module_param(debuglevel, int, 0644);
19049 +module_param(tspecCompliance, int, 0644);
19050 +module_param(onebitmode, int, 0644);
19051 +module_param(busspeedlow, int, 0644);
19052 +module_param(skipflash, int, 0644);
19053 +module_param(wmitimeout, int, 0644);
19054 +module_param(wlanNodeCaching, int, 0644);
19055 +module_param(logWmiRawMsgs, int, 0644);
19056 +module_param(enableuartprint, int, 0644);
19057 +module_param(enabletimerwar, int, 0644);
19058 +module_param(mbox_yield_limit, int, 0644);
19059 +module_param(reduce_credit_dribble, int, 0644);
19060 +module_param(allow_trace_signal, int, 0644);
19061 +#ifdef CONFIG_HOST_TCMD_SUPPORT
19062 +module_param(testmode, int, 0644);
19063 +#endif
19064 +#else
19065 +
19066 +#define __user
19067 +/* for linux 2.4 and lower */
19068 +MODULE_PARM(bmienable,"i");
19069 +MODULE_PARM(bypasswmi,"i");
19070 +MODULE_PARM(debuglevel, "i");
19071 +MODULE_PARM(onebitmode,"i");
19072 +MODULE_PARM(busspeedlow, "i");
19073 +MODULE_PARM(skipflash, "i");
19074 +MODULE_PARM(wmitimeout, "i");
19075 +MODULE_PARM(wlanNodeCaching, "i");
19076 +MODULE_PARM(enableuartprint,"i");
19077 +MODULE_PARM(logWmiRawMsgs, "i");
19078 +MODULE_PARM(enabletimerwar,"i");
19079 +MODULE_PARM(mbox_yield_limit,"i");
19080 +MODULE_PARM(reduce_credit_dribble,"i");
19081 +MODULE_PARM(allow_trace_signal,"i");
19082 +#ifdef CONFIG_HOST_TCMD_SUPPORT
19083 +MODULE_PARM(testmode, "i");
19084 +#endif
19085 +#endif
19086 +
19087 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,10)
19088 +/* in 2.6.10 and later this is now a pointer to a uint */
19089 +unsigned int _mboxnum = HTC_MAILBOX_NUM_MAX;
19090 +#define mboxnum &_mboxnum
19091 +#else
19092 +unsigned int mboxnum = HTC_MAILBOX_NUM_MAX;
19093 +#endif
19094 +
19095 +#ifdef CONFIG_AR6000_WLAN_RESET
19096 +unsigned int resetok = 1;
19097 +#else
19098 +unsigned int resetok = 0;
19099 +#endif
19100 +
19101 +#ifdef DEBUG
19102 +A_UINT32 g_dbg_flags = DBG_DEFAULTS;
19103 +unsigned int debugflags = 0;
19104 +int debugdriver = 1;
19105 +unsigned int debughtc = 128;
19106 +unsigned int debugbmi = 1;
19107 +unsigned int debughif = 2;
19108 +unsigned int txcreditsavailable[HTC_MAILBOX_NUM_MAX] = {0};
19109 +unsigned int txcreditsconsumed[HTC_MAILBOX_NUM_MAX] = {0};
19110 +unsigned int txcreditintrenable[HTC_MAILBOX_NUM_MAX] = {0};
19111 +unsigned int txcreditintrenableaggregate[HTC_MAILBOX_NUM_MAX] = {0};
19112 +
19113 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
19114 +module_param(debugflags, int, 0644);
19115 +module_param(debugdriver, int, 0644);
19116 +module_param(debughtc, int, 0644);
19117 +module_param(debugbmi, int, 0644);
19118 +module_param(debughif, int, 0644);
19119 +module_param(resetok, int, 0644);
19120 +module_param_array(txcreditsavailable, int, mboxnum, 0644);
19121 +module_param_array(txcreditsconsumed, int, mboxnum, 0644);
19122 +module_param_array(txcreditintrenable, int, mboxnum, 0644);
19123 +module_param_array(txcreditintrenableaggregate, int, mboxnum, 0644);
19124 +#else
19125 +/* linux 2.4 and lower */
19126 +MODULE_PARM(debugflags,"i");
19127 +MODULE_PARM(debugdriver, "i");
19128 +MODULE_PARM(debughtc, "i");
19129 +MODULE_PARM(debugbmi, "i");
19130 +MODULE_PARM(debughif, "i");
19131 +MODULE_PARM(resetok, "i");
19132 +MODULE_PARM(txcreditsavailable, "0-3i");
19133 +MODULE_PARM(txcreditsconsumed, "0-3i");
19134 +MODULE_PARM(txcreditintrenable, "0-3i");
19135 +MODULE_PARM(txcreditintrenableaggregate, "0-3i");
19136 +#endif
19137 +
19138 +#endif /* DEBUG */
19139 +
19140 +unsigned int tx_attempt[HTC_MAILBOX_NUM_MAX] = {0};
19141 +unsigned int tx_post[HTC_MAILBOX_NUM_MAX] = {0};
19142 +unsigned int tx_complete[HTC_MAILBOX_NUM_MAX] = {0};
19143 +unsigned int hifBusRequestNumMax = 40;
19144 +unsigned int war23838_disabled = 0;
19145 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19146 +unsigned int enableAPTCHeuristics = 1;
19147 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19148 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
19149 +module_param_array(tx_attempt, int, mboxnum, 0644);
19150 +module_param_array(tx_post, int, mboxnum, 0644);
19151 +module_param_array(tx_complete, int, mboxnum, 0644);
19152 +module_param(hifBusRequestNumMax, int, 0644);
19153 +module_param(war23838_disabled, int, 0644);
19154 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19155 +module_param(enableAPTCHeuristics, int, 0644);
19156 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19157 +#else
19158 +MODULE_PARM(tx_attempt, "0-3i");
19159 +MODULE_PARM(tx_post, "0-3i");
19160 +MODULE_PARM(tx_complete, "0-3i");
19161 +MODULE_PARM(hifBusRequestNumMax, "i");
19162 +MODULE_PARM(war23838_disabled, "i");
19163 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19164 +MODULE_PARM(enableAPTCHeuristics, "i");
19165 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19166 +#endif
19167 +
19168 +#ifdef BLOCK_TX_PATH_FLAG
19169 +int blocktx = 0;
19170 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
19171 +module_param(blocktx, int, 0644);
19172 +#else
19173 +MODULE_PARM(blocktx, "i");
19174 +#endif
19175 +#endif /* BLOCK_TX_PATH_FLAG */
19176 +
19177 +// TODO move to arsoft_c
19178 +USER_RSSI_THOLD rssi_map[12];
19179 +
19180 +int reconnect_flag = 0;
19181 +
19182 +DECLARE_WAIT_QUEUE_HEAD(ar6000_scan_queue);
19183 +
19184 +/* Function declarations */
19185 +static int ar6000_init_module(void);
19186 +static void ar6000_cleanup_module(void);
19187 +
19188 +int ar6000_init(struct net_device *dev);
19189 +static int ar6000_open(struct net_device *dev);
19190 +static int ar6000_close(struct net_device *dev);
19191 +static void ar6000_init_control_info(AR_SOFTC_T *ar);
19192 +static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev);
19193 +
19194 +static void ar6000_destroy(struct net_device *dev, unsigned int unregister);
19195 +static void ar6000_detect_error(unsigned long ptr);
19196 +static struct net_device_stats *ar6000_get_stats(struct net_device *dev);
19197 +static struct iw_statistics *ar6000_get_iwstats(struct net_device * dev);
19198 +
19199 +/*
19200 + * HTC service connection handlers
19201 + */
19202 +static void ar6000_avail_ev(HTC_HANDLE HTCHandle);
19203 +
19204 +static void ar6000_unavail_ev(void *Instance);
19205 +
19206 +static void ar6000_target_failure(void *Instance, A_STATUS Status);
19207 +
19208 +static void ar6000_rx(void *Context, HTC_PACKET *pPacket);
19209 +
19210 +static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint);
19211 +
19212 +static void ar6000_tx_complete(void *Context, HTC_PACKET *pPacket);
19213 +
19214 +static void ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint);
19215 +
19216 +static void ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint);
19217 +
19218 +/*
19219 + * Static variables
19220 + */
19221 +
19222 +static struct net_device *ar6000_devices[MAX_AR6000];
19223 +extern struct iw_handler_def ath_iw_handler_def;
19224 +DECLARE_WAIT_QUEUE_HEAD(arEvent);
19225 +static void ar6000_cookie_init(AR_SOFTC_T *ar);
19226 +static void ar6000_cookie_cleanup(AR_SOFTC_T *ar);
19227 +static void ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie);
19228 +static struct ar_cookie *ar6000_alloc_cookie(AR_SOFTC_T *ar);
19229 +static void ar6000_TxDataCleanup(AR_SOFTC_T *ar);
19230 +
19231 +#ifdef USER_KEYS
19232 +static A_STATUS ar6000_reinstall_keys(AR_SOFTC_T *ar,A_UINT8 key_op_ctrl);
19233 +#endif
19234 +
19235 +
19236 +static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM];
19237 +
19238 +#define HOST_INTEREST_ITEM_ADDRESS(ar, item) \
19239 +((ar->arTargetType == TARGET_TYPE_AR6001) ? \
19240 + AR6001_HOST_INTEREST_ITEM_ADDRESS(item) : \
19241 + AR6002_HOST_INTEREST_ITEM_ADDRESS(item))
19242 +
19243 +
19244 +/* Debug log support */
19245 +
19246 +/*
19247 + * Flag to govern whether the debug logs should be parsed in the kernel
19248 + * or reported to the application.
19249 + */
19250 +#ifdef DEBUG
19251 +#define REPORT_DEBUG_LOGS_TO_APP
19252 +#endif
19253 +
19254 +A_STATUS
19255 +ar6000_set_host_app_area(AR_SOFTC_T *ar)
19256 +{
19257 + A_UINT32 address, data;
19258 + struct host_app_area_s host_app_area;
19259 +
19260 + /* Fetch the address of the host_app_area_s instance in the host interest area */
19261 + address = HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest);
19262 + if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != A_OK) {
19263 + return A_ERROR;
19264 + }
19265 + address = data;
19266 + host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
19267 + if (ar6000_WriteDataDiag(ar->arHifDevice, address,
19268 + (A_UCHAR *)&host_app_area,
19269 + sizeof(struct host_app_area_s)) != A_OK)
19270 + {
19271 + return A_ERROR;
19272 + }
19273 +
19274 + return A_OK;
19275 +}
19276 +
19277 +A_UINT32
19278 +dbglog_get_debug_hdr_ptr(AR_SOFTC_T *ar)
19279 +{
19280 + A_UINT32 param;
19281 + A_UINT32 address;
19282 + A_STATUS status;
19283 +
19284 + address = HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr);
19285 + if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address,
19286 + (A_UCHAR *)&param, 4)) != A_OK)
19287 + {
19288 + param = 0;
19289 + }
19290 +
19291 + return param;
19292 +}
19293 +
19294 +/*
19295 + * The dbglog module has been initialized. Its ok to access the relevant
19296 + * data stuctures over the diagnostic window.
19297 + */
19298 +void
19299 +ar6000_dbglog_init_done(AR_SOFTC_T *ar)
19300 +{
19301 + ar->dbglog_init_done = TRUE;
19302 +}
19303 +
19304 +A_UINT32
19305 +dbglog_get_debug_fragment(A_INT8 *datap, A_UINT32 len, A_UINT32 limit)
19306 +{
19307 + A_INT32 *buffer;
19308 + A_UINT32 count;
19309 + A_UINT32 numargs;
19310 + A_UINT32 length;
19311 + A_UINT32 fraglen;
19312 +
19313 + count = fraglen = 0;
19314 + buffer = (A_INT32 *)datap;
19315 + length = (limit >> 2);
19316 +
19317 + if (len <= limit) {
19318 + fraglen = len;
19319 + } else {
19320 + while (count < length) {
19321 + numargs = DBGLOG_GET_NUMARGS(buffer[count]);
19322 + fraglen = (count << 2);
19323 + count += numargs + 1;
19324 + }
19325 + }
19326 +
19327 + return fraglen;
19328 +}
19329 +
19330 +void
19331 +dbglog_parse_debug_logs(A_INT8 *datap, A_UINT32 len)
19332 +{
19333 + A_INT32 *buffer;
19334 + A_UINT32 count;
19335 + A_UINT32 timestamp;
19336 + A_UINT32 debugid;
19337 + A_UINT32 moduleid;
19338 + A_UINT32 numargs;
19339 + A_UINT32 length;
19340 +
19341 + count = 0;
19342 + buffer = (A_INT32 *)datap;
19343 + length = (len >> 2);
19344 + while (count < length) {
19345 + debugid = DBGLOG_GET_DBGID(buffer[count]);
19346 + moduleid = DBGLOG_GET_MODULEID(buffer[count]);
19347 + numargs = DBGLOG_GET_NUMARGS(buffer[count]);
19348 + timestamp = DBGLOG_GET_TIMESTAMP(buffer[count]);
19349 + switch (numargs) {
19350 + case 0:
19351 + AR_DEBUG_PRINTF("%d %d (%d)\n", moduleid, debugid, timestamp);
19352 + break;
19353 +
19354 + case 1:
19355 + AR_DEBUG_PRINTF("%d %d (%d): 0x%x\n", moduleid, debugid,
19356 + timestamp, buffer[count+1]);
19357 + break;
19358 +
19359 + case 2:
19360 + AR_DEBUG_PRINTF("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid,
19361 + timestamp, buffer[count+1], buffer[count+2]);
19362 + break;
19363 +
19364 + default:
19365 + AR_DEBUG_PRINTF("Invalid args: %d\n", numargs);
19366 + }
19367 + count += numargs + 1;
19368 + }
19369 +}
19370 +
19371 +int
19372 +ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
19373 +{
19374 + struct dbglog_hdr_s debug_hdr;
19375 + struct dbglog_buf_s debug_buf;
19376 + A_UINT32 address;
19377 + A_UINT32 length;
19378 + A_UINT32 dropped;
19379 + A_UINT32 firstbuf;
19380 + A_UINT32 debug_hdr_ptr;
19381 +
19382 + if (!ar->dbglog_init_done) return A_ERROR;
19383 +
19384 +#ifndef CONFIG_AR6000_WLAN_DEBUG
19385 + return 0;
19386 +#endif
19387 +
19388 + AR6000_SPIN_LOCK(&ar->arLock, 0);
19389 +
19390 + if (ar->dbgLogFetchInProgress) {
19391 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
19392 + return A_EBUSY;
19393 + }
19394 +
19395 + /* block out others */
19396 + ar->dbgLogFetchInProgress = TRUE;
19397 +
19398 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
19399 +
19400 + debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar);
19401 + printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr);
19402 +
19403 + /* Get the contents of the ring buffer */
19404 + if (debug_hdr_ptr) {
19405 + address = debug_hdr_ptr;
19406 + length = sizeof(struct dbglog_hdr_s);
19407 + ar6000_ReadDataDiag(ar->arHifDevice, address,
19408 + (A_UCHAR *)&debug_hdr, length);
19409 + address = (A_UINT32)debug_hdr.dbuf;
19410 + firstbuf = address;
19411 + dropped = debug_hdr.dropped;
19412 + length = sizeof(struct dbglog_buf_s);
19413 + ar6000_ReadDataDiag(ar->arHifDevice, address,
19414 + (A_UCHAR *)&debug_buf, length);
19415 +
19416 + do {
19417 + address = (A_UINT32)debug_buf.buffer;
19418 + length = debug_buf.length;
19419 + if ((length) && (debug_buf.length <= debug_buf.bufsize)) {
19420 + /* Rewind the index if it is about to overrun the buffer */
19421 + if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) {
19422 + ar->log_cnt = 0;
19423 + }
19424 + if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
19425 + (A_UCHAR *)&ar->log_buffer[ar->log_cnt], length))
19426 + {
19427 + break;
19428 + }
19429 + ar6000_dbglog_event(ar, dropped, &ar->log_buffer[ar->log_cnt], length);
19430 + ar->log_cnt += length;
19431 + } else {
19432 + AR_DEBUG_PRINTF("Length: %d (Total size: %d)\n",
19433 + debug_buf.length, debug_buf.bufsize);
19434 + }
19435 +
19436 + address = (A_UINT32)debug_buf.next;
19437 + length = sizeof(struct dbglog_buf_s);
19438 + if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
19439 + (A_UCHAR *)&debug_buf, length))
19440 + {
19441 + break;
19442 + }
19443 +
19444 + } while (address != firstbuf);
19445 + }
19446 +
19447 + ar->dbgLogFetchInProgress = FALSE;
19448 +
19449 + return A_OK;
19450 +}
19451 +
19452 +void
19453 +ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped,
19454 + A_INT8 *buffer, A_UINT32 length)
19455 +{
19456 +#ifdef REPORT_DEBUG_LOGS_TO_APP
19457 + #define MAX_WIRELESS_EVENT_SIZE 252
19458 + /*
19459 + * Break it up into chunks of MAX_WIRELESS_EVENT_SIZE bytes of messages.
19460 + * There seems to be a limitation on the length of message that could be
19461 + * transmitted to the user app via this mechanism.
19462 + */
19463 + A_UINT32 send, sent;
19464 +
19465 + sent = 0;
19466 + send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
19467 + MAX_WIRELESS_EVENT_SIZE);
19468 + while (send) {
19469 + ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, &buffer[sent], send);
19470 + sent += send;
19471 + send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
19472 + MAX_WIRELESS_EVENT_SIZE);
19473 + }
19474 +#else
19475 + AR_DEBUG_PRINTF("Dropped logs: 0x%x\nDebug info length: %d\n",
19476 + dropped, length);
19477 +
19478 + /* Interpret the debug logs */
19479 + dbglog_parse_debug_logs(buffer, length);
19480 +#endif /* REPORT_DEBUG_LOGS_TO_APP */
19481 +}
19482 +
19483 +
19484 +
19485 +static int __init
19486 +ar6000_init_module(void)
19487 +{
19488 + static int probed = 0;
19489 + A_STATUS status;
19490 + HTC_INIT_INFO initInfo;
19491 +
19492 + A_MEMZERO(&initInfo,sizeof(initInfo));
19493 + initInfo.AddInstance = ar6000_avail_ev;
19494 + initInfo.DeleteInstance = ar6000_unavail_ev;
19495 + initInfo.TargetFailure = ar6000_target_failure;
19496 +
19497 +
19498 +#ifdef DEBUG
19499 + /* Set the debug flags if specified at load time */
19500 + if(debugflags != 0)
19501 + {
19502 + g_dbg_flags = debugflags;
19503 + }
19504 +#endif
19505 +
19506 + if (probed) {
19507 + return -ENODEV;
19508 + }
19509 + probed++;
19510 +
19511 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19512 + memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD));
19513 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19514 +
19515 +#ifdef CONFIG_HOST_GPIO_SUPPORT
19516 + ar6000_gpio_init();
19517 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
19518 +
19519 + status = HTCInit(&initInfo);
19520 + if(status != A_OK)
19521 + return -ENODEV;
19522 +
19523 + return 0;
19524 +}
19525 +
19526 +static void __exit
19527 +ar6000_cleanup_module(void)
19528 +{
19529 + int i = 0;
19530 + struct net_device *ar6000_netdev;
19531 +
19532 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19533 + /* Delete the Adaptive Power Control timer */
19534 + if (timer_pending(&aptcTimer)) {
19535 + del_timer_sync(&aptcTimer);
19536 + }
19537 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19538 +
19539 + for (i=0; i < MAX_AR6000; i++) {
19540 + if (ar6000_devices[i] != NULL) {
19541 + ar6000_netdev = ar6000_devices[i];
19542 + ar6000_devices[i] = NULL;
19543 + ar6000_destroy(ar6000_netdev, 1);
19544 + }
19545 + }
19546 +
19547 + /* shutting down HTC will cause the HIF layer to detach from the
19548 + * underlying bus driver which will cause the subsequent deletion of
19549 + * all HIF and HTC instances */
19550 + HTCShutDown();
19551 +
19552 + AR_DEBUG_PRINTF("ar6000_cleanup: success\n");
19553 +}
19554 +
19555 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19556 +void
19557 +aptcTimerHandler(unsigned long arg)
19558 +{
19559 + A_UINT32 numbytes;
19560 + A_UINT32 throughput;
19561 + AR_SOFTC_T *ar;
19562 + A_STATUS status;
19563 +
19564 + ar = (AR_SOFTC_T *)arg;
19565 + A_ASSERT(ar != NULL);
19566 + A_ASSERT(!timer_pending(&aptcTimer));
19567 +
19568 + AR6000_SPIN_LOCK(&ar->arLock, 0);
19569 +
19570 + /* Get the number of bytes transferred */
19571 + numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
19572 + aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
19573 +
19574 + /* Calculate and decide based on throughput thresholds */
19575 + throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */
19576 + if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) {
19577 + /* Enable Sleep and delete the timer */
19578 + A_ASSERT(ar->arWmiReady == TRUE);
19579 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
19580 + status = wmi_powermode_cmd(ar->arWmi, REC_POWER);
19581 + AR6000_SPIN_LOCK(&ar->arLock, 0);
19582 + A_ASSERT(status == A_OK);
19583 + aptcTR.timerScheduled = FALSE;
19584 + } else {
19585 + A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
19586 + }
19587 +
19588 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
19589 +}
19590 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19591 +
19592 +
19593 +
19594 +/* set HTC block size, assume BMI is already initialized */
19595 +A_STATUS ar6000_SetHTCBlockSize(AR_SOFTC_T *ar)
19596 +{
19597 + A_STATUS status;
19598 + A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX];
19599 +
19600 + do {
19601 + /* get the block sizes */
19602 + status = HIFConfigureDevice(ar->arHifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
19603 + blocksizes, sizeof(blocksizes));
19604 +
19605 + if (A_FAILED(status)) {
19606 + AR_DEBUG_PRINTF("Failed to get block size info from HIF layer...\n");
19607 + break;
19608 + }
19609 + /* note: we actually get the block size for mailbox 1, for SDIO the block
19610 + * size on mailbox 0 is artificially set to 1 */
19611 + /* must be a power of 2 */
19612 + A_ASSERT((blocksizes[1] & (blocksizes[1] - 1)) == 0);
19613 +
19614 + /* set the host interest area for the block size */
19615 + status = BMIWriteMemory(ar->arHifDevice,
19616 + HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_io_block_sz),
19617 + (A_UCHAR *)&blocksizes[1],
19618 + 4);
19619 +
19620 + if (A_FAILED(status)) {
19621 + AR_DEBUG_PRINTF("BMIWriteMemory for IO block size failed \n");
19622 + break;
19623 + }
19624 +
19625 + AR_DEBUG_PRINTF("Block Size Set: %d (target address:0x%X)\n",
19626 + blocksizes[1], HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_io_block_sz));
19627 +
19628 + /* set the host interest area for the mbox ISR yield limit */
19629 + status = BMIWriteMemory(ar->arHifDevice,
19630 + HOST_INTEREST_ITEM_ADDRESS(ar, hi_mbox_isr_yield_limit),
19631 + (A_UCHAR *)&mbox_yield_limit,
19632 + 4);
19633 +
19634 + if (A_FAILED(status)) {
19635 + AR_DEBUG_PRINTF("BMIWriteMemory for yield limit failed \n");
19636 + break;
19637 + }
19638 +
19639 + } while (FALSE);
19640 +
19641 + return status;
19642 +}
19643 +
19644 +static void free_raw_buffers(AR_SOFTC_T *ar)
19645 +{
19646 + int i, j;
19647 +
19648 + for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) {
19649 + for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++)
19650 + kfree(ar->raw_htc_read_buffer[i][j]);
19651 + for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++)
19652 + kfree(ar->raw_htc_write_buffer[i][j]);
19653 + }
19654 +}
19655 +
19656 +static int alloc_raw_buffers(AR_SOFTC_T *ar)
19657 +{
19658 + int i, j;
19659 + raw_htc_buffer *b;
19660 +
19661 + for (i = 0; i != HTC_RAW_STREAM_NUM_MAX; i++) {
19662 + for (j = 0; j != RAW_HTC_READ_BUFFERS_NUM; j++) {
19663 + b = kzalloc(sizeof(*b), GFP_KERNEL);
19664 + if (!b)
19665 + return -ENOMEM;
19666 + ar->raw_htc_read_buffer[i][j] = b;
19667 + }
19668 + for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++) {
19669 + b = kzalloc(sizeof(*b), GFP_KERNEL);
19670 + if (!b)
19671 + return -ENOMEM;
19672 + ar->raw_htc_write_buffer[i][j] = b;
19673 + }
19674 + }
19675 + return 0;
19676 +}
19677 +
19678 +/*
19679 + * HTC Event handlers
19680 + */
19681 +static void
19682 +ar6000_avail_ev(HTC_HANDLE HTCHandle)
19683 +{
19684 + int i;
19685 + struct net_device *dev;
19686 + AR_SOFTC_T *ar;
19687 + int device_index = 0;
19688 +
19689 + AR_DEBUG_PRINTF("ar6000_available\n");
19690 +
19691 + for (i=0; i < MAX_AR6000; i++) {
19692 + if (ar6000_devices[i] == NULL) {
19693 + break;
19694 + }
19695 + }
19696 +
19697 + if (i == MAX_AR6000) {
19698 + AR_DEBUG_PRINTF("ar6000_available: max devices reached\n");
19699 + return;
19700 + }
19701 +
19702 + /* Save this. It gives a bit better readability especially since */
19703 + /* we use another local "i" variable below. */
19704 + device_index = i;
19705 +
19706 + A_ASSERT(HTCHandle != NULL);
19707 +
19708 + dev = alloc_etherdev(sizeof(AR_SOFTC_T));
19709 + if (dev == NULL) {
19710 + AR_DEBUG_PRINTF("ar6000_available: can't alloc etherdev\n");
19711 + return;
19712 + }
19713 +
19714 + ether_setup(dev);
19715 +
19716 + if (netdev_priv(dev) == NULL) {
19717 + printk(KERN_CRIT "ar6000_available: Could not allocate memory\n");
19718 + return;
19719 + }
19720 +
19721 + A_MEMZERO(netdev_priv(dev), sizeof(AR_SOFTC_T));
19722 +
19723 + ar = (AR_SOFTC_T *)netdev_priv(dev);
19724 + ar->arNetDev = dev;
19725 + ar->arHtcTarget = HTCHandle;
19726 + ar->arHifDevice = HTCGetHifDevice(HTCHandle);
19727 + ar->arWlanState = WLAN_ENABLED;
19728 + ar->arRadioSwitch = WLAN_ENABLED;
19729 + ar->arDeviceIndex = device_index;
19730 +
19731 + A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev);
19732 + ar->arHBChallengeResp.seqNum = 0;
19733 + ar->arHBChallengeResp.outstanding = FALSE;
19734 + ar->arHBChallengeResp.missCnt = 0;
19735 + ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT;
19736 + ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT;
19737 +
19738 + ar6000_init_control_info(ar);
19739 + init_waitqueue_head(&arEvent);
19740 + sema_init(&ar->arSem, 1);
19741 +
19742 + if (alloc_raw_buffers(ar)) {
19743 + free_raw_buffers(ar);
19744 + /*
19745 + * @@@ Clean up our own mess, but for anything else, cheerfully mimick
19746 + * the beautiful error non-handling of the rest of this function.
19747 + */
19748 + return;
19749 + }
19750 +
19751 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19752 + A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar);
19753 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19754 +
19755 + /*
19756 + * If requested, perform some magic which requires no cooperation from
19757 + * the Target. It causes the Target to ignore flash and execute to the
19758 + * OS from ROM.
19759 + *
19760 + * This is intended to support recovery from a corrupted flash on Targets
19761 + * that support flash.
19762 + */
19763 + if (skipflash)
19764 + {
19765 + ar6000_reset_device_skipflash(ar->arHifDevice);
19766 + }
19767 +
19768 + BMIInit();
19769 + {
19770 + struct bmi_target_info targ_info;
19771 +
19772 + if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != A_OK) {
19773 + return;
19774 + }
19775 +
19776 + ar->arVersion.target_ver = targ_info.target_ver;
19777 + ar->arTargetType = targ_info.target_type;
19778 + }
19779 +
19780 + if (enableuartprint) {
19781 + A_UINT32 param;
19782 + param = 1;
19783 + if (BMIWriteMemory(ar->arHifDevice,
19784 + HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable),
19785 + (A_UCHAR *)&param,
19786 + 4)!= A_OK)
19787 + {
19788 + AR_DEBUG_PRINTF("BMIWriteMemory for enableuartprint failed \n");
19789 + return ;
19790 + }
19791 + AR_DEBUG_PRINTF("Serial console prints enabled\n");
19792 + }
19793 +#ifdef CONFIG_HOST_TCMD_SUPPORT
19794 + if(testmode) {
19795 + ar->arTargetMode = AR6000_TCMD_MODE;
19796 + }else {
19797 + ar->arTargetMode = AR6000_WLAN_MODE;
19798 + }
19799 +#endif
19800 + if (enabletimerwar) {
19801 + A_UINT32 param;
19802 +
19803 + if (BMIReadMemory(ar->arHifDevice,
19804 + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
19805 + (A_UCHAR *)&param,
19806 + 4)!= A_OK)
19807 + {
19808 + AR_DEBUG_PRINTF("BMIReadMemory for enabletimerwar failed \n");
19809 + return;
19810 + }
19811 +
19812 + param |= HI_OPTION_TIMER_WAR;
19813 +
19814 + if (BMIWriteMemory(ar->arHifDevice,
19815 + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
19816 + (A_UCHAR *)&param,
19817 + 4) != A_OK)
19818 + {
19819 + AR_DEBUG_PRINTF("BMIWriteMemory for enabletimerwar failed \n");
19820 + return;
19821 + }
19822 + AR_DEBUG_PRINTF("Timer WAR enabled\n");
19823 + }
19824 +
19825 +
19826 + /* since BMIInit is called in the driver layer, we have to set the block
19827 + * size here for the target */
19828 +
19829 + if (A_FAILED(ar6000_SetHTCBlockSize(ar))) {
19830 + return;
19831 + }
19832 +
19833 + spin_lock_init(&ar->arLock);
19834 +
19835 + /* Don't install the init function if BMI is requested */
19836 + if(!bmienable)
19837 + {
19838 + dev->init = ar6000_init;
19839 + } else {
19840 + AR_DEBUG_PRINTF(" BMI enabled \n");
19841 + }
19842 +
19843 + dev->open = &ar6000_open;
19844 + dev->stop = &ar6000_close;
19845 + dev->hard_start_xmit = &ar6000_data_tx;
19846 + dev->get_stats = &ar6000_get_stats;
19847 +
19848 + /* dev->tx_timeout = ar6000_tx_timeout; */
19849 + dev->do_ioctl = &ar6000_ioctl;
19850 + dev->watchdog_timeo = AR6000_TX_TIMEOUT;
19851 + ar6000_ioctl_iwsetup(&ath_iw_handler_def);
19852 + dev->wireless_handlers = &ath_iw_handler_def;
19853 + ath_iw_handler_def.get_wireless_stats = ar6000_get_iwstats; /*Displayed via proc fs */
19854 +
19855 + /*
19856 + * We need the OS to provide us with more headroom in order to
19857 + * perform dix to 802.3, WMI header encap, and the HTC header
19858 + */
19859 + dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) +
19860 + sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN;
19861 +
19862 + /* This runs the init function */
19863 + SET_NETDEV_DEV(dev, HIFGetOSDevice(ar->arHifDevice));
19864 + if (register_netdev(dev)) {
19865 + AR_DEBUG_PRINTF("ar6000_avail: register_netdev failed\n");
19866 + ar6000_destroy(dev, 0);
19867 + return;
19868 + }
19869 +
19870 + HTCSetInstance(ar->arHtcTarget, ar);
19871 +
19872 + /* We only register the device in the global list if we succeed. */
19873 + /* If the device is in the global list, it will be destroyed */
19874 + /* when the module is unloaded. */
19875 + ar6000_devices[device_index] = dev;
19876 +
19877 + AR_DEBUG_PRINTF("ar6000_avail: name=%s htcTarget=0x%x, dev=0x%x (%d), ar=0x%x\n",
19878 + dev->name, (A_UINT32)HTCHandle, (A_UINT32)dev, device_index,
19879 + (A_UINT32)ar);
19880 +}
19881 +
19882 +static void ar6000_target_failure(void *Instance, A_STATUS Status)
19883 +{
19884 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
19885 + WMI_TARGET_ERROR_REPORT_EVENT errEvent;
19886 + static A_BOOL sip = FALSE;
19887 +
19888 + if (Status != A_OK) {
19889 + if (timer_pending(&ar->arHBChallengeResp.timer)) {
19890 + A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
19891 + }
19892 +
19893 + /* try dumping target assertion information (if any) */
19894 + ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType);
19895 +
19896 + /*
19897 + * Fetch the logs from the target via the diagnostic
19898 + * window.
19899 + */
19900 + ar6000_dbglog_get_debug_logs(ar);
19901 +
19902 + /* Report the error only once */
19903 + if (!sip) {
19904 + sip = TRUE;
19905 + errEvent.errorVal = WMI_TARGET_COM_ERR |
19906 + WMI_TARGET_FATAL_ERR;
19907 +#ifdef SEND_EVENT_TO_APP
19908 + ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
19909 + (A_UINT8 *)&errEvent,
19910 + sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
19911 +#endif
19912 + }
19913 + }
19914 +}
19915 +
19916 +static void
19917 +ar6000_unavail_ev(void *Instance)
19918 +{
19919 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
19920 + /* NULL out it's entry in the global list */
19921 + ar6000_devices[ar->arDeviceIndex] = NULL;
19922 + ar6000_destroy(ar->arNetDev, 1);
19923 +}
19924 +
19925 +/*
19926 + * We need to differentiate between the surprise and planned removal of the
19927 + * device because of the following consideration:
19928 + * - In case of surprise removal, the hcd already frees up the pending
19929 + * for the device and hence there is no need to unregister the function
19930 + * driver inorder to get these requests. For planned removal, the function
19931 + * driver has to explictly unregister itself to have the hcd return all the
19932 + * pending requests before the data structures for the devices are freed up.
19933 + * Note that as per the current implementation, the function driver will
19934 + * end up releasing all the devices since there is no API to selectively
19935 + * release a particular device.
19936 + * - Certain commands issued to the target can be skipped for surprise
19937 + * removal since they will anyway not go through.
19938 + */
19939 +static void
19940 +ar6000_destroy(struct net_device *dev, unsigned int unregister)
19941 +{
19942 + AR_SOFTC_T *ar;
19943 +
19944 + AR_DEBUG_PRINTF("+ar6000_destroy \n");
19945 +
19946 + if((dev == NULL) || ((ar = netdev_priv(dev)) == NULL))
19947 + {
19948 + AR_DEBUG_PRINTF("%s(): Failed to get device structure.\n", __func__);
19949 + return;
19950 + }
19951 +
19952 + /* Clear the tx counters */
19953 + memset(tx_attempt, 0, sizeof(tx_attempt));
19954 + memset(tx_post, 0, sizeof(tx_post));
19955 + memset(tx_complete, 0, sizeof(tx_complete));
19956 +
19957 + /* Free up the device data structure */
19958 + if (unregister) {
19959 + unregister_netdev(dev);
19960 + } else {
19961 + ar6000_close(dev);
19962 + }
19963 +
19964 + free_raw_buffers(ar);
19965 +
19966 +#ifndef free_netdev
19967 + kfree(dev);
19968 +#else
19969 + free_netdev(dev);
19970 +#endif
19971 +
19972 + AR_DEBUG_PRINTF("-ar6000_destroy \n");
19973 +}
19974 +
19975 +static void ar6000_detect_error(unsigned long ptr)
19976 +{
19977 + struct net_device *dev = (struct net_device *)ptr;
19978 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
19979 + WMI_TARGET_ERROR_REPORT_EVENT errEvent;
19980 +
19981 + AR6000_SPIN_LOCK(&ar->arLock, 0);
19982 +
19983 + if (ar->arHBChallengeResp.outstanding) {
19984 + ar->arHBChallengeResp.missCnt++;
19985 + } else {
19986 + ar->arHBChallengeResp.missCnt = 0;
19987 + }
19988 +
19989 + if (ar->arHBChallengeResp.missCnt > ar->arHBChallengeResp.missThres) {
19990 + /* Send Error Detect event to the application layer and do not reschedule the error detection module timer */
19991 + ar->arHBChallengeResp.missCnt = 0;
19992 + ar->arHBChallengeResp.seqNum = 0;
19993 + errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR;
19994 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
19995 +#ifdef SEND_EVENT_TO_APP
19996 + ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
19997 + (A_UINT8 *)&errEvent,
19998 + sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
19999 +#endif
20000 + return;
20001 + }
20002 +
20003 + /* Generate the sequence number for the next challenge */
20004 + ar->arHBChallengeResp.seqNum++;
20005 + ar->arHBChallengeResp.outstanding = TRUE;
20006 +
20007 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20008 +
20009 + /* Send the challenge on the control channel */
20010 + if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != A_OK) {
20011 + AR_DEBUG_PRINTF("Unable to send heart beat challenge\n");
20012 + }
20013 +
20014 +
20015 + /* Reschedule the timer for the next challenge */
20016 + A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
20017 +}
20018 +
20019 +void ar6000_init_profile_info(AR_SOFTC_T *ar)
20020 +{
20021 + ar->arSsidLen = 0;
20022 + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
20023 + ar->arNetworkType = INFRA_NETWORK;
20024 + ar->arDot11AuthMode = OPEN_AUTH;
20025 + ar->arAuthMode = NONE_AUTH;
20026 + ar->arPairwiseCrypto = NONE_CRYPT;
20027 + ar->arPairwiseCryptoLen = 0;
20028 + ar->arGroupCrypto = NONE_CRYPT;
20029 + ar->arGroupCryptoLen = 0;
20030 + A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
20031 + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
20032 + A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
20033 + ar->arBssChannel = 0;
20034 +}
20035 +
20036 +static void
20037 +ar6000_init_control_info(AR_SOFTC_T *ar)
20038 +{
20039 + ar->arWmiEnabled = FALSE;
20040 + ar6000_init_profile_info(ar);
20041 + ar->arDefTxKeyIndex = 0;
20042 + A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
20043 + ar->arChannelHint = 0;
20044 + ar->arListenInterval = MAX_LISTEN_INTERVAL;
20045 + ar->arVersion.host_ver = AR6K_SW_VERSION;
20046 + ar->arRssi = 0;
20047 + ar->arTxPwr = 0;
20048 + ar->arTxPwrSet = FALSE;
20049 + ar->arSkipScan = 0;
20050 + ar->arBeaconInterval = 0;
20051 + ar->arBitRate = 0;
20052 + ar->arMaxRetries = 0;
20053 + ar->arWmmEnabled = TRUE;
20054 +}
20055 +
20056 +static int
20057 +ar6000_open(struct net_device *dev)
20058 +{
20059 + /* Wake up the queues */
20060 + netif_start_queue(dev);
20061 +
20062 + return 0;
20063 +}
20064 +
20065 +static int
20066 +ar6000_close(struct net_device *dev)
20067 +{
20068 + AR_SOFTC_T *ar = netdev_priv(dev);
20069 +
20070 + /* Stop the transmit queues */
20071 + netif_stop_queue(dev);
20072 +
20073 + /* Disable the target and the interrupts associated with it */
20074 + if (ar->arWmiReady == TRUE)
20075 + {
20076 + if (!bypasswmi)
20077 + {
20078 + if (ar->arConnected == TRUE || ar->arConnectPending == TRUE)
20079 + {
20080 + AR_DEBUG_PRINTF("%s(): Disconnect\n", __func__);
20081 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20082 + ar6000_init_profile_info(ar);
20083 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20084 + wmi_disconnect_cmd(ar->arWmi);
20085 + }
20086 +
20087 + ar6000_dbglog_get_debug_logs(ar);
20088 + ar->arWmiReady = FALSE;
20089 + ar->arConnected = FALSE;
20090 + ar->arConnectPending = FALSE;
20091 + wmi_shutdown(ar->arWmi);
20092 + ar->arWmiEnabled = FALSE;
20093 + ar->arWmi = NULL;
20094 + ar->arWlanState = WLAN_ENABLED;
20095 +#ifdef USER_KEYS
20096 + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
20097 + ar->user_key_ctrl = 0;
20098 +#endif
20099 + }
20100 +
20101 + AR_DEBUG_PRINTF("%s(): WMI stopped\n", __func__);
20102 + }
20103 + else
20104 + {
20105 + AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n",
20106 + __func__, (unsigned int) ar, (unsigned int) ar->arWmi);
20107 +
20108 + /* Shut down WMI if we have started it */
20109 + if(ar->arWmiEnabled == TRUE)
20110 + {
20111 + AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__);
20112 + wmi_shutdown(ar->arWmi);
20113 + ar->arWmiEnabled = FALSE;
20114 + ar->arWmi = NULL;
20115 + }
20116 + }
20117 +
20118 + /* stop HTC */
20119 + HTCStop(ar->arHtcTarget);
20120 +
20121 + /* set the instance to NULL so we do not get called back on remove incase we
20122 + * we're explicity destroyed by module unload */
20123 + HTCSetInstance(ar->arHtcTarget, NULL);
20124 +
20125 + if (resetok) {
20126 + /* try to reset the device if we can
20127 + * The driver may have been configure NOT to reset the target during
20128 + * a debug session */
20129 + AR_DEBUG_PRINTF(" Attempting to reset target on instance destroy.... \n");
20130 + ar6000_reset_device(ar->arHifDevice, ar->arTargetType);
20131 + } else {
20132 + AR_DEBUG_PRINTF(" Host does not want target reset. \n");
20133 + }
20134 +
20135 + /* Done with cookies */
20136 + ar6000_cookie_cleanup(ar);
20137 +
20138 + /* Cleanup BMI */
20139 + BMIInit();
20140 +
20141 + return 0;
20142 +}
20143 +
20144 +/* connect to a service */
20145 +static A_STATUS ar6000_connectservice(AR_SOFTC_T *ar,
20146 + HTC_SERVICE_CONNECT_REQ *pConnect,
20147 + WMI_PRI_STREAM_ID WmiStreamID,
20148 + char *pDesc)
20149 +{
20150 + A_STATUS status;
20151 + HTC_SERVICE_CONNECT_RESP response;
20152 +
20153 + do {
20154 +
20155 + A_MEMZERO(&response,sizeof(response));
20156 +
20157 + status = HTCConnectService(ar->arHtcTarget,
20158 + pConnect,
20159 + &response);
20160 +
20161 + if (A_FAILED(status)) {
20162 + AR_DEBUG_PRINTF(" Failed to connect to %s service status:%d \n", pDesc, status);
20163 + break;
20164 + }
20165 +
20166 + if (WmiStreamID == WMI_NOT_MAPPED) {
20167 + /* done */
20168 + break;
20169 + }
20170 +
20171 + /* set endpoint mapping for the WMI stream in the driver layer */
20172 + arSetWMIStream2EndpointIDMap(ar,WmiStreamID,response.Endpoint);
20173 +
20174 + } while (FALSE);
20175 +
20176 + return status;
20177 +}
20178 +
20179 +static void ar6000_TxDataCleanup(AR_SOFTC_T *ar)
20180 +{
20181 + /* flush all the data (non-control) streams
20182 + * we only flush packets that are tagged as data, we leave any control packets that
20183 + * were in the TX queues alone */
20184 + HTCFlushEndpoint(ar->arHtcTarget,
20185 + arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI),
20186 + AR6K_DATA_PKT_TAG);
20187 + HTCFlushEndpoint(ar->arHtcTarget,
20188 + arWMIStream2EndpointID(ar,WMI_LOW_PRI),
20189 + AR6K_DATA_PKT_TAG);
20190 + HTCFlushEndpoint(ar->arHtcTarget,
20191 + arWMIStream2EndpointID(ar,WMI_HIGH_PRI),
20192 + AR6K_DATA_PKT_TAG);
20193 + HTCFlushEndpoint(ar->arHtcTarget,
20194 + arWMIStream2EndpointID(ar,WMI_HIGHEST_PRI),
20195 + AR6K_DATA_PKT_TAG);
20196 +}
20197 +
20198 +/* This function does one time initialization for the lifetime of the device */
20199 +int ar6000_init(struct net_device *dev)
20200 +{
20201 + AR_SOFTC_T *ar;
20202 + A_STATUS status;
20203 + A_INT32 timeleft;
20204 +
20205 + if((ar = netdev_priv(dev)) == NULL)
20206 + {
20207 + return(-EIO);
20208 + }
20209 +
20210 + /* Do we need to finish the BMI phase */
20211 + if(BMIDone(ar->arHifDevice) != A_OK)
20212 + {
20213 + return -EIO;
20214 + }
20215 +
20216 + if (!bypasswmi)
20217 + {
20218 +#if 0 /* TBDXXX */
20219 + if (ar->arVersion.host_ver != ar->arVersion.target_ver) {
20220 + A_PRINTF("WARNING: Host version 0x%x does not match Target "
20221 + " version 0x%x!\n",
20222 + ar->arVersion.host_ver, ar->arVersion.target_ver);
20223 + }
20224 +#endif
20225 +
20226 + /* Indicate that WMI is enabled (although not ready yet) */
20227 + ar->arWmiEnabled = TRUE;
20228 + if ((ar->arWmi = wmi_init((void *) ar)) == NULL)
20229 + {
20230 + AR_DEBUG_PRINTF("%s() Failed to initialize WMI.\n", __func__);
20231 + return(-EIO);
20232 + }
20233 +
20234 + AR_DEBUG_PRINTF("%s() Got WMI @ 0x%08x.\n", __func__,
20235 + (unsigned int) ar->arWmi);
20236 + }
20237 +
20238 + do {
20239 + HTC_SERVICE_CONNECT_REQ connect;
20240 +
20241 + /* the reason we have to wait for the target here is that the driver layer
20242 + * has to init BMI in order to set the host block size,
20243 + */
20244 + status = HTCWaitTarget(ar->arHtcTarget);
20245 +
20246 + if (A_FAILED(status)) {
20247 + break;
20248 + }
20249 +
20250 + A_MEMZERO(&connect,sizeof(connect));
20251 + /* meta data is unused for now */
20252 + connect.pMetaData = NULL;
20253 + connect.MetaDataLength = 0;
20254 + /* these fields are the same for all service endpoints */
20255 + connect.EpCallbacks.pContext = ar;
20256 + connect.EpCallbacks.EpTxComplete = ar6000_tx_complete;
20257 + connect.EpCallbacks.EpRecv = ar6000_rx;
20258 + connect.EpCallbacks.EpRecvRefill = ar6000_rx_refill;
20259 + connect.EpCallbacks.EpSendFull = ar6000_tx_queue_full;
20260 + connect.EpCallbacks.EpSendAvail = ar6000_tx_queue_avail;
20261 + /* set the max queue depth so that our ar6000_tx_queue_full handler gets called.
20262 + * Linux has the peculiarity of not providing flow control between the
20263 + * NIC and the network stack. There is no API to indicate that a TX packet
20264 + * was sent which could provide some back pressure to the network stack.
20265 + * Under linux you would have to wait till the network stack consumed all sk_buffs
20266 + * before any back-flow kicked in. Which isn't very friendly.
20267 + * So we have to manage this ourselves */
20268 + connect.MaxSendQueueDepth = 32;
20269 +
20270 + /* connect to control service */
20271 + connect.ServiceID = WMI_CONTROL_SVC;
20272 + status = ar6000_connectservice(ar,
20273 + &connect,
20274 + WMI_CONTROL_PRI,
20275 + "WMI CONTROL");
20276 + if (A_FAILED(status)) {
20277 + break;
20278 + }
20279 +
20280 + /* for the remaining data services set the connection flag to reduce dribbling,
20281 + * if configured to do so */
20282 + if (reduce_credit_dribble) {
20283 + connect.ConnectionFlags |= HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE;
20284 + /* the credit dribble trigger threshold is (reduce_credit_dribble - 1) for a value
20285 + * of 0-3 */
20286 + connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
20287 + connect.ConnectionFlags |=
20288 + ((A_UINT16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
20289 + }
20290 + /* connect to best-effort service */
20291 + connect.ServiceID = WMI_DATA_BE_SVC;
20292 +
20293 + status = ar6000_connectservice(ar,
20294 + &connect,
20295 + WMI_BEST_EFFORT_PRI,
20296 + "WMI DATA BE");
20297 + if (A_FAILED(status)) {
20298 + break;
20299 + }
20300 +
20301 + /* connect to back-ground
20302 + * map this to WMI LOW_PRI */
20303 + connect.ServiceID = WMI_DATA_BK_SVC;
20304 + status = ar6000_connectservice(ar,
20305 + &connect,
20306 + WMI_LOW_PRI,
20307 + "WMI DATA BK");
20308 + if (A_FAILED(status)) {
20309 + break;
20310 + }
20311 +
20312 + /* connect to Video service, map this to
20313 + * to HI PRI */
20314 + connect.ServiceID = WMI_DATA_VI_SVC;
20315 + status = ar6000_connectservice(ar,
20316 + &connect,
20317 + WMI_HIGH_PRI,
20318 + "WMI DATA VI");
20319 + if (A_FAILED(status)) {
20320 + break;
20321 + }
20322 +
20323 + /* connect to VO service, this is currently not
20324 + * mapped to a WMI priority stream due to historical reasons.
20325 + * WMI originally defined 3 priorities over 3 mailboxes
20326 + * We can change this when WMI is reworked so that priorities are not
20327 + * dependent on mailboxes */
20328 + connect.ServiceID = WMI_DATA_VO_SVC;
20329 + status = ar6000_connectservice(ar,
20330 + &connect,
20331 + WMI_HIGHEST_PRI,
20332 + "WMI DATA VO");
20333 + if (A_FAILED(status)) {
20334 + break;
20335 + }
20336 +
20337 + A_ASSERT(arWMIStream2EndpointID(ar,WMI_CONTROL_PRI) != 0);
20338 + A_ASSERT(arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI) != 0);
20339 + A_ASSERT(arWMIStream2EndpointID(ar,WMI_LOW_PRI) != 0);
20340 + A_ASSERT(arWMIStream2EndpointID(ar,WMI_HIGH_PRI) != 0);
20341 + A_ASSERT(arWMIStream2EndpointID(ar,WMI_HIGHEST_PRI) != 0);
20342 + } while (FALSE);
20343 +
20344 + if (A_FAILED(status)) {
20345 + return (-EIO);
20346 + }
20347 +
20348 + /*
20349 + * give our connected endpoints some buffers
20350 + */
20351 + ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_CONTROL_PRI));
20352 +
20353 + ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI));
20354 +
20355 + /*
20356 + * We will post the receive buffers only for SPE testing and so we are
20357 + * making it conditional on the 'bypasswmi' flag.
20358 + */
20359 + if (bypasswmi) {
20360 + ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_LOW_PRI));
20361 + ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_HIGH_PRI));
20362 + }
20363 +
20364 + /* setup credit distribution */
20365 + ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo);
20366 +
20367 + /* Since cookies are used for HTC transports, they should be */
20368 + /* initialized prior to enabling HTC. */
20369 + ar6000_cookie_init(ar);
20370 +
20371 + /* start HTC */
20372 + status = HTCStart(ar->arHtcTarget);
20373 +
20374 + if (status != A_OK) {
20375 + if (ar->arWmiEnabled == TRUE) {
20376 + wmi_shutdown(ar->arWmi);
20377 + ar->arWmiEnabled = FALSE;
20378 + ar->arWmi = NULL;
20379 + }
20380 + ar6000_cookie_cleanup(ar);
20381 + return -EIO;
20382 + }
20383 +
20384 + if (!bypasswmi) {
20385 + /* Wait for Wmi event to be ready */
20386 + timeleft = wait_event_interruptible_timeout(arEvent,
20387 + (ar->arWmiReady == TRUE), wmitimeout * HZ);
20388 +
20389 + if(!timeleft || signal_pending(current))
20390 + {
20391 + AR_DEBUG_PRINTF("WMI is not ready or wait was interrupted\n");
20392 +#if defined(DWSIM) /* TBDXXX */
20393 + AR_DEBUG_PRINTF(".....but proceed anyway.\n");
20394 +#else
20395 + return -EIO;
20396 +#endif
20397 + }
20398 +
20399 + AR_DEBUG_PRINTF("%s() WMI is ready\n", __func__);
20400 +
20401 + /* Communicate the wmi protocol verision to the target */
20402 + if ((ar6000_set_host_app_area(ar)) != A_OK) {
20403 + AR_DEBUG_PRINTF("Unable to set the host app area\n");
20404 + }
20405 + }
20406 +
20407 + ar->arNumDataEndPts = 1;
20408 +
20409 + return(0);
20410 +}
20411 +
20412 +
20413 +void
20414 +ar6000_bitrate_rx(void *devt, A_INT32 rateKbps)
20415 +{
20416 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
20417 +
20418 + ar->arBitRate = rateKbps;
20419 + wake_up(&arEvent);
20420 +}
20421 +
20422 +void
20423 +ar6000_ratemask_rx(void *devt, A_UINT16 ratemask)
20424 +{
20425 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
20426 +
20427 + ar->arRateMask = ratemask;
20428 + wake_up(&arEvent);
20429 +}
20430 +
20431 +void
20432 +ar6000_txPwr_rx(void *devt, A_UINT8 txPwr)
20433 +{
20434 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
20435 +
20436 + ar->arTxPwr = txPwr;
20437 + wake_up(&arEvent);
20438 +}
20439 +
20440 +
20441 +void
20442 +ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList)
20443 +{
20444 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
20445 +
20446 + A_MEMCPY(ar->arChannelList, chanList, numChan * sizeof (A_UINT16));
20447 + ar->arNumChannels = numChan;
20448 +
20449 + wake_up(&arEvent);
20450 +}
20451 +
20452 +A_UINT8
20453 +ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, A_UINT32 * mapNo)
20454 +{
20455 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
20456 + A_UINT8 *datap;
20457 + ATH_MAC_HDR *macHdr;
20458 + A_UINT32 i, eptMap;
20459 +
20460 + (*mapNo) = 0;
20461 + datap = A_NETBUF_DATA(skb);
20462 + macHdr = (ATH_MAC_HDR *)(datap + sizeof(WMI_DATA_HDR));
20463 + if (IEEE80211_IS_MULTICAST(macHdr->dstMac)) {
20464 + return ENDPOINT_2;
20465 + }
20466 +
20467 + eptMap = -1;
20468 + for (i = 0; i < ar->arNodeNum; i ++) {
20469 + if (IEEE80211_ADDR_EQ(macHdr->dstMac, ar->arNodeMap[i].macAddress)) {
20470 + (*mapNo) = i + 1;
20471 + ar->arNodeMap[i].txPending ++;
20472 + return ar->arNodeMap[i].epId;
20473 + }
20474 +
20475 + if ((eptMap == -1) && !ar->arNodeMap[i].txPending) {
20476 + eptMap = i;
20477 + }
20478 + }
20479 +
20480 + if (eptMap == -1) {
20481 + eptMap = ar->arNodeNum;
20482 + ar->arNodeNum ++;
20483 + A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM);
20484 + }
20485 +
20486 + A_MEMCPY(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN);
20487 +
20488 + for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) {
20489 + if (!ar->arTxPending[i]) {
20490 + ar->arNodeMap[eptMap].epId = i;
20491 + break;
20492 + }
20493 + // No free endpoint is available, start redistribution on the inuse endpoints.
20494 + if (i == ENDPOINT_5) {
20495 + ar->arNodeMap[eptMap].epId = ar->arNexEpId;
20496 + ar->arNexEpId ++;
20497 + if (ar->arNexEpId > ENDPOINT_5) {
20498 + ar->arNexEpId = ENDPOINT_2;
20499 + }
20500 + }
20501 + }
20502 +
20503 + (*mapNo) = eptMap + 1;
20504 + ar->arNodeMap[eptMap].txPending ++;
20505 +
20506 + return ar->arNodeMap[eptMap].epId;
20507 +}
20508 +
20509 +#ifdef DEBUG
20510 +static void ar6000_dump_skb(struct sk_buff *skb)
20511 +{
20512 + u_char *ch;
20513 + for (ch = A_NETBUF_DATA(skb);
20514 + (A_UINT32)ch < ((A_UINT32)A_NETBUF_DATA(skb) +
20515 + A_NETBUF_LEN(skb)); ch++)
20516 + {
20517 + AR_DEBUG_PRINTF("%2.2x ", *ch);
20518 + }
20519 + AR_DEBUG_PRINTF("\n");
20520 +}
20521 +#endif
20522 +
20523 +static int
20524 +ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
20525 +{
20526 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
20527 + WMI_PRI_STREAM_ID streamID = WMI_NOT_MAPPED;
20528 + A_UINT32 mapNo = 0;
20529 + int len;
20530 + struct ar_cookie *cookie;
20531 + A_BOOL checkAdHocPsMapping = FALSE;
20532 +
20533 +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
20534 + skb->list = NULL;
20535 +#endif
20536 +
20537 + AR_DEBUG2_PRINTF("ar6000_data_tx start - skb=0x%x, data=0x%x, len=0x%x\n",
20538 + (A_UINT32)skb, (A_UINT32)A_NETBUF_DATA(skb),
20539 + A_NETBUF_LEN(skb));
20540 +#ifdef CONFIG_HOST_TCMD_SUPPORT
20541 + /* TCMD doesnt support any data, free the buf and return */
20542 + if(ar->arTargetMode == AR6000_TCMD_MODE) {
20543 + A_NETBUF_FREE(skb);
20544 + return 0;
20545 + }
20546 +#endif
20547 + do {
20548 +
20549 + if (ar->arWmiReady == FALSE && bypasswmi == 0) {
20550 + break;
20551 + }
20552 +
20553 +#ifdef BLOCK_TX_PATH_FLAG
20554 + if (blocktx) {
20555 + break;
20556 + }
20557 +#endif /* BLOCK_TX_PATH_FLAG */
20558 +
20559 + if (ar->arWmiEnabled) {
20560 + if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len) {
20561 + struct sk_buff *newbuf;
20562 + /*
20563 + * We really should have gotten enough headroom but sometimes
20564 + * we still get packets with not enough headroom. Copy the packet.
20565 + */
20566 + len = A_NETBUF_LEN(skb);
20567 + newbuf = A_NETBUF_ALLOC(len);
20568 + if (newbuf == NULL) {
20569 + break;
20570 + }
20571 + A_NETBUF_PUT(newbuf, len);
20572 + A_MEMCPY(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len);
20573 + A_NETBUF_FREE(skb);
20574 + skb = newbuf;
20575 + /* fall through and assemble header */
20576 + }
20577 +
20578 + if (wmi_dix_2_dot3(ar->arWmi, skb) != A_OK) {
20579 + AR_DEBUG_PRINTF("ar6000_data_tx - wmi_dix_2_dot3 failed\n");
20580 + break;
20581 + }
20582 +
20583 + if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE) != A_OK) {
20584 + AR_DEBUG_PRINTF("ar6000_data_tx - wmi_data_hdr_add failed\n");
20585 + break;
20586 + }
20587 +
20588 + if ((ar->arNetworkType == ADHOC_NETWORK) &&
20589 + ar->arIbssPsEnable && ar->arConnected) {
20590 + /* flag to check adhoc mapping once we take the lock below: */
20591 + checkAdHocPsMapping = TRUE;
20592 +
20593 + } else {
20594 + /* get the stream mapping */
20595 + if (ar->arWmmEnabled) {
20596 + streamID = wmi_get_stream_id(ar->arWmi,
20597 + wmi_implicit_create_pstream(ar->arWmi, skb, UPLINK_TRAFFIC, UNDEFINED_PRI));
20598 + } else {
20599 + streamID = WMI_BEST_EFFORT_PRI;
20600 + }
20601 + }
20602 +
20603 + } else {
20604 + struct iphdr *ipHdr;
20605 + /*
20606 + * the endpoint is directly based on the TOS field in the IP
20607 + * header **** only for testing ******
20608 + */
20609 + ipHdr = A_NETBUF_DATA(skb) + sizeof(ATH_MAC_HDR);
20610 + /* here we map the TOS field to an endpoint number, this is for
20611 + * the endpointping test application */
20612 + streamID = IP_TOS_TO_WMI_PRI(ipHdr->tos);
20613 + }
20614 +
20615 + } while (FALSE);
20616 +
20617 + /* did we succeed ? */
20618 + if ((streamID == WMI_NOT_MAPPED) && !checkAdHocPsMapping) {
20619 + /* cleanup and exit */
20620 + A_NETBUF_FREE(skb);
20621 + AR6000_STAT_INC(ar, tx_dropped);
20622 + AR6000_STAT_INC(ar, tx_aborted_errors);
20623 + return 0;
20624 + }
20625 +
20626 + cookie = NULL;
20627 +
20628 + /* take the lock to protect driver data */
20629 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20630 +
20631 + do {
20632 +
20633 + if (checkAdHocPsMapping) {
20634 + streamID = ar6000_ibss_map_epid(skb, dev, &mapNo);
20635 + }
20636 +
20637 + A_ASSERT(streamID != WMI_NOT_MAPPED);
20638 +
20639 + /* validate that the endpoint is connected */
20640 + if (arWMIStream2EndpointID(ar,streamID) == 0) {
20641 + AR_DEBUG_PRINTF("Stream %d is NOT mapped!\n",streamID);
20642 + break;
20643 + }
20644 + /* allocate resource for this packet */
20645 + cookie = ar6000_alloc_cookie(ar);
20646 +
20647 + if (cookie != NULL) {
20648 + /* update counts while the lock is held */
20649 + ar->arTxPending[streamID]++;
20650 + ar->arTotalTxDataPending++;
20651 + }
20652 +
20653 + } while (FALSE);
20654 +
20655 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20656 +
20657 + if (cookie != NULL) {
20658 + cookie->arc_bp[0] = (A_UINT32)skb;
20659 + cookie->arc_bp[1] = mapNo;
20660 + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
20661 + cookie,
20662 + A_NETBUF_DATA(skb),
20663 + A_NETBUF_LEN(skb),
20664 + arWMIStream2EndpointID(ar,streamID),
20665 + AR6K_DATA_PKT_TAG);
20666 +
20667 +#ifdef DEBUG
20668 + if (debugdriver >= 3) {
20669 + ar6000_dump_skb(skb);
20670 + }
20671 +#endif
20672 + /* HTC interface is asynchronous, if this fails, cleanup will happen in
20673 + * the ar6000_tx_complete callback */
20674 + HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
20675 + } else {
20676 + /* no packet to send, cleanup */
20677 + A_NETBUF_FREE(skb);
20678 + AR6000_STAT_INC(ar, tx_dropped);
20679 + AR6000_STAT_INC(ar, tx_aborted_errors);
20680 + }
20681 +
20682 + return 0;
20683 +}
20684 +
20685 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
20686 +static void
20687 +tvsub(register struct timeval *out, register struct timeval *in)
20688 +{
20689 + if((out->tv_usec -= in->tv_usec) < 0) {
20690 + out->tv_sec--;
20691 + out->tv_usec += 1000000;
20692 + }
20693 + out->tv_sec -= in->tv_sec;
20694 +}
20695 +
20696 +void
20697 +applyAPTCHeuristics(AR_SOFTC_T *ar)
20698 +{
20699 + A_UINT32 duration;
20700 + A_UINT32 numbytes;
20701 + A_UINT32 throughput;
20702 + struct timeval ts;
20703 + A_STATUS status;
20704 +
20705 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20706 +
20707 + if ((enableAPTCHeuristics) && (!aptcTR.timerScheduled)) {
20708 + do_gettimeofday(&ts);
20709 + tvsub(&ts, &aptcTR.samplingTS);
20710 + duration = ts.tv_sec * 1000 + ts.tv_usec / 1000; /* ms */
20711 + numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
20712 +
20713 + if (duration > APTC_TRAFFIC_SAMPLING_INTERVAL) {
20714 + /* Initialize the time stamp and byte count */
20715 + aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
20716 + do_gettimeofday(&aptcTR.samplingTS);
20717 +
20718 + /* Calculate and decide based on throughput thresholds */
20719 + throughput = ((numbytes * 8) / duration);
20720 + if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) {
20721 + /* Disable Sleep and schedule a timer */
20722 + A_ASSERT(ar->arWmiReady == TRUE);
20723 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20724 + status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER);
20725 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20726 + A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
20727 + aptcTR.timerScheduled = TRUE;
20728 + }
20729 + }
20730 + }
20731 +
20732 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20733 +}
20734 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
20735 +
20736 +static void
20737 +ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint)
20738 +{
20739 + AR_SOFTC_T *ar = (AR_SOFTC_T *) Context;
20740 +
20741 + if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) {
20742 + if (!bypasswmi) {
20743 + /* under normal WMI if this is getting full, then something is running rampant
20744 + * the host should not be exhausting the WMI queue with too many commands
20745 + * the only exception to this is during testing using endpointping */
20746 +
20747 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20748 + /* set flag to handle subsequent messages */
20749 + ar->arWMIControlEpFull = TRUE;
20750 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20751 + AR_DEBUG_PRINTF("WMI Control Endpoint is FULL!!! \n");
20752 + }
20753 + } else {
20754 + /* one of the data endpoints queues is getting full..need to stop network stack
20755 + * the queue will resume after credits received */
20756 + netif_stop_queue(ar->arNetDev);
20757 + }
20758 +}
20759 +
20760 +static void
20761 +ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint)
20762 +{
20763 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
20764 +
20765 + if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) {
20766 + /* FIXME: what do for it? */
20767 + } else {
20768 + /* Wake up interface, rescheduling prevented. */
20769 + if (ar->arConnected == TRUE || bypasswmi)
20770 + netif_wake_queue(ar->arNetDev);
20771 + }
20772 +}
20773 +
20774 +static void
20775 +ar6000_tx_complete(void *Context, HTC_PACKET *pPacket)
20776 +{
20777 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
20778 + void *cookie = (void *)pPacket->pPktContext;
20779 + struct sk_buff *skb = NULL;
20780 + A_UINT32 mapNo = 0;
20781 + A_STATUS status;
20782 + struct ar_cookie * ar_cookie;
20783 + WMI_PRI_STREAM_ID streamID;
20784 + A_BOOL wakeEvent = FALSE;
20785 +
20786 + status = pPacket->Status;
20787 + ar_cookie = (struct ar_cookie *)cookie;
20788 + skb = (struct sk_buff *)ar_cookie->arc_bp[0];
20789 + streamID = arEndpoint2WMIStreamID(ar,pPacket->Endpoint);
20790 + mapNo = ar_cookie->arc_bp[1];
20791 +
20792 + A_ASSERT(skb);
20793 + A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(skb));
20794 +
20795 + if (A_SUCCESS(status)) {
20796 + A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(skb));
20797 + }
20798 +
20799 + AR_DEBUG2_PRINTF("ar6000_tx_complete skb=0x%x data=0x%x len=0x%x sid=%d ",
20800 + (A_UINT32)skb, (A_UINT32)pPacket->pBuffer,
20801 + pPacket->ActualLength,
20802 + streamID);
20803 +
20804 + /* lock the driver as we update internal state */
20805 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20806 +
20807 + ar->arTxPending[streamID]--;
20808 +
20809 + if ((streamID != WMI_CONTROL_PRI) || bypasswmi) {
20810 + ar->arTotalTxDataPending--;
20811 + }
20812 +
20813 + if (streamID == WMI_CONTROL_PRI)
20814 + {
20815 + if (ar->arWMIControlEpFull) {
20816 + /* since this packet completed, the WMI EP is no longer full */
20817 + ar->arWMIControlEpFull = FALSE;
20818 + }
20819 +
20820 + if (ar->arTxPending[streamID] == 0) {
20821 + wakeEvent = TRUE;
20822 + }
20823 + }
20824 +
20825 + if (A_FAILED(status)) {
20826 + AR_DEBUG_PRINTF("%s() -TX ERROR, status: 0x%x\n", __func__,
20827 + status);
20828 + AR6000_STAT_INC(ar, tx_errors);
20829 + } else {
20830 + AR_DEBUG2_PRINTF("OK\n");
20831 + AR6000_STAT_INC(ar, tx_packets);
20832 + ar->arNetStats.tx_bytes += A_NETBUF_LEN(skb);
20833 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
20834 + aptcTR.bytesTransmitted += a_netbuf_to_len(skb);
20835 + applyAPTCHeuristics(ar);
20836 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
20837 + }
20838 +
20839 + // TODO this needs to be looked at
20840 + if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable
20841 + && (streamID != WMI_CONTROL_PRI) && mapNo)
20842 + {
20843 + mapNo --;
20844 + ar->arNodeMap[mapNo].txPending --;
20845 +
20846 + if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) {
20847 + A_UINT32 i;
20848 + for (i = ar->arNodeNum; i > 0; i --) {
20849 + if (!ar->arNodeMap[i - 1].txPending) {
20850 + A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping));
20851 + ar->arNodeNum --;
20852 + } else {
20853 + break;
20854 + }
20855 + }
20856 + }
20857 + }
20858 +
20859 + /* Freeing a cookie should not be contingent on either of */
20860 + /* these flags, just if we have a cookie or not. */
20861 + /* Can we even get here without a cookie? Fix later. */
20862 + if (ar->arWmiReady == TRUE || (bypasswmi))
20863 + {
20864 + ar6000_free_cookie(ar, cookie);
20865 + }
20866 +
20867 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20868 +
20869 + /* lock is released, we can freely call other kernel APIs */
20870 +
20871 + /* this indirectly frees the HTC_PACKET */
20872 + A_NETBUF_FREE(skb);
20873 +
20874 + if (wakeEvent) {
20875 + wake_up(&arEvent);
20876 + }
20877 +}
20878 +
20879 +/*
20880 + * Receive event handler. This is called by HTC when a packet is received
20881 + */
20882 +int pktcount;
20883 +static void
20884 +ar6000_rx(void *Context, HTC_PACKET *pPacket)
20885 +{
20886 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
20887 + struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext;
20888 + int minHdrLen;
20889 + A_STATUS status = pPacket->Status;
20890 + WMI_PRI_STREAM_ID streamID = arEndpoint2WMIStreamID(ar,pPacket->Endpoint);
20891 + HTC_ENDPOINT_ID ept = pPacket->Endpoint;
20892 +
20893 + A_ASSERT((status != A_OK) || (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN)));
20894 +
20895 + AR_DEBUG2_PRINTF("ar6000_rx ar=0x%x sid=%d, skb=0x%x, data=0x%x, len=0x%x ",
20896 + (A_UINT32)ar, streamID, (A_UINT32)skb, (A_UINT32)pPacket->pBuffer,
20897 + pPacket->ActualLength);
20898 + if (status != A_OK) {
20899 + AR_DEBUG2_PRINTF("ERR\n");
20900 + } else {
20901 + AR_DEBUG2_PRINTF("OK\n");
20902 + }
20903 +
20904 + /* take lock to protect buffer counts
20905 + * and adaptive power throughput state */
20906 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20907 +
20908 + ar->arRxBuffers[streamID]--;
20909 +
20910 + if (A_SUCCESS(status)) {
20911 + AR6000_STAT_INC(ar, rx_packets);
20912 + ar->arNetStats.rx_bytes += pPacket->ActualLength;
20913 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
20914 + aptcTR.bytesReceived += a_netbuf_to_len(skb);
20915 + applyAPTCHeuristics(ar);
20916 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
20917 +
20918 + A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN);
20919 + A_NETBUF_PULL(skb, HTC_HEADER_LEN);
20920 +
20921 +#ifdef DEBUG
20922 + if (debugdriver >= 2) {
20923 + ar6000_dump_skb(skb);
20924 + }
20925 +#endif /* DEBUG */
20926 + }
20927 +
20928 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20929 +
20930 + if (status != A_OK) {
20931 + AR6000_STAT_INC(ar, rx_errors);
20932 + A_NETBUF_FREE(skb);
20933 + } else if (ar->arWmiEnabled == TRUE) {
20934 + if (streamID == WMI_CONTROL_PRI) {
20935 + /*
20936 + * this is a wmi control msg
20937 + */
20938 + wmi_control_rx(ar->arWmi, skb);
20939 + } else {
20940 + WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb);
20941 + if (WMI_DATA_HDR_IS_MSG_TYPE(dhdr, CNTL_MSGTYPE)) {
20942 + /*
20943 + * this is a wmi control msg
20944 + */
20945 + /* strip off WMI hdr */
20946 + wmi_data_hdr_remove(ar->arWmi, skb);
20947 + wmi_control_rx(ar->arWmi, skb);
20948 + } else {
20949 + /*
20950 + * this is a wmi data packet
20951 + */
20952 + minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) +
20953 + sizeof(ATH_LLC_SNAP_HDR);
20954 +
20955 + if ((pPacket->ActualLength < minHdrLen) ||
20956 + (pPacket->ActualLength > AR6000_BUFFER_SIZE))
20957 + {
20958 + /*
20959 + * packet is too short or too long
20960 + */
20961 + AR_DEBUG_PRINTF("TOO SHORT or TOO LONG\n");
20962 + AR6000_STAT_INC(ar, rx_errors);
20963 + AR6000_STAT_INC(ar, rx_length_errors);
20964 + A_NETBUF_FREE(skb);
20965 + } else {
20966 + if (ar->arWmmEnabled) {
20967 + wmi_implicit_create_pstream(ar->arWmi, skb,
20968 + DNLINK_TRAFFIC, UNDEFINED_PRI);
20969 + }
20970 +#if 0
20971 + /* Access RSSI values here */
20972 + AR_DEBUG_PRINTF("RSSI %d\n",
20973 + ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi);
20974 +#endif
20975 + wmi_data_hdr_remove(ar->arWmi, skb);
20976 + wmi_dot3_2_dix(ar->arWmi, skb);
20977 +
20978 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
20979 + /*
20980 + * extra push and memcpy, for eth_type_trans() of 2.4 kernel
20981 + * will pull out hard_header_len bytes of the skb.
20982 + */
20983 + A_NETBUF_PUSH(skb, sizeof(WMI_DATA_HDR) + sizeof(ATH_LLC_SNAP_HDR) + HTC_HEADER_LEN);
20984 + A_MEMCPY(A_NETBUF_DATA(skb), A_NETBUF_DATA(skb) + sizeof(WMI_DATA_HDR) +
20985 + sizeof(ATH_LLC_SNAP_HDR) + HTC_HEADER_LEN, sizeof(ATH_MAC_HDR));
20986 +#endif
20987 + if ((ar->arNetDev->flags & IFF_UP) == IFF_UP)
20988 + {
20989 + skb->dev = ar->arNetDev;
20990 + skb->protocol = eth_type_trans(skb, ar->arNetDev);
20991 + netif_rx(skb);
20992 + }
20993 + else
20994 + {
20995 + A_NETBUF_FREE(skb);
20996 + }
20997 + }
20998 + }
20999 + }
21000 + } else {
21001 + if ((ar->arNetDev->flags & IFF_UP) == IFF_UP)
21002 + {
21003 + skb->dev = ar->arNetDev;
21004 + skb->protocol = eth_type_trans(skb, ar->arNetDev);
21005 + netif_rx(skb);
21006 + }
21007 + else
21008 + {
21009 + A_NETBUF_FREE(skb);
21010 + }
21011 + }
21012 +
21013 + if (status != A_ECANCELED) {
21014 + /*
21015 + * HTC provides A_ECANCELED status when it doesn't want to be refilled
21016 + * (probably due to a shutdown)
21017 + */
21018 + ar6000_rx_refill(Context, ept);
21019 + }
21020 +
21021 +
21022 +}
21023 +
21024 +static void
21025 +ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint)
21026 +{
21027 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
21028 + void *osBuf;
21029 + int RxBuffers;
21030 + int buffersToRefill;
21031 + HTC_PACKET *pPacket;
21032 + WMI_PRI_STREAM_ID streamId = arEndpoint2WMIStreamID(ar,Endpoint);
21033 +
21034 + buffersToRefill = (int)AR6000_MAX_RX_BUFFERS -
21035 + (int)ar->arRxBuffers[streamId];
21036 +
21037 + if (buffersToRefill <= 0) {
21038 + /* fast return, nothing to fill */
21039 + return;
21040 + }
21041 +
21042 + AR_DEBUG2_PRINTF("ar6000_rx_refill: providing htc with %d buffers at eid=%d\n",
21043 + buffersToRefill, Endpoint);
21044 +
21045 + for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) {
21046 + osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE);
21047 + if (NULL == osBuf) {
21048 + break;
21049 + }
21050 + /* the HTC packet wrapper is at the head of the reserved area
21051 + * in the skb */
21052 + pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf));
21053 + /* set re-fill info */
21054 + SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint);
21055 + /* add this packet */
21056 + HTCAddReceivePkt(ar->arHtcTarget, pPacket);
21057 + }
21058 +
21059 + /* update count */
21060 + AR6000_SPIN_LOCK(&ar->arLock, 0);
21061 + ar->arRxBuffers[streamId] += RxBuffers;
21062 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
21063 +}
21064 +
21065 +static struct net_device_stats *
21066 +ar6000_get_stats(struct net_device *dev)
21067 +{
21068 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
21069 + return &ar->arNetStats;
21070 +}
21071 +
21072 +static struct iw_statistics *
21073 +ar6000_get_iwstats(struct net_device * dev)
21074 +{
21075 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
21076 + TARGET_STATS *pStats = &ar->arTargetStats;
21077 + struct iw_statistics * pIwStats = &ar->arIwStats;
21078 +
21079 + if ((ar->arWmiReady == FALSE)
21080 + /*
21081 + * The in_atomic function is used to determine if the scheduling is
21082 + * allowed in the current context or not. This was introduced in 2.6
21083 + * From what I have read on the differences between 2.4 and 2.6, the
21084 + * 2.4 kernel did not support preemption and so this check might not
21085 + * be required for 2.4 kernels.
21086 + */
21087 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
21088 + || (in_atomic())
21089 +#endif
21090 + )
21091 + {
21092 + pIwStats->status = 0;
21093 + pIwStats->qual.qual = 0;
21094 + pIwStats->qual.level =0;
21095 + pIwStats->qual.noise = 0;
21096 + pIwStats->discard.code =0;
21097 + pIwStats->discard.retries=0;
21098 + pIwStats->miss.beacon =0;
21099 + return pIwStats;
21100 + }
21101 + if (down_interruptible(&ar->arSem)) {
21102 + pIwStats->status = 0;
21103 + return pIwStats;
21104 + }
21105 +
21106 +
21107 + ar->statsUpdatePending = TRUE;
21108 +
21109 + if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
21110 + up(&ar->arSem);
21111 + pIwStats->status = 0;
21112 + return pIwStats;
21113 + }
21114 +
21115 + wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
21116 +
21117 + if (signal_pending(current)) {
21118 + AR_DEBUG_PRINTF("ar6000 : WMI get stats timeout \n");
21119 + up(&ar->arSem);
21120 + pIwStats->status = 0;
21121 + return pIwStats;
21122 + }
21123 + pIwStats->status = 1 ;
21124 + pIwStats->qual.qual = pStats->cs_aveBeacon_rssi;
21125 + pIwStats->qual.level =pStats->cs_aveBeacon_rssi + 161; /* noise is -95 dBm */
21126 + pIwStats->qual.noise = pStats->noise_floor_calibation;
21127 + pIwStats->discard.code = pStats->rx_decrypt_err;
21128 + pIwStats->discard.retries = pStats->tx_retry_cnt;
21129 + pIwStats->miss.beacon = pStats->cs_bmiss_cnt;
21130 + up(&ar->arSem);
21131 + return pIwStats;
21132 +}
21133 +
21134 +void
21135 +ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap)
21136 +{
21137 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
21138 + struct net_device *dev = ar->arNetDev;
21139 +
21140 + ar->arWmiReady = TRUE;
21141 + wake_up(&arEvent);
21142 + A_MEMCPY(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN);
21143 + AR_DEBUG_PRINTF("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
21144 + dev->dev_addr[0], dev->dev_addr[1],
21145 + dev->dev_addr[2], dev->dev_addr[3],
21146 + dev->dev_addr[4], dev->dev_addr[5]);
21147 +
21148 + ar->arPhyCapability = phyCap;
21149 +}
21150 +
21151 +A_UINT8
21152 +ar6000_iptos_to_userPriority(A_UINT8 *pkt)
21153 +{
21154 + struct iphdr *ipHdr = (struct iphdr *)pkt;
21155 + A_UINT8 userPriority;
21156 +
21157 + /*
21158 + * IP Tos format :
21159 + * (Refer Pg 57 WMM-test-plan-v1.2)
21160 + * IP-TOS - 8bits
21161 + * : DSCP(6-bits) ECN(2-bits)
21162 + * : DSCP - P2 P1 P0 X X X
21163 + * where (P2 P1 P0) form 802.1D
21164 + */
21165 + userPriority = ipHdr->tos >> 5;
21166 + return (userPriority & 0x7);
21167 +}
21168 +
21169 +void
21170 +ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid,
21171 + A_UINT16 listenInterval, A_UINT16 beaconInterval,
21172 + NETWORK_TYPE networkType, A_UINT8 beaconIeLen,
21173 + A_UINT8 assocReqLen, A_UINT8 assocRespLen,
21174 + A_UINT8 *assocInfo)
21175 +{
21176 + union iwreq_data wrqu;
21177 + int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos;
21178 + static const char *tag1 = "ASSOCINFO(ReqIEs=";
21179 + static const char *tag2 = "ASSOCRESPIE=";
21180 + static const char *beaconIetag = "BEACONIE=";
21181 + char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + sizeof(tag1)];
21182 + char *pos;
21183 + A_UINT8 key_op_ctrl;
21184 +
21185 + A_MEMCPY(ar->arBssid, bssid, sizeof(ar->arBssid));
21186 + ar->arBssChannel = channel;
21187 +
21188 + A_PRINTF("AR6000 connected event on freq %d ", channel);
21189 + A_PRINTF("with bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
21190 + " listenInterval=%d, beaconInterval = %d, beaconIeLen = %d assocReqLen=%d"
21191 + " assocRespLen =%d\n",
21192 + bssid[0], bssid[1], bssid[2],
21193 + bssid[3], bssid[4], bssid[5],
21194 + listenInterval, beaconInterval,
21195 + beaconIeLen, assocReqLen, assocRespLen);
21196 + if (networkType & ADHOC_NETWORK) {
21197 + if (networkType & ADHOC_CREATOR) {
21198 + A_PRINTF("Network: Adhoc (Creator)\n");
21199 + } else {
21200 + A_PRINTF("Network: Adhoc (Joiner)\n");
21201 + }
21202 + } else {
21203 + A_PRINTF("Network: Infrastructure\n");
21204 + }
21205 +
21206 + if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) {
21207 + AR_DEBUG_PRINTF("\nBeaconIEs= ");
21208 +
21209 + beacon_ie_pos = 0;
21210 + A_MEMZERO(buf, sizeof(buf));
21211 + sprintf(buf, "%s", beaconIetag);
21212 + pos = buf + 9;
21213 + for (i = beacon_ie_pos; i < beacon_ie_pos + beaconIeLen; i++) {
21214 + AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
21215 + sprintf(pos, "%2.2x", assocInfo[i]);
21216 + pos += 2;
21217 + }
21218 + AR_DEBUG_PRINTF("\n");
21219 +
21220 + A_MEMZERO(&wrqu, sizeof(wrqu));
21221 + wrqu.data.length = strlen(buf);
21222 + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
21223 + }
21224 +
21225 + if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2))))
21226 + {
21227 + assoc_resp_ie_pos = beaconIeLen + assocReqLen +
21228 + sizeof(A_UINT16) + /* capinfo*/
21229 + sizeof(A_UINT16) + /* status Code */
21230 + sizeof(A_UINT16) ; /* associd */
21231 + A_MEMZERO(buf, sizeof(buf));
21232 + sprintf(buf, "%s", tag2);
21233 + pos = buf + 12;
21234 + AR_DEBUG_PRINTF("\nAssocRespIEs= ");
21235 + /*
21236 + * The Association Response Frame w.o. the WLAN header is delivered to
21237 + * the host, so skip over to the IEs
21238 + */
21239 + for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i++)
21240 + {
21241 + AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
21242 + sprintf(pos, "%2.2x", assocInfo[i]);
21243 + pos += 2;
21244 + }
21245 + AR_DEBUG_PRINTF("\n");
21246 +
21247 + A_MEMZERO(&wrqu, sizeof(wrqu));
21248 + wrqu.data.length = strlen(buf);
21249 + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
21250 + }
21251 +
21252 + if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) {
21253 + /*
21254 + * assoc Request includes capability and listen interval. Skip these.
21255 + */
21256 + assoc_req_ie_pos = beaconIeLen +
21257 + sizeof(A_UINT16) + /* capinfo*/
21258 + sizeof(A_UINT16); /* listen interval */
21259 +
21260 + A_MEMZERO(buf, sizeof(buf));
21261 + sprintf(buf, "%s", tag1);
21262 + pos = buf + 17;
21263 + AR_DEBUG_PRINTF("AssocReqIEs= ");
21264 + for (i = assoc_req_ie_pos; i < assoc_req_ie_pos + assocReqLen - 4; i++) {
21265 + AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
21266 + sprintf(pos, "%2.2x", assocInfo[i]);
21267 + pos += 2;;
21268 + }
21269 + AR_DEBUG_PRINTF("\n");
21270 +
21271 + A_MEMZERO(&wrqu, sizeof(wrqu));
21272 + wrqu.data.length = strlen(buf);
21273 + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
21274 + }
21275 +
21276 +#ifdef USER_KEYS
21277 + if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN &&
21278 + ar->user_saved_keys.keyOk == TRUE)
21279 + {
21280 +
21281 + key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC;
21282 + if (ar->user_key_ctrl & AR6000_USER_SETKEYS_RSC_UNCHANGED) {
21283 + key_op_ctrl &= ~KEY_OP_INIT_RSC;
21284 + } else {
21285 + key_op_ctrl |= KEY_OP_INIT_RSC;
21286 + }
21287 + ar6000_reinstall_keys(ar, key_op_ctrl);
21288 + }
21289 +#endif /* USER_KEYS */
21290 +
21291 + /* flush data queues */
21292 + ar6000_TxDataCleanup(ar);
21293 +
21294 + netif_start_queue(ar->arNetDev);
21295 +
21296 + if ((OPEN_AUTH == ar->arDot11AuthMode) &&
21297 + (NONE_AUTH == ar->arAuthMode) &&
21298 + (WEP_CRYPT == ar->arPairwiseCrypto))
21299 + {
21300 + if (!ar->arConnected) {
21301 + ar6000_install_static_wep_keys(ar);
21302 + }
21303 + }
21304 +
21305 + ar->arConnected = TRUE;
21306 + ar->arConnectPending = FALSE;
21307 +
21308 + reconnect_flag = 0;
21309 +
21310 + A_MEMZERO(&wrqu, sizeof(wrqu));
21311 + A_MEMCPY(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN);
21312 + wrqu.addr.sa_family = ARPHRD_ETHER;
21313 + wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL);
21314 + if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) {
21315 + A_MEMZERO(ar->arNodeMap, sizeof(ar->arNodeMap));
21316 + ar->arNodeNum = 0;
21317 + ar->arNexEpId = ENDPOINT_2;
21318 + }
21319 +
21320 +}
21321 +
21322 +void ar6000_set_numdataendpts(AR_SOFTC_T *ar, A_UINT32 num)
21323 +{
21324 + A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1));
21325 + ar->arNumDataEndPts = num;
21326 +}
21327 +
21328 +void
21329 +ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
21330 + A_UINT8 assocRespLen, A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus)
21331 +{
21332 + A_UINT8 i;
21333 +
21334 + A_PRINTF("AR6000 disconnected");
21335 + if (bssid[0] || bssid[1] || bssid[2] || bssid[3] || bssid[4] || bssid[5]) {
21336 + A_PRINTF(" from %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",
21337 + bssid[0], bssid[1], bssid[2], bssid[3], bssid[4], bssid[5]);
21338 + }
21339 + A_PRINTF("\n");
21340 +
21341 + AR_DEBUG_PRINTF("\nDisconnect Reason is %d", reason);
21342 + AR_DEBUG_PRINTF("\nProtocol Reason/Status Code is %d", protocolReasonStatus);
21343 + AR_DEBUG_PRINTF("\nAssocResp Frame = %s",
21344 + assocRespLen ? " " : "NULL");
21345 + for (i = 0; i < assocRespLen; i++) {
21346 + if (!(i % 0x10)) {
21347 + AR_DEBUG_PRINTF("\n");
21348 + }
21349 + AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
21350 + }
21351 + AR_DEBUG_PRINTF("\n");
21352 + /*
21353 + * If the event is due to disconnect cmd from the host, only they the target
21354 + * would stop trying to connect. Under any other condition, target would
21355 + * keep trying to connect.
21356 + *
21357 + */
21358 + if( reason == DISCONNECT_CMD)
21359 + {
21360 + ar->arConnectPending = FALSE;
21361 + } else {
21362 + ar->arConnectPending = TRUE;
21363 + if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) ||
21364 + ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) {
21365 + ar->arConnected = TRUE;
21366 + return;
21367 + }
21368 + }
21369 + ar->arConnected = FALSE;
21370 +
21371 + if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) {
21372 + reconnect_flag = 0;
21373 + }
21374 +
21375 +#ifdef USER_KEYS
21376 + if (reason != CSERV_DISCONNECT)
21377 + {
21378 + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
21379 + ar->user_key_ctrl = 0;
21380 + }
21381 +#endif /* USER_KEYS */
21382 +
21383 + netif_stop_queue(ar->arNetDev);
21384 + A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
21385 + ar->arBssChannel = 0;
21386 + ar->arBeaconInterval = 0;
21387 +
21388 + ar6000_TxDataCleanup(ar);
21389 +}
21390 +
21391 +void
21392 +ar6000_regDomain_event(AR_SOFTC_T *ar, A_UINT32 regCode)
21393 +{
21394 + A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode);
21395 + ar->arRegCode = regCode;
21396 +}
21397 +
21398 +void
21399 +ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info)
21400 +{
21401 + static const char *tag = "PRE-AUTH";
21402 + char buf[128];
21403 + union iwreq_data wrqu;
21404 + int i;
21405 +
21406 + AR_DEBUG_PRINTF("AR6000 Neighbor Report Event\n");
21407 + for (i=0; i < numAps; info++, i++) {
21408 + AR_DEBUG_PRINTF("bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",
21409 + info->bssid[0], info->bssid[1], info->bssid[2],
21410 + info->bssid[3], info->bssid[4], info->bssid[5]);
21411 + if (info->bssFlags & WMI_PREAUTH_CAPABLE_BSS) {
21412 + AR_DEBUG_PRINTF("preauth-cap");
21413 + }
21414 + if (info->bssFlags & WMI_PMKID_VALID_BSS) {
21415 + AR_DEBUG_PRINTF(" pmkid-valid\n");
21416 + continue; /* we skip bss if the pmkid is already valid */
21417 + }
21418 + AR_DEBUG_PRINTF("\n");
21419 + snprintf(buf, sizeof(buf), "%s%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x%2.2x",
21420 + tag,
21421 + info->bssid[0], info->bssid[1], info->bssid[2],
21422 + info->bssid[3], info->bssid[4], info->bssid[5],
21423 + i, info->bssFlags);
21424 + A_MEMZERO(&wrqu, sizeof(wrqu));
21425 + wrqu.data.length = strlen(buf);
21426 + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
21427 + }
21428 +}
21429 +
21430 +void
21431 +ar6000_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
21432 +{
21433 + static const char *tag = "MLME-MICHAELMICFAILURE.indication";
21434 + char buf[128];
21435 + union iwreq_data wrqu;
21436 +
21437 + A_PRINTF("AR6000 TKIP MIC error received for keyid %d %scast\n",
21438 + keyid, ismcast ? "multi": "uni");
21439 + snprintf(buf, sizeof(buf), "%s(keyid=%d %scat)", tag, keyid,
21440 + ismcast ? "multi" : "uni");
21441 + memset(&wrqu, 0, sizeof(wrqu));
21442 + wrqu.data.length = strlen(buf);
21443 + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
21444 +}
21445 +
21446 +void
21447 +ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
21448 +{
21449 + AR_DEBUG_PRINTF("AR6000 scan complete: %d\n", status);
21450 +
21451 + ar->scan_complete = 1;
21452 + wake_up_interruptible(&ar6000_scan_queue);
21453 +}
21454 +
21455 +void
21456 +ar6000_targetStats_event(AR_SOFTC_T *ar, WMI_TARGET_STATS *pTarget)
21457 +{
21458 + TARGET_STATS *pStats = &ar->arTargetStats;
21459 + A_UINT8 ac;
21460 +
21461 + /*A_PRINTF("AR6000 updating target stats\n");*/
21462 + pStats->tx_packets += pTarget->txrxStats.tx_stats.tx_packets;
21463 + pStats->tx_bytes += pTarget->txrxStats.tx_stats.tx_bytes;
21464 + pStats->tx_unicast_pkts += pTarget->txrxStats.tx_stats.tx_unicast_pkts;
21465 + pStats->tx_unicast_bytes += pTarget->txrxStats.tx_stats.tx_unicast_bytes;
21466 + pStats->tx_multicast_pkts += pTarget->txrxStats.tx_stats.tx_multicast_pkts;
21467 + pStats->tx_multicast_bytes += pTarget->txrxStats.tx_stats.tx_multicast_bytes;
21468 + pStats->tx_broadcast_pkts += pTarget->txrxStats.tx_stats.tx_broadcast_pkts;
21469 + pStats->tx_broadcast_bytes += pTarget->txrxStats.tx_stats.tx_broadcast_bytes;
21470 + pStats->tx_rts_success_cnt += pTarget->txrxStats.tx_stats.tx_rts_success_cnt;
21471 + for(ac = 0; ac < WMM_NUM_AC; ac++)
21472 + pStats->tx_packet_per_ac[ac] += pTarget->txrxStats.tx_stats.tx_packet_per_ac[ac];
21473 + pStats->tx_errors += pTarget->txrxStats.tx_stats.tx_errors;
21474 + pStats->tx_failed_cnt += pTarget->txrxStats.tx_stats.tx_failed_cnt;
21475 + pStats->tx_retry_cnt += pTarget->txrxStats.tx_stats.tx_retry_cnt;
21476 + pStats->tx_rts_fail_cnt += pTarget->txrxStats.tx_stats.tx_rts_fail_cnt;
21477 + pStats->tx_unicast_rate = wmi_get_rate(pTarget->txrxStats.tx_stats.tx_unicast_rate);
21478 +
21479 + pStats->rx_packets += pTarget->txrxStats.rx_stats.rx_packets;
21480 + pStats->rx_bytes += pTarget->txrxStats.rx_stats.rx_bytes;
21481 + pStats->rx_unicast_pkts += pTarget->txrxStats.rx_stats.rx_unicast_pkts;
21482 + pStats->rx_unicast_bytes += pTarget->txrxStats.rx_stats.rx_unicast_bytes;
21483 + pStats->rx_multicast_pkts += pTarget->txrxStats.rx_stats.rx_multicast_pkts;
21484 + pStats->rx_multicast_bytes += pTarget->txrxStats.rx_stats.rx_multicast_bytes;
21485 + pStats->rx_broadcast_pkts += pTarget->txrxStats.rx_stats.rx_broadcast_pkts;
21486 + pStats->rx_broadcast_bytes += pTarget->txrxStats.rx_stats.rx_broadcast_bytes;
21487 + pStats->rx_fragment_pkt += pTarget->txrxStats.rx_stats.rx_fragment_pkt;
21488 + pStats->rx_errors += pTarget->txrxStats.rx_stats.rx_errors;
21489 + pStats->rx_crcerr += pTarget->txrxStats.rx_stats.rx_crcerr;
21490 + pStats->rx_key_cache_miss += pTarget->txrxStats.rx_stats.rx_key_cache_miss;
21491 + pStats->rx_decrypt_err += pTarget->txrxStats.rx_stats.rx_decrypt_err;
21492 + pStats->rx_duplicate_frames += pTarget->txrxStats.rx_stats.rx_duplicate_frames;
21493 + pStats->rx_unicast_rate = wmi_get_rate(pTarget->txrxStats.rx_stats.rx_unicast_rate);
21494 +
21495 +
21496 + pStats->tkip_local_mic_failure
21497 + += pTarget->txrxStats.tkipCcmpStats.tkip_local_mic_failure;
21498 + pStats->tkip_counter_measures_invoked
21499 + += pTarget->txrxStats.tkipCcmpStats.tkip_counter_measures_invoked;
21500 + pStats->tkip_replays += pTarget->txrxStats.tkipCcmpStats.tkip_replays;
21501 + pStats->tkip_format_errors += pTarget->txrxStats.tkipCcmpStats.tkip_format_errors;
21502 + pStats->ccmp_format_errors += pTarget->txrxStats.tkipCcmpStats.ccmp_format_errors;
21503 + pStats->ccmp_replays += pTarget->txrxStats.tkipCcmpStats.ccmp_replays;
21504 +
21505 +
21506 + pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cnt;
21507 + pStats->noise_floor_calibation = pTarget->noise_floor_calibation;
21508 +
21509 + pStats->cs_bmiss_cnt += pTarget->cservStats.cs_bmiss_cnt;
21510 + pStats->cs_lowRssi_cnt += pTarget->cservStats.cs_lowRssi_cnt;
21511 + pStats->cs_connect_cnt += pTarget->cservStats.cs_connect_cnt;
21512 + pStats->cs_disconnect_cnt += pTarget->cservStats.cs_disconnect_cnt;
21513 + pStats->cs_aveBeacon_snr = pTarget->cservStats.cs_aveBeacon_snr;
21514 + pStats->cs_aveBeacon_rssi = pTarget->cservStats.cs_aveBeacon_rssi;
21515 + pStats->cs_lastRoam_msec = pTarget->cservStats.cs_lastRoam_msec;
21516 + pStats->cs_snr = pTarget->cservStats.cs_snr;
21517 + pStats->cs_rssi = pTarget->cservStats.cs_rssi;
21518 +
21519 + pStats->lq_val = pTarget->lqVal;
21520 +
21521 + pStats->wow_num_pkts_dropped += pTarget->wowStats.wow_num_pkts_dropped;
21522 + pStats->wow_num_host_pkt_wakeups += pTarget->wowStats.wow_num_host_pkt_wakeups;
21523 + pStats->wow_num_host_event_wakeups += pTarget->wowStats.wow_num_host_event_wakeups;
21524 + pStats->wow_num_events_discarded += pTarget->wowStats.wow_num_events_discarded;
21525 +
21526 + ar->statsUpdatePending = FALSE;
21527 + wake_up(&arEvent);
21528 +}
21529 +
21530 +void
21531 +ar6000_rssiThreshold_event(AR_SOFTC_T *ar, WMI_RSSI_THRESHOLD_VAL newThreshold, A_INT16 rssi)
21532 +{
21533 + USER_RSSI_THOLD userRssiThold;
21534 +
21535 + userRssiThold.tag = rssi_map[newThreshold].tag;
21536 + userRssiThold.rssi = rssi;
21537 + AR_DEBUG2_PRINTF("rssi Threshold range = %d tag = %d rssi = %d\n", newThreshold, userRssiThold.tag, rssi);
21538 +#ifdef SEND_EVENT_TO_APP
21539 + ar6000_send_event_to_app(ar, WMI_RSSI_THRESHOLD_EVENTID,(A_UINT8 *)&userRssiThold, sizeof(USER_RSSI_THOLD));
21540 +#endif
21541 +}
21542 +
21543 +
21544 +void
21545 +ar6000_hbChallengeResp_event(AR_SOFTC_T *ar, A_UINT32 cookie, A_UINT32 source)
21546 +{
21547 + if (source == APP_HB_CHALLENGE) {
21548 + /* Report it to the app in case it wants a positive acknowledgement */
21549 +#ifdef SEND_EVENT_TO_APP
21550 + ar6000_send_event_to_app(ar, WMIX_HB_CHALLENGE_RESP_EVENTID,
21551 + (A_UINT8 *)&cookie, sizeof(cookie));
21552 +#endif
21553 + } else {
21554 + /* This would ignore the replys that come in after their due time */
21555 + if (cookie == ar->arHBChallengeResp.seqNum) {
21556 + ar->arHBChallengeResp.outstanding = FALSE;
21557 + }
21558 + }
21559 +}
21560 +
21561 +
21562 +void
21563 +ar6000_reportError_event(AR_SOFTC_T *ar, WMI_TARGET_ERROR_VAL errorVal)
21564 +{
21565 + char *errString[] = {
21566 + [WMI_TARGET_PM_ERR_FAIL] "WMI_TARGET_PM_ERR_FAIL",
21567 + [WMI_TARGET_KEY_NOT_FOUND] "WMI_TARGET_KEY_NOT_FOUND",
21568 + [WMI_TARGET_DECRYPTION_ERR] "WMI_TARGET_DECRYPTION_ERR",
21569 + [WMI_TARGET_BMISS] "WMI_TARGET_BMISS",
21570 + [WMI_PSDISABLE_NODE_JOIN] "WMI_PSDISABLE_NODE_JOIN"
21571 + };
21572 +
21573 + A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal);
21574 +
21575 + /* One error is reported at a time, and errorval is a bitmask */
21576 + if(errorVal & (errorVal - 1))
21577 + return;
21578 +
21579 + A_PRINTF("AR6000 Error type = ");
21580 + switch(errorVal)
21581 + {
21582 + case WMI_TARGET_PM_ERR_FAIL:
21583 + case WMI_TARGET_KEY_NOT_FOUND:
21584 + case WMI_TARGET_DECRYPTION_ERR:
21585 + case WMI_TARGET_BMISS:
21586 + case WMI_PSDISABLE_NODE_JOIN:
21587 + A_PRINTF("%s\n", errString[errorVal]);
21588 + break;
21589 + default:
21590 + A_PRINTF("INVALID\n");
21591 + break;
21592 + }
21593 +
21594 +}
21595 +
21596 +
21597 +void
21598 +ar6000_cac_event(AR_SOFTC_T *ar, A_UINT8 ac, A_UINT8 cacIndication,
21599 + A_UINT8 statusCode, A_UINT8 *tspecSuggestion)
21600 +{
21601 + WMM_TSPEC_IE *tspecIe;
21602 +
21603 + /*
21604 + * This is the TSPEC IE suggestion from AP.
21605 + * Suggestion provided by AP under some error
21606 + * cases, could be helpful for the host app.
21607 + * Check documentation.
21608 + */
21609 + tspecIe = (WMM_TSPEC_IE *)tspecSuggestion;
21610 +
21611 + /*
21612 + * What do we do, if we get TSPEC rejection? One thought
21613 + * that comes to mind is implictly delete the pstream...
21614 + */
21615 + A_PRINTF("AR6000 CAC notification. "
21616 + "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n",
21617 + ac, cacIndication, statusCode);
21618 +}
21619 +
21620 +#define AR6000_PRINT_BSSID(_pBss) do { \
21621 + A_PRINTF("%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ",\
21622 + (_pBss)[0],(_pBss)[1],(_pBss)[2],(_pBss)[3],\
21623 + (_pBss)[4],(_pBss)[5]); \
21624 +} while(0)
21625 +
21626 +void
21627 +ar6000_roam_tbl_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_TBL *pTbl)
21628 +{
21629 + A_UINT8 i;
21630 +
21631 + A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n",
21632 + pTbl->numEntries, pTbl->roamMode);
21633 + for (i= 0; i < pTbl->numEntries; i++) {
21634 + A_PRINTF("[%d]bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x ", i,
21635 + pTbl->bssRoamInfo[i].bssid[0], pTbl->bssRoamInfo[i].bssid[1],
21636 + pTbl->bssRoamInfo[i].bssid[2],
21637 + pTbl->bssRoamInfo[i].bssid[3],
21638 + pTbl->bssRoamInfo[i].bssid[4],
21639 + pTbl->bssRoamInfo[i].bssid[5]);
21640 + A_PRINTF("RSSI %d RSSIDT %d LAST RSSI %d UTIL %d ROAM_UTIL %d"
21641 + " BIAS %d\n",
21642 + pTbl->bssRoamInfo[i].rssi,
21643 + pTbl->bssRoamInfo[i].rssidt,
21644 + pTbl->bssRoamInfo[i].last_rssi,
21645 + pTbl->bssRoamInfo[i].util,
21646 + pTbl->bssRoamInfo[i].roam_util,
21647 + pTbl->bssRoamInfo[i].bias);
21648 + }
21649 +}
21650 +
21651 +void
21652 +ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply)
21653 +{
21654 + A_UINT8 i,j;
21655 +
21656 + /*Each event now contains exactly one filter, see bug 26613*/
21657 + A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num, wow_reply->num_filters);
21658 + A_PRINTF("wow mode = %s host mode = %s\n",
21659 + (wow_reply->wow_mode == 0? "disabled":"enabled"),
21660 + (wow_reply->host_mode == 1 ? "awake":"asleep"));
21661 +
21662 +
21663 + /*If there are no patterns, the reply will only contain generic
21664 + WoW information. Pattern information will exist only if there are
21665 + patterns present. Bug 26716*/
21666 +
21667 + /* If this event contains pattern information, display it*/
21668 + if (wow_reply->this_filter_num) {
21669 + i=0;
21670 + A_PRINTF("id=%d size=%d offset=%d\n",
21671 + wow_reply->wow_filters[i].wow_filter_id,
21672 + wow_reply->wow_filters[i].wow_filter_size,
21673 + wow_reply->wow_filters[i].wow_filter_offset);
21674 + A_PRINTF("wow pattern = ");
21675 + for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) {
21676 + A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_pattern[j]);
21677 + }
21678 +
21679 + A_PRINTF("\nwow mask = ");
21680 + for (j=0; j< wow_reply->wow_filters[i].wow_filter_size; j++) {
21681 + A_PRINTF("%2.2x",wow_reply->wow_filters[i].wow_filter_mask[j]);
21682 + }
21683 + A_PRINTF("\n");
21684 + }
21685 +}
21686 +
21687 +/*
21688 + * Report the Roaming related data collected on the target
21689 + */
21690 +void
21691 +ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p)
21692 +{
21693 + A_PRINTF("Disconnect Data : BSSID: ");
21694 + AR6000_PRINT_BSSID(p->disassoc_bssid);
21695 + A_PRINTF(" RSSI %d DISASSOC Time %d NO_TXRX_TIME %d\n",
21696 + p->disassoc_bss_rssi,p->disassoc_time,
21697 + p->no_txrx_time);
21698 + A_PRINTF("Connect Data: BSSID: ");
21699 + AR6000_PRINT_BSSID(p->assoc_bssid);
21700 + A_PRINTF(" RSSI %d ASSOC Time %d TXRX_TIME %d\n",
21701 + p->assoc_bss_rssi,p->assoc_time,
21702 + p->allow_txrx_time);
21703 + A_PRINTF("Last Data Tx Time (b4 Disassoc) %d "\
21704 + "First Data Tx Time (after Assoc) %d\n",
21705 + p->last_data_txrx_time, p->first_data_txrx_time);
21706 +}
21707 +
21708 +void
21709 +ar6000_roam_data_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_DATA *p)
21710 +{
21711 + switch (p->roamDataType) {
21712 + case ROAM_DATA_TIME:
21713 + ar6000_display_roam_time(&p->u.roamTime);
21714 + break;
21715 + default:
21716 + break;
21717 + }
21718 +}
21719 +
21720 +void
21721 +ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len)
21722 +{
21723 + struct sk_buff *skb;
21724 + WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap;
21725 +
21726 +
21727 + if (!ar->arMgmtFilter) {
21728 + return;
21729 + }
21730 + if (((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_BEACON) &&
21731 + (bih->frameType != BEACON_FTYPE)) ||
21732 + ((ar->arMgmtFilter & IEEE80211_FILTER_TYPE_PROBE_RESP) &&
21733 + (bih->frameType != PROBERESP_FTYPE)))
21734 + {
21735 + return;
21736 + }
21737 +
21738 + if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) {
21739 +
21740 + A_NETBUF_PUT(skb, len);
21741 + A_MEMCPY(A_NETBUF_DATA(skb), datap, len);
21742 + skb->dev = ar->arNetDev;
21743 + printk("MAC RAW...\n");
21744 +// skb->mac.raw = A_NETBUF_DATA(skb);
21745 + skb->ip_summed = CHECKSUM_NONE;
21746 + skb->pkt_type = PACKET_OTHERHOST;
21747 + skb->protocol = __constant_htons(0x0019);
21748 + netif_rx(skb);
21749 + }
21750 +}
21751 +
21752 +A_UINT32 wmiSendCmdNum;
21753 +
21754 +A_STATUS
21755 +ar6000_control_tx(void *devt, void *osbuf, WMI_PRI_STREAM_ID streamID)
21756 +{
21757 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
21758 + A_STATUS status = A_OK;
21759 + struct ar_cookie *cookie = NULL;
21760 + int i;
21761 +
21762 + /* take lock to protect ar6000_alloc_cookie() */
21763 + AR6000_SPIN_LOCK(&ar->arLock, 0);
21764 +
21765 + do {
21766 +
21767 + AR_DEBUG2_PRINTF("ar_contrstatus = ol_tx: skb=0x%x, len=0x%x, sid=%d\n",
21768 + (A_UINT32)osbuf, A_NETBUF_LEN(osbuf), streamID);
21769 +
21770 + if ((streamID == WMI_CONTROL_PRI) && (ar->arWMIControlEpFull)) {
21771 + /* control endpoint is full, don't allocate resources, we
21772 + * are just going to drop this packet */
21773 + cookie = NULL;
21774 + AR_DEBUG_PRINTF(" WMI Control EP full, dropping packet : 0x%X, len:%d \n",
21775 + (A_UINT32)osbuf, A_NETBUF_LEN(osbuf));
21776 + } else {
21777 + cookie = ar6000_alloc_cookie(ar);
21778 + }
21779 +
21780 + if (cookie == NULL) {
21781 + status = A_NO_MEMORY;
21782 + break;
21783 + }
21784 +
21785 + if(logWmiRawMsgs) {
21786 + A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum);
21787 + for(i = 0; i < a_netbuf_to_len(osbuf); i++)
21788 + A_PRINTF("%x ", ((A_UINT8 *)a_netbuf_to_data(osbuf))[i]);
21789 + A_PRINTF("\n");
21790 + }
21791 +
21792 + wmiSendCmdNum++;
21793 +
21794 + } while (FALSE);
21795 +
21796 + if (cookie != NULL) {
21797 + /* got a structure to send it out on */
21798 + ar->arTxPending[streamID]++;
21799 +
21800 + if (streamID != WMI_CONTROL_PRI) {
21801 + ar->arTotalTxDataPending++;
21802 + }
21803 + }
21804 +
21805 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
21806 +
21807 + if (cookie != NULL) {
21808 + cookie->arc_bp[0] = (A_UINT32)osbuf;
21809 + cookie->arc_bp[1] = 0;
21810 + SET_HTC_PACKET_INFO_TX(&cookie->HtcPkt,
21811 + cookie,
21812 + A_NETBUF_DATA(osbuf),
21813 + A_NETBUF_LEN(osbuf),
21814 + arWMIStream2EndpointID(ar,streamID),
21815 + AR6K_CONTROL_PKT_TAG);
21816 + /* this interface is asynchronous, if there is an error, cleanup will happen in the
21817 + * TX completion callback */
21818 + HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
21819 + status = A_OK;
21820 + }
21821 +
21822 + return status;
21823 +}
21824 +
21825 +/* indicate tx activity or inactivity on a WMI stream */
21826 +void ar6000_indicate_tx_activity(void *devt, A_UINT8 TrafficClass, A_BOOL Active)
21827 +{
21828 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
21829 + WMI_PRI_STREAM_ID streamid;
21830 +
21831 + if (ar->arWmiEnabled) {
21832 + streamid = wmi_get_stream_id(ar->arWmi, TrafficClass);
21833 + } else {
21834 + /* for mbox ping testing, the traffic class is mapped directly as a stream ID,
21835 + * see handling of AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE in ioctl.c */
21836 + streamid = (WMI_PRI_STREAM_ID)TrafficClass;
21837 + }
21838 +
21839 + /* notify HTC, this may cause credit distribution changes */
21840 +
21841 + HTCIndicateActivityChange(ar->arHtcTarget,
21842 + arWMIStream2EndpointID(ar,streamid),
21843 + Active);
21844 +
21845 +}
21846 +
21847 +module_init(ar6000_init_module);
21848 +module_exit(ar6000_cleanup_module);
21849 +
21850 +/* Init cookie queue */
21851 +static void
21852 +ar6000_cookie_init(AR_SOFTC_T *ar)
21853 +{
21854 + A_UINT32 i;
21855 +
21856 + ar->arCookieList = NULL;
21857 + A_MEMZERO(s_ar_cookie_mem, sizeof(s_ar_cookie_mem));
21858 +
21859 + for (i = 0; i < MAX_COOKIE_NUM; i++) {
21860 + ar6000_free_cookie(ar, &s_ar_cookie_mem[i]);
21861 + }
21862 +}
21863 +
21864 +/* cleanup cookie queue */
21865 +static void
21866 +ar6000_cookie_cleanup(AR_SOFTC_T *ar)
21867 +{
21868 + /* It is gone .... */
21869 + ar->arCookieList = NULL;
21870 +}
21871 +
21872 +/* Init cookie queue */
21873 +static void
21874 +ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie)
21875 +{
21876 + /* Insert first */
21877 + A_ASSERT(ar != NULL);
21878 + A_ASSERT(cookie != NULL);
21879 + cookie->arc_list_next = ar->arCookieList;
21880 + ar->arCookieList = cookie;
21881 +}
21882 +
21883 +/* cleanup cookie queue */
21884 +static struct ar_cookie *
21885 +ar6000_alloc_cookie(AR_SOFTC_T *ar)
21886 +{
21887 + struct ar_cookie *cookie;
21888 +
21889 + cookie = ar->arCookieList;
21890 + if(cookie != NULL)
21891 + {
21892 + ar->arCookieList = cookie->arc_list_next;
21893 + }
21894 +
21895 + return cookie;
21896 +}
21897 +
21898 +#ifdef SEND_EVENT_TO_APP
21899 +/*
21900 + * This function is used to send event which come from taget to
21901 + * the application. The buf which send to application is include
21902 + * the event ID and event content.
21903 + */
21904 +#define EVENT_ID_LEN 2
21905 +void ar6000_send_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
21906 + A_UINT8 *datap, int len)
21907 +{
21908 +
21909 +#if (WIRELESS_EXT >= 15)
21910 +
21911 +/* note: IWEVCUSTOM only exists in wireless extensions after version 15 */
21912 +
21913 + char *buf;
21914 + A_UINT16 size;
21915 + union iwreq_data wrqu;
21916 +
21917 + size = len + EVENT_ID_LEN;
21918 +
21919 + if (size > IW_CUSTOM_MAX) {
21920 + AR_DEBUG_PRINTF("WMI event ID : 0x%4.4X, len = %d too big for IWEVCUSTOM (max=%d) \n",
21921 + eventId, size, IW_CUSTOM_MAX);
21922 + return;
21923 + }
21924 +
21925 + buf = A_MALLOC_NOWAIT(size);
21926 + A_MEMZERO(buf, size);
21927 + A_MEMCPY(buf, &eventId, EVENT_ID_LEN);
21928 + A_MEMCPY(buf+EVENT_ID_LEN, datap, len);
21929 +
21930 + //AR_DEBUG_PRINTF("event ID = %d,len = %d\n",*(A_UINT16*)buf, size);
21931 + A_MEMZERO(&wrqu, sizeof(wrqu));
21932 + wrqu.data.length = size;
21933 + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
21934 +
21935 + A_FREE(buf);
21936 +#endif
21937 +
21938 +
21939 +}
21940 +#endif
21941 +
21942 +
21943 +void
21944 +ar6000_tx_retry_err_event(void *devt)
21945 +{
21946 + AR_DEBUG2_PRINTF("Tx retries reach maximum!\n");
21947 +}
21948 +
21949 +void
21950 +ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, A_UINT8 snr)
21951 +{
21952 + AR_DEBUG2_PRINTF("snr threshold range %d, snr %d\n", newThreshold, snr);
21953 +}
21954 +
21955 +void
21956 +ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, A_UINT8 lq)
21957 +{
21958 + AR_DEBUG2_PRINTF("lq threshold range %d, lq %d\n", newThreshold, lq);
21959 +}
21960 +
21961 +
21962 +
21963 +A_UINT32
21964 +a_copy_to_user(void *to, const void *from, A_UINT32 n)
21965 +{
21966 + return(copy_to_user(to, from, n));
21967 +}
21968 +
21969 +A_UINT32
21970 +a_copy_from_user(void *to, const void *from, A_UINT32 n)
21971 +{
21972 + return(copy_from_user(to, from, n));
21973 +}
21974 +
21975 +
21976 +A_STATUS
21977 +ar6000_get_driver_cfg(struct net_device *dev,
21978 + A_UINT16 cfgParam,
21979 + void *result)
21980 +{
21981 +
21982 + A_STATUS ret = 0;
21983 +
21984 + switch(cfgParam)
21985 + {
21986 + case AR6000_DRIVER_CFG_GET_WLANNODECACHING:
21987 + *((A_UINT32 *)result) = wlanNodeCaching;
21988 + break;
21989 + case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS:
21990 + *((A_UINT32 *)result) = logWmiRawMsgs;
21991 + break;
21992 + default:
21993 + ret = EINVAL;
21994 + break;
21995 + }
21996 +
21997 + return ret;
21998 +}
21999 +
22000 +void
22001 +ar6000_keepalive_rx(void *devt, A_UINT8 configured)
22002 +{
22003 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
22004 +
22005 + ar->arKeepaliveConfigured = configured;
22006 + wake_up(&arEvent);
22007 +}
22008 +
22009 +void
22010 +ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID, WMI_PMKID *pmkidList)
22011 +{
22012 + A_UINT8 i, j;
22013 +
22014 + A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID);
22015 +
22016 + for (i = 0; i < numPMKID; i++) {
22017 + A_PRINTF("\nPMKID %d ", i);
22018 + for (j = 0; j < WMI_PMKID_LEN; j++) {
22019 + A_PRINTF("%2.2x", pmkidList->pmkid[j]);
22020 + }
22021 + pmkidList++;
22022 + }
22023 +}
22024 +
22025 +#ifdef USER_KEYS
22026 +static A_STATUS
22027 +
22028 +ar6000_reinstall_keys(AR_SOFTC_T *ar, A_UINT8 key_op_ctrl)
22029 +{
22030 + A_STATUS status = A_OK;
22031 + struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik;
22032 + struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik;
22033 + CRYPTO_TYPE keyType = ar->user_saved_keys.keyType;
22034 +
22035 + if (IEEE80211_CIPHER_CCKM_KRK != uik->ik_type) {
22036 + if (NONE_CRYPT == keyType) {
22037 + goto _reinstall_keys_out;
22038 + }
22039 +
22040 + if (uik->ik_keylen) {
22041 + status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix,
22042 + ar->user_saved_keys.keyType, PAIRWISE_USAGE,
22043 + uik->ik_keylen, (A_UINT8 *)&uik->ik_keyrsc,
22044 + uik->ik_keydata, key_op_ctrl, SYNC_BEFORE_WMIFLAG);
22045 + }
22046 +
22047 + } else {
22048 + status = wmi_add_krk_cmd(ar->arWmi, uik->ik_keydata);
22049 + }
22050 +
22051 + if (IEEE80211_CIPHER_CCKM_KRK != bik->ik_type) {
22052 + if (NONE_CRYPT == keyType) {
22053 + goto _reinstall_keys_out;
22054 + }
22055 +
22056 + if (bik->ik_keylen) {
22057 + status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix,
22058 + ar->user_saved_keys.keyType, GROUP_USAGE,
22059 + bik->ik_keylen, (A_UINT8 *)&bik->ik_keyrsc,
22060 + bik->ik_keydata, key_op_ctrl, NO_SYNC_WMIFLAG);
22061 + }
22062 + } else {
22063 + status = wmi_add_krk_cmd(ar->arWmi, bik->ik_keydata);
22064 + }
22065 +
22066 +_reinstall_keys_out:
22067 + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
22068 + ar->user_key_ctrl = 0;
22069 +
22070 + return status;
22071 +}
22072 +#endif /* USER_KEYS */
22073 +
22074 +
22075 +void
22076 +ar6000_dset_open_req(
22077 + void *context,
22078 + A_UINT32 id,
22079 + A_UINT32 targHandle,
22080 + A_UINT32 targReplyFn,
22081 + A_UINT32 targReplyArg)
22082 +{
22083 +}
22084 +
22085 +void
22086 +ar6000_dset_close(
22087 + void *context,
22088 + A_UINT32 access_cookie)
22089 +{
22090 + return;
22091 +}
22092 +
22093 +void
22094 +ar6000_dset_data_req(
22095 + void *context,
22096 + A_UINT32 accessCookie,
22097 + A_UINT32 offset,
22098 + A_UINT32 length,
22099 + A_UINT32 targBuf,
22100 + A_UINT32 targReplyFn,
22101 + A_UINT32 targReplyArg)
22102 +{
22103 +}
22104 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ar6000_drv.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ar6000_drv.h
22105 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ar6000_drv.h 1970-01-01 01:00:00.000000000 +0100
22106 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ar6000_drv.h 2009-05-10 22:27:59.000000000 +0200
22107 @@ -0,0 +1,360 @@
22108 +/*
22109 + *
22110 + * Copyright (c) 2004-2007 Atheros Communications Inc.
22111 + * All rights reserved.
22112 + *
22113 + *
22114 + * This program is free software; you can redistribute it and/or modify
22115 + * it under the terms of the GNU General Public License version 2 as
22116 + * published by the Free Software Foundation;
22117 + *
22118 + * Software distributed under the License is distributed on an "AS
22119 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
22120 + * implied. See the License for the specific language governing
22121 + * rights and limitations under the License.
22122 + *
22123 + *
22124 + *
22125 + */
22126 +
22127 +#ifndef _AR6000_H_
22128 +#define _AR6000_H_
22129 +
22130 +#include <linux/version.h>
22131 +
22132 +
22133 +#include <linux/autoconf.h>
22134 +#include <linux/init.h>
22135 +#include <linux/kernel.h>
22136 +#include <linux/spinlock.h>
22137 +#include <linux/skbuff.h>
22138 +#include <linux/if_ether.h>
22139 +#include <linux/netdevice.h>
22140 +#include <linux/etherdevice.h>
22141 +#include <net/iw_handler.h>
22142 +#include <linux/if_arp.h>
22143 +#include <linux/ip.h>
22144 +#include <linux/semaphore.h>
22145 +#include <linux/wireless.h>
22146 +#include <linux/module.h>
22147 +#include <asm/io.h>
22148 +
22149 +#include <a_config.h>
22150 +#include <athdefs.h>
22151 +#include "a_types.h"
22152 +#include "a_osapi.h"
22153 +#include "htc_api.h"
22154 +#include "wmi.h"
22155 +#include "a_drv.h"
22156 +#include "bmi.h"
22157 +#include <ieee80211.h>
22158 +#include <ieee80211_ioctl.h>
22159 +#include <wlan_api.h>
22160 +#include <wmi_api.h>
22161 +#include "gpio_api.h"
22162 +#include "gpio.h"
22163 +#include <host_version.h>
22164 +#include <linux/rtnetlink.h>
22165 +#include <linux/init.h>
22166 +#include <linux/moduleparam.h>
22167 +#include "AR6Khwreg.h"
22168 +#include "ar6000_api.h"
22169 +#ifdef CONFIG_HOST_TCMD_SUPPORT
22170 +#include <testcmd.h>
22171 +#endif
22172 +
22173 +#include "targaddrs.h"
22174 +#include "dbglog_api.h"
22175 +#include "ar6000_diag.h"
22176 +#include "common_drv.h"
22177 +
22178 +#ifndef __dev_put
22179 +#define __dev_put(dev) dev_put(dev)
22180 +#endif
22181 +
22182 +#ifdef USER_KEYS
22183 +
22184 +#define USER_SAVEDKEYS_STAT_INIT 0
22185 +#define USER_SAVEDKEYS_STAT_RUN 1
22186 +
22187 +// TODO this needs to move into the AR_SOFTC struct
22188 +struct USER_SAVEDKEYS {
22189 + struct ieee80211req_key ucast_ik;
22190 + struct ieee80211req_key bcast_ik;
22191 + CRYPTO_TYPE keyType;
22192 + A_BOOL keyOk;
22193 +};
22194 +#endif
22195 +
22196 +#define DBG_INFO 0x00000001
22197 +#define DBG_ERROR 0x00000002
22198 +#define DBG_WARNING 0x00000004
22199 +#define DBG_SDIO 0x00000008
22200 +#define DBG_HIF 0x00000010
22201 +#define DBG_HTC 0x00000020
22202 +#define DBG_WMI 0x00000040
22203 +#define DBG_WMI2 0x00000080
22204 +#define DBG_DRIVER 0x00000100
22205 +
22206 +#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING)
22207 +
22208 +
22209 +#ifdef DEBUG
22210 +#define AR_DEBUG_PRINTF(args...) if (debugdriver) A_PRINTF(args);
22211 +#define AR_DEBUG2_PRINTF(args...) if (debugdriver >= 2) A_PRINTF(args);
22212 +extern int debugdriver;
22213 +#else
22214 +#define AR_DEBUG_PRINTF(args...)
22215 +#define AR_DEBUG2_PRINTF(args...)
22216 +#endif
22217 +
22218 +A_STATUS ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
22219 +A_STATUS ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
22220 +
22221 +#ifdef __cplusplus
22222 +extern "C" {
22223 +#endif
22224 +
22225 +#define MAX_AR6000 1
22226 +#define AR6000_MAX_RX_BUFFERS 16
22227 +#define AR6000_BUFFER_SIZE 1664
22228 +#define AR6000_TX_TIMEOUT 10
22229 +#define AR6000_ETH_ADDR_LEN 6
22230 +#define AR6000_MAX_ENDPOINTS 4
22231 +#define MAX_NODE_NUM 15
22232 +#define MAX_COOKIE_NUM 150
22233 +#define AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT 1
22234 +#define AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT 1
22235 +
22236 +enum {
22237 + DRV_HB_CHALLENGE = 0,
22238 + APP_HB_CHALLENGE
22239 +};
22240 +
22241 +/* HTC RAW streams */
22242 +typedef enum _HTC_RAW_STREAM_ID {
22243 + HTC_RAW_STREAM_NOT_MAPPED = -1,
22244 + HTC_RAW_STREAM_0 = 0,
22245 + HTC_RAW_STREAM_1 = 1,
22246 + HTC_RAW_STREAM_2 = 2,
22247 + HTC_RAW_STREAM_3 = 3,
22248 + HTC_RAW_STREAM_NUM_MAX
22249 +} HTC_RAW_STREAM_ID;
22250 +
22251 +#define RAW_HTC_READ_BUFFERS_NUM 4
22252 +#define RAW_HTC_WRITE_BUFFERS_NUM 4
22253 +
22254 +typedef struct {
22255 + int currPtr;
22256 + int length;
22257 + unsigned char data[AR6000_BUFFER_SIZE];
22258 + HTC_PACKET HTCPacket;
22259 +} raw_htc_buffer;
22260 +
22261 +#ifdef CONFIG_HOST_TCMD_SUPPORT
22262 +/*
22263 + * add TCMD_MODE besides wmi and bypasswmi
22264 + * in TCMD_MODE, only few TCMD releated wmi commands
22265 + * counld be hanlder
22266 + */
22267 +enum {
22268 + AR6000_WMI_MODE = 0,
22269 + AR6000_BYPASS_MODE,
22270 + AR6000_TCMD_MODE,
22271 + AR6000_WLAN_MODE
22272 +};
22273 +#endif /* CONFIG_HOST_TCMD_SUPPORT */
22274 +
22275 +struct ar_wep_key {
22276 + A_UINT8 arKeyIndex;
22277 + A_UINT8 arKeyLen;
22278 + A_UINT8 arKey[64];
22279 +} ;
22280 +
22281 +struct ar_node_mapping {
22282 + A_UINT8 macAddress[6];
22283 + A_UINT8 epId;
22284 + A_UINT8 txPending;
22285 +};
22286 +
22287 +struct ar_cookie {
22288 + A_UINT32 arc_bp[2]; /* Must be first field */
22289 + HTC_PACKET HtcPkt; /* HTC packet wrapper */
22290 + struct ar_cookie *arc_list_next;
22291 +};
22292 +
22293 +struct ar_hb_chlng_resp {
22294 + A_TIMER timer;
22295 + A_UINT32 frequency;
22296 + A_UINT32 seqNum;
22297 + A_BOOL outstanding;
22298 + A_UINT8 missCnt;
22299 + A_UINT8 missThres;
22300 +};
22301 +
22302 +typedef struct ar6_softc {
22303 + struct net_device *arNetDev; /* net_device pointer */
22304 + void *arWmi;
22305 + int arTxPending[WMI_PRI_MAX_COUNT];
22306 + int arTotalTxDataPending;
22307 + A_UINT8 arNumDataEndPts;
22308 + A_BOOL arWmiEnabled;
22309 + A_BOOL arWmiReady;
22310 + A_BOOL arConnected;
22311 + A_BOOL arRadioSwitch;
22312 + HTC_HANDLE arHtcTarget;
22313 + void *arHifDevice;
22314 + spinlock_t arLock;
22315 + struct semaphore arSem;
22316 + int arRxBuffers[WMI_PRI_MAX_COUNT];
22317 + int arSsidLen;
22318 + u_char arSsid[32];
22319 + A_UINT8 arNetworkType;
22320 + A_UINT8 arDot11AuthMode;
22321 + A_UINT8 arAuthMode;
22322 + A_UINT8 arPairwiseCrypto;
22323 + A_UINT8 arPairwiseCryptoLen;
22324 + A_UINT8 arGroupCrypto;
22325 + A_UINT8 arGroupCryptoLen;
22326 + A_UINT8 arDefTxKeyIndex;
22327 + struct ar_wep_key arWepKeyList[WMI_MAX_KEY_INDEX + 1];
22328 + A_UINT8 arBssid[6];
22329 + A_UINT8 arReqBssid[6];
22330 + A_UINT16 arChannelHint;
22331 + A_UINT16 arBssChannel;
22332 + A_UINT16 arListenInterval;
22333 + struct ar6000_version arVersion;
22334 + A_UINT32 arTargetType;
22335 + A_INT8 arRssi;
22336 + A_UINT8 arTxPwr;
22337 + A_BOOL arTxPwrSet;
22338 + A_INT32 arBitRate;
22339 + struct net_device_stats arNetStats;
22340 + struct iw_statistics arIwStats;
22341 + A_INT8 arNumChannels;
22342 + A_UINT16 arChannelList[32];
22343 + A_UINT32 arRegCode;
22344 + A_BOOL statsUpdatePending;
22345 + TARGET_STATS arTargetStats;
22346 + A_INT8 arMaxRetries;
22347 + A_UINT8 arPhyCapability;
22348 +#ifdef CONFIG_HOST_TCMD_SUPPORT
22349 + A_UINT8 tcmdRxReport;
22350 + A_UINT32 tcmdRxTotalPkt;
22351 + A_INT32 tcmdRxRssi;
22352 + A_UINT32 tcmdPm;
22353 + A_UINT32 arTargetMode;
22354 +#endif
22355 + AR6000_WLAN_STATE arWlanState;
22356 + struct ar_node_mapping arNodeMap[MAX_NODE_NUM];
22357 + A_UINT8 arIbssPsEnable;
22358 + A_UINT8 arNodeNum;
22359 + A_UINT8 arNexEpId;
22360 + struct ar_cookie *arCookieList;
22361 + A_UINT16 arRateMask;
22362 + A_UINT8 arSkipScan;
22363 + A_UINT16 arBeaconInterval;
22364 + A_BOOL arConnectPending;
22365 + A_BOOL arWmmEnabled;
22366 + struct ar_hb_chlng_resp arHBChallengeResp;
22367 + A_UINT8 arKeepaliveConfigured;
22368 + A_UINT32 arMgmtFilter;
22369 + HTC_ENDPOINT_ID arWmi2EpMapping[WMI_PRI_MAX_COUNT];
22370 + WMI_PRI_STREAM_ID arEp2WmiMapping[ENDPOINT_MAX];
22371 +#ifdef HTC_RAW_INTERFACE
22372 + HTC_ENDPOINT_ID arRaw2EpMapping[HTC_RAW_STREAM_NUM_MAX];
22373 + HTC_RAW_STREAM_ID arEp2RawMapping[ENDPOINT_MAX];
22374 + struct semaphore raw_htc_read_sem[HTC_RAW_STREAM_NUM_MAX];
22375 + struct semaphore raw_htc_write_sem[HTC_RAW_STREAM_NUM_MAX];
22376 + wait_queue_head_t raw_htc_read_queue[HTC_RAW_STREAM_NUM_MAX];
22377 + wait_queue_head_t raw_htc_write_queue[HTC_RAW_STREAM_NUM_MAX];
22378 + raw_htc_buffer *raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM];
22379 + raw_htc_buffer *raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM];
22380 + A_BOOL write_buffer_available[HTC_RAW_STREAM_NUM_MAX];
22381 + A_BOOL read_buffer_available[HTC_RAW_STREAM_NUM_MAX];
22382 +#endif
22383 + A_BOOL arRawIfInit;
22384 + int arDeviceIndex;
22385 + COMMON_CREDIT_STATE_INFO arCreditStateInfo;
22386 + A_BOOL arWMIControlEpFull;
22387 + A_BOOL dbgLogFetchInProgress;
22388 + A_UCHAR log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE];
22389 + A_UINT32 log_cnt;
22390 + A_UINT32 dbglog_init_done;
22391 + A_UINT32 arConnectCtrlFlags;
22392 + A_UINT32 scan_complete;
22393 +#ifdef USER_KEYS
22394 + A_INT32 user_savedkeys_stat;
22395 + A_UINT32 user_key_ctrl;
22396 + struct USER_SAVEDKEYS user_saved_keys;
22397 +#endif
22398 +} AR_SOFTC_T;
22399 +
22400 +
22401 +#define arWMIStream2EndpointID(ar,wmi) (ar)->arWmi2EpMapping[(wmi)]
22402 +#define arSetWMIStream2EndpointIDMap(ar,wmi,ep) \
22403 +{ (ar)->arWmi2EpMapping[(wmi)] = (ep); \
22404 + (ar)->arEp2WmiMapping[(ep)] = (wmi); }
22405 +#define arEndpoint2WMIStreamID(ar,ep) (ar)->arEp2WmiMapping[(ep)]
22406 +
22407 +#define arRawIfEnabled(ar) (ar)->arRawIfInit
22408 +#define arRawStream2EndpointID(ar,raw) (ar)->arRaw2EpMapping[(raw)]
22409 +#define arSetRawStream2EndpointIDMap(ar,raw,ep) \
22410 +{ (ar)->arRaw2EpMapping[(raw)] = (ep); \
22411 + (ar)->arEp2RawMapping[(ep)] = (raw); }
22412 +#define arEndpoint2RawStreamID(ar,ep) (ar)->arEp2RawMapping[(ep)]
22413 +
22414 +struct ar_giwscan_param {
22415 + char *current_ev;
22416 + char *end_buf;
22417 + A_BOOL firstPass;
22418 +};
22419 +
22420 +#define AR6000_STAT_INC(ar, stat) (ar->arNetStats.stat++)
22421 +
22422 +#define AR6000_SPIN_LOCK(lock, param) do { \
22423 + if (irqs_disabled()) { \
22424 + AR_DEBUG_PRINTF("IRQs disabled:AR6000_LOCK\n"); \
22425 + } \
22426 + spin_lock_bh(lock); \
22427 +} while (0)
22428 +
22429 +#define AR6000_SPIN_UNLOCK(lock, param) do { \
22430 + if (irqs_disabled()) { \
22431 + AR_DEBUG_PRINTF("IRQs disabled: AR6000_UNLOCK\n"); \
22432 + } \
22433 + spin_unlock_bh(lock); \
22434 +} while (0)
22435 +
22436 +int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
22437 +int ar6000_ioctl_dispatcher(struct net_device *dev, struct ifreq *rq, int cmd);
22438 +void ar6000_ioctl_iwsetup(struct iw_handler_def *def);
22439 +void ar6000_gpio_init(void);
22440 +void ar6000_init_profile_info(AR_SOFTC_T *ar);
22441 +void ar6000_install_static_wep_keys(AR_SOFTC_T *ar);
22442 +int ar6000_init(struct net_device *dev);
22443 +int ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar);
22444 +A_STATUS ar6000_SetHTCBlockSize(AR_SOFTC_T *ar);
22445 +
22446 +#ifdef HTC_RAW_INTERFACE
22447 +
22448 +#ifndef __user
22449 +#define __user
22450 +#endif
22451 +
22452 +int ar6000_htc_raw_open(AR_SOFTC_T *ar);
22453 +int ar6000_htc_raw_close(AR_SOFTC_T *ar);
22454 +ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar,
22455 + HTC_RAW_STREAM_ID StreamID,
22456 + char __user *buffer, size_t count);
22457 +ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar,
22458 + HTC_RAW_STREAM_ID StreamID,
22459 + char __user *buffer, size_t count);
22460 +
22461 +#endif /* HTC_RAW_INTERFACE */
22462 +
22463 +#ifdef __cplusplus
22464 +}
22465 +#endif
22466 +
22467 +#endif /* _AR6000_H_ */
22468 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ar6000_raw_if.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ar6000_raw_if.c
22469 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ar6000_raw_if.c 1970-01-01 01:00:00.000000000 +0100
22470 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ar6000_raw_if.c 2009-05-10 22:27:59.000000000 +0200
22471 @@ -0,0 +1,440 @@
22472 +/*
22473 + *
22474 + * Copyright (c) 2004-2007 Atheros Communications Inc.
22475 + * All rights reserved.
22476 + *
22477 + *
22478 + * This program is free software; you can redistribute it and/or modify
22479 + * it under the terms of the GNU General Public License version 2 as
22480 + * published by the Free Software Foundation;
22481 + *
22482 + * Software distributed under the License is distributed on an "AS
22483 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
22484 + * implied. See the License for the specific language governing
22485 + * rights and limitations under the License.
22486 + *
22487 + *
22488 + *
22489 + */
22490 +
22491 +#include "ar6000_drv.h"
22492 +
22493 +#ifdef HTC_RAW_INTERFACE
22494 +
22495 +static void
22496 +ar6000_htc_raw_read_cb(void *Context, HTC_PACKET *pPacket)
22497 +{
22498 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
22499 + raw_htc_buffer *busy;
22500 + HTC_RAW_STREAM_ID streamID;
22501 +
22502 + busy = (raw_htc_buffer *)pPacket->pPktContext;
22503 + A_ASSERT(busy != NULL);
22504 +
22505 + if (pPacket->Status == A_ECANCELED) {
22506 + /*
22507 + * HTC provides A_ECANCELED status when it doesn't want to be refilled
22508 + * (probably due to a shutdown)
22509 + */
22510 + return;
22511 + }
22512 +
22513 + streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint);
22514 + A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED);
22515 +
22516 +#ifdef CF
22517 + if (down_trylock(&ar->raw_htc_read_sem[streamID])) {
22518 +#else
22519 + if (down_interruptible(&ar->raw_htc_read_sem[streamID])) {
22520 +#endif /* CF */
22521 + AR_DEBUG2_PRINTF("Unable to down the semaphore\n");
22522 + }
22523 +
22524 + A_ASSERT((pPacket->Status != A_OK) ||
22525 + (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN)));
22526 +
22527 + busy->length = pPacket->ActualLength + HTC_HEADER_LEN;
22528 + busy->currPtr = HTC_HEADER_LEN;
22529 + ar->read_buffer_available[streamID] = TRUE;
22530 + //AR_DEBUG_PRINTF("raw read cb: 0x%X 0x%X \n", busy->currPtr,busy->length);
22531 + up(&ar->raw_htc_read_sem[streamID]);
22532 +
22533 + /* Signal the waiting process */
22534 + AR_DEBUG2_PRINTF("Waking up the StreamID(%d) read process\n", streamID);
22535 + wake_up_interruptible(&ar->raw_htc_read_queue[streamID]);
22536 +}
22537 +
22538 +static void
22539 +ar6000_htc_raw_write_cb(void *Context, HTC_PACKET *pPacket)
22540 +{
22541 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
22542 + raw_htc_buffer *free;
22543 + HTC_RAW_STREAM_ID streamID;
22544 +
22545 + free = (raw_htc_buffer *)pPacket->pPktContext;
22546 + A_ASSERT(free != NULL);
22547 +
22548 + if (pPacket->Status == A_ECANCELED) {
22549 + /*
22550 + * HTC provides A_ECANCELED status when it doesn't want to be refilled
22551 + * (probably due to a shutdown)
22552 + */
22553 + return;
22554 + }
22555 +
22556 + streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint);
22557 + A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED);
22558 +
22559 +#ifdef CF
22560 + if (down_trylock(&ar->raw_htc_write_sem[streamID])) {
22561 +#else
22562 + if (down_interruptible(&ar->raw_htc_write_sem[streamID])) {
22563 +#endif
22564 + AR_DEBUG2_PRINTF("Unable to down the semaphore\n");
22565 + }
22566 +
22567 + A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN));
22568 +
22569 + free->length = 0;
22570 + ar->write_buffer_available[streamID] = TRUE;
22571 + up(&ar->raw_htc_write_sem[streamID]);
22572 +
22573 + /* Signal the waiting process */
22574 + AR_DEBUG2_PRINTF("Waking up the StreamID(%d) write process\n", streamID);
22575 + wake_up_interruptible(&ar->raw_htc_write_queue[streamID]);
22576 +}
22577 +
22578 +/* connect to a service */
22579 +static A_STATUS ar6000_connect_raw_service(AR_SOFTC_T *ar,
22580 + HTC_RAW_STREAM_ID StreamID)
22581 +{
22582 + A_STATUS status;
22583 + HTC_SERVICE_CONNECT_RESP response;
22584 + A_UINT8 streamNo;
22585 + HTC_SERVICE_CONNECT_REQ connect;
22586 +
22587 + do {
22588 +
22589 + A_MEMZERO(&connect,sizeof(connect));
22590 + /* pass the stream ID as meta data to the RAW streams service */
22591 + streamNo = (A_UINT8)StreamID;
22592 + connect.pMetaData = &streamNo;
22593 + connect.MetaDataLength = sizeof(A_UINT8);
22594 + /* these fields are the same for all endpoints */
22595 + connect.EpCallbacks.pContext = ar;
22596 + connect.EpCallbacks.EpTxComplete = ar6000_htc_raw_write_cb;
22597 + connect.EpCallbacks.EpRecv = ar6000_htc_raw_read_cb;
22598 + /* simple interface, we don't need these optional callbacks */
22599 + connect.EpCallbacks.EpRecvRefill = NULL;
22600 + connect.EpCallbacks.EpSendFull = NULL;
22601 + connect.EpCallbacks.EpSendAvail = NULL;
22602 + connect.MaxSendQueueDepth = RAW_HTC_WRITE_BUFFERS_NUM;
22603 +
22604 + /* connect to the raw streams service, we may be able to get 1 or more
22605 + * connections, depending on WHAT is running on the target */
22606 + connect.ServiceID = HTC_RAW_STREAMS_SVC;
22607 +
22608 + A_MEMZERO(&response,sizeof(response));
22609 +
22610 + /* try to connect to the raw stream, it is okay if this fails with
22611 + * status HTC_SERVICE_NO_MORE_EP */
22612 + status = HTCConnectService(ar->arHtcTarget,
22613 + &connect,
22614 + &response);
22615 +
22616 + if (A_FAILED(status)) {
22617 + if (response.ConnectRespCode == HTC_SERVICE_NO_MORE_EP) {
22618 + AR_DEBUG_PRINTF("HTC RAW , No more streams allowed \n");
22619 + status = A_OK;
22620 + }
22621 + break;
22622 + }
22623 +
22624 + /* set endpoint mapping for the RAW HTC streams */
22625 + arSetRawStream2EndpointIDMap(ar,StreamID,response.Endpoint);
22626 +
22627 + AR_DEBUG_PRINTF("HTC RAW : stream ID: %d, endpoint: %d\n",
22628 + StreamID, arRawStream2EndpointID(ar,StreamID));
22629 +
22630 + } while (FALSE);
22631 +
22632 + return status;
22633 +}
22634 +
22635 +int ar6000_htc_raw_open(AR_SOFTC_T *ar)
22636 +{
22637 + A_STATUS status;
22638 + int streamID, endPt, count2;
22639 + raw_htc_buffer *buffer;
22640 + HTC_SERVICE_ID servicepriority;
22641 +
22642 + A_ASSERT(ar->arHtcTarget != NULL);
22643 +
22644 + /* wait for target */
22645 + status = HTCWaitTarget(ar->arHtcTarget);
22646 +
22647 + if (A_FAILED(status)) {
22648 + AR_DEBUG_PRINTF("HTCWaitTarget failed (%d)\n", status);
22649 + return -ENODEV;
22650 + }
22651 +
22652 + for (endPt = 0; endPt < ENDPOINT_MAX; endPt++) {
22653 + ar->arEp2RawMapping[endPt] = HTC_RAW_STREAM_NOT_MAPPED;
22654 + }
22655 +
22656 + for (streamID = HTC_RAW_STREAM_0; streamID < HTC_RAW_STREAM_NUM_MAX; streamID++) {
22657 + /* Initialize the data structures */
22658 + init_MUTEX(&ar->raw_htc_read_sem[streamID]);
22659 + init_MUTEX(&ar->raw_htc_write_sem[streamID]);
22660 + init_waitqueue_head(&ar->raw_htc_read_queue[streamID]);
22661 + init_waitqueue_head(&ar->raw_htc_write_queue[streamID]);
22662 +
22663 + /* try to connect to the raw service */
22664 + status = ar6000_connect_raw_service(ar,streamID);
22665 +
22666 + if (A_FAILED(status)) {
22667 + break;
22668 + }
22669 +
22670 + if (arRawStream2EndpointID(ar,streamID) == 0) {
22671 + break;
22672 + }
22673 +
22674 + for (count2 = 0; count2 < RAW_HTC_READ_BUFFERS_NUM; count2 ++) {
22675 + /* Initialize the receive buffers */
22676 + buffer = ar->raw_htc_write_buffer[streamID][count2];
22677 + memset(buffer, 0, sizeof(raw_htc_buffer));
22678 + buffer = ar->raw_htc_read_buffer[streamID][count2];
22679 + memset(buffer, 0, sizeof(raw_htc_buffer));
22680 +
22681 + SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket,
22682 + buffer,
22683 + buffer->data,
22684 + AR6000_BUFFER_SIZE,
22685 + arRawStream2EndpointID(ar,streamID));
22686 +
22687 + /* Queue buffers to HTC for receive */
22688 + if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != A_OK)
22689 + {
22690 + BMIInit();
22691 + return -EIO;
22692 + }
22693 + }
22694 +
22695 + for (count2 = 0; count2 < RAW_HTC_WRITE_BUFFERS_NUM; count2 ++) {
22696 + /* Initialize the receive buffers */
22697 + buffer = ar->raw_htc_write_buffer[streamID][count2];
22698 + memset(buffer, 0, sizeof(raw_htc_buffer));
22699 + }
22700 +
22701 + ar->read_buffer_available[streamID] = FALSE;
22702 + ar->write_buffer_available[streamID] = TRUE;
22703 + }
22704 +
22705 + if (A_FAILED(status)) {
22706 + return -EIO;
22707 + }
22708 +
22709 + AR_DEBUG_PRINTF("HTC RAW, number of streams the target supports: %d \n", streamID);
22710 +
22711 + servicepriority = HTC_RAW_STREAMS_SVC; /* only 1 */
22712 +
22713 + /* set callbacks and priority list */
22714 + HTCSetCreditDistribution(ar->arHtcTarget,
22715 + ar,
22716 + NULL, /* use default */
22717 + NULL, /* use default */
22718 + &servicepriority,
22719 + 1);
22720 +
22721 + /* Start the HTC component */
22722 + if ((status = HTCStart(ar->arHtcTarget)) != A_OK) {
22723 + BMIInit();
22724 + return -EIO;
22725 + }
22726 +
22727 + (ar)->arRawIfInit = TRUE;
22728 +
22729 + return 0;
22730 +}
22731 +
22732 +int ar6000_htc_raw_close(AR_SOFTC_T *ar)
22733 +{
22734 + A_PRINTF("ar6000_htc_raw_close called \n");
22735 + HTCStop(ar->arHtcTarget);
22736 +
22737 + /* reset the device */
22738 + ar6000_reset_device(ar->arHifDevice, ar->arTargetType);
22739 + /* Initialize the BMI component */
22740 + BMIInit();
22741 +
22742 + return 0;
22743 +}
22744 +
22745 +raw_htc_buffer *
22746 +get_filled_buffer(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID)
22747 +{
22748 + int count;
22749 + raw_htc_buffer *busy;
22750 +
22751 + /* Check for data */
22752 + for (count = 0; count < RAW_HTC_READ_BUFFERS_NUM; count ++) {
22753 + busy = ar->raw_htc_read_buffer[StreamID][count];
22754 + if (busy->length) {
22755 + break;
22756 + }
22757 + }
22758 + if (busy->length) {
22759 + ar->read_buffer_available[StreamID] = TRUE;
22760 + } else {
22761 + ar->read_buffer_available[StreamID] = FALSE;
22762 + }
22763 +
22764 + return busy;
22765 +}
22766 +
22767 +ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
22768 + char __user *buffer, size_t length)
22769 +{
22770 + int readPtr;
22771 + raw_htc_buffer *busy;
22772 +
22773 + if (arRawStream2EndpointID(ar,StreamID) == 0) {
22774 + AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID);
22775 + return -EFAULT;
22776 + }
22777 +
22778 + if (down_interruptible(&ar->raw_htc_read_sem[StreamID])) {
22779 + return -ERESTARTSYS;
22780 + }
22781 +
22782 + busy = get_filled_buffer(ar,StreamID);
22783 + while (!ar->read_buffer_available[StreamID]) {
22784 + up(&ar->raw_htc_read_sem[StreamID]);
22785 +
22786 + /* Wait for the data */
22787 + AR_DEBUG2_PRINTF("Sleeping StreamID(%d) read process\n", StreamID);
22788 + if (wait_event_interruptible(ar->raw_htc_read_queue[StreamID],
22789 + ar->read_buffer_available[StreamID]))
22790 + {
22791 + return -EINTR;
22792 + }
22793 + if (down_interruptible(&ar->raw_htc_read_sem[StreamID])) {
22794 + return -ERESTARTSYS;
22795 + }
22796 + busy = get_filled_buffer(ar,StreamID);
22797 + }
22798 +
22799 + /* Read the data */
22800 + readPtr = busy->currPtr;
22801 + if (length > busy->length - HTC_HEADER_LEN) {
22802 + length = busy->length - HTC_HEADER_LEN;
22803 + }
22804 + if (copy_to_user(buffer, &busy->data[readPtr], length)) {
22805 + up(&ar->raw_htc_read_sem[StreamID]);
22806 + return -EFAULT;
22807 + }
22808 +
22809 + busy->currPtr += length;
22810 +
22811 + //AR_DEBUG_PRINTF("raw read ioctl: currPTR : 0x%X 0x%X \n", busy->currPtr,busy->length);
22812 +
22813 + if (busy->currPtr == busy->length)
22814 + {
22815 + busy->currPtr = 0;
22816 + busy->length = 0;
22817 + HTC_PACKET_RESET_RX(&busy->HTCPacket);
22818 + //AR_DEBUG_PRINTF("raw read ioctl: ep for packet:%d \n", busy->HTCPacket.Endpoint);
22819 + HTCAddReceivePkt(ar->arHtcTarget, &busy->HTCPacket);
22820 + }
22821 + ar->read_buffer_available[StreamID] = FALSE;
22822 + up(&ar->raw_htc_read_sem[StreamID]);
22823 +
22824 + return length;
22825 +}
22826 +
22827 +static raw_htc_buffer *
22828 +get_free_buffer(AR_SOFTC_T *ar, HTC_ENDPOINT_ID StreamID)
22829 +{
22830 + int count;
22831 + raw_htc_buffer *free;
22832 +
22833 + free = NULL;
22834 + for (count = 0; count < RAW_HTC_WRITE_BUFFERS_NUM; count ++) {
22835 + free = ar->raw_htc_write_buffer[StreamID][count];
22836 + if (free->length == 0) {
22837 + break;
22838 + }
22839 + }
22840 + if (!free->length) {
22841 + ar->write_buffer_available[StreamID] = TRUE;
22842 + } else {
22843 + ar->write_buffer_available[StreamID] = FALSE;
22844 + }
22845 +
22846 + return free;
22847 +}
22848 +
22849 +ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
22850 + char __user *buffer, size_t length)
22851 +{
22852 + int writePtr;
22853 + raw_htc_buffer *free;
22854 +
22855 + if (arRawStream2EndpointID(ar,StreamID) == 0) {
22856 + AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID);
22857 + return -EFAULT;
22858 + }
22859 +
22860 + if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) {
22861 + return -ERESTARTSYS;
22862 + }
22863 +
22864 + /* Search for a free buffer */
22865 + free = get_free_buffer(ar,StreamID);
22866 +
22867 + /* Check if there is space to write else wait */
22868 + while (!ar->write_buffer_available[StreamID]) {
22869 + up(&ar->raw_htc_write_sem[StreamID]);
22870 +
22871 + /* Wait for buffer to become free */
22872 + AR_DEBUG2_PRINTF("Sleeping StreamID(%d) write process\n", StreamID);
22873 + if (wait_event_interruptible(ar->raw_htc_write_queue[StreamID],
22874 + ar->write_buffer_available[StreamID]))
22875 + {
22876 + return -EINTR;
22877 + }
22878 + if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) {
22879 + return -ERESTARTSYS;
22880 + }
22881 + free = get_free_buffer(ar,StreamID);
22882 + }
22883 +
22884 + /* Send the data */
22885 + writePtr = HTC_HEADER_LEN;
22886 + if (length > (AR6000_BUFFER_SIZE - HTC_HEADER_LEN)) {
22887 + length = AR6000_BUFFER_SIZE - HTC_HEADER_LEN;
22888 + }
22889 +
22890 + if (copy_from_user(&free->data[writePtr], buffer, length)) {
22891 + up(&ar->raw_htc_read_sem[StreamID]);
22892 + return -EFAULT;
22893 + }
22894 +
22895 + free->length = length;
22896 +
22897 + SET_HTC_PACKET_INFO_TX(&free->HTCPacket,
22898 + free,
22899 + &free->data[writePtr],
22900 + length,
22901 + arRawStream2EndpointID(ar,StreamID),
22902 + AR6K_DATA_PKT_TAG);
22903 +
22904 + HTCSendPkt(ar->arHtcTarget,&free->HTCPacket);
22905 +
22906 + ar->write_buffer_available[StreamID] = FALSE;
22907 + up(&ar->raw_htc_write_sem[StreamID]);
22908 +
22909 + return length;
22910 +}
22911 +#endif /* HTC_RAW_INTERFACE */
22912 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ar6xapi_linux.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ar6xapi_linux.h
22913 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ar6xapi_linux.h 1970-01-01 01:00:00.000000000 +0100
22914 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ar6xapi_linux.h 2009-05-10 22:27:59.000000000 +0200
22915 @@ -0,0 +1,128 @@
22916 +#ifndef _AR6XAPI_LINUX_H
22917 +#define _AR6XAPI_LINUX_H
22918 +/*
22919 + *
22920 + * Copyright (c) 2004-2007 Atheros Communications Inc.
22921 + * All rights reserved.
22922 + *
22923 + *
22924 + * This program is free software; you can redistribute it and/or modify
22925 + * it under the terms of the GNU General Public License version 2 as
22926 + * published by the Free Software Foundation;
22927 + *
22928 + * Software distributed under the License is distributed on an "AS
22929 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
22930 + * implied. See the License for the specific language governing
22931 + * rights and limitations under the License.
22932 + *
22933 + *
22934 + *
22935 + */
22936 +
22937 +#ifdef __cplusplus
22938 +extern "C" {
22939 +#endif
22940 +
22941 +struct ar6_softc;
22942 +
22943 +void ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap);
22944 +A_UINT8 ar6000_iptos_to_userPriority(A_UINT8 *pkt);
22945 +A_STATUS ar6000_control_tx(void *devt, void *osbuf, WMI_PRI_STREAM_ID streamID);
22946 +void ar6000_connect_event(struct ar6_softc *ar, A_UINT16 channel,
22947 + A_UINT8 *bssid, A_UINT16 listenInterval,
22948 + A_UINT16 beaconInterval, NETWORK_TYPE networkType,
22949 + A_UINT8 beaconIeLen, A_UINT8 assocReqLen,
22950 + A_UINT8 assocRespLen,A_UINT8 *assocInfo);
22951 +void ar6000_disconnect_event(struct ar6_softc *ar, A_UINT8 reason,
22952 + A_UINT8 *bssid, A_UINT8 assocRespLen,
22953 + A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus);
22954 +void ar6000_tkip_micerr_event(struct ar6_softc *ar, A_UINT8 keyid,
22955 + A_BOOL ismcast);
22956 +void ar6000_bitrate_rx(void *devt, A_INT32 rateKbps);
22957 +void ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList);
22958 +void ar6000_regDomain_event(struct ar6_softc *ar, A_UINT32 regCode);
22959 +void ar6000_txPwr_rx(void *devt, A_UINT8 txPwr);
22960 +void ar6000_keepalive_rx(void *devt, A_UINT8 configured);
22961 +void ar6000_neighborReport_event(struct ar6_softc *ar, int numAps,
22962 + WMI_NEIGHBOR_INFO *info);
22963 +void ar6000_set_numdataendpts(struct ar6_softc *ar, A_UINT32 num);
22964 +void ar6000_scanComplete_event(struct ar6_softc *ar, A_STATUS status);
22965 +void ar6000_targetStats_event(struct ar6_softc *ar, WMI_TARGET_STATS *pStats);
22966 +void ar6000_rssiThreshold_event(struct ar6_softc *ar,
22967 + WMI_RSSI_THRESHOLD_VAL newThreshold,
22968 + A_INT16 rssi);
22969 +void ar6000_reportError_event(struct ar6_softc *, WMI_TARGET_ERROR_VAL errorVal);
22970 +void ar6000_cac_event(struct ar6_softc *ar, A_UINT8 ac, A_UINT8 cac_indication,
22971 + A_UINT8 statusCode, A_UINT8 *tspecSuggestion);
22972 +void ar6000_hbChallengeResp_event(struct ar6_softc *, A_UINT32 cookie, A_UINT32 source);
22973 +void
22974 +ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl);
22975 +
22976 +void
22977 +ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p);
22978 +
22979 +void
22980 +ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters,
22981 + WMI_GET_WOW_LIST_REPLY *wow_reply);
22982 +
22983 +void ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID,
22984 + WMI_PMKID *pmkidList);
22985 +
22986 +void ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values);
22987 +void ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value);
22988 +void ar6000_gpio_ack_rx(void);
22989 +
22990 +void ar6000_dbglog_init_done(struct ar6_softc *ar);
22991 +
22992 +#ifdef SEND_EVENT_TO_APP
22993 +void ar6000_send_event_to_app(struct ar6_softc *ar, A_UINT16 eventId, A_UINT8 *datap, int len);
22994 +#endif
22995 +
22996 +#ifdef CONFIG_HOST_TCMD_SUPPORT
22997 +void ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len);
22998 +#endif
22999 +
23000 +void ar6000_tx_retry_err_event(void *devt);
23001 +
23002 +void ar6000_snrThresholdEvent_rx(void *devt,
23003 + WMI_SNR_THRESHOLD_VAL newThreshold,
23004 + A_UINT8 snr);
23005 +
23006 +void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, A_UINT8 lqVal);
23007 +
23008 +
23009 +void ar6000_ratemask_rx(void *devt, A_UINT16 ratemask);
23010 +
23011 +A_STATUS ar6000_get_driver_cfg(struct net_device *dev,
23012 + A_UINT16 cfgParam,
23013 + void *result);
23014 +void ar6000_bssInfo_event_rx(struct ar6_softc *ar, A_UINT8 *data, int len);
23015 +
23016 +void ar6000_dbglog_event(struct ar6_softc *ar, A_UINT32 dropped,
23017 + A_INT8 *buffer, A_UINT32 length);
23018 +
23019 +int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar);
23020 +
23021 +void ar6000_indicate_tx_activity(void *devt, A_UINT8 trafficClass, A_BOOL Active);
23022 +
23023 +void ar6000_dset_open_req(void *devt,
23024 + A_UINT32 id,
23025 + A_UINT32 targ_handle,
23026 + A_UINT32 targ_reply_fn,
23027 + A_UINT32 targ_reply_arg);
23028 +void ar6000_dset_close(void *devt, A_UINT32 access_cookie);
23029 +void ar6000_dset_data_req(void *devt,
23030 + A_UINT32 access_cookie,
23031 + A_UINT32 offset,
23032 + A_UINT32 length,
23033 + A_UINT32 targ_buf,
23034 + A_UINT32 targ_reply_fn,
23035 + A_UINT32 targ_reply_arg);
23036 +
23037 +
23038 +
23039 +#ifdef __cplusplus
23040 +}
23041 +#endif
23042 +
23043 +#endif
23044 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/athdrv_linux.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/athdrv_linux.h
23045 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/athdrv_linux.h 1970-01-01 01:00:00.000000000 +0100
23046 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/athdrv_linux.h 2009-05-10 22:27:59.000000000 +0200
23047 @@ -0,0 +1,993 @@
23048 +/*
23049 + * Copyright (c) 2004-2006 Atheros Communications Inc.
23050 + * All rights reserved.
23051 + *
23052 + *
23053 + *
23054 + * This program is free software; you can redistribute it and/or modify
23055 + * it under the terms of the GNU General Public License version 2 as
23056 + * published by the Free Software Foundation;
23057 + *
23058 + * Software distributed under the License is distributed on an "AS
23059 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
23060 + * implied. See the License for the specific language governing
23061 + * rights and limitations under the License.
23062 + *
23063 + *
23064 + *
23065 + */
23066 +
23067 +#ifndef _ATHDRV_LINUX_H
23068 +#define _ATHDRV_LINUX_H
23069 +
23070 +#ifdef __cplusplus
23071 +extern "C" {
23072 +#endif
23073 +
23074 +
23075 +/*
23076 + * There are two types of ioctl's here: Standard ioctls and
23077 + * eXtended ioctls. All extended ioctls (XIOCTL) are multiplexed
23078 + * off of the single ioctl command, AR6000_IOCTL_EXTENDED. The
23079 + * arguments for every XIOCTL starts with a 32-bit command word
23080 + * that is used to select which extended ioctl is in use. After
23081 + * the command word are command-specific arguments.
23082 + */
23083 +
23084 +/* Linux standard Wireless Extensions, private ioctl interfaces */
23085 +#define IEEE80211_IOCTL_SETPARAM (SIOCIWFIRSTPRIV+0)
23086 +#define IEEE80211_IOCTL_GETPARAM (SIOCIWFIRSTPRIV+1)
23087 +#define IEEE80211_IOCTL_SETKEY (SIOCIWFIRSTPRIV+2)
23088 +#define IEEE80211_IOCTL_SETWMMPARAMS (SIOCIWFIRSTPRIV+3)
23089 +#define IEEE80211_IOCTL_DELKEY (SIOCIWFIRSTPRIV+4)
23090 +#define IEEE80211_IOCTL_GETWMMPARAMS (SIOCIWFIRSTPRIV+5)
23091 +#define IEEE80211_IOCTL_SETOPTIE (SIOCIWFIRSTPRIV+6)
23092 +#define IEEE80211_IOCTL_SETMLME (SIOCIWFIRSTPRIV+7)
23093 +//#define IEEE80211_IOCTL_GETOPTIE (SIOCIWFIRSTPRIV+7)
23094 +#define IEEE80211_IOCTL_ADDPMKID (SIOCIWFIRSTPRIV+8)
23095 +//#define IEEE80211_IOCTL_SETAUTHALG (SIOCIWFIRSTPRIV+10)
23096 +#define IEEE80211_IOCTL_LASTONE (SIOCIWFIRSTPRIV+9)
23097 +
23098 +
23099 +
23100 +/* ====WMI Ioctls==== */
23101 +/*
23102 + *
23103 + * Many ioctls simply provide WMI services to application code:
23104 + * an application makes such an ioctl call with a set of arguments
23105 + * that are packaged into the corresponding WMI message, and sent
23106 + * to the Target.
23107 + */
23108 +
23109 +#define AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+10)
23110 +/*
23111 + * arguments:
23112 + * ar6000_version *revision
23113 + */
23114 +
23115 +#define AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+11)
23116 +/*
23117 + * arguments:
23118 + * WMI_POWER_MODE_CMD pwrModeCmd (see include/wmi.h)
23119 + * uses: WMI_SET_POWER_MODE_CMDID
23120 + */
23121 +
23122 +#define AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+12)
23123 +/*
23124 + * arguments:
23125 + * WMI_SCAN_PARAMS_CMD scanParams (see include/wmi.h)
23126 + * uses: WMI_SET_SCAN_PARAMS_CMDID
23127 + */
23128 +
23129 +#define AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+13)
23130 +/*
23131 + * arguments:
23132 + * UINT32 listenInterval
23133 + * uses: WMI_SET_LISTEN_INT_CMDID
23134 + */
23135 +
23136 +#define AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+14)
23137 +/*
23138 + * arguments:
23139 + * WMI_BSS_FILTER filter (see include/wmi.h)
23140 + * uses: WMI_SET_BSS_FILTER_CMDID
23141 + */
23142 +
23143 +#define AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16)
23144 +/*
23145 + * arguments:
23146 + * WMI_CHANNEL_PARAMS_CMD chParams
23147 + * uses: WMI_SET_CHANNEL_PARAMS_CMDID
23148 + */
23149 +
23150 +#define AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17)
23151 +/*
23152 + * arguments:
23153 + * WMI_PROBED_SSID_CMD probedSsids (see include/wmi.h)
23154 + * uses: WMI_SETPROBED_SSID_CMDID
23155 + */
23156 +
23157 +#define AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18)
23158 +/*
23159 + * arguments:
23160 + * WMI_POWER_PARAMS_CMD powerParams (see include/wmi.h)
23161 + * uses: WMI_SET_POWER_PARAMS_CMDID
23162 + */
23163 +
23164 +#define AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19)
23165 +/*
23166 + * arguments:
23167 + * WMI_ADD_BAD_AP_CMD badAPs (see include/wmi.h)
23168 + * uses: WMI_ADD_BAD_AP_CMDID
23169 + */
23170 +
23171 +#define AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20)
23172 +/*
23173 + * arguments:
23174 + * ar6000_queuereq queueRequest (see below)
23175 + */
23176 +
23177 +#define AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21)
23178 +/*
23179 + * arguments:
23180 + * WMI_CREATE_PSTREAM createPstreamCmd (see include/wmi.h)
23181 + * uses: WMI_CREATE_PSTREAM_CMDID
23182 + */
23183 +
23184 +#define AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22)
23185 +/*
23186 + * arguments:
23187 + * WMI_DELETE_PSTREAM_CMD deletePstreamCmd (see include/wmi.h)
23188 + * uses: WMI_DELETE_PSTREAM_CMDID
23189 + */
23190 +
23191 +#define AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23)
23192 +/*
23193 + * arguments:
23194 + * WMI_SNR_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h)
23195 + * uses: WMI_SNR_THRESHOLD_PARAMS_CMDID
23196 + */
23197 +
23198 +#define AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24)
23199 +/*
23200 + * arguments:
23201 + * WMI_TARGET_ERROR_REPORT_BITMASK errorReportBitMask (see include/wmi.h)
23202 + * uses: WMI_TARGET_ERROR_REPORT_BITMASK_CMDID
23203 + */
23204 +
23205 +#define AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25)
23206 +/*
23207 + * arguments:
23208 + * TARGET_STATS *targetStats (see below)
23209 + * uses: WMI_GET_STATISTICS_CMDID
23210 + */
23211 +
23212 +#define AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26)
23213 +/*
23214 + * arguments:
23215 + * WMI_SET_ASSOC_INFO_CMD setAssocInfoCmd
23216 + * uses: WMI_SET_ASSOC_INFO_CMDID
23217 + */
23218 +
23219 +#define AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27)
23220 +/*
23221 + * arguments:
23222 + * WMI_SET_ACCESS_PARAMS_CMD setAccessParams (see include/wmi.h)
23223 + * uses: WMI_SET_ACCESS_PARAMS_CMDID
23224 + */
23225 +
23226 +#define AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28)
23227 +/*
23228 + * arguments:
23229 + * UINT32 beaconMissTime
23230 + * uses: WMI_SET_BMISS_TIME_CMDID
23231 + */
23232 +
23233 +#define AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29)
23234 +/*
23235 + * arguments:
23236 + * WMI_DISC_TIMEOUT_CMD disconnectTimeoutCmd (see include/wmi.h)
23237 + * uses: WMI_SET_DISC_TIMEOUT_CMDID
23238 + */
23239 +
23240 +#define AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30)
23241 +/*
23242 + * arguments:
23243 + * WMI_IBSS_PM_CAPS_CMD ibssPowerMgmtCapsCmd
23244 + * uses: WMI_SET_IBSS_PM_CAPS_CMDID
23245 + */
23246 +
23247 +/*
23248 + * There is a very small space available for driver-private
23249 + * wireless ioctls. In order to circumvent this limitation,
23250 + * we multiplex a bunch of ioctls (XIOCTLs) on top of a
23251 + * single AR6000_IOCTL_EXTENDED ioctl.
23252 + */
23253 +#define AR6000_IOCTL_EXTENDED (SIOCIWFIRSTPRIV+31)
23254 +
23255 +
23256 +/* ====BMI Extended Ioctls==== */
23257 +
23258 +#define AR6000_XIOCTL_BMI_DONE 1
23259 +/*
23260 + * arguments:
23261 + * UINT32 cmd (AR6000_XIOCTL_BMI_DONE)
23262 + * uses: BMI_DONE
23263 + */
23264 +
23265 +#define AR6000_XIOCTL_BMI_READ_MEMORY 2
23266 +/*
23267 + * arguments:
23268 + * union {
23269 + * struct {
23270 + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_MEMORY)
23271 + * UINT32 address
23272 + * UINT32 length
23273 + * }
23274 + * char results[length]
23275 + * }
23276 + * uses: BMI_READ_MEMORY
23277 + */
23278 +
23279 +#define AR6000_XIOCTL_BMI_WRITE_MEMORY 3
23280 +/*
23281 + * arguments:
23282 + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_MEMORY)
23283 + * UINT32 address
23284 + * UINT32 length
23285 + * char data[length]
23286 + * uses: BMI_WRITE_MEMORY
23287 + */
23288 +
23289 +#define AR6000_XIOCTL_BMI_EXECUTE 4
23290 +/*
23291 + * arguments:
23292 + * UINT32 cmd (AR6000_XIOCTL_BMI_EXECUTE)
23293 + * UINT32 TargetAddress
23294 + * UINT32 parameter
23295 + * uses: BMI_EXECUTE
23296 + */
23297 +
23298 +#define AR6000_XIOCTL_BMI_SET_APP_START 5
23299 +/*
23300 + * arguments:
23301 + * UINT32 cmd (AR6000_XIOCTL_BMI_SET_APP_START)
23302 + * UINT32 TargetAddress
23303 + * uses: BMI_SET_APP_START
23304 + */
23305 +
23306 +#define AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6
23307 +/*
23308 + * arguments:
23309 + * union {
23310 + * struct {
23311 + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_SOC_REGISTER)
23312 + * UINT32 TargetAddress, 32-bit aligned
23313 + * }
23314 + * UINT32 result
23315 + * }
23316 + * uses: BMI_READ_SOC_REGISTER
23317 + */
23318 +
23319 +#define AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7
23320 +/*
23321 + * arguments:
23322 + * struct {
23323 + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER)
23324 + * UINT32 TargetAddress, 32-bit aligned
23325 + * UINT32 newValue
23326 + * }
23327 + * uses: BMI_WRITE_SOC_REGISTER
23328 + */
23329 +
23330 +#define AR6000_XIOCTL_BMI_TEST 8
23331 +/*
23332 + * arguments:
23333 + * UINT32 cmd (AR6000_XIOCTL_BMI_TEST)
23334 + * UINT32 address
23335 + * UINT32 length
23336 + * UINT32 count
23337 + */
23338 +
23339 +
23340 +
23341 +/* Historical Host-side DataSet support */
23342 +#define AR6000_XIOCTL_UNUSED9 9
23343 +#define AR6000_XIOCTL_UNUSED10 10
23344 +#define AR6000_XIOCTL_UNUSED11 11
23345 +
23346 +/* ====Misc Extended Ioctls==== */
23347 +
23348 +#define AR6000_XIOCTL_FORCE_TARGET_RESET 12
23349 +/*
23350 + * arguments:
23351 + * UINT32 cmd (AR6000_XIOCTL_FORCE_TARGET_RESET)
23352 + */
23353 +
23354 +
23355 +#ifdef HTC_RAW_INTERFACE
23356 +/* HTC Raw Interface Ioctls */
23357 +#define AR6000_XIOCTL_HTC_RAW_OPEN 13
23358 +/*
23359 + * arguments:
23360 + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_OPEN)
23361 + */
23362 +
23363 +#define AR6000_XIOCTL_HTC_RAW_CLOSE 14
23364 +/*
23365 + * arguments:
23366 + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_CLOSE)
23367 + */
23368 +
23369 +#define AR6000_XIOCTL_HTC_RAW_READ 15
23370 +/*
23371 + * arguments:
23372 + * union {
23373 + * struct {
23374 + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_READ)
23375 + * UINT32 mailboxID
23376 + * UINT32 length
23377 + * }
23378 + * results[length]
23379 + * }
23380 + */
23381 +
23382 +#define AR6000_XIOCTL_HTC_RAW_WRITE 16
23383 +/*
23384 + * arguments:
23385 + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_WRITE)
23386 + * UINT32 mailboxID
23387 + * UINT32 length
23388 + * char buffer[length]
23389 + */
23390 +#endif /* HTC_RAW_INTERFACE */
23391 +
23392 +#define AR6000_XIOCTL_CHECK_TARGET_READY 17
23393 +/*
23394 + * arguments:
23395 + * UINT32 cmd (AR6000_XIOCTL_CHECK_TARGET_READY)
23396 + */
23397 +
23398 +
23399 +
23400 +/* ====GPIO (General Purpose I/O) Extended Ioctls==== */
23401 +
23402 +#define AR6000_XIOCTL_GPIO_OUTPUT_SET 18
23403 +/*
23404 + * arguments:
23405 + * UINT32 cmd (AR6000_XIOCTL_GPIO_OUTPUT_SET)
23406 + * ar6000_gpio_output_set_cmd_s (see below)
23407 + * uses: WMIX_GPIO_OUTPUT_SET_CMDID
23408 + */
23409 +
23410 +#define AR6000_XIOCTL_GPIO_INPUT_GET 19
23411 +/*
23412 + * arguments:
23413 + * UINT32 cmd (AR6000_XIOCTL_GPIO_INPUT_GET)
23414 + * uses: WMIX_GPIO_INPUT_GET_CMDID
23415 + */
23416 +
23417 +#define AR6000_XIOCTL_GPIO_REGISTER_SET 20
23418 +/*
23419 + * arguments:
23420 + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_SET)
23421 + * ar6000_gpio_register_cmd_s (see below)
23422 + * uses: WMIX_GPIO_REGISTER_SET_CMDID
23423 + */
23424 +
23425 +#define AR6000_XIOCTL_GPIO_REGISTER_GET 21
23426 +/*
23427 + * arguments:
23428 + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_GET)
23429 + * ar6000_gpio_register_cmd_s (see below)
23430 + * uses: WMIX_GPIO_REGISTER_GET_CMDID
23431 + */
23432 +
23433 +#define AR6000_XIOCTL_GPIO_INTR_ACK 22
23434 +/*
23435 + * arguments:
23436 + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_ACK)
23437 + * ar6000_cpio_intr_ack_cmd_s (see below)
23438 + * uses: WMIX_GPIO_INTR_ACK_CMDID
23439 + */
23440 +
23441 +#define AR6000_XIOCTL_GPIO_INTR_WAIT 23
23442 +/*
23443 + * arguments:
23444 + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_WAIT)
23445 + */
23446 +
23447 +
23448 +
23449 +/* ====more wireless commands==== */
23450 +
23451 +#define AR6000_XIOCTL_SET_ADHOC_BSSID 24
23452 +/*
23453 + * arguments:
23454 + * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BSSID)
23455 + * WMI_SET_ADHOC_BSSID_CMD setAdHocBssidCmd (see include/wmi.h)
23456 + */
23457 +
23458 +#define AR6000_XIOCTL_SET_OPT_MODE 25
23459 +/*
23460 + * arguments:
23461 + * UINT32 cmd (AR6000_XIOCTL_SET_OPT_MODE)
23462 + * WMI_SET_OPT_MODE_CMD setOptModeCmd (see include/wmi.h)
23463 + * uses: WMI_SET_OPT_MODE_CMDID
23464 + */
23465 +
23466 +#define AR6000_XIOCTL_OPT_SEND_FRAME 26
23467 +/*
23468 + * arguments:
23469 + * UINT32 cmd (AR6000_XIOCTL_OPT_SEND_FRAME)
23470 + * WMI_OPT_TX_FRAME_CMD optTxFrameCmd (see include/wmi.h)
23471 + * uses: WMI_OPT_TX_FRAME_CMDID
23472 + */
23473 +
23474 +#define AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL 27
23475 +/*
23476 + * arguments:
23477 + * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL)
23478 + * WMI_BEACON_INT_CMD beaconIntCmd (see include/wmi.h)
23479 + * uses: WMI_SET_BEACON_INT_CMDID
23480 + */
23481 +
23482 +
23483 +#define IEEE80211_IOCTL_SETAUTHALG 28
23484 +
23485 +
23486 +#define AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29
23487 +/*
23488 + * arguments:
23489 + * UINT32 cmd (AR6000_XIOCTL_SET_VOICE_PKT_SIZE)
23490 + * WMI_SET_VOICE_PKT_SIZE_CMD setVoicePktSizeCmd (see include/wmi.h)
23491 + * uses: WMI_SET_VOICE_PKT_SIZE_CMDID
23492 + */
23493 +
23494 +
23495 +#define AR6000_XIOCTL_SET_MAX_SP 30
23496 +/*
23497 + * arguments:
23498 + * UINT32 cmd (AR6000_XIOCTL_SET_MAX_SP)
23499 + * WMI_SET_MAX_SP_LEN_CMD maxSPLen(see include/wmi.h)
23500 + * uses: WMI_SET_MAX_SP_LEN_CMDID
23501 + */
23502 +
23503 +#define AR6000_XIOCTL_WMI_GET_ROAM_TBL 31
23504 +
23505 +#define AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32
23506 +
23507 +#define AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33
23508 +
23509 +
23510 +/*
23511 + * arguments:
23512 + * UINT32 cmd (AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS)
23513 + * WMI_SET_POWERSAVE_TIMERS_CMD powerSaveTimers(see include/wmi.h)
23514 + * WMI_SET_POWERSAVE_TIMERS_CMDID
23515 + */
23516 +
23517 +#define AR6000_XIOCTRL_WMI_GET_POWER_MODE 34
23518 +/*
23519 + * arguments:
23520 + * UINT32 cmd (AR6000_XIOCTRL_WMI_GET_POWER_MODE)
23521 + */
23522 +
23523 +#define AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35
23524 +typedef enum {
23525 + WLAN_DISABLED,
23526 + WLAN_ENABLED
23527 +} AR6000_WLAN_STATE;
23528 +/*
23529 + * arguments:
23530 + * enable/disable
23531 + */
23532 +
23533 +#define AR6000_XIOCTL_WMI_GET_ROAM_DATA 36
23534 +
23535 +#define AR6000_XIOCTL_WMI_SETRETRYLIMITS 37
23536 +/*
23537 + * arguments:
23538 + * WMI_SET_RETRY_LIMITS_CMD ibssSetRetryLimitsCmd
23539 + * uses: WMI_SET_RETRY_LIMITS_CMDID
23540 + */
23541 +
23542 +#ifdef CONFIG_HOST_TCMD_SUPPORT
23543 +/* ====extended commands for radio test ==== */
23544 +
23545 +#define AR6000_XIOCTL_TCMD_CONT_TX 38
23546 +/*
23547 + * arguments:
23548 + * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_TX)
23549 + * WMI_TCMD_CONT_TX_CMD contTxCmd (see include/wmi.h)
23550 + * uses: WMI_TCMD_CONT_TX_CMDID
23551 + */
23552 +
23553 +#define AR6000_XIOCTL_TCMD_CONT_RX 39
23554 +/*
23555 + * arguments:
23556 + * UINT32 cmd (AR6000_XIOCTL_TCMD_CONT_RX)
23557 + * WMI_TCMD_CONT_RX_CMD rxCmd (see include/wmi.h)
23558 + * uses: WMI_TCMD_CONT_RX_CMDID
23559 + */
23560 +
23561 +#define AR6000_XIOCTL_TCMD_PM 40
23562 +/*
23563 + * arguments:
23564 + * UINT32 cmd (AR6000_XIOCTL_TCMD_PM)
23565 + * WMI_TCMD_PM_CMD pmCmd (see include/wmi.h)
23566 + * uses: WMI_TCMD_PM_CMDID
23567 + */
23568 +
23569 +#endif /* CONFIG_HOST_TCMD_SUPPORT */
23570 +
23571 +#define AR6000_XIOCTL_WMI_STARTSCAN 41
23572 +/*
23573 + * arguments:
23574 + * UINT32 cmd (AR6000_XIOCTL_WMI_STARTSCAN)
23575 + * UINT8 scanType
23576 + * UINT8 scanConnected
23577 + * A_BOOL forceFgScan
23578 + * uses: WMI_START_SCAN_CMDID
23579 + */
23580 +
23581 +#define AR6000_XIOCTL_WMI_SETFIXRATES 42
23582 +
23583 +#define AR6000_XIOCTL_WMI_GETFIXRATES 43
23584 +
23585 +
23586 +#define AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44
23587 +/*
23588 + * arguments:
23589 + * WMI_RSSI_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h)
23590 + * uses: WMI_RSSI_THRESHOLD_PARAMS_CMDID
23591 + */
23592 +
23593 +#define AR6000_XIOCTL_WMI_CLR_RSSISNR 45
23594 +/*
23595 + * arguments:
23596 + * WMI_CLR_RSSISNR_CMD thresholdParams (see include/wmi.h)
23597 + * uses: WMI_CLR_RSSISNR_CMDID
23598 + */
23599 +
23600 +#define AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46
23601 +/*
23602 + * arguments:
23603 + * WMI_LQ_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h)
23604 + * uses: WMI_LQ_THRESHOLD_PARAMS_CMDID
23605 + */
23606 +
23607 +#define AR6000_XIOCTL_WMI_SET_RTS 47
23608 +/*
23609 + * arguments:
23610 + * WMI_SET_RTS_MODE_CMD (see include/wmi.h)
23611 + * uses: WMI_SET_RTS_MODE_CMDID
23612 + */
23613 +
23614 +#define AR6000_XIOCTL_WMI_SET_LPREAMBLE 48
23615 +
23616 +#define AR6000_XIOCTL_WMI_SET_AUTHMODE 49
23617 +/*
23618 + * arguments:
23619 + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_AUTHMODE)
23620 + * UINT8 mode
23621 + * uses: WMI_SET_RECONNECT_AUTH_MODE_CMDID
23622 + */
23623 +
23624 +#define AR6000_XIOCTL_WMI_SET_REASSOCMODE 50
23625 +
23626 +/*
23627 + * arguments:
23628 + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_WMM)
23629 + * UINT8 mode
23630 + * uses: WMI_SET_WMM_CMDID
23631 + */
23632 +#define AR6000_XIOCTL_WMI_SET_WMM 51
23633 +
23634 +/*
23635 + * arguments:
23636 + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS)
23637 + * UINT32 frequency
23638 + * UINT8 threshold
23639 + */
23640 +#define AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52
23641 +
23642 +/*
23643 + * arguments:
23644 + * UINT32 cmd (AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP)
23645 + * UINT32 cookie
23646 + */
23647 +#define AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53
23648 +
23649 +/*
23650 + * arguments:
23651 + * UINT32 cmd (AR6000_XIOCTL_WMI_GET_RD)
23652 + * UINT32 regDomain
23653 + */
23654 +#define AR6000_XIOCTL_WMI_GET_RD 54
23655 +
23656 +#define AR6000_XIOCTL_DIAG_READ 55
23657 +
23658 +#define AR6000_XIOCTL_DIAG_WRITE 56
23659 +
23660 +/*
23661 + * arguments cmd (AR6000_XIOCTL_SET_TXOP)
23662 + * WMI_TXOP_CFG txopEnable
23663 + */
23664 +#define AR6000_XIOCTL_WMI_SET_TXOP 57
23665 +
23666 +#ifdef USER_KEYS
23667 +/*
23668 + * arguments:
23669 + * UINT32 cmd (AR6000_XIOCTL_USER_SETKEYS)
23670 + * UINT32 keyOpCtrl
23671 + * uses AR6000_USER_SETKEYS_INFO
23672 + */
23673 +#define AR6000_XIOCTL_USER_SETKEYS 58
23674 +#endif /* USER_KEYS */
23675 +
23676 +#define AR6000_XIOCTL_WMI_SET_KEEPALIVE 59
23677 +/*
23678 + * arguments:
23679 + * UINT8 cmd (AR6000_XIOCTL_WMI_SET_KEEPALIVE)
23680 + * UINT8 keepaliveInterval
23681 + * uses: WMI_SET_KEEPALIVE_CMDID
23682 + */
23683 +
23684 +#define AR6000_XIOCTL_WMI_GET_KEEPALIVE 60
23685 +/*
23686 + * arguments:
23687 + * UINT8 cmd (AR6000_XIOCTL_WMI_GET_KEEPALIVE)
23688 + * UINT8 keepaliveInterval
23689 + * A_BOOL configured
23690 + * uses: WMI_GET_KEEPALIVE_CMDID
23691 + */
23692 +
23693 +/* ====ROM Patching Extended Ioctls==== */
23694 +
23695 +#define AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61
23696 +/*
23697 + * arguments:
23698 + * union {
23699 + * struct {
23700 + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_INSTALL)
23701 + * UINT32 ROM Address
23702 + * UINT32 RAM Address
23703 + * UINT32 number of bytes
23704 + * UINT32 activate? (0 or 1)
23705 + * }
23706 + * A_UINT32 resulting rompatch ID
23707 + * }
23708 + * uses: BMI_ROMPATCH_INSTALL
23709 + */
23710 +
23711 +#define AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62
23712 +/*
23713 + * arguments:
23714 + * struct {
23715 + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL)
23716 + * UINT32 rompatch ID
23717 + * }
23718 + * uses: BMI_ROMPATCH_UNINSTALL
23719 + */
23720 +
23721 +#define AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63
23722 +/*
23723 + * arguments:
23724 + * struct {
23725 + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE)
23726 + * UINT32 rompatch count
23727 + * UINT32 rompatch IDs[rompatch count]
23728 + * }
23729 + * uses: BMI_ROMPATCH_ACTIVATE
23730 + */
23731 +
23732 +#define AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64
23733 +/*
23734 + * arguments:
23735 + * struct {
23736 + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE)
23737 + * UINT32 rompatch count
23738 + * UINT32 rompatch IDs[rompatch count]
23739 + * }
23740 + * uses: BMI_ROMPATCH_DEACTIVATE
23741 + */
23742 +
23743 +#define AR6000_XIOCTL_WMI_SET_APPIE 65
23744 +/*
23745 + * arguments:
23746 + * struct {
23747 + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_APPIE)
23748 + * UINT32 app_frmtype;
23749 + * UINT32 app_buflen;
23750 + * UINT8 app_buf[];
23751 + * }
23752 + */
23753 +#define AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66
23754 +/*
23755 + * arguments:
23756 + * A_UINT32 filter_type;
23757 + */
23758 +
23759 +#define AR6000_XIOCTL_DBGLOG_CFG_MODULE 67
23760 +
23761 +#define AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68
23762 +
23763 +#define AR6000_XIOCTL_WMI_SET_WSC_STATUS 70
23764 +/*
23765 + * arguments:
23766 + * A_UINT32 wsc_status;
23767 + * (WSC_REG_INACTIVE or WSC_REG_ACTIVE)
23768 + */
23769 +
23770 +/*
23771 + * arguments:
23772 + * struct {
23773 + * A_UINT8 streamType;
23774 + * A_UINT8 status;
23775 + * }
23776 + * uses: WMI_SET_BT_STATUS_CMDID
23777 + */
23778 +#define AR6000_XIOCTL_WMI_SET_BT_STATUS 71
23779 +
23780 +/*
23781 + * arguments:
23782 + * struct {
23783 + * A_UINT8 paramType;
23784 + * union {
23785 + * A_UINT8 noSCOPkts;
23786 + * BT_PARAMS_A2DP a2dpParams;
23787 + * BT_COEX_REGS regs;
23788 + * };
23789 + * }
23790 + * uses: WMI_SET_BT_PARAM_CMDID
23791 + */
23792 +#define AR6000_XIOCTL_WMI_SET_BT_PARAMS 72
23793 +
23794 +#define AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE 73
23795 +#define AR6000_XIOCTL_WMI_SET_WOW_MODE 74
23796 +#define AR6000_XIOCTL_WMI_GET_WOW_LIST 75
23797 +#define AR6000_XIOCTL_WMI_ADD_WOW_PATTERN 76
23798 +#define AR6000_XIOCTL_WMI_DEL_WOW_PATTERN 77
23799 +
23800 +
23801 +
23802 +#define AR6000_XIOCTL_TARGET_INFO 78
23803 +/*
23804 + * arguments:
23805 + * UINT32 cmd (AR6000_XIOCTL_TARGET_INFO)
23806 + * A_UINT32 TargetVersion (returned)
23807 + * A_UINT32 TargetType (returned)
23808 + * (See also bmi_msg.h target_ver and target_type)
23809 + */
23810 +
23811 +#define AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79
23812 +/*
23813 + * arguments:
23814 + * none
23815 + */
23816 +
23817 +#define AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80
23818 +/*
23819 + * This ioctl is used to emulate traffic activity
23820 + * timeouts. Activity/inactivity will trigger the driver
23821 + * to re-balance credits.
23822 + *
23823 + * arguments:
23824 + * ar6000_traffic_activity_change
23825 + */
23826 +
23827 +#define AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81
23828 +/*
23829 + * This ioctl is used to set the connect control flags
23830 + *
23831 + * arguments:
23832 + * A_UINT32 connectCtrlFlags
23833 + */
23834 +
23835 +#define AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82
23836 +/*
23837 + * This IOCTL sets any Authentication,Key Management and Protection
23838 + * related parameters. This is used along with the information set in
23839 + * Connect Command.
23840 + * Currently this enables Multiple PMKIDs to an AP.
23841 + *
23842 + * arguments:
23843 + * struct {
23844 + * A_UINT32 akmpInfo;
23845 + * }
23846 + * uses: WMI_SET_AKMP_PARAMS_CMD
23847 + */
23848 +
23849 +#define AR6000_XIOCTL_WMI_GET_PMKID_LIST 83
23850 +
23851 +#define AR6000_XIOCTL_WMI_SET_PMKID_LIST 84
23852 +/*
23853 + * This IOCTL is used to set a list of PMKIDs. This list of
23854 + * PMKIDs is used in the [Re]AssocReq Frame. This list is used
23855 + * only if the MultiPMKID option is enabled via the
23856 + * AR6000_XIOCTL_WMI_SET_AKMP_PARAMS IOCTL.
23857 + *
23858 + * arguments:
23859 + * struct {
23860 + * A_UINT32 numPMKID;
23861 + * WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE];
23862 + * }
23863 + * uses: WMI_SET_PMKIDLIST_CMD
23864 + */
23865 +
23866 +/* Historical DSETPATCH support for INI patches */
23867 +#define AR6000_XIOCTL_UNUSED90 90
23868 +
23869 +
23870 +
23871 +/* used by AR6000_IOCTL_WMI_GETREV */
23872 +struct ar6000_version {
23873 + A_UINT32 host_ver;
23874 + A_UINT32 target_ver;
23875 +};
23876 +
23877 +/* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */
23878 +struct ar6000_queuereq {
23879 + A_UINT8 trafficClass;
23880 + A_UINT16 activeTsids;
23881 +};
23882 +
23883 +/* used by AR6000_IOCTL_WMI_GET_TARGET_STATS */
23884 +typedef struct targetStats_t {
23885 + A_UINT64 tx_packets;
23886 + A_UINT64 tx_bytes;
23887 + A_UINT64 tx_unicast_pkts;
23888 + A_UINT64 tx_unicast_bytes;
23889 + A_UINT64 tx_multicast_pkts;
23890 + A_UINT64 tx_multicast_bytes;
23891 + A_UINT64 tx_broadcast_pkts;
23892 + A_UINT64 tx_broadcast_bytes;
23893 + A_UINT64 tx_rts_success_cnt;
23894 + A_UINT64 tx_packet_per_ac[4];
23895 +
23896 + A_UINT64 tx_errors;
23897 + A_UINT64 tx_failed_cnt;
23898 + A_UINT64 tx_retry_cnt;
23899 + A_UINT64 tx_rts_fail_cnt;
23900 + A_INT32 tx_unicast_rate;
23901 + A_UINT64 rx_packets;
23902 + A_UINT64 rx_bytes;
23903 + A_UINT64 rx_unicast_pkts;
23904 + A_UINT64 rx_unicast_bytes;
23905 + A_UINT64 rx_multicast_pkts;
23906 + A_UINT64 rx_multicast_bytes;
23907 + A_UINT64 rx_broadcast_pkts;
23908 + A_UINT64 rx_broadcast_bytes;
23909 + A_UINT64 rx_fragment_pkt;
23910 +
23911 + A_UINT64 rx_errors;
23912 + A_UINT64 rx_crcerr;
23913 + A_UINT64 rx_key_cache_miss;
23914 + A_UINT64 rx_decrypt_err;
23915 + A_UINT64 rx_duplicate_frames;
23916 + A_INT32 rx_unicast_rate;
23917 +
23918 + A_UINT64 tkip_local_mic_failure;
23919 + A_UINT64 tkip_counter_measures_invoked;
23920 + A_UINT64 tkip_replays;
23921 + A_UINT64 tkip_format_errors;
23922 + A_UINT64 ccmp_format_errors;
23923 + A_UINT64 ccmp_replays;
23924 +
23925 + A_UINT64 power_save_failure_cnt;
23926 + A_INT16 noise_floor_calibation;
23927 +
23928 + A_UINT64 cs_bmiss_cnt;
23929 + A_UINT64 cs_lowRssi_cnt;
23930 + A_UINT64 cs_connect_cnt;
23931 + A_UINT64 cs_disconnect_cnt;
23932 + A_UINT8 cs_aveBeacon_snr;
23933 + A_INT16 cs_aveBeacon_rssi;
23934 + A_UINT8 cs_lastRoam_msec;
23935 + A_UINT8 cs_snr;
23936 + A_INT16 cs_rssi;
23937 +
23938 + A_UINT32 lq_val;
23939 +
23940 + A_UINT32 wow_num_pkts_dropped;
23941 + A_UINT8 wow_num_host_pkt_wakeups;
23942 + A_UINT8 wow_num_host_event_wakeups;
23943 + A_UINT16 wow_num_events_discarded;
23944 +
23945 +}TARGET_STATS;
23946 +
23947 +typedef struct targetStats_cmd_t {
23948 + TARGET_STATS targetStats;
23949 + int clearStats;
23950 +} TARGET_STATS_CMD;
23951 +
23952 +/* used by AR6000_XIOCTL_USER_SETKEYS */
23953 +
23954 +/*
23955 + * Setting this bit to 1 doesnot initialize the RSC on the firmware
23956 + */
23957 +#define AR6000_XIOCTL_USER_SETKEYS_RSC_CTRL 1
23958 +#define AR6000_USER_SETKEYS_RSC_UNCHANGED 0x00000002
23959 +
23960 +typedef struct {
23961 + A_UINT32 keyOpCtrl; /* Bit Map of Key Mgmt Ctrl Flags */
23962 +} AR6000_USER_SETKEYS_INFO;
23963 +
23964 +
23965 +/* used by AR6000_XIOCTL_GPIO_OUTPUT_SET */
23966 +struct ar6000_gpio_output_set_cmd_s {
23967 + A_UINT32 set_mask;
23968 + A_UINT32 clear_mask;
23969 + A_UINT32 enable_mask;
23970 + A_UINT32 disable_mask;
23971 +};
23972 +
23973 +/*
23974 + * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET
23975 + */
23976 +struct ar6000_gpio_register_cmd_s {
23977 + A_UINT32 gpioreg_id;
23978 + A_UINT32 value;
23979 +};
23980 +
23981 +/* used by AR6000_XIOCTL_GPIO_INTR_ACK */
23982 +struct ar6000_gpio_intr_ack_cmd_s {
23983 + A_UINT32 ack_mask;
23984 +};
23985 +
23986 +/* used by AR6000_XIOCTL_GPIO_INTR_WAIT */
23987 +struct ar6000_gpio_intr_wait_cmd_s {
23988 + A_UINT32 intr_mask;
23989 + A_UINT32 input_values;
23990 +};
23991 +
23992 +/* used by the AR6000_XIOCTL_DBGLOG_CFG_MODULE */
23993 +typedef struct ar6000_dbglog_module_config_s {
23994 + A_UINT32 valid;
23995 + A_UINT16 mmask;
23996 + A_UINT16 tsr;
23997 + A_BOOL rep;
23998 + A_UINT16 size;
23999 +} DBGLOG_MODULE_CONFIG;
24000 +
24001 +typedef struct user_rssi_thold_t {
24002 + A_INT16 tag;
24003 + A_INT16 rssi;
24004 +} USER_RSSI_THOLD;
24005 +
24006 +typedef struct user_rssi_params_t {
24007 + A_UINT8 weight;
24008 + A_UINT32 pollTime;
24009 + USER_RSSI_THOLD tholds[12];
24010 +} USER_RSSI_PARAMS;
24011 +
24012 +/*
24013 + * Host driver may have some config parameters. Typically, these
24014 + * config params are one time config parameters. These could
24015 + * correspond to any of the underlying modules. Host driver exposes
24016 + * an api for the underlying modules to get this config.
24017 + */
24018 +#define AR6000_DRIVER_CFG_BASE 0x8000
24019 +
24020 +/* Should driver perform wlan node caching? */
24021 +#define AR6000_DRIVER_CFG_GET_WLANNODECACHING 0x8001
24022 +/*Should we log raw WMI msgs */
24023 +#define AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS 0x8002
24024 +
24025 +/* used by AR6000_XIOCTL_DIAG_READ & AR6000_XIOCTL_DIAG_WRITE */
24026 +struct ar6000_diag_window_cmd_s {
24027 + unsigned int addr;
24028 + unsigned int value;
24029 +};
24030 +
24031 +
24032 +struct ar6000_traffic_activity_change {
24033 + A_UINT32 StreamID; /* stream ID to indicate activity change */
24034 + A_UINT32 Active; /* active (1) or inactive (0) */
24035 +};
24036 +
24037 +#ifdef __cplusplus
24038 +}
24039 +#endif
24040 +#endif
24041 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/athtypes_linux.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/athtypes_linux.h
24042 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/athtypes_linux.h 1970-01-01 01:00:00.000000000 +0100
24043 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/athtypes_linux.h 2009-05-10 22:27:59.000000000 +0200
24044 @@ -0,0 +1,47 @@
24045 +/*
24046 + * $Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/include/athtypes_linux.h#1 $
24047 + *
24048 + * This file contains the definitions of the basic atheros data types.
24049 + * It is used to map the data types in atheros files to a platform specific
24050 + * type.
24051 + *
24052 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
24053 + *
24054 + *
24055 + * This program is free software; you can redistribute it and/or modify
24056 + * it under the terms of the GNU General Public License version 2 as
24057 + * published by the Free Software Foundation;
24058 + *
24059 + * Software distributed under the License is distributed on an "AS
24060 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
24061 + * implied. See the License for the specific language governing
24062 + * rights and limitations under the License.
24063 + *
24064 + *
24065 + *
24066 + */
24067 +
24068 +#ifndef _ATHTYPES_LINUX_H_
24069 +#define _ATHTYPES_LINUX_H_
24070 +
24071 +#ifdef __KERNEL__
24072 +#include <linux/types.h>
24073 +#endif
24074 +
24075 +typedef int8_t A_INT8;
24076 +typedef int16_t A_INT16;
24077 +typedef int32_t A_INT32;
24078 +typedef int64_t A_INT64;
24079 +
24080 +typedef u_int8_t A_UINT8;
24081 +typedef u_int16_t A_UINT16;
24082 +typedef u_int32_t A_UINT32;
24083 +typedef u_int64_t A_UINT64;
24084 +
24085 +typedef int A_BOOL;
24086 +typedef char A_CHAR;
24087 +typedef unsigned char A_UCHAR;
24088 +typedef unsigned long A_ATH_TIMER;
24089 +
24090 +
24091 +#endif /* _ATHTYPES_LINUX_H_ */
24092 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/config_linux.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/config_linux.h
24093 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/config_linux.h 1970-01-01 01:00:00.000000000 +0100
24094 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/config_linux.h 2009-05-10 22:27:59.000000000 +0200
24095 @@ -0,0 +1,44 @@
24096 +/*
24097 + * Copyright (c) 2004-2007 Atheros Communications Inc.
24098 + * All rights reserved.
24099 + *
24100 + *
24101 + * This program is free software; you can redistribute it and/or modify
24102 + * it under the terms of the GNU General Public License version 2 as
24103 + * published by the Free Software Foundation;
24104 + *
24105 + * Software distributed under the License is distributed on an "AS
24106 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
24107 + * implied. See the License for the specific language governing
24108 + * rights and limitations under the License.
24109 + *
24110 + *
24111 + *
24112 + */
24113 +
24114 +#ifndef _CONFIG_LINUX_H_
24115 +#define _CONFIG_LINUX_H_
24116 +
24117 +#ifdef __cplusplus
24118 +extern "C" {
24119 +#endif
24120 +
24121 +/*
24122 + * Host-side GPIO support is optional.
24123 + * If run-time access to GPIO pins is not required, then
24124 + * this should be changed to #undef.
24125 + */
24126 +#define CONFIG_HOST_GPIO_SUPPORT
24127 +
24128 +/*
24129 + * Host side Test Command support
24130 + */
24131 +#define CONFIG_HOST_TCMD_SUPPORT
24132 +
24133 +#define USE_4BYTE_REGISTER_ACCESS
24134 +
24135 +#ifdef __cplusplus
24136 +}
24137 +#endif
24138 +
24139 +#endif
24140 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/debug_linux.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/debug_linux.h
24141 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/debug_linux.h 1970-01-01 01:00:00.000000000 +0100
24142 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/debug_linux.h 2009-05-10 22:27:59.000000000 +0200
24143 @@ -0,0 +1,86 @@
24144 +/*
24145 + * Copyright (c) 2004-2006 Atheros Communications Inc.
24146 + * All rights reserved.
24147 + *
24148 + *
24149 + * This program is free software; you can redistribute it and/or modify
24150 + * it under the terms of the GNU General Public License version 2 as
24151 + * published by the Free Software Foundation;
24152 + *
24153 + * Software distributed under the License is distributed on an "AS
24154 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
24155 + * implied. See the License for the specific language governing
24156 + * rights and limitations under the License.
24157 + *
24158 + *
24159 + *
24160 + */
24161 +
24162 +#ifndef _DEBUG_LINUX_H_
24163 +#define _DEBUG_LINUX_H_
24164 +
24165 +#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING)
24166 +
24167 +extern A_UINT32 g_dbg_flags;
24168 +
24169 +#define DBGFMT "%s() : "
24170 +#define DBGARG __func__
24171 +#define DBGFN A_PRINTF
24172 +
24173 +/* ------- Debug related stuff ------- */
24174 +enum {
24175 + ATH_DEBUG_SEND = 0x0001,
24176 + ATH_DEBUG_RECV = 0x0002,
24177 + ATH_DEBUG_SYNC = 0x0004,
24178 + ATH_DEBUG_DUMP = 0x0008,
24179 + ATH_DEBUG_IRQ = 0x0010,
24180 + ATH_DEBUG_TRC = 0x0020,
24181 + ATH_DEBUG_WARN = 0x0040,
24182 + ATH_DEBUG_ERR = 0x0080,
24183 + ATH_LOG_INF = 0x0100,
24184 + ATH_DEBUG_BMI = 0x0110,
24185 + ATH_DEBUG_WMI = 0x0120,
24186 + ATH_DEBUG_HIF = 0x0140,
24187 + ATH_DEBUG_HTC = 0x0180,
24188 + ATH_DEBUG_WLAN = 0x1000,
24189 + ATH_LOG_ERR = 0x1010,
24190 + ATH_DEBUG_ANY = 0xFFFF,
24191 +};
24192 +
24193 +#ifdef DEBUG
24194 +
24195 +#define A_DPRINTF(f, a) \
24196 + if(g_dbg_flags & (f)) \
24197 + { \
24198 + DBGFN a ; \
24199 + }
24200 +
24201 +
24202 +// TODO FIX usage of A_PRINTF!
24203 +#define AR_DEBUG_LVL_CHECK(lvl) (debughtc & (lvl))
24204 +#define AR_DEBUG_PRINTBUF(buffer, length, desc) do { \
24205 + if (debughtc & ATH_DEBUG_DUMP) { \
24206 + DebugDumpBytes(buffer, length,desc); \
24207 + } \
24208 +} while(0)
24209 +#define PRINTX_ARG(arg...) arg
24210 +#define AR_DEBUG_PRINTF(flags, args) do { \
24211 + if (debughtc & (flags)) { \
24212 + A_PRINTF(KERN_ALERT PRINTX_ARG args); \
24213 + } \
24214 +} while (0)
24215 +#define AR_DEBUG_ASSERT(test) do { \
24216 + if (!(test)) { \
24217 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#test)); \
24218 + } \
24219 +} while(0)
24220 +extern int debughtc;
24221 +#else
24222 +#define AR_DEBUG_PRINTF(flags, args)
24223 +#define AR_DEBUG_PRINTBUF(buffer, length, desc)
24224 +#define AR_DEBUG_ASSERT(test)
24225 +#define AR_DEBUG_LVL_CHECK(lvl) 0
24226 +#define A_DPRINTF(f, a)
24227 +#endif
24228 +
24229 +#endif /* _DEBUG_LINUX_H_ */
24230 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ioctl.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ioctl.c
24231 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/ioctl.c 1970-01-01 01:00:00.000000000 +0100
24232 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/ioctl.c 2009-05-10 22:27:59.000000000 +0200
24233 @@ -0,0 +1,2540 @@
24234 +/*
24235 + *
24236 + * Copyright (c) 2004-2007 Atheros Communications Inc.
24237 + * All rights reserved.
24238 + *
24239 + *
24240 + * This program is free software; you can redistribute it and/or modify
24241 + * it under the terms of the GNU General Public License version 2 as
24242 + * published by the Free Software Foundation;
24243 + *
24244 + * Software distributed under the License is distributed on an "AS
24245 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
24246 + * implied. See the License for the specific language governing
24247 + * rights and limitations under the License.
24248 + *
24249 + *
24250 + *
24251 + */
24252 +
24253 +#include "ar6000_drv.h"
24254 +
24255 +static A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
24256 +static A_UINT8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
24257 +extern USER_RSSI_THOLD rssi_map[12];
24258 +extern unsigned int wmitimeout;
24259 +extern A_WAITQUEUE_HEAD arEvent;
24260 +extern int tspecCompliance;
24261 +extern int bmienable;
24262 +extern int bypasswmi;
24263 +
24264 +static int
24265 +ar6000_ioctl_get_roam_tbl(struct net_device *dev, struct ifreq *rq)
24266 +{
24267 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24268 +
24269 + if (ar->arWmiReady == FALSE) {
24270 + return -EIO;
24271 + }
24272 +
24273 + if(wmi_get_roam_tbl_cmd(ar->arWmi) != A_OK) {
24274 + return -EIO;
24275 + }
24276 +
24277 + return 0;
24278 +}
24279 +
24280 +static int
24281 +ar6000_ioctl_get_roam_data(struct net_device *dev, struct ifreq *rq)
24282 +{
24283 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24284 +
24285 + if (ar->arWmiReady == FALSE) {
24286 + return -EIO;
24287 + }
24288 +
24289 +
24290 + /* currently assume only roam times are required */
24291 + if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != A_OK) {
24292 + return -EIO;
24293 + }
24294 +
24295 +
24296 + return 0;
24297 +}
24298 +
24299 +static int
24300 +ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata)
24301 +{
24302 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24303 + WMI_SET_ROAM_CTRL_CMD cmd;
24304 + A_UINT8 size = sizeof(cmd);
24305 +
24306 + if (ar->arWmiReady == FALSE) {
24307 + return -EIO;
24308 + }
24309 +
24310 +
24311 + if (copy_from_user(&cmd, userdata, size)) {
24312 + return -EFAULT;
24313 + }
24314 +
24315 + if (cmd.roamCtrlType == WMI_SET_HOST_BIAS) {
24316 + if (cmd.info.bssBiasInfo.numBss > 1) {
24317 + size += (cmd.info.bssBiasInfo.numBss - 1) * sizeof(WMI_BSS_BIAS);
24318 + }
24319 + }
24320 +
24321 + if (copy_from_user(&cmd, userdata, size)) {
24322 + return -EFAULT;
24323 + }
24324 +
24325 + if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != A_OK) {
24326 + return -EIO;
24327 + }
24328 +
24329 + return 0;
24330 +}
24331 +
24332 +static int
24333 +ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata)
24334 +{
24335 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24336 + WMI_POWERSAVE_TIMERS_POLICY_CMD cmd;
24337 + A_UINT8 size = sizeof(cmd);
24338 +
24339 + if (ar->arWmiReady == FALSE) {
24340 + return -EIO;
24341 + }
24342 +
24343 + if (copy_from_user(&cmd, userdata, size)) {
24344 + return -EFAULT;
24345 + }
24346 +
24347 + if (copy_from_user(&cmd, userdata, size)) {
24348 + return -EFAULT;
24349 + }
24350 +
24351 + if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != A_OK) {
24352 + return -EIO;
24353 + }
24354 +
24355 + return 0;
24356 +}
24357 +
24358 +static int
24359 +ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq)
24360 +{
24361 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24362 + WMI_SET_WMM_CMD cmd;
24363 + A_STATUS ret;
24364 +
24365 + if ((dev->flags & IFF_UP) != IFF_UP) {
24366 + return -EIO;
24367 + }
24368 + if (ar->arWmiReady == FALSE) {
24369 + return -EIO;
24370 + }
24371 +
24372 + if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
24373 + sizeof(cmd)))
24374 + {
24375 + return -EFAULT;
24376 + }
24377 +
24378 + if (cmd.status == WMI_WMM_ENABLED) {
24379 + ar->arWmmEnabled = TRUE;
24380 + } else {
24381 + ar->arWmmEnabled = FALSE;
24382 + }
24383 +
24384 + ret = wmi_set_wmm_cmd(ar->arWmi, cmd.status);
24385 +
24386 + switch (ret) {
24387 + case A_OK:
24388 + return 0;
24389 + case A_EBUSY :
24390 + return -EBUSY;
24391 + case A_NO_MEMORY:
24392 + return -ENOMEM;
24393 + case A_EINVAL:
24394 + default:
24395 + return -EFAULT;
24396 + }
24397 +}
24398 +
24399 +static int
24400 +ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq)
24401 +{
24402 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24403 + WMI_SET_WMM_TXOP_CMD cmd;
24404 + A_STATUS ret;
24405 +
24406 + if ((dev->flags & IFF_UP) != IFF_UP) {
24407 + return -EIO;
24408 + }
24409 + if (ar->arWmiReady == FALSE) {
24410 + return -EIO;
24411 + }
24412 +
24413 + if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
24414 + sizeof(cmd)))
24415 + {
24416 + return -EFAULT;
24417 + }
24418 +
24419 + ret = wmi_set_wmm_txop(ar->arWmi, cmd.txopEnable);
24420 +
24421 + switch (ret) {
24422 + case A_OK:
24423 + return 0;
24424 + case A_EBUSY :
24425 + return -EBUSY;
24426 + case A_NO_MEMORY:
24427 + return -ENOMEM;
24428 + case A_EINVAL:
24429 + default:
24430 + return -EFAULT;
24431 + }
24432 +}
24433 +
24434 +static int
24435 +ar6000_ioctl_get_rd(struct net_device *dev, struct ifreq *rq)
24436 +{
24437 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24438 + A_STATUS ret = 0;
24439 +
24440 + if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == FALSE) {
24441 + return -EIO;
24442 + }
24443 +
24444 + if(copy_to_user((char *)((unsigned int*)rq->ifr_data + 1),
24445 + &ar->arRegCode, sizeof(ar->arRegCode)))
24446 + ret = -EFAULT;
24447 +
24448 + return ret;
24449 +}
24450 +
24451 +
24452 +/* Get power mode command */
24453 +static int
24454 +ar6000_ioctl_get_power_mode(struct net_device *dev, struct ifreq *rq)
24455 +{
24456 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24457 + WMI_POWER_MODE_CMD power_mode;
24458 + int ret = 0;
24459 +
24460 + if (ar->arWmiReady == FALSE) {
24461 + return -EIO;
24462 + }
24463 +
24464 + power_mode.powerMode = wmi_get_power_mode_cmd(ar->arWmi);
24465 + if (copy_to_user(rq->ifr_data, &power_mode, sizeof(WMI_POWER_MODE_CMD))) {
24466 + ret = -EFAULT;
24467 + }
24468 +
24469 + return ret;
24470 +}
24471 +
24472 +
24473 +static int
24474 +ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq)
24475 +{
24476 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24477 + WMI_CHANNEL_PARAMS_CMD cmd, *cmdp;
24478 + int ret = 0;
24479 +
24480 + if (ar->arWmiReady == FALSE) {
24481 + return -EIO;
24482 + }
24483 +
24484 +
24485 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24486 + return -EFAULT;
24487 + }
24488 +
24489 + if (cmd.numChannels > 1) {
24490 + cmdp = A_MALLOC(130);
24491 + if (copy_from_user(cmdp, rq->ifr_data,
24492 + sizeof (*cmdp) +
24493 + ((cmd.numChannels - 1) * sizeof(A_UINT16))))
24494 + {
24495 + kfree(cmdp);
24496 + return -EFAULT;
24497 + }
24498 + } else {
24499 + cmdp = &cmd;
24500 + }
24501 +
24502 + if ((ar->arPhyCapability == WMI_11G_CAPABILITY) &&
24503 + ((cmdp->phyMode == WMI_11A_MODE) || (cmdp->phyMode == WMI_11AG_MODE)))
24504 + {
24505 + ret = -EINVAL;
24506 + }
24507 +
24508 + if (!ret &&
24509 + (wmi_set_channelParams_cmd(ar->arWmi, cmdp->scanParam, cmdp->phyMode,
24510 + cmdp->numChannels, cmdp->channelList)
24511 + != A_OK))
24512 + {
24513 + ret = -EIO;
24514 + }
24515 +
24516 + if (cmd.numChannels > 1) {
24517 + kfree(cmdp);
24518 + }
24519 +
24520 + return ret;
24521 +}
24522 +
24523 +static int
24524 +ar6000_ioctl_set_snr_threshold(struct net_device *dev, struct ifreq *rq)
24525 +{
24526 +
24527 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24528 + WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
24529 + int ret = 0;
24530 +
24531 + if (ar->arWmiReady == FALSE) {
24532 + return -EIO;
24533 + }
24534 +
24535 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24536 + return -EFAULT;
24537 + }
24538 +
24539 + if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != A_OK ) {
24540 + ret = -EIO;
24541 + }
24542 +
24543 + return ret;
24544 +}
24545 +
24546 +static int
24547 +ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
24548 +{
24549 +#define SWAP_THOLD(thold1, thold2) do { \
24550 + USER_RSSI_THOLD tmpThold; \
24551 + tmpThold.tag = thold1.tag; \
24552 + tmpThold.rssi = thold1.rssi; \
24553 + thold1.tag = thold2.tag; \
24554 + thold1.rssi = thold2.rssi; \
24555 + thold2.tag = tmpThold.tag; \
24556 + thold2.rssi = tmpThold.rssi; \
24557 +} while (0)
24558 +
24559 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24560 + WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
24561 + USER_RSSI_PARAMS rssiParams;
24562 + A_INT32 i, j;
24563 +
24564 + int ret = 0;
24565 +
24566 + if (ar->arWmiReady == FALSE) {
24567 + return -EIO;
24568 + }
24569 +
24570 + if (copy_from_user((char *)&rssiParams, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(USER_RSSI_PARAMS))) {
24571 + return -EFAULT;
24572 + }
24573 + cmd.weight = rssiParams.weight;
24574 + cmd.pollTime = rssiParams.pollTime;
24575 +
24576 + A_MEMCPY(rssi_map, &rssiParams.tholds, sizeof(rssi_map));
24577 + /*
24578 + * only 6 elements, so use bubble sorting, in ascending order
24579 + */
24580 + for (i = 5; i > 0; i--) {
24581 + for (j = 0; j < i; j++) { /* above tholds */
24582 + if (rssi_map[j+1].rssi < rssi_map[j].rssi) {
24583 + SWAP_THOLD(rssi_map[j+1], rssi_map[j]);
24584 + } else if (rssi_map[j+1].rssi == rssi_map[j].rssi) {
24585 + return EFAULT;
24586 + }
24587 + }
24588 + }
24589 + for (i = 11; i > 6; i--) {
24590 + for (j = 6; j < i; j++) { /* below tholds */
24591 + if (rssi_map[j+1].rssi < rssi_map[j].rssi) {
24592 + SWAP_THOLD(rssi_map[j+1], rssi_map[j]);
24593 + } else if (rssi_map[j+1].rssi == rssi_map[j].rssi) {
24594 + return EFAULT;
24595 + }
24596 + }
24597 + }
24598 +
24599 +#ifdef DEBUG
24600 + for (i = 0; i < 12; i++) {
24601 + AR_DEBUG2_PRINTF("thold[%d].tag: %d, thold[%d].rssi: %d \n",
24602 + i, rssi_map[i].tag, i, rssi_map[i].rssi);
24603 + }
24604 +#endif
24605 + cmd.thresholdAbove1_Val = rssi_map[0].rssi;
24606 + cmd.thresholdAbove2_Val = rssi_map[1].rssi;
24607 + cmd.thresholdAbove3_Val = rssi_map[2].rssi;
24608 + cmd.thresholdAbove4_Val = rssi_map[3].rssi;
24609 + cmd.thresholdAbove5_Val = rssi_map[4].rssi;
24610 + cmd.thresholdAbove6_Val = rssi_map[5].rssi;
24611 + cmd.thresholdBelow1_Val = rssi_map[6].rssi;
24612 + cmd.thresholdBelow2_Val = rssi_map[7].rssi;
24613 + cmd.thresholdBelow3_Val = rssi_map[8].rssi;
24614 + cmd.thresholdBelow4_Val = rssi_map[9].rssi;
24615 + cmd.thresholdBelow5_Val = rssi_map[10].rssi;
24616 + cmd.thresholdBelow6_Val = rssi_map[11].rssi;
24617 +
24618 + if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != A_OK ) {
24619 + ret = -EIO;
24620 + }
24621 +
24622 + return ret;
24623 +}
24624 +
24625 +static int
24626 +ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq)
24627 +{
24628 +
24629 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24630 + WMI_LQ_THRESHOLD_PARAMS_CMD cmd;
24631 + int ret = 0;
24632 +
24633 + if (ar->arWmiReady == FALSE) {
24634 + return -EIO;
24635 + }
24636 +
24637 + if (copy_from_user(&cmd, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(cmd))) {
24638 + return -EFAULT;
24639 + }
24640 +
24641 + if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != A_OK ) {
24642 + ret = -EIO;
24643 + }
24644 +
24645 + return ret;
24646 +}
24647 +
24648 +
24649 +static int
24650 +ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq)
24651 +{
24652 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24653 + WMI_PROBED_SSID_CMD cmd;
24654 + int ret = 0;
24655 +
24656 + if (ar->arWmiReady == FALSE) {
24657 + return -EIO;
24658 + }
24659 +
24660 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24661 + return -EFAULT;
24662 + }
24663 +
24664 + if (wmi_probedSsid_cmd(ar->arWmi, cmd.entryIndex, cmd.flag, cmd.ssidLength,
24665 + cmd.ssid) != A_OK)
24666 + {
24667 + ret = -EIO;
24668 + }
24669 +
24670 + return ret;
24671 +}
24672 +
24673 +static int
24674 +ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq)
24675 +{
24676 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24677 + WMI_ADD_BAD_AP_CMD cmd;
24678 + int ret = 0;
24679 +
24680 + if (ar->arWmiReady == FALSE) {
24681 + return -EIO;
24682 + }
24683 +
24684 +
24685 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24686 + return -EFAULT;
24687 + }
24688 +
24689 + if (cmd.badApIndex > WMI_MAX_BAD_AP_INDEX) {
24690 + return -EIO;
24691 + }
24692 +
24693 + if (A_MEMCMP(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) {
24694 + /*
24695 + * This is a delete badAP.
24696 + */
24697 + if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != A_OK) {
24698 + ret = -EIO;
24699 + }
24700 + } else {
24701 + if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != A_OK) {
24702 + ret = -EIO;
24703 + }
24704 + }
24705 +
24706 + return ret;
24707 +}
24708 +
24709 +static int
24710 +ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq)
24711 +{
24712 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24713 + WMI_CREATE_PSTREAM_CMD cmd;
24714 + A_STATUS ret;
24715 +
24716 + if (ar->arWmiReady == FALSE) {
24717 + return -EIO;
24718 + }
24719 +
24720 +
24721 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24722 + return -EFAULT;
24723 + }
24724 +
24725 + ret = wmi_verify_tspec_params(&cmd, tspecCompliance);
24726 + if (ret == A_OK)
24727 + ret = wmi_create_pstream_cmd(ar->arWmi, &cmd);
24728 +
24729 + switch (ret) {
24730 + case A_OK:
24731 + return 0;
24732 + case A_EBUSY :
24733 + return -EBUSY;
24734 + case A_NO_MEMORY:
24735 + return -ENOMEM;
24736 + case A_EINVAL:
24737 + default:
24738 + return -EFAULT;
24739 + }
24740 +}
24741 +
24742 +static int
24743 +ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq)
24744 +{
24745 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24746 + WMI_DELETE_PSTREAM_CMD cmd;
24747 + int ret = 0;
24748 +
24749 + if (ar->arWmiReady == FALSE) {
24750 + return -EIO;
24751 + }
24752 +
24753 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24754 + return -EFAULT;
24755 + }
24756 +
24757 + ret = wmi_delete_pstream_cmd(ar->arWmi, cmd.trafficClass, cmd.tsid);
24758 +
24759 + switch (ret) {
24760 + case A_OK:
24761 + return 0;
24762 + case A_EBUSY :
24763 + return -EBUSY;
24764 + case A_NO_MEMORY:
24765 + return -ENOMEM;
24766 + case A_EINVAL:
24767 + default:
24768 + return -EFAULT;
24769 + }
24770 +}
24771 +
24772 +static int
24773 +ar6000_ioctl_get_qos_queue(struct net_device *dev, struct ifreq *rq)
24774 +{
24775 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24776 + struct ar6000_queuereq qreq;
24777 + int ret = 0;
24778 +
24779 + if (ar->arWmiReady == FALSE) {
24780 + return -EIO;
24781 + }
24782 +
24783 + if( copy_from_user(&qreq, rq->ifr_data,
24784 + sizeof(struct ar6000_queuereq)))
24785 + return -EFAULT;
24786 +
24787 + qreq.activeTsids = wmi_get_mapped_qos_queue(ar->arWmi, qreq.trafficClass);
24788 +
24789 + if (copy_to_user(rq->ifr_data, &qreq,
24790 + sizeof(struct ar6000_queuereq)))
24791 + {
24792 + ret = -EFAULT;
24793 + }
24794 +
24795 + return ret;
24796 +}
24797 +
24798 +#ifdef CONFIG_HOST_TCMD_SUPPORT
24799 +static A_STATUS
24800 +ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
24801 + struct ifreq *rq, A_UINT8 *data, A_UINT32 len)
24802 +{
24803 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24804 + A_UINT32 buf[2];
24805 + int ret = 0;
24806 +
24807 + if (ar->arWmiReady == FALSE) {
24808 + return -EIO;
24809 + }
24810 +
24811 + if (down_interruptible(&ar->arSem)) {
24812 + return -ERESTARTSYS;
24813 + }
24814 + ar->tcmdRxReport = 0;
24815 + if (wmi_test_cmd(ar->arWmi, data, len) != A_OK) {
24816 + up(&ar->arSem);
24817 + return -EIO;
24818 + }
24819 +
24820 + wait_event_interruptible_timeout(arEvent, ar->tcmdRxReport != 0, wmitimeout * HZ);
24821 +
24822 + if (signal_pending(current)) {
24823 + ret = -EINTR;
24824 + }
24825 +
24826 + buf[0] = ar->tcmdRxTotalPkt;
24827 + buf[1] = ar->tcmdRxRssi;
24828 + if (!ret && copy_to_user(rq->ifr_data, buf, sizeof(buf))) {
24829 + ret = -EFAULT;
24830 + }
24831 +
24832 + up(&ar->arSem);
24833 +
24834 + return ret;
24835 +}
24836 +
24837 +void
24838 +ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len)
24839 +{
24840 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
24841 + TCMD_CONT_RX * rx_rep = (TCMD_CONT_RX *)results;
24842 +
24843 + ar->tcmdRxTotalPkt = rx_rep->u.report.totalPkt;
24844 + ar->tcmdRxRssi = rx_rep->u.report.rssiInDBm;
24845 + ar->tcmdRxReport = 1;
24846 +
24847 + wake_up(&arEvent);
24848 +}
24849 +#endif /* CONFIG_HOST_TCMD_SUPPORT*/
24850 +
24851 +static int
24852 +ar6000_ioctl_set_error_report_bitmask(struct net_device *dev, struct ifreq *rq)
24853 +{
24854 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24855 + WMI_TARGET_ERROR_REPORT_BITMASK cmd;
24856 + int ret = 0;
24857 +
24858 + if (ar->arWmiReady == FALSE) {
24859 + return -EIO;
24860 + }
24861 +
24862 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24863 + return -EFAULT;
24864 + }
24865 +
24866 + ret = wmi_set_error_report_bitmask(ar->arWmi, cmd.bitmask);
24867 +
24868 + return (ret==0 ? ret : -EINVAL);
24869 +}
24870 +
24871 +static int
24872 +ar6000_clear_target_stats(struct net_device *dev)
24873 +{
24874 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24875 + TARGET_STATS *pStats = &ar->arTargetStats;
24876 + int ret = 0;
24877 +
24878 + if (ar->arWmiReady == FALSE) {
24879 + return -EIO;
24880 + }
24881 + AR6000_SPIN_LOCK(&ar->arLock, 0);
24882 + A_MEMZERO(pStats, sizeof(TARGET_STATS));
24883 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
24884 + return ret;
24885 +}
24886 +
24887 +static int
24888 +ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
24889 +{
24890 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24891 + TARGET_STATS_CMD cmd;
24892 + TARGET_STATS *pStats = &ar->arTargetStats;
24893 + int ret = 0;
24894 +
24895 + if (ar->arWmiReady == FALSE) {
24896 + return -EIO;
24897 + }
24898 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24899 + return -EFAULT;
24900 + }
24901 + if (down_interruptible(&ar->arSem)) {
24902 + return -ERESTARTSYS;
24903 + }
24904 +
24905 + ar->statsUpdatePending = TRUE;
24906 +
24907 + if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
24908 + up(&ar->arSem);
24909 + return -EIO;
24910 + }
24911 +
24912 + wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
24913 +
24914 + if (signal_pending(current)) {
24915 + ret = -EINTR;
24916 + }
24917 +
24918 + if (!ret && copy_to_user(rq->ifr_data, pStats, sizeof(*pStats))) {
24919 + ret = -EFAULT;
24920 + }
24921 +
24922 + if (cmd.clearStats == 1) {
24923 + ret = ar6000_clear_target_stats(dev);
24924 + }
24925 +
24926 + up(&ar->arSem);
24927 +
24928 + return ret;
24929 +}
24930 +
24931 +static int
24932 +ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq)
24933 +{
24934 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24935 + WMI_SET_ACCESS_PARAMS_CMD cmd;
24936 + int ret = 0;
24937 +
24938 + if (ar->arWmiReady == FALSE) {
24939 + return -EIO;
24940 + }
24941 +
24942 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24943 + return -EFAULT;
24944 + }
24945 +
24946 + if (wmi_set_access_params_cmd(ar->arWmi, cmd.txop, cmd.eCWmin, cmd.eCWmax,
24947 + cmd.aifsn) == A_OK)
24948 + {
24949 + ret = 0;
24950 + } else {
24951 + ret = -EINVAL;
24952 + }
24953 +
24954 + return (ret);
24955 +}
24956 +
24957 +static int
24958 +ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq)
24959 +{
24960 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24961 + WMI_DISC_TIMEOUT_CMD cmd;
24962 + int ret = 0;
24963 +
24964 + if (ar->arWmiReady == FALSE) {
24965 + return -EIO;
24966 + }
24967 +
24968 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24969 + return -EFAULT;
24970 + }
24971 +
24972 + if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == A_OK)
24973 + {
24974 + ret = 0;
24975 + } else {
24976 + ret = -EINVAL;
24977 + }
24978 +
24979 + return (ret);
24980 +}
24981 +
24982 +static int
24983 +ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char * userdata)
24984 +{
24985 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24986 + WMI_SET_VOICE_PKT_SIZE_CMD cmd;
24987 + int ret = 0;
24988 +
24989 + if (ar->arWmiReady == FALSE) {
24990 + return -EIO;
24991 + }
24992 +
24993 + if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
24994 + return -EFAULT;
24995 + }
24996 +
24997 + if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == A_OK)
24998 + {
24999 + ret = 0;
25000 + } else {
25001 + ret = -EINVAL;
25002 + }
25003 +
25004 +
25005 + return (ret);
25006 +}
25007 +
25008 +static int
25009 +ar6000_xioctl_set_max_sp_len(struct net_device *dev, char * userdata)
25010 +{
25011 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25012 + WMI_SET_MAX_SP_LEN_CMD cmd;
25013 + int ret = 0;
25014 +
25015 + if (ar->arWmiReady == FALSE) {
25016 + return -EIO;
25017 + }
25018 +
25019 + if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
25020 + return -EFAULT;
25021 + }
25022 +
25023 + if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == A_OK)
25024 + {
25025 + ret = 0;
25026 + } else {
25027 + ret = -EINVAL;
25028 + }
25029 +
25030 + return (ret);
25031 +}
25032 +
25033 +
25034 +static int
25035 +ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char * userdata)
25036 +{
25037 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25038 + WMI_SET_BT_STATUS_CMD cmd;
25039 + int ret = 0;
25040 +
25041 + if (ar->arWmiReady == FALSE) {
25042 + return -EIO;
25043 + }
25044 +
25045 + if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
25046 + return -EFAULT;
25047 + }
25048 +
25049 + if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == A_OK)
25050 + {
25051 + ret = 0;
25052 + } else {
25053 + ret = -EINVAL;
25054 + }
25055 +
25056 + return (ret);
25057 +}
25058 +
25059 +static int
25060 +ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char * userdata)
25061 +{
25062 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25063 + WMI_SET_BT_PARAMS_CMD cmd;
25064 + int ret = 0;
25065 +
25066 + if (ar->arWmiReady == FALSE) {
25067 + return -EIO;
25068 + }
25069 +
25070 + if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
25071 + return -EFAULT;
25072 + }
25073 +
25074 + if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == A_OK)
25075 + {
25076 + ret = 0;
25077 + } else {
25078 + ret = -EINVAL;
25079 + }
25080 +
25081 + return (ret);
25082 +}
25083 +
25084 +#ifdef CONFIG_HOST_GPIO_SUPPORT
25085 +struct ar6000_gpio_intr_wait_cmd_s gpio_intr_results;
25086 +/* gpio_reg_results and gpio_data_available are protected by arSem */
25087 +static struct ar6000_gpio_register_cmd_s gpio_reg_results;
25088 +static A_BOOL gpio_data_available; /* Requested GPIO data available */
25089 +static A_BOOL gpio_intr_available; /* GPIO interrupt info available */
25090 +static A_BOOL gpio_ack_received; /* GPIO ack was received */
25091 +
25092 +/* Host-side initialization for General Purpose I/O support */
25093 +void ar6000_gpio_init(void)
25094 +{
25095 + gpio_intr_available = FALSE;
25096 + gpio_data_available = FALSE;
25097 + gpio_ack_received = FALSE;
25098 +}
25099 +
25100 +/*
25101 + * Called when a GPIO interrupt is received from the Target.
25102 + * intr_values shows which GPIO pins have interrupted.
25103 + * input_values shows a recent value of GPIO pins.
25104 + */
25105 +void
25106 +ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values)
25107 +{
25108 + gpio_intr_results.intr_mask = intr_mask;
25109 + gpio_intr_results.input_values = input_values;
25110 + *((volatile A_BOOL *)&gpio_intr_available) = TRUE;
25111 + wake_up(&arEvent);
25112 +}
25113 +
25114 +/*
25115 + * This is called when a response is received from the Target
25116 + * for a previous or ar6000_gpio_input_get or ar6000_gpio_register_get
25117 + * call.
25118 + */
25119 +void
25120 +ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value)
25121 +{
25122 + gpio_reg_results.gpioreg_id = reg_id;
25123 + gpio_reg_results.value = value;
25124 + *((volatile A_BOOL *)&gpio_data_available) = TRUE;
25125 + wake_up(&arEvent);
25126 +}
25127 +
25128 +/*
25129 + * This is called when an acknowledgement is received from the Target
25130 + * for a previous or ar6000_gpio_output_set or ar6000_gpio_register_set
25131 + * call.
25132 + */
25133 +void
25134 +ar6000_gpio_ack_rx(void)
25135 +{
25136 + gpio_ack_received = TRUE;
25137 + wake_up(&arEvent);
25138 +}
25139 +
25140 +A_STATUS
25141 +ar6000_gpio_output_set(struct net_device *dev,
25142 + A_UINT32 set_mask,
25143 + A_UINT32 clear_mask,
25144 + A_UINT32 enable_mask,
25145 + A_UINT32 disable_mask)
25146 +{
25147 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25148 +
25149 + gpio_ack_received = FALSE;
25150 + return wmi_gpio_output_set(ar->arWmi,
25151 + set_mask, clear_mask, enable_mask, disable_mask);
25152 +}
25153 +
25154 +static A_STATUS
25155 +ar6000_gpio_input_get(struct net_device *dev)
25156 +{
25157 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25158 +
25159 + *((volatile A_BOOL *)&gpio_data_available) = FALSE;
25160 + return wmi_gpio_input_get(ar->arWmi);
25161 +}
25162 +
25163 +static A_STATUS
25164 +ar6000_gpio_register_set(struct net_device *dev,
25165 + A_UINT32 gpioreg_id,
25166 + A_UINT32 value)
25167 +{
25168 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25169 +
25170 + gpio_ack_received = FALSE;
25171 + return wmi_gpio_register_set(ar->arWmi, gpioreg_id, value);
25172 +}
25173 +
25174 +static A_STATUS
25175 +ar6000_gpio_register_get(struct net_device *dev,
25176 + A_UINT32 gpioreg_id)
25177 +{
25178 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25179 +
25180 + *((volatile A_BOOL *)&gpio_data_available) = FALSE;
25181 + return wmi_gpio_register_get(ar->arWmi, gpioreg_id);
25182 +}
25183 +
25184 +static A_STATUS
25185 +ar6000_gpio_intr_ack(struct net_device *dev,
25186 + A_UINT32 ack_mask)
25187 +{
25188 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25189 +
25190 + gpio_intr_available = FALSE;
25191 + return wmi_gpio_intr_ack(ar->arWmi, ack_mask);
25192 +}
25193 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
25194 +
25195 +int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
25196 +{
25197 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25198 + HIF_DEVICE *hifDevice = ar->arHifDevice;
25199 + int ret, param, param2;
25200 + unsigned int address = 0;
25201 + unsigned int length = 0;
25202 + unsigned char *buffer;
25203 + char *userdata;
25204 + A_UINT32 connectCtrlFlags;
25205 +
25206 +
25207 + static WMI_SCAN_PARAMS_CMD scParams = {0, 0, 0, 0, 0,
25208 + WMI_SHORTSCANRATIO_DEFAULT,
25209 + DEFAULT_SCAN_CTRL_FLAGS,
25210 + 0};
25211 + WMI_SET_AKMP_PARAMS_CMD akmpParams;
25212 + WMI_SET_PMKID_LIST_CMD pmkidInfo;
25213 +
25214 + if (cmd == AR6000_IOCTL_EXTENDED)
25215 + {
25216 + /*
25217 + * This allows for many more wireless ioctls than would otherwise
25218 + * be available. Applications embed the actual ioctl command in
25219 + * the first word of the parameter block, and use the command
25220 + * AR6000_IOCTL_EXTENDED_CMD on the ioctl call.
25221 + */
25222 + get_user(cmd, (int *)rq->ifr_data);
25223 + userdata = (char *)(((unsigned int *)rq->ifr_data)+1);
25224 + }
25225 + else
25226 + {
25227 + userdata = (char *)rq->ifr_data;
25228 + }
25229 +
25230 + if ((ar->arWlanState == WLAN_DISABLED) &&
25231 + ((cmd != AR6000_XIOCTRL_WMI_SET_WLAN_STATE) &&
25232 + (cmd != AR6000_XIOCTL_DIAG_READ) &&
25233 + (cmd != AR6000_XIOCTL_DIAG_WRITE)))
25234 + {
25235 + return -EIO;
25236 + }
25237 +
25238 + ret = 0;
25239 + switch(cmd)
25240 + {
25241 +#ifdef CONFIG_HOST_TCMD_SUPPORT
25242 + case AR6000_XIOCTL_TCMD_CONT_TX:
25243 + {
25244 + TCMD_CONT_TX txCmd;
25245 +
25246 + if (ar->tcmdPm == TCMD_PM_SLEEP) {
25247 + A_PRINTF("Can NOT send tx tcmd when target is asleep! \n");
25248 + return -EFAULT;
25249 + }
25250 +
25251 + if(copy_from_user(&txCmd, userdata, sizeof(TCMD_CONT_TX)))
25252 + return -EFAULT;
25253 + wmi_test_cmd(ar->arWmi,(A_UINT8 *)&txCmd, sizeof(TCMD_CONT_TX));
25254 + }
25255 + break;
25256 + case AR6000_XIOCTL_TCMD_CONT_RX:
25257 + {
25258 + TCMD_CONT_RX rxCmd;
25259 +
25260 + if (ar->tcmdPm == TCMD_PM_SLEEP) {
25261 + A_PRINTF("Can NOT send rx tcmd when target is asleep! \n");
25262 + return -EFAULT;
25263 + }
25264 + if(copy_from_user(&rxCmd, userdata, sizeof(TCMD_CONT_RX)))
25265 + return -EFAULT;
25266 + switch(rxCmd.act)
25267 + {
25268 + case TCMD_CONT_RX_PROMIS:
25269 + case TCMD_CONT_RX_FILTER:
25270 + case TCMD_CONT_RX_SETMAC:
25271 + wmi_test_cmd(ar->arWmi,(A_UINT8 *)&rxCmd,
25272 + sizeof(TCMD_CONT_RX));
25273 + break;
25274 + case TCMD_CONT_RX_REPORT:
25275 + ar6000_ioctl_tcmd_get_rx_report(dev, rq,
25276 + (A_UINT8 *)&rxCmd, sizeof(TCMD_CONT_RX));
25277 + break;
25278 + default:
25279 + A_PRINTF("Unknown Cont Rx mode: %d\n",rxCmd.act);
25280 + return -EINVAL;
25281 + }
25282 + }
25283 + break;
25284 + case AR6000_XIOCTL_TCMD_PM:
25285 + {
25286 + TCMD_PM pmCmd;
25287 +
25288 + if(copy_from_user(&pmCmd, userdata, sizeof(TCMD_PM)))
25289 + return -EFAULT;
25290 + ar->tcmdPm = pmCmd.mode;
25291 + wmi_test_cmd(ar->arWmi, (A_UINT8*)&pmCmd, sizeof(TCMD_PM));
25292 + }
25293 + break;
25294 +#endif /* CONFIG_HOST_TCMD_SUPPORT */
25295 +
25296 + case AR6000_XIOCTL_BMI_DONE:
25297 + if(bmienable)
25298 + {
25299 + ret = ar6000_init(dev);
25300 + }
25301 + else
25302 + {
25303 + ret = BMIDone(hifDevice);
25304 + }
25305 + break;
25306 +
25307 + case AR6000_XIOCTL_BMI_READ_MEMORY:
25308 + get_user(address, (unsigned int *)userdata);
25309 + get_user(length, (unsigned int *)userdata + 1);
25310 + AR_DEBUG_PRINTF("Read Memory (address: 0x%x, length: %d)\n",
25311 + address, length);
25312 + if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
25313 + A_MEMZERO(buffer, length);
25314 + ret = BMIReadMemory(hifDevice, address, buffer, length);
25315 + if (copy_to_user(rq->ifr_data, buffer, length)) {
25316 + ret = -EFAULT;
25317 + }
25318 + A_FREE(buffer);
25319 + } else {
25320 + ret = -ENOMEM;
25321 + }
25322 + break;
25323 +
25324 + case AR6000_XIOCTL_BMI_WRITE_MEMORY:
25325 + get_user(address, (unsigned int *)userdata);
25326 + get_user(length, (unsigned int *)userdata + 1);
25327 + AR_DEBUG_PRINTF("Write Memory (address: 0x%x, length: %d)\n",
25328 + address, length);
25329 + if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
25330 + A_MEMZERO(buffer, length);
25331 + if (copy_from_user(buffer, &userdata[sizeof(address) +
25332 + sizeof(length)], length))
25333 + {
25334 + ret = -EFAULT;
25335 + } else {
25336 + ret = BMIWriteMemory(hifDevice, address, buffer, length);
25337 + }
25338 + A_FREE(buffer);
25339 + } else {
25340 + ret = -ENOMEM;
25341 + }
25342 + break;
25343 +
25344 + case AR6000_XIOCTL_BMI_TEST:
25345 + AR_DEBUG_PRINTF("No longer supported\n");
25346 + ret = -EOPNOTSUPP;
25347 + break;
25348 +
25349 + case AR6000_XIOCTL_BMI_EXECUTE:
25350 + get_user(address, (unsigned int *)userdata);
25351 + get_user(param, (unsigned int *)userdata + 1);
25352 + AR_DEBUG_PRINTF("Execute (address: 0x%x, param: %d)\n",
25353 + address, param);
25354 + ret = BMIExecute(hifDevice, address, &param);
25355 + put_user(param, (unsigned int *)rq->ifr_data); /* return value */
25356 + break;
25357 +
25358 + case AR6000_XIOCTL_BMI_SET_APP_START:
25359 + get_user(address, (unsigned int *)userdata);
25360 + AR_DEBUG_PRINTF("Set App Start (address: 0x%x)\n", address);
25361 + ret = BMISetAppStart(hifDevice, address);
25362 + break;
25363 +
25364 + case AR6000_XIOCTL_BMI_READ_SOC_REGISTER:
25365 + get_user(address, (unsigned int *)userdata);
25366 + ret = BMIReadSOCRegister(hifDevice, address, &param);
25367 + put_user(param, (unsigned int *)rq->ifr_data); /* return value */
25368 + break;
25369 +
25370 + case AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER:
25371 + get_user(address, (unsigned int *)userdata);
25372 + get_user(param, (unsigned int *)userdata + 1);
25373 + ret = BMIWriteSOCRegister(hifDevice, address, param);
25374 + break;
25375 +
25376 +#ifdef HTC_RAW_INTERFACE
25377 + case AR6000_XIOCTL_HTC_RAW_OPEN:
25378 + ret = A_OK;
25379 + if (!arRawIfEnabled(ar)) {
25380 + /* make sure block size is set in case the target was reset since last
25381 + * BMI phase (i.e. flashup downloads) */
25382 + ret = ar6000_SetHTCBlockSize(ar);
25383 + if (A_FAILED(ret)) {
25384 + break;
25385 + }
25386 + /* Terminate the BMI phase */
25387 + ret = BMIDone(hifDevice);
25388 + if (ret == A_OK) {
25389 + ret = ar6000_htc_raw_open(ar);
25390 + }
25391 + }
25392 + break;
25393 +
25394 + case AR6000_XIOCTL_HTC_RAW_CLOSE:
25395 + if (arRawIfEnabled(ar)) {
25396 + ret = ar6000_htc_raw_close(ar);
25397 + arRawIfEnabled(ar) = FALSE;
25398 + } else {
25399 + ret = A_ERROR;
25400 + }
25401 + break;
25402 +
25403 + case AR6000_XIOCTL_HTC_RAW_READ:
25404 + if (arRawIfEnabled(ar)) {
25405 + unsigned int streamID;
25406 + get_user(streamID, (unsigned int *)userdata);
25407 + get_user(length, (unsigned int *)userdata + 1);
25408 + buffer = rq->ifr_data + sizeof(length);
25409 + ret = ar6000_htc_raw_read(ar, (HTC_RAW_STREAM_ID)streamID,
25410 + buffer, length);
25411 + put_user(ret, (unsigned int *)rq->ifr_data);
25412 + } else {
25413 + ret = A_ERROR;
25414 + }
25415 + break;
25416 +
25417 + case AR6000_XIOCTL_HTC_RAW_WRITE:
25418 + if (arRawIfEnabled(ar)) {
25419 + unsigned int streamID;
25420 + get_user(streamID, (unsigned int *)userdata);
25421 + get_user(length, (unsigned int *)userdata + 1);
25422 + buffer = userdata + sizeof(streamID) + sizeof(length);
25423 + ret = ar6000_htc_raw_write(ar, (HTC_RAW_STREAM_ID)streamID,
25424 + buffer, length);
25425 + put_user(ret, (unsigned int *)rq->ifr_data);
25426 + } else {
25427 + ret = A_ERROR;
25428 + }
25429 + break;
25430 +#endif /* HTC_RAW_INTERFACE */
25431 +
25432 + case AR6000_IOCTL_WMI_GETREV:
25433 + {
25434 + if (copy_to_user(rq->ifr_data, &ar->arVersion,
25435 + sizeof(ar->arVersion)))
25436 + {
25437 + ret = -EFAULT;
25438 + }
25439 + break;
25440 + }
25441 + case AR6000_IOCTL_WMI_SETPWR:
25442 + {
25443 + WMI_POWER_MODE_CMD pwrModeCmd;
25444 +
25445 + if (ar->arWmiReady == FALSE) {
25446 + ret = -EIO;
25447 + } else if (copy_from_user(&pwrModeCmd, userdata,
25448 + sizeof(pwrModeCmd)))
25449 + {
25450 + ret = -EFAULT;
25451 + } else {
25452 + if (wmi_powermode_cmd(ar->arWmi, pwrModeCmd.powerMode)
25453 + != A_OK)
25454 + {
25455 + ret = -EIO;
25456 + }
25457 + }
25458 + break;
25459 + }
25460 + case AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS:
25461 + {
25462 + WMI_IBSS_PM_CAPS_CMD ibssPmCaps;
25463 +
25464 + if (ar->arWmiReady == FALSE) {
25465 + ret = -EIO;
25466 + } else if (copy_from_user(&ibssPmCaps, userdata,
25467 + sizeof(ibssPmCaps)))
25468 + {
25469 + ret = -EFAULT;
25470 + } else {
25471 + if (wmi_ibsspmcaps_cmd(ar->arWmi, ibssPmCaps.power_saving, ibssPmCaps.ttl,
25472 + ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != A_OK)
25473 + {
25474 + ret = -EIO;
25475 + }
25476 + AR6000_SPIN_LOCK(&ar->arLock, 0);
25477 + ar->arIbssPsEnable = ibssPmCaps.power_saving;
25478 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
25479 + }
25480 + break;
25481 + }
25482 + case AR6000_IOCTL_WMI_SET_PMPARAMS:
25483 + {
25484 + WMI_POWER_PARAMS_CMD pmParams;
25485 +
25486 + if (ar->arWmiReady == FALSE) {
25487 + ret = -EIO;
25488 + } else if (copy_from_user(&pmParams, userdata,
25489 + sizeof(pmParams)))
25490 + {
25491 + ret = -EFAULT;
25492 + } else {
25493 + if (wmi_pmparams_cmd(ar->arWmi, pmParams.idle_period,
25494 + pmParams.pspoll_number,
25495 + pmParams.dtim_policy) != A_OK)
25496 + {
25497 + ret = -EIO;
25498 + }
25499 + }
25500 + break;
25501 + }
25502 + case AR6000_IOCTL_WMI_SETSCAN:
25503 + {
25504 + if (ar->arWmiReady == FALSE) {
25505 + ret = -EIO;
25506 + } else if (copy_from_user(&scParams, userdata,
25507 + sizeof(scParams)))
25508 + {
25509 + ret = -EFAULT;
25510 + } else {
25511 + if (CAN_SCAN_IN_CONNECT(scParams.scanCtrlFlags)) {
25512 + ar->arSkipScan = FALSE;
25513 + } else {
25514 + ar->arSkipScan = TRUE;
25515 + }
25516 +
25517 + if (wmi_scanparams_cmd(ar->arWmi, scParams.fg_start_period,
25518 + scParams.fg_end_period,
25519 + scParams.bg_period,
25520 + scParams.minact_chdwell_time,
25521 + scParams.maxact_chdwell_time,
25522 + scParams.pas_chdwell_time,
25523 + scParams.shortScanRatio,
25524 + scParams.scanCtrlFlags,
25525 + scParams.max_dfsch_act_time) != A_OK)
25526 + {
25527 + ret = -EIO;
25528 + }
25529 + }
25530 + break;
25531 + }
25532 + case AR6000_IOCTL_WMI_SETLISTENINT:
25533 + {
25534 + WMI_LISTEN_INT_CMD listenCmd;
25535 +
25536 + if (ar->arWmiReady == FALSE) {
25537 + ret = -EIO;
25538 + } else if (copy_from_user(&listenCmd, userdata,
25539 + sizeof(listenCmd)))
25540 + {
25541 + ret = -EFAULT;
25542 + } else {
25543 + if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != A_OK) {
25544 + ret = -EIO;
25545 + } else {
25546 + AR6000_SPIN_LOCK(&ar->arLock, 0);
25547 + ar->arListenInterval = param;
25548 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
25549 + }
25550 +
25551 + }
25552 + break;
25553 + }
25554 + case AR6000_IOCTL_WMI_SET_BMISS_TIME:
25555 + {
25556 + WMI_BMISS_TIME_CMD bmissCmd;
25557 +
25558 + if (ar->arWmiReady == FALSE) {
25559 + ret = -EIO;
25560 + } else if (copy_from_user(&bmissCmd, userdata,
25561 + sizeof(bmissCmd)))
25562 + {
25563 + ret = -EFAULT;
25564 + } else {
25565 + if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != A_OK) {
25566 + ret = -EIO;
25567 + }
25568 + }
25569 + break;
25570 + }
25571 + case AR6000_IOCTL_WMI_SETBSSFILTER:
25572 + {
25573 + if (ar->arWmiReady == FALSE) {
25574 + ret = -EIO;
25575 + } else {
25576 +
25577 + get_user(param, (unsigned char *)userdata);
25578 + get_user(param2, (unsigned int *)(userdata + 1));
25579 + printk("SETBSSFILTER: filter 0x%x, mask: 0x%x\n", param, param2);
25580 + if (wmi_bssfilter_cmd(ar->arWmi, param, param2) != A_OK) {
25581 + ret = -EIO;
25582 + }
25583 + }
25584 + break;
25585 + }
25586 + case AR6000_IOCTL_WMI_SET_SNRTHRESHOLD:
25587 + {
25588 + ret = ar6000_ioctl_set_snr_threshold(dev, rq);
25589 + break;
25590 + }
25591 + case AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD:
25592 + {
25593 + ret = ar6000_ioctl_set_rssi_threshold(dev, rq);
25594 + break;
25595 + }
25596 + case AR6000_XIOCTL_WMI_CLR_RSSISNR:
25597 + {
25598 + if (ar->arWmiReady == FALSE) {
25599 + ret = -EIO;
25600 + }
25601 + ret = wmi_clr_rssi_snr(ar->arWmi);
25602 + break;
25603 + }
25604 + case AR6000_XIOCTL_WMI_SET_LQTHRESHOLD:
25605 + {
25606 + ret = ar6000_ioctl_set_lq_threshold(dev, rq);
25607 + break;
25608 + }
25609 + case AR6000_XIOCTL_WMI_SET_LPREAMBLE:
25610 + {
25611 + WMI_SET_LPREAMBLE_CMD setLpreambleCmd;
25612 +
25613 + if (ar->arWmiReady == FALSE) {
25614 + ret = -EIO;
25615 + } else if (copy_from_user(&setLpreambleCmd, userdata,
25616 + sizeof(setLpreambleCmd)))
25617 + {
25618 + ret = -EFAULT;
25619 + } else {
25620 + if (wmi_set_lpreamble_cmd(ar->arWmi, setLpreambleCmd.status)
25621 + != A_OK)
25622 + {
25623 + ret = -EIO;
25624 + }
25625 + }
25626 +
25627 + break;
25628 + }
25629 + case AR6000_XIOCTL_WMI_SET_RTS:
25630 + {
25631 + WMI_SET_RTS_CMD rtsCmd;
25632 +
25633 + if (ar->arWmiReady == FALSE) {
25634 + ret = -EIO;
25635 + } else if (copy_from_user(&rtsCmd, userdata,
25636 + sizeof(rtsCmd)))
25637 + {
25638 + ret = -EFAULT;
25639 + } else {
25640 + if (wmi_set_rts_cmd(ar->arWmi, rtsCmd.threshold)
25641 + != A_OK)
25642 + {
25643 + ret = -EIO;
25644 + }
25645 + }
25646 +
25647 + break;
25648 + }
25649 + case AR6000_XIOCTL_WMI_SET_WMM:
25650 + {
25651 + ret = ar6000_ioctl_set_wmm(dev, rq);
25652 + break;
25653 + }
25654 + case AR6000_XIOCTL_WMI_SET_TXOP:
25655 + {
25656 + ret = ar6000_ioctl_set_txop(dev, rq);
25657 + break;
25658 + }
25659 + case AR6000_XIOCTL_WMI_GET_RD:
25660 + {
25661 + ret = ar6000_ioctl_get_rd(dev, rq);
25662 + break;
25663 + }
25664 + case AR6000_IOCTL_WMI_SET_CHANNELPARAMS:
25665 + {
25666 + ret = ar6000_ioctl_set_channelParams(dev, rq);
25667 + break;
25668 + }
25669 + case AR6000_IOCTL_WMI_SET_PROBEDSSID:
25670 + {
25671 + ret = ar6000_ioctl_set_probedSsid(dev, rq);
25672 + break;
25673 + }
25674 + case AR6000_IOCTL_WMI_SET_BADAP:
25675 + {
25676 + ret = ar6000_ioctl_set_badAp(dev, rq);
25677 + break;
25678 + }
25679 + case AR6000_IOCTL_WMI_CREATE_QOS:
25680 + {
25681 + ret = ar6000_ioctl_create_qos(dev, rq);
25682 + break;
25683 + }
25684 + case AR6000_IOCTL_WMI_DELETE_QOS:
25685 + {
25686 + ret = ar6000_ioctl_delete_qos(dev, rq);
25687 + break;
25688 + }
25689 + case AR6000_IOCTL_WMI_GET_QOS_QUEUE:
25690 + {
25691 + ret = ar6000_ioctl_get_qos_queue(dev, rq);
25692 + break;
25693 + }
25694 + case AR6000_IOCTL_WMI_GET_TARGET_STATS:
25695 + {
25696 + ret = ar6000_ioctl_get_target_stats(dev, rq);
25697 + break;
25698 + }
25699 + case AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK:
25700 + {
25701 + ret = ar6000_ioctl_set_error_report_bitmask(dev, rq);
25702 + break;
25703 + }
25704 + case AR6000_IOCTL_WMI_SET_ASSOC_INFO:
25705 + {
25706 + WMI_SET_ASSOC_INFO_CMD cmd;
25707 + A_UINT8 assocInfo[WMI_MAX_ASSOC_INFO_LEN];
25708 +
25709 + if (ar->arWmiReady == FALSE) {
25710 + ret = -EIO;
25711 + } else {
25712 + get_user(cmd.ieType, userdata);
25713 + if (cmd.ieType >= WMI_MAX_ASSOC_INFO_TYPE) {
25714 + ret = -EIO;
25715 + } else {
25716 + get_user(cmd.bufferSize, userdata + 1);
25717 + if (cmd.bufferSize > WMI_MAX_ASSOC_INFO_LEN) {
25718 + ret = -EFAULT;
25719 + break;
25720 + }
25721 + if (copy_from_user(assocInfo, userdata + 2,
25722 + cmd.bufferSize))
25723 + {
25724 + ret = -EFAULT;
25725 + } else {
25726 + if (wmi_associnfo_cmd(ar->arWmi, cmd.ieType,
25727 + cmd.bufferSize,
25728 + assocInfo) != A_OK)
25729 + {
25730 + ret = -EIO;
25731 + }
25732 + }
25733 + }
25734 + }
25735 + break;
25736 + }
25737 + case AR6000_IOCTL_WMI_SET_ACCESS_PARAMS:
25738 + {
25739 + ret = ar6000_ioctl_set_access_params(dev, rq);
25740 + break;
25741 + }
25742 + case AR6000_IOCTL_WMI_SET_DISC_TIMEOUT:
25743 + {
25744 + ret = ar6000_ioctl_set_disconnect_timeout(dev, rq);
25745 + break;
25746 + }
25747 + case AR6000_XIOCTL_FORCE_TARGET_RESET:
25748 + {
25749 + if (ar->arHtcTarget)
25750 + {
25751 +// HTCForceReset(htcTarget);
25752 + }
25753 + else
25754 + {
25755 + AR_DEBUG_PRINTF("ar6000_ioctl cannot attempt reset.\n");
25756 + }
25757 + break;
25758 + }
25759 + case AR6000_XIOCTL_TARGET_INFO:
25760 + case AR6000_XIOCTL_CHECK_TARGET_READY: /* backwards compatibility */
25761 + {
25762 + /* If we made it to here, then the Target exists and is ready. */
25763 +
25764 + if (cmd == AR6000_XIOCTL_TARGET_INFO) {
25765 + if (copy_to_user((A_UINT32 *)rq->ifr_data, &ar->arVersion.target_ver,
25766 + sizeof(ar->arVersion.target_ver)))
25767 + {
25768 + ret = -EFAULT;
25769 + }
25770 + if (copy_to_user(((A_UINT32 *)rq->ifr_data)+1, &ar->arTargetType,
25771 + sizeof(ar->arTargetType)))
25772 + {
25773 + ret = -EFAULT;
25774 + }
25775 + }
25776 + break;
25777 + }
25778 + case AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS:
25779 + {
25780 + WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD hbparam;
25781 +
25782 + if (copy_from_user(&hbparam, userdata, sizeof(hbparam)))
25783 + {
25784 + ret = -EFAULT;
25785 + } else {
25786 + AR6000_SPIN_LOCK(&ar->arLock, 0);
25787 + /* Start a cyclic timer with the parameters provided. */
25788 + if (hbparam.frequency) {
25789 + ar->arHBChallengeResp.frequency = hbparam.frequency;
25790 + }
25791 + if (hbparam.threshold) {
25792 + ar->arHBChallengeResp.missThres = hbparam.threshold;
25793 + }
25794 +
25795 + /* Delete the pending timer and start a new one */
25796 + if (timer_pending(&ar->arHBChallengeResp.timer)) {
25797 + A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
25798 + }
25799 + A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
25800 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
25801 + }
25802 + break;
25803 + }
25804 + case AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP:
25805 + {
25806 + A_UINT32 cookie;
25807 +
25808 + if (copy_from_user(&cookie, userdata, sizeof(cookie))) {
25809 + return -EFAULT;
25810 + }
25811 +
25812 + /* Send the challenge on the control channel */
25813 + if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != A_OK) {
25814 + return -EIO;
25815 + }
25816 + break;
25817 + }
25818 +#ifdef USER_KEYS
25819 + case AR6000_XIOCTL_USER_SETKEYS:
25820 + {
25821 +
25822 + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_RUN;
25823 +
25824 + if (copy_from_user(&ar->user_key_ctrl, userdata,
25825 + sizeof(ar->user_key_ctrl)))
25826 + {
25827 + return -EFAULT;
25828 + }
25829 +
25830 + A_PRINTF("ar6000 USER set key %x\n", ar->user_key_ctrl);
25831 + break;
25832 + }
25833 +#endif /* USER_KEYS */
25834 +
25835 +#ifdef CONFIG_HOST_GPIO_SUPPORT
25836 + case AR6000_XIOCTL_GPIO_OUTPUT_SET:
25837 + {
25838 + struct ar6000_gpio_output_set_cmd_s gpio_output_set_cmd;
25839 +
25840 + if (ar->arWmiReady == FALSE) {
25841 + return -EIO;
25842 + }
25843 + if (down_interruptible(&ar->arSem)) {
25844 + return -ERESTARTSYS;
25845 + }
25846 +
25847 + if (copy_from_user(&gpio_output_set_cmd, userdata,
25848 + sizeof(gpio_output_set_cmd)))
25849 + {
25850 + ret = -EFAULT;
25851 + } else {
25852 + ret = ar6000_gpio_output_set(dev,
25853 + gpio_output_set_cmd.set_mask,
25854 + gpio_output_set_cmd.clear_mask,
25855 + gpio_output_set_cmd.enable_mask,
25856 + gpio_output_set_cmd.disable_mask);
25857 + if (ret != A_OK) {
25858 + ret = EIO;
25859 + }
25860 + }
25861 + up(&ar->arSem);
25862 + break;
25863 + }
25864 + case AR6000_XIOCTL_GPIO_INPUT_GET:
25865 + {
25866 + if (ar->arWmiReady == FALSE) {
25867 + return -EIO;
25868 + }
25869 + if (down_interruptible(&ar->arSem)) {
25870 + return -ERESTARTSYS;
25871 + }
25872 +
25873 + ret = ar6000_gpio_input_get(dev);
25874 + if (ret != A_OK) {
25875 + up(&ar->arSem);
25876 + return -EIO;
25877 + }
25878 +
25879 + /* Wait for Target to respond. */
25880 + wait_event_interruptible(arEvent, gpio_data_available);
25881 + if (signal_pending(current)) {
25882 + ret = -EINTR;
25883 + } else {
25884 + A_ASSERT(gpio_reg_results.gpioreg_id == GPIO_ID_NONE);
25885 +
25886 + if (copy_to_user(userdata, &gpio_reg_results.value,
25887 + sizeof(gpio_reg_results.value)))
25888 + {
25889 + ret = -EFAULT;
25890 + }
25891 + }
25892 + up(&ar->arSem);
25893 + break;
25894 + }
25895 + case AR6000_XIOCTL_GPIO_REGISTER_SET:
25896 + {
25897 + struct ar6000_gpio_register_cmd_s gpio_register_cmd;
25898 +
25899 + if (ar->arWmiReady == FALSE) {
25900 + return -EIO;
25901 + }
25902 + if (down_interruptible(&ar->arSem)) {
25903 + return -ERESTARTSYS;
25904 + }
25905 +
25906 + if (copy_from_user(&gpio_register_cmd, userdata,
25907 + sizeof(gpio_register_cmd)))
25908 + {
25909 + ret = -EFAULT;
25910 + } else {
25911 + ret = ar6000_gpio_register_set(dev,
25912 + gpio_register_cmd.gpioreg_id,
25913 + gpio_register_cmd.value);
25914 + if (ret != A_OK) {
25915 + ret = EIO;
25916 + }
25917 +
25918 + /* Wait for acknowledgement from Target */
25919 + wait_event_interruptible(arEvent, gpio_ack_received);
25920 + if (signal_pending(current)) {
25921 + ret = -EINTR;
25922 + }
25923 + }
25924 + up(&ar->arSem);
25925 + break;
25926 + }
25927 + case AR6000_XIOCTL_GPIO_REGISTER_GET:
25928 + {
25929 + struct ar6000_gpio_register_cmd_s gpio_register_cmd;
25930 +
25931 + if (ar->arWmiReady == FALSE) {
25932 + return -EIO;
25933 + }
25934 + if (down_interruptible(&ar->arSem)) {
25935 + return -ERESTARTSYS;
25936 + }
25937 +
25938 + if (copy_from_user(&gpio_register_cmd, userdata,
25939 + sizeof(gpio_register_cmd)))
25940 + {
25941 + ret = -EFAULT;
25942 + } else {
25943 + ret = ar6000_gpio_register_get(dev, gpio_register_cmd.gpioreg_id);
25944 + if (ret != A_OK) {
25945 + up(&ar->arSem);
25946 + return -EIO;
25947 + }
25948 +
25949 + /* Wait for Target to respond. */
25950 + wait_event_interruptible(arEvent, gpio_data_available);
25951 + if (signal_pending(current)) {
25952 + ret = -EINTR;
25953 + } else {
25954 + A_ASSERT(gpio_register_cmd.gpioreg_id == gpio_reg_results.gpioreg_id);
25955 + if (copy_to_user(userdata, &gpio_reg_results,
25956 + sizeof(gpio_reg_results)))
25957 + {
25958 + ret = -EFAULT;
25959 + }
25960 + }
25961 + }
25962 + up(&ar->arSem);
25963 + break;
25964 + }
25965 + case AR6000_XIOCTL_GPIO_INTR_ACK:
25966 + {
25967 + struct ar6000_gpio_intr_ack_cmd_s gpio_intr_ack_cmd;
25968 +
25969 + if (ar->arWmiReady == FALSE) {
25970 + return -EIO;
25971 + }
25972 + if (down_interruptible(&ar->arSem)) {
25973 + return -ERESTARTSYS;
25974 + }
25975 +
25976 + if (copy_from_user(&gpio_intr_ack_cmd, userdata,
25977 + sizeof(gpio_intr_ack_cmd)))
25978 + {
25979 + ret = -EFAULT;
25980 + } else {
25981 + ret = ar6000_gpio_intr_ack(dev, gpio_intr_ack_cmd.ack_mask);
25982 + if (ret != A_OK) {
25983 + ret = EIO;
25984 + }
25985 + }
25986 + up(&ar->arSem);
25987 + break;
25988 + }
25989 + case AR6000_XIOCTL_GPIO_INTR_WAIT:
25990 + {
25991 + /* Wait for Target to report an interrupt. */
25992 + dev_hold(dev);
25993 + rtnl_unlock();
25994 + wait_event_interruptible(arEvent, gpio_intr_available);
25995 + rtnl_lock();
25996 + __dev_put(dev);
25997 +
25998 + if (signal_pending(current)) {
25999 + ret = -EINTR;
26000 + } else {
26001 + if (copy_to_user(userdata, &gpio_intr_results,
26002 + sizeof(gpio_intr_results)))
26003 + {
26004 + ret = -EFAULT;
26005 + }
26006 + }
26007 + break;
26008 + }
26009 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
26010 +
26011 + case AR6000_XIOCTL_DBGLOG_CFG_MODULE:
26012 + {
26013 + struct ar6000_dbglog_module_config_s config;
26014 +
26015 + if (copy_from_user(&config, userdata, sizeof(config))) {
26016 + return -EFAULT;
26017 + }
26018 +
26019 + /* Send the challenge on the control channel */
26020 + if (wmi_config_debug_module_cmd(ar->arWmi, config.mmask,
26021 + config.tsr, config.rep,
26022 + config.size, config.valid) != A_OK)
26023 + {
26024 + return -EIO;
26025 + }
26026 + break;
26027 + }
26028 +
26029 + case AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS:
26030 + {
26031 + /* Send the challenge on the control channel */
26032 + if (ar6000_dbglog_get_debug_logs(ar) != A_OK)
26033 + {
26034 + return -EIO;
26035 + }
26036 + break;
26037 + }
26038 +
26039 + case AR6000_XIOCTL_SET_ADHOC_BSSID:
26040 + {
26041 + WMI_SET_ADHOC_BSSID_CMD adhocBssid;
26042 +
26043 + if (ar->arWmiReady == FALSE) {
26044 + ret = -EIO;
26045 + } else if (copy_from_user(&adhocBssid, userdata,
26046 + sizeof(adhocBssid)))
26047 + {
26048 + ret = -EFAULT;
26049 + } else if (A_MEMCMP(adhocBssid.bssid, bcast_mac,
26050 + AR6000_ETH_ADDR_LEN) == 0)
26051 + {
26052 + ret = -EFAULT;
26053 + } else {
26054 +
26055 + A_MEMCPY(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid));
26056 + }
26057 + break;
26058 + }
26059 +
26060 + case AR6000_XIOCTL_SET_OPT_MODE:
26061 + {
26062 + WMI_SET_OPT_MODE_CMD optModeCmd;
26063 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
26064 +
26065 + if (ar->arWmiReady == FALSE) {
26066 + ret = -EIO;
26067 + } else if (copy_from_user(&optModeCmd, userdata,
26068 + sizeof(optModeCmd)))
26069 + {
26070 + ret = -EFAULT;
26071 + } else if (ar->arConnected && optModeCmd.optMode == SPECIAL_ON) {
26072 + ret = -EFAULT;
26073 +
26074 + } else if (wmi_set_opt_mode_cmd(ar->arWmi, optModeCmd.optMode)
26075 + != A_OK)
26076 + {
26077 + ret = -EIO;
26078 + }
26079 + break;
26080 + }
26081 +
26082 + case AR6000_XIOCTL_OPT_SEND_FRAME:
26083 + {
26084 + WMI_OPT_TX_FRAME_CMD optTxFrmCmd;
26085 + A_UINT8 data[MAX_OPT_DATA_LEN];
26086 +
26087 + if (ar->arWmiReady == FALSE) {
26088 + ret = -EIO;
26089 + } else if (copy_from_user(&optTxFrmCmd, userdata,
26090 + sizeof(optTxFrmCmd)))
26091 + {
26092 + ret = -EFAULT;
26093 + } else if (copy_from_user(data,
26094 + userdata+sizeof(WMI_OPT_TX_FRAME_CMD)-1,
26095 + optTxFrmCmd.optIEDataLen))
26096 + {
26097 + ret = -EFAULT;
26098 + } else {
26099 + ret = wmi_opt_tx_frame_cmd(ar->arWmi,
26100 + optTxFrmCmd.frmType,
26101 + optTxFrmCmd.dstAddr,
26102 + optTxFrmCmd.bssid,
26103 + optTxFrmCmd.optIEDataLen,
26104 + data);
26105 + }
26106 +
26107 + break;
26108 + }
26109 + case AR6000_XIOCTL_WMI_SETRETRYLIMITS:
26110 + {
26111 + WMI_SET_RETRY_LIMITS_CMD setRetryParams;
26112 +
26113 + if (ar->arWmiReady == FALSE) {
26114 + ret = -EIO;
26115 + } else if (copy_from_user(&setRetryParams, userdata,
26116 + sizeof(setRetryParams)))
26117 + {
26118 + ret = -EFAULT;
26119 + } else {
26120 + if (wmi_set_retry_limits_cmd(ar->arWmi, setRetryParams.frameType,
26121 + setRetryParams.trafficClass,
26122 + setRetryParams.maxRetries,
26123 + setRetryParams.enableNotify) != A_OK)
26124 + {
26125 + ret = -EIO;
26126 + }
26127 + AR6000_SPIN_LOCK(&ar->arLock, 0);
26128 + ar->arMaxRetries = setRetryParams.maxRetries;
26129 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
26130 + }
26131 + break;
26132 + }
26133 +
26134 + case AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL:
26135 + {
26136 + WMI_BEACON_INT_CMD bIntvlCmd;
26137 +
26138 + if (ar->arWmiReady == FALSE) {
26139 + ret = -EIO;
26140 + } else if (copy_from_user(&bIntvlCmd, userdata,
26141 + sizeof(bIntvlCmd)))
26142 + {
26143 + ret = -EFAULT;
26144 + } else if (wmi_set_adhoc_bconIntvl_cmd(ar->arWmi, bIntvlCmd.beaconInterval)
26145 + != A_OK)
26146 + {
26147 + ret = -EIO;
26148 + }
26149 + break;
26150 + }
26151 + case IEEE80211_IOCTL_SETAUTHALG:
26152 + {
26153 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
26154 + struct ieee80211req_authalg req;
26155 +
26156 + if (ar->arWmiReady == FALSE) {
26157 + ret = -EIO;
26158 + } else if (copy_from_user(&req, userdata,
26159 + sizeof(struct ieee80211req_authalg)))
26160 + {
26161 + ret = -EFAULT;
26162 + } else if (req.auth_alg == AUTH_ALG_OPEN_SYSTEM) {
26163 + ar->arDot11AuthMode = OPEN_AUTH;
26164 + ar->arPairwiseCrypto = NONE_CRYPT;
26165 + ar->arGroupCrypto = NONE_CRYPT;
26166 + } else if (req.auth_alg == AUTH_ALG_LEAP) {
26167 + ar->arDot11AuthMode = LEAP_AUTH;
26168 + } else {
26169 + ret = -EIO;
26170 + }
26171 + break;
26172 + }
26173 +
26174 + case AR6000_XIOCTL_SET_VOICE_PKT_SIZE:
26175 + ret = ar6000_xioctl_set_voice_pkt_size(dev, userdata);
26176 + break;
26177 +
26178 + case AR6000_XIOCTL_SET_MAX_SP:
26179 + ret = ar6000_xioctl_set_max_sp_len(dev, userdata);
26180 + break;
26181 +
26182 + case AR6000_XIOCTL_WMI_GET_ROAM_TBL:
26183 + ret = ar6000_ioctl_get_roam_tbl(dev, rq);
26184 + break;
26185 + case AR6000_XIOCTL_WMI_SET_ROAM_CTRL:
26186 + ret = ar6000_ioctl_set_roam_ctrl(dev, userdata);
26187 + break;
26188 + case AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS:
26189 + ret = ar6000_ioctl_set_powersave_timers(dev, userdata);
26190 + break;
26191 + case AR6000_XIOCTRL_WMI_GET_POWER_MODE:
26192 + ret = ar6000_ioctl_get_power_mode(dev, rq);
26193 + break;
26194 + case AR6000_XIOCTRL_WMI_SET_WLAN_STATE:
26195 + get_user(ar->arWlanState, (unsigned int *)userdata);
26196 + if (ar->arWmiReady == FALSE) {
26197 + ret = -EIO;
26198 + break;
26199 + }
26200 +
26201 + if (ar->arWlanState == WLAN_ENABLED) {
26202 + /* Enable foreground scanning */
26203 + if (wmi_scanparams_cmd(ar->arWmi, scParams.fg_start_period,
26204 + scParams.fg_end_period,
26205 + scParams.bg_period,
26206 + scParams.minact_chdwell_time,
26207 + scParams.maxact_chdwell_time,
26208 + scParams.pas_chdwell_time,
26209 + scParams.shortScanRatio,
26210 + scParams.scanCtrlFlags,
26211 + scParams.max_dfsch_act_time) != A_OK)
26212 + {
26213 + ret = -EIO;
26214 + }
26215 + if (ar->arSsidLen) {
26216 + ar->arConnectPending = TRUE;
26217 + if (wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
26218 + ar->arDot11AuthMode, ar->arAuthMode,
26219 + ar->arPairwiseCrypto,
26220 + ar->arPairwiseCryptoLen,
26221 + ar->arGroupCrypto, ar->arGroupCryptoLen,
26222 + ar->arSsidLen, ar->arSsid,
26223 + ar->arReqBssid, ar->arChannelHint,
26224 + ar->arConnectCtrlFlags) != A_OK)
26225 + {
26226 + ret = -EIO;
26227 + ar->arConnectPending = FALSE;
26228 + }
26229 + }
26230 + } else {
26231 + /* Disconnect from the AP and disable foreground scanning */
26232 + AR6000_SPIN_LOCK(&ar->arLock, 0);
26233 + if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) {
26234 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
26235 + wmi_disconnect_cmd(ar->arWmi);
26236 + } else {
26237 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
26238 + }
26239 +
26240 + if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0xFF, 0) != A_OK)
26241 + {
26242 + ret = -EIO;
26243 + }
26244 + }
26245 + break;
26246 + case AR6000_XIOCTL_WMI_GET_ROAM_DATA:
26247 + ret = ar6000_ioctl_get_roam_data(dev, rq);
26248 + break;
26249 + case AR6000_XIOCTL_WMI_SET_BT_STATUS:
26250 + ret = ar6000_xioctl_set_bt_status_cmd(dev, userdata);
26251 + break;
26252 + case AR6000_XIOCTL_WMI_SET_BT_PARAMS:
26253 + ret = ar6000_xioctl_set_bt_params_cmd(dev, userdata);
26254 + break;
26255 + case AR6000_XIOCTL_WMI_STARTSCAN:
26256 + {
26257 + WMI_START_SCAN_CMD setStartScanCmd;
26258 +
26259 + if (ar->arWmiReady == FALSE) {
26260 + ret = -EIO;
26261 + } else if (copy_from_user(&setStartScanCmd, userdata,
26262 + sizeof(setStartScanCmd)))
26263 + {
26264 + ret = -EFAULT;
26265 + } else {
26266 + if (wmi_startscan_cmd(ar->arWmi, setStartScanCmd.scanType,
26267 + setStartScanCmd.forceFgScan,
26268 + setStartScanCmd.isLegacy,
26269 + setStartScanCmd.homeDwellTime,
26270 + setStartScanCmd.forceScanInterval) != A_OK)
26271 + {
26272 + ret = -EIO;
26273 + }
26274 + }
26275 + break;
26276 + }
26277 + case AR6000_XIOCTL_WMI_SETFIXRATES:
26278 + {
26279 + WMI_FIX_RATES_CMD setFixRatesCmd;
26280 + A_STATUS returnStatus;
26281 +
26282 + if (ar->arWmiReady == FALSE) {
26283 + ret = -EIO;
26284 + } else if (copy_from_user(&setFixRatesCmd, userdata,
26285 + sizeof(setFixRatesCmd)))
26286 + {
26287 + ret = -EFAULT;
26288 + } else {
26289 + returnStatus = wmi_set_fixrates_cmd(ar->arWmi, setFixRatesCmd.fixRateMask);
26290 + if (returnStatus == A_EINVAL)
26291 + {
26292 + ret = -EINVAL;
26293 + }
26294 + else if(returnStatus != A_OK) {
26295 + ret = -EIO;
26296 + }
26297 + }
26298 + break;
26299 + }
26300 +
26301 + case AR6000_XIOCTL_WMI_GETFIXRATES:
26302 + {
26303 + WMI_FIX_RATES_CMD getFixRatesCmd;
26304 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
26305 + int ret = 0;
26306 +
26307 + if (ar->arWmiReady == FALSE) {
26308 + return -EIO;
26309 + }
26310 +
26311 + if (down_interruptible(&ar->arSem)) {
26312 + return -ERESTARTSYS;
26313 + }
26314 + /* Used copy_from_user/copy_to_user to access user space data */
26315 + if (copy_from_user(&getFixRatesCmd, userdata, sizeof(getFixRatesCmd))) {
26316 + ret = -EFAULT;
26317 + } else {
26318 + ar->arRateMask = 0xFFFF;
26319 +
26320 + if (wmi_get_ratemask_cmd(ar->arWmi) != A_OK) {
26321 + up(&ar->arSem);
26322 + return -EIO;
26323 + }
26324 +
26325 + wait_event_interruptible_timeout(arEvent, ar->arRateMask != 0xFFFF, wmitimeout * HZ);
26326 +
26327 + if (signal_pending(current)) {
26328 + ret = -EINTR;
26329 + }
26330 +
26331 + if (!ret) {
26332 + getFixRatesCmd.fixRateMask = ar->arRateMask;
26333 + }
26334 +
26335 + if(copy_to_user(userdata, &getFixRatesCmd, sizeof(getFixRatesCmd))) {
26336 + ret = -EFAULT;
26337 + }
26338 +
26339 + up(&ar->arSem);
26340 + }
26341 + break;
26342 + }
26343 + case AR6000_XIOCTL_WMI_SET_AUTHMODE:
26344 + {
26345 + WMI_SET_AUTH_MODE_CMD setAuthMode;
26346 +
26347 + if (ar->arWmiReady == FALSE) {
26348 + ret = -EIO;
26349 + } else if (copy_from_user(&setAuthMode, userdata,
26350 + sizeof(setAuthMode)))
26351 + {
26352 + ret = -EFAULT;
26353 + } else {
26354 + if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != A_OK)
26355 + {
26356 + ret = -EIO;
26357 + }
26358 + }
26359 + break;
26360 + }
26361 + case AR6000_XIOCTL_WMI_SET_REASSOCMODE:
26362 + {
26363 + WMI_SET_REASSOC_MODE_CMD setReassocMode;
26364 +
26365 + if (ar->arWmiReady == FALSE) {
26366 + ret = -EIO;
26367 + } else if (copy_from_user(&setReassocMode, userdata,
26368 + sizeof(setReassocMode)))
26369 + {
26370 + ret = -EFAULT;
26371 + } else {
26372 + if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != A_OK)
26373 + {
26374 + ret = -EIO;
26375 + }
26376 + }
26377 + break;
26378 + }
26379 + case AR6000_XIOCTL_DIAG_READ:
26380 + {
26381 + A_UINT32 addr, data;
26382 + get_user(addr, (unsigned int *)userdata);
26383 + if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != A_OK) {
26384 + ret = -EIO;
26385 + }
26386 + put_user(data, (unsigned int *)userdata + 1);
26387 + break;
26388 + }
26389 + case AR6000_XIOCTL_DIAG_WRITE:
26390 + {
26391 + A_UINT32 addr, data;
26392 + get_user(addr, (unsigned int *)userdata);
26393 + get_user(data, (unsigned int *)userdata + 1);
26394 + if (ar6000_WriteRegDiag(ar->arHifDevice, &addr, &data) != A_OK) {
26395 + ret = -EIO;
26396 + }
26397 + break;
26398 + }
26399 + case AR6000_XIOCTL_WMI_SET_KEEPALIVE:
26400 + {
26401 + WMI_SET_KEEPALIVE_CMD setKeepAlive;
26402 + if (ar->arWmiReady == FALSE) {
26403 + return -EIO;
26404 + } else if (copy_from_user(&setKeepAlive, userdata,
26405 + sizeof(setKeepAlive))){
26406 + ret = -EFAULT;
26407 + } else {
26408 + if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != A_OK) {
26409 + ret = -EIO;
26410 + }
26411 + }
26412 + break;
26413 + }
26414 + case AR6000_XIOCTL_WMI_GET_KEEPALIVE:
26415 + {
26416 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
26417 + WMI_GET_KEEPALIVE_CMD getKeepAlive;
26418 + int ret = 0;
26419 + if (ar->arWmiReady == FALSE) {
26420 + return -EIO;
26421 + }
26422 + if (down_interruptible(&ar->arSem)) {
26423 + return -ERESTARTSYS;
26424 + }
26425 + if (copy_from_user(&getKeepAlive, userdata,sizeof(getKeepAlive))) {
26426 + ret = -EFAULT;
26427 + } else {
26428 + getKeepAlive.keepaliveInterval = wmi_get_keepalive_cmd(ar->arWmi);
26429 + ar->arKeepaliveConfigured = 0xFF;
26430 + if (wmi_get_keepalive_configured(ar->arWmi) != A_OK){
26431 + up(&ar->arSem);
26432 + return -EIO;
26433 + }
26434 + wait_event_interruptible_timeout(arEvent, ar->arKeepaliveConfigured != 0xFF, wmitimeout * HZ);
26435 + if (signal_pending(current)) {
26436 + ret = -EINTR;
26437 + }
26438 +
26439 + if (!ret) {
26440 + getKeepAlive.configured = ar->arKeepaliveConfigured;
26441 + }
26442 + if (copy_to_user(userdata, &getKeepAlive, sizeof(getKeepAlive))) {
26443 + ret = -EFAULT;
26444 + }
26445 + up(&ar->arSem);
26446 + }
26447 + break;
26448 + }
26449 + case AR6000_XIOCTL_WMI_SET_APPIE:
26450 + {
26451 + WMI_SET_APPIE_CMD appIEcmd;
26452 + A_UINT8 appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN];
26453 + A_UINT32 fType,ieLen;
26454 +
26455 + if (ar->arWmiReady == FALSE) {
26456 + return -EIO;
26457 + }
26458 + get_user(fType, (A_UINT32 *)userdata);
26459 + appIEcmd.mgmtFrmType = fType;
26460 + if (appIEcmd.mgmtFrmType >= IEEE80211_APPIE_NUM_OF_FRAME) {
26461 + ret = -EIO;
26462 + } else {
26463 + get_user(ieLen, (A_UINT32 *)(userdata + 4));
26464 + appIEcmd.ieLen = ieLen;
26465 + if (appIEcmd.ieLen > IEEE80211_APPIE_FRAME_MAX_LEN) {
26466 + ret = -EIO;
26467 + break;
26468 + }
26469 + if (copy_from_user(appIeInfo, userdata + 8, appIEcmd.ieLen)) {
26470 + ret = -EFAULT;
26471 + } else {
26472 + if (wmi_set_appie_cmd(ar->arWmi, appIEcmd.mgmtFrmType,
26473 + appIEcmd.ieLen, appIeInfo) != A_OK)
26474 + {
26475 + ret = -EIO;
26476 + }
26477 + }
26478 + }
26479 + break;
26480 + }
26481 + case AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER:
26482 + {
26483 + WMI_BSS_FILTER_CMD cmd;
26484 + A_UINT32 filterType;
26485 +
26486 + if (copy_from_user(&filterType, userdata, sizeof(A_UINT32)))
26487 + {
26488 + return -EFAULT;
26489 + }
26490 + if (filterType & (IEEE80211_FILTER_TYPE_BEACON |
26491 + IEEE80211_FILTER_TYPE_PROBE_RESP))
26492 + {
26493 + cmd.bssFilter = ALL_BSS_FILTER;
26494 + } else {
26495 + cmd.bssFilter = NONE_BSS_FILTER;
26496 + }
26497 + if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != A_OK) {
26498 + ret = -EIO;
26499 + }
26500 +
26501 + AR6000_SPIN_LOCK(&ar->arLock, 0);
26502 + ar->arMgmtFilter = filterType;
26503 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
26504 + break;
26505 + }
26506 + case AR6000_XIOCTL_WMI_SET_WSC_STATUS:
26507 + {
26508 + A_UINT32 wsc_status;
26509 +
26510 + if (copy_from_user(&wsc_status, userdata, sizeof(A_UINT32)))
26511 + {
26512 + return -EFAULT;
26513 + }
26514 + if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != A_OK) {
26515 + ret = -EIO;
26516 + }
26517 + break;
26518 + }
26519 + case AR6000_XIOCTL_BMI_ROMPATCH_INSTALL:
26520 + {
26521 + A_UINT32 ROM_addr;
26522 + A_UINT32 RAM_addr;
26523 + A_UINT32 nbytes;
26524 + A_UINT32 do_activate;
26525 + A_UINT32 rompatch_id;
26526 +
26527 + get_user(ROM_addr, (A_UINT32 *)userdata);
26528 + get_user(RAM_addr, (A_UINT32 *)userdata + 1);
26529 + get_user(nbytes, (A_UINT32 *)userdata + 2);
26530 + get_user(do_activate, (A_UINT32 *)userdata + 3);
26531 + AR_DEBUG_PRINTF("Install rompatch from ROM: 0x%x to RAM: 0x%x length: %d\n",
26532 + ROM_addr, RAM_addr, nbytes);
26533 + ret = BMIrompatchInstall(hifDevice, ROM_addr, RAM_addr,
26534 + nbytes, do_activate, &rompatch_id);
26535 + if (ret == A_OK) {
26536 + put_user(rompatch_id, (unsigned int *)rq->ifr_data); /* return value */
26537 + }
26538 + break;
26539 + }
26540 +
26541 + case AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL:
26542 + {
26543 + A_UINT32 rompatch_id;
26544 +
26545 + get_user(rompatch_id, (A_UINT32 *)userdata);
26546 + AR_DEBUG_PRINTF("UNinstall rompatch_id %d\n", rompatch_id);
26547 + ret = BMIrompatchUninstall(hifDevice, rompatch_id);
26548 + break;
26549 + }
26550 +
26551 + case AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE:
26552 + case AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE:
26553 + {
26554 + A_UINT32 rompatch_count;
26555 +
26556 + get_user(rompatch_count, (A_UINT32 *)userdata);
26557 + AR_DEBUG_PRINTF("Change rompatch activation count=%d\n", rompatch_count);
26558 + length = sizeof(A_UINT32) * rompatch_count;
26559 + if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
26560 + A_MEMZERO(buffer, length);
26561 + if (copy_from_user(buffer, &userdata[sizeof(rompatch_count)], length))
26562 + {
26563 + ret = -EFAULT;
26564 + } else {
26565 + if (cmd == AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) {
26566 + ret = BMIrompatchActivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
26567 + } else {
26568 + ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
26569 + }
26570 + }
26571 + A_FREE(buffer);
26572 + } else {
26573 + ret = -ENOMEM;
26574 + }
26575 +
26576 + break;
26577 + }
26578 +
26579 + case AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE:
26580 + {
26581 + WMI_SET_HOST_SLEEP_MODE_CMD setHostSleepMode;
26582 +
26583 + if (ar->arWmiReady == FALSE) {
26584 + ret = -EIO;
26585 + } else if (copy_from_user(&setHostSleepMode, userdata,
26586 + sizeof(setHostSleepMode)))
26587 + {
26588 + ret = -EFAULT;
26589 + } else {
26590 + if (wmi_set_host_sleep_mode_cmd(ar->arWmi,
26591 + &setHostSleepMode) != A_OK)
26592 + {
26593 + ret = -EIO;
26594 + }
26595 + }
26596 + break;
26597 + }
26598 + case AR6000_XIOCTL_WMI_SET_WOW_MODE:
26599 + {
26600 + WMI_SET_WOW_MODE_CMD setWowMode;
26601 +
26602 + if (ar->arWmiReady == FALSE) {
26603 + ret = -EIO;
26604 + } else if (copy_from_user(&setWowMode, userdata,
26605 + sizeof(setWowMode)))
26606 + {
26607 + ret = -EFAULT;
26608 + } else {
26609 + if (wmi_set_wow_mode_cmd(ar->arWmi,
26610 + &setWowMode) != A_OK)
26611 + {
26612 + ret = -EIO;
26613 + }
26614 + }
26615 + break;
26616 + }
26617 + case AR6000_XIOCTL_WMI_GET_WOW_LIST:
26618 + {
26619 + WMI_GET_WOW_LIST_CMD getWowList;
26620 +
26621 + if (ar->arWmiReady == FALSE) {
26622 + ret = -EIO;
26623 + } else if (copy_from_user(&getWowList, userdata,
26624 + sizeof(getWowList)))
26625 + {
26626 + ret = -EFAULT;
26627 + } else {
26628 + if (wmi_get_wow_list_cmd(ar->arWmi,
26629 + &getWowList) != A_OK)
26630 + {
26631 + ret = -EIO;
26632 + }
26633 + }
26634 + break;
26635 + }
26636 + case AR6000_XIOCTL_WMI_ADD_WOW_PATTERN:
26637 + {
26638 +#define WOW_PATTERN_SIZE 64
26639 +#define WOW_MASK_SIZE 64
26640 +
26641 + WMI_ADD_WOW_PATTERN_CMD cmd;
26642 + A_UINT8 mask_data[WOW_PATTERN_SIZE]={0};
26643 + A_UINT8 pattern_data[WOW_PATTERN_SIZE]={0};
26644 +
26645 + if (ar->arWmiReady == FALSE) {
26646 + ret = -EIO;
26647 + } else {
26648 +
26649 + if(copy_from_user(&cmd, userdata,
26650 + sizeof(WMI_ADD_WOW_PATTERN_CMD)))
26651 + return -EFAULT;
26652 + if (copy_from_user(pattern_data,
26653 + userdata + 3,
26654 + cmd.filter_size)){
26655 + ret = -EFAULT;
26656 + break;
26657 + }
26658 + if (copy_from_user(mask_data,
26659 + (userdata + 3 + cmd.filter_size),
26660 + cmd.filter_size)){
26661 + ret = -EFAULT;
26662 + break;
26663 + } else {
26664 + if (wmi_add_wow_pattern_cmd(ar->arWmi,
26665 + &cmd, pattern_data, mask_data, cmd.filter_size) != A_OK){
26666 + ret = -EIO;
26667 + }
26668 + }
26669 + }
26670 +#undef WOW_PATTERN_SIZE
26671 +#undef WOW_MASK_SIZE
26672 + break;
26673 + }
26674 + case AR6000_XIOCTL_WMI_DEL_WOW_PATTERN:
26675 + {
26676 + WMI_DEL_WOW_PATTERN_CMD delWowPattern;
26677 +
26678 + if (ar->arWmiReady == FALSE) {
26679 + ret = -EIO;
26680 + } else if (copy_from_user(&delWowPattern, userdata,
26681 + sizeof(delWowPattern)))
26682 + {
26683 + ret = -EFAULT;
26684 + } else {
26685 + if (wmi_del_wow_pattern_cmd(ar->arWmi,
26686 + &delWowPattern) != A_OK)
26687 + {
26688 + ret = -EIO;
26689 + }
26690 + }
26691 + break;
26692 + }
26693 + case AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE:
26694 + if (ar->arHtcTarget != NULL) {
26695 + HTCDumpCreditStates(ar->arHtcTarget);
26696 + }
26697 + break;
26698 + case AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE:
26699 + if (ar->arHtcTarget != NULL) {
26700 + struct ar6000_traffic_activity_change data;
26701 +
26702 + if (copy_from_user(&data, userdata, sizeof(data)))
26703 + {
26704 + return -EFAULT;
26705 + }
26706 + /* note, this is used for testing (mbox ping testing), indicate activity
26707 + * change using the stream ID as the traffic class */
26708 + ar6000_indicate_tx_activity(ar,
26709 + (A_UINT8)data.StreamID,
26710 + data.Active ? TRUE : FALSE);
26711 + }
26712 + break;
26713 + case AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS:
26714 + if (ar->arWmiReady == FALSE) {
26715 + ret = -EIO;
26716 + } else if (copy_from_user(&connectCtrlFlags, userdata,
26717 + sizeof(connectCtrlFlags)))
26718 + {
26719 + ret = -EFAULT;
26720 + } else {
26721 + ar->arConnectCtrlFlags = connectCtrlFlags;
26722 + }
26723 + break;
26724 + case AR6000_XIOCTL_WMI_SET_AKMP_PARAMS:
26725 + if (ar->arWmiReady == FALSE) {
26726 + ret = -EIO;
26727 + } else if (copy_from_user(&akmpParams, userdata,
26728 + sizeof(WMI_SET_AKMP_PARAMS_CMD)))
26729 + {
26730 + ret = -EFAULT;
26731 + } else {
26732 + if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != A_OK) {
26733 + ret = -EIO;
26734 + }
26735 + }
26736 + break;
26737 + case AR6000_XIOCTL_WMI_SET_PMKID_LIST:
26738 + if (ar->arWmiReady == FALSE) {
26739 + ret = -EIO;
26740 + } else {
26741 + if (copy_from_user(&pmkidInfo.numPMKID, userdata,
26742 + sizeof(pmkidInfo.numPMKID)))
26743 + {
26744 + ret = -EFAULT;
26745 + break;
26746 + }
26747 + if (copy_from_user(&pmkidInfo.pmkidList,
26748 + userdata + sizeof(pmkidInfo.numPMKID),
26749 + pmkidInfo.numPMKID * sizeof(WMI_PMKID)))
26750 + {
26751 + ret = -EFAULT;
26752 + break;
26753 + }
26754 + if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != A_OK) {
26755 + ret = -EIO;
26756 + }
26757 + }
26758 + break;
26759 + case AR6000_XIOCTL_WMI_GET_PMKID_LIST:
26760 + if (ar->arWmiReady == FALSE) {
26761 + ret = -EIO;
26762 + } else {
26763 + if (wmi_get_pmkid_list_cmd(ar->arWmi) != A_OK) {
26764 + ret = -EIO;
26765 + }
26766 + }
26767 + break;
26768 + default:
26769 + ret = -EOPNOTSUPP;
26770 + }
26771 + return ret;
26772 +}
26773 +
26774 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/netbuf.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/netbuf.c
26775 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/netbuf.c 1970-01-01 01:00:00.000000000 +0100
26776 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/netbuf.c 2009-05-10 22:27:59.000000000 +0200
26777 @@ -0,0 +1,225 @@
26778 +
26779 +/*
26780 + *
26781 + * Copyright (c) 2004-2007 Atheros Communications Inc.
26782 + * All rights reserved.
26783 + *
26784 + *
26785 + * This program is free software; you can redistribute it and/or modify
26786 + * it under the terms of the GNU General Public License version 2 as
26787 + * published by the Free Software Foundation;
26788 + *
26789 + * Software distributed under the License is distributed on an "AS
26790 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
26791 + * implied. See the License for the specific language governing
26792 + * rights and limitations under the License.
26793 + *
26794 + *
26795 + *
26796 + */
26797 +#include <linux/kernel.h>
26798 +#include <linux/skbuff.h>
26799 +#include <a_config.h>
26800 +#include "athdefs.h"
26801 +#include "a_types.h"
26802 +#include "a_osapi.h"
26803 +#include "htc_packet.h"
26804 +
26805 +#define AR6000_DATA_OFFSET 64
26806 +
26807 +void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt)
26808 +{
26809 + skb_queue_tail((struct sk_buff_head *) q, (struct sk_buff *) pkt);
26810 +}
26811 +
26812 +void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt)
26813 +{
26814 + skb_queue_head((struct sk_buff_head *) q, (struct sk_buff *) pkt);
26815 +}
26816 +
26817 +void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q)
26818 +{
26819 + return((void *) skb_dequeue((struct sk_buff_head *) q));
26820 +}
26821 +
26822 +int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q)
26823 +{
26824 + return(skb_queue_len((struct sk_buff_head *) q));
26825 +}
26826 +
26827 +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q)
26828 +{
26829 + return(skb_queue_empty((struct sk_buff_head *) q));
26830 +}
26831 +
26832 +void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q)
26833 +{
26834 + skb_queue_head_init((struct sk_buff_head *) q);
26835 +}
26836 +
26837 +void *
26838 +a_netbuf_alloc(int size)
26839 +{
26840 + struct sk_buff *skb;
26841 + skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(HTC_PACKET) + size);
26842 + skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(HTC_PACKET));
26843 + return ((void *)skb);
26844 +}
26845 +
26846 +/*
26847 + * Allocate an SKB w.o. any encapsulation requirement.
26848 + */
26849 +void *
26850 +a_netbuf_alloc_raw(int size)
26851 +{
26852 + struct sk_buff *skb;
26853 +
26854 + skb = dev_alloc_skb(size);
26855 +
26856 + return ((void *)skb);
26857 +}
26858 +
26859 +void
26860 +a_netbuf_free(void *bufPtr)
26861 +{
26862 + struct sk_buff *skb = (struct sk_buff *)bufPtr;
26863 +
26864 + dev_kfree_skb(skb);
26865 +}
26866 +
26867 +A_UINT32
26868 +a_netbuf_to_len(void *bufPtr)
26869 +{
26870 + return (((struct sk_buff *)bufPtr)->len);
26871 +}
26872 +
26873 +void *
26874 +a_netbuf_to_data(void *bufPtr)
26875 +{
26876 + return (((struct sk_buff *)bufPtr)->data);
26877 +}
26878 +
26879 +/*
26880 + * Add len # of bytes to the beginning of the network buffer
26881 + * pointed to by bufPtr
26882 + */
26883 +A_STATUS
26884 +a_netbuf_push(void *bufPtr, A_INT32 len)
26885 +{
26886 + skb_push((struct sk_buff *)bufPtr, len);
26887 +
26888 + return A_OK;
26889 +}
26890 +
26891 +/*
26892 + * Add len # of bytes to the beginning of the network buffer
26893 + * pointed to by bufPtr and also fill with data
26894 + */
26895 +A_STATUS
26896 +a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len)
26897 +{
26898 + skb_push((struct sk_buff *) bufPtr, len);
26899 + A_MEMCPY(((struct sk_buff *)bufPtr)->data, srcPtr, len);
26900 +
26901 + return A_OK;
26902 +}
26903 +
26904 +/*
26905 + * Add len # of bytes to the end of the network buffer
26906 + * pointed to by bufPtr
26907 + */
26908 +A_STATUS
26909 +a_netbuf_put(void *bufPtr, A_INT32 len)
26910 +{
26911 + skb_put((struct sk_buff *)bufPtr, len);
26912 +
26913 + return A_OK;
26914 +}
26915 +
26916 +/*
26917 + * Add len # of bytes to the end of the network buffer
26918 + * pointed to by bufPtr and also fill with data
26919 + */
26920 +A_STATUS
26921 +a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len)
26922 +{
26923 + char *start = ((struct sk_buff *)bufPtr)->data +
26924 + ((struct sk_buff *)bufPtr)->len;
26925 + skb_put((struct sk_buff *)bufPtr, len);
26926 + A_MEMCPY(start, srcPtr, len);
26927 +
26928 + return A_OK;
26929 +}
26930 +
26931 +
26932 +/*
26933 + * Trim the network buffer pointed to by bufPtr to len # of bytes
26934 + */
26935 +A_STATUS
26936 +a_netbuf_setlen(void *bufPtr, A_INT32 len)
26937 +{
26938 + skb_trim((struct sk_buff *)bufPtr, len);
26939 +
26940 + return A_OK;
26941 +}
26942 +
26943 +/*
26944 + * Chop of len # of bytes from the end of the buffer.
26945 + */
26946 +A_STATUS
26947 +a_netbuf_trim(void *bufPtr, A_INT32 len)
26948 +{
26949 + skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
26950 +
26951 + return A_OK;
26952 +}
26953 +
26954 +/*
26955 + * Chop of len # of bytes from the end of the buffer and return the data.
26956 + */
26957 +A_STATUS
26958 +a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len)
26959 +{
26960 + char *start = ((struct sk_buff *)bufPtr)->data +
26961 + (((struct sk_buff *)bufPtr)->len - len);
26962 +
26963 + A_MEMCPY(dstPtr, start, len);
26964 + skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
26965 +
26966 + return A_OK;
26967 +}
26968 +
26969 +
26970 +/*
26971 + * Returns the number of bytes available to a a_netbuf_push()
26972 + */
26973 +A_INT32
26974 +a_netbuf_headroom(void *bufPtr)
26975 +{
26976 + return (skb_headroom((struct sk_buff *)bufPtr));
26977 +}
26978 +
26979 +/*
26980 + * Removes specified number of bytes from the beginning of the buffer
26981 + */
26982 +A_STATUS
26983 +a_netbuf_pull(void *bufPtr, A_INT32 len)
26984 +{
26985 + skb_pull((struct sk_buff *)bufPtr, len);
26986 +
26987 + return A_OK;
26988 +}
26989 +
26990 +/*
26991 + * Removes specified number of bytes from the beginning of the buffer
26992 + * and return the data
26993 + */
26994 +A_STATUS
26995 +a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len)
26996 +{
26997 + A_MEMCPY(dstPtr, ((struct sk_buff *)bufPtr)->data, len);
26998 + skb_pull((struct sk_buff *)bufPtr, len);
26999 +
27000 + return A_OK;
27001 +}
27002 +
27003 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/osapi_linux.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/osapi_linux.h
27004 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/osapi_linux.h 1970-01-01 01:00:00.000000000 +0100
27005 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/osapi_linux.h 2009-05-10 22:27:59.000000000 +0200
27006 @@ -0,0 +1,319 @@
27007 +/*
27008 + * $Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/include/osapi_linux.h#1 $
27009 + *
27010 + * This file contains the definitions of the basic atheros data types.
27011 + * It is used to map the data types in atheros files to a platform specific
27012 + * type.
27013 + *
27014 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
27015 + *
27016 + *
27017 + * This program is free software; you can redistribute it and/or modify
27018 + * it under the terms of the GNU General Public License version 2 as
27019 + * published by the Free Software Foundation;
27020 + *
27021 + * Software distributed under the License is distributed on an "AS
27022 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
27023 + * implied. See the License for the specific language governing
27024 + * rights and limitations under the License.
27025 + *
27026 + *
27027 + *
27028 + */
27029 +
27030 +#ifndef _OSAPI_LINUX_H_
27031 +#define _OSAPI_LINUX_H_
27032 +
27033 +#ifdef __KERNEL__
27034 +
27035 +#include <linux/version.h>
27036 +#include <linux/types.h>
27037 +#include <linux/kernel.h>
27038 +#include <linux/string.h>
27039 +#include <linux/skbuff.h>
27040 +#include <linux/netdevice.h>
27041 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
27042 +#include <linux/jiffies.h>
27043 +#endif
27044 +#include <linux/timer.h>
27045 +#include <linux/delay.h>
27046 +#include <linux/wait.h>
27047 +#ifdef KERNEL_2_4
27048 +#include <asm/arch/irq.h>
27049 +#include <asm/irq.h>
27050 +#endif
27051 +
27052 +#ifdef __GNUC__
27053 +#define __ATTRIB_PACK __attribute__ ((packed))
27054 +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2)))
27055 +#define __ATTRIB_NORETURN __attribute__ ((noreturn))
27056 +#ifndef INLINE
27057 +#define INLINE __inline__
27058 +#endif
27059 +#else /* Not GCC */
27060 +#define __ATTRIB_PACK
27061 +#define __ATTRIB_PRINTF
27062 +#define __ATTRIB_NORETURN
27063 +#ifndef INLINE
27064 +#define INLINE __inline
27065 +#endif
27066 +#endif /* End __GNUC__ */
27067 +
27068 +#define PREPACK
27069 +#define POSTPACK __ATTRIB_PACK
27070 +
27071 +/*
27072 + * Endianes macros
27073 + */
27074 +#define A_BE2CPU8(x) ntohb(x)
27075 +#define A_BE2CPU16(x) ntohs(x)
27076 +#define A_BE2CPU32(x) ntohl(x)
27077 +
27078 +#define A_LE2CPU8(x) (x)
27079 +#define A_LE2CPU16(x) (x)
27080 +#define A_LE2CPU32(x) (x)
27081 +
27082 +#define A_CPU2BE8(x) htonb(x)
27083 +#define A_CPU2BE16(x) htons(x)
27084 +#define A_CPU2BE32(x) htonl(x)
27085 +
27086 +#define A_MEMCPY(dst, src, len) memcpy((A_UINT8 *)(dst), (src), (len))
27087 +#define A_MEMZERO(addr, len) memset(addr, 0, len)
27088 +#define A_MEMCMP(addr1, addr2, len) memcmp((addr1), (addr2), (len))
27089 +#define A_MALLOC(size) kmalloc((size), GFP_KERNEL)
27090 +#define A_MALLOC_NOWAIT(size) kmalloc((size), GFP_ATOMIC)
27091 +#define A_FREE(addr) kfree(addr)
27092 +#define A_PRINTF(args...) printk(args)
27093 +
27094 +/* Mutual Exclusion */
27095 +typedef spinlock_t A_MUTEX_T;
27096 +#define A_MUTEX_INIT(mutex) spin_lock_init(mutex)
27097 +#define A_MUTEX_LOCK(mutex) spin_lock_bh(mutex)
27098 +#define A_MUTEX_UNLOCK(mutex) spin_unlock_bh(mutex)
27099 +#define A_IS_MUTEX_VALID(mutex) TRUE /* okay to return true, since A_MUTEX_DELETE does nothing */
27100 +#define A_MUTEX_DELETE(mutex) /* spin locks are not kernel resources so nothing to free.. */
27101 +
27102 +/* Get current time in ms adding a constant offset (in ms) */
27103 +#define A_GET_MS(offset) \
27104 + (jiffies + ((offset) / 1000) * HZ)
27105 +
27106 +/*
27107 + * Timer Functions
27108 + */
27109 +#define A_MDELAY(msecs) mdelay(msecs)
27110 +typedef struct timer_list A_TIMER;
27111 +
27112 +#define A_INIT_TIMER(pTimer, pFunction, pArg) do { \
27113 + init_timer(pTimer); \
27114 + (pTimer)->function = (pFunction); \
27115 + (pTimer)->data = (unsigned long)(pArg); \
27116 +} while (0)
27117 +
27118 +/*
27119 + * Start a Timer that elapses after 'periodMSec' milli-seconds
27120 + * Support is provided for a one-shot timer. The 'repeatFlag' is
27121 + * ignored.
27122 + */
27123 +#define A_TIMEOUT_MS(pTimer, periodMSec, repeatFlag) do { \
27124 + if (repeatFlag) { \
27125 + printk("\n" __FILE__ ":%d: Timer Repeat requested\n",__LINE__); \
27126 + panic("Timer Repeat"); \
27127 + } \
27128 + mod_timer((pTimer), jiffies + HZ * (periodMSec) / 1000); \
27129 +} while (0)
27130 +
27131 +/*
27132 + * Cancel the Timer.
27133 + */
27134 +#define A_UNTIMEOUT(pTimer) do { \
27135 + del_timer((pTimer)); \
27136 +} while (0)
27137 +
27138 +#define A_DELETE_TIMER(pTimer) do { \
27139 +} while (0)
27140 +
27141 +/*
27142 + * Wait Queue related functions
27143 + */
27144 +typedef wait_queue_head_t A_WAITQUEUE_HEAD;
27145 +#define A_INIT_WAITQUEUE_HEAD(head) init_waitqueue_head(head)
27146 +#ifndef wait_event_interruptible_timeout
27147 +#define __wait_event_interruptible_timeout(wq, condition, ret) \
27148 +do { \
27149 + wait_queue_t __wait; \
27150 + init_waitqueue_entry(&__wait, current); \
27151 + \
27152 + add_wait_queue(&wq, &__wait); \
27153 + for (;;) { \
27154 + set_current_state(TASK_INTERRUPTIBLE); \
27155 + if (condition) \
27156 + break; \
27157 + if (!signal_pending(current)) { \
27158 + ret = schedule_timeout(ret); \
27159 + if (!ret) \
27160 + break; \
27161 + continue; \
27162 + } \
27163 + ret = -ERESTARTSYS; \
27164 + break; \
27165 + } \
27166 + current->state = TASK_RUNNING; \
27167 + remove_wait_queue(&wq, &__wait); \
27168 +} while (0)
27169 +
27170 +#define wait_event_interruptible_timeout(wq, condition, timeout) \
27171 +({ \
27172 + long __ret = timeout; \
27173 + if (!(condition)) \
27174 + __wait_event_interruptible_timeout(wq, condition, __ret); \
27175 + __ret; \
27176 +})
27177 +#endif /* wait_event_interruptible_timeout */
27178 +
27179 +#define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \
27180 + wait_event_interruptible_timeout(head, condition, timeout); \
27181 +} while (0)
27182 +
27183 +#define A_WAKE_UP(head) wake_up(head)
27184 +
27185 +#ifdef DEBUG
27186 +#define A_ASSERT(expr) \
27187 + if (!(expr)) { \
27188 + printk(KERN_ALERT "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \
27189 + panic(#expr); \
27190 + }
27191 +
27192 +#else
27193 +#define A_ASSERT(expr)
27194 +#endif /* DEBUG */
27195 +
27196 +/*
27197 + * Initialization of the network buffer subsystem
27198 + */
27199 +#define A_NETBUF_INIT()
27200 +
27201 +/*
27202 + * Network buffer queue support
27203 + */
27204 +typedef struct sk_buff_head A_NETBUF_QUEUE_T;
27205 +
27206 +#define A_NETBUF_QUEUE_INIT(q) \
27207 + a_netbuf_queue_init(q)
27208 +
27209 +#define A_NETBUF_ENQUEUE(q, pkt) \
27210 + a_netbuf_enqueue((q), (pkt))
27211 +#define A_NETBUF_PREQUEUE(q, pkt) \
27212 + a_netbuf_prequeue((q), (pkt))
27213 +#define A_NETBUF_DEQUEUE(q) \
27214 + (a_netbuf_dequeue(q))
27215 +#define A_NETBUF_QUEUE_SIZE(q) \
27216 + a_netbuf_queue_size(q)
27217 +#define A_NETBUF_QUEUE_EMPTY(q) \
27218 + a_netbuf_queue_empty(q)
27219 +
27220 +/*
27221 + * Network buffer support
27222 + */
27223 +#define A_NETBUF_ALLOC(size) \
27224 + a_netbuf_alloc(size)
27225 +#define A_NETBUF_ALLOC_RAW(size) \
27226 + a_netbuf_alloc_raw(size)
27227 +#define A_NETBUF_FREE(bufPtr) \
27228 + a_netbuf_free(bufPtr)
27229 +#define A_NETBUF_DATA(bufPtr) \
27230 + a_netbuf_to_data(bufPtr)
27231 +#define A_NETBUF_LEN(bufPtr) \
27232 + a_netbuf_to_len(bufPtr)
27233 +#define A_NETBUF_PUSH(bufPtr, len) \
27234 + a_netbuf_push(bufPtr, len)
27235 +#define A_NETBUF_PUT(bufPtr, len) \
27236 + a_netbuf_put(bufPtr, len)
27237 +#define A_NETBUF_TRIM(bufPtr,len) \
27238 + a_netbuf_trim(bufPtr, len)
27239 +#define A_NETBUF_PULL(bufPtr, len) \
27240 + a_netbuf_pull(bufPtr, len)
27241 +#define A_NETBUF_HEADROOM(bufPtr)\
27242 + a_netbuf_headroom(bufPtr)
27243 +#define A_NETBUF_SETLEN(bufPtr,len) \
27244 + a_netbuf_setlen(bufPtr, len)
27245 +
27246 +/* Add data to end of a buffer */
27247 +#define A_NETBUF_PUT_DATA(bufPtr, srcPtr, len) \
27248 + a_netbuf_put_data(bufPtr, srcPtr, len)
27249 +
27250 +/* Add data to start of the buffer */
27251 +#define A_NETBUF_PUSH_DATA(bufPtr, srcPtr, len) \
27252 + a_netbuf_push_data(bufPtr, srcPtr, len)
27253 +
27254 +/* Remove data at start of the buffer */
27255 +#define A_NETBUF_PULL_DATA(bufPtr, dstPtr, len) \
27256 + a_netbuf_pull_data(bufPtr, dstPtr, len)
27257 +
27258 +/* Remove data from the end of the buffer */
27259 +#define A_NETBUF_TRIM_DATA(bufPtr, dstPtr, len) \
27260 + a_netbuf_trim_data(bufPtr, dstPtr, len)
27261 +
27262 +/* View data as "size" contiguous bytes of type "t" */
27263 +#define A_NETBUF_VIEW_DATA(bufPtr, t, size) \
27264 + (t )( ((struct skbuf *)(bufPtr))->data)
27265 +
27266 +/* return the beginning of the headroom for the buffer */
27267 +#define A_NETBUF_HEAD(bufPtr) \
27268 + ((((struct sk_buff *)(bufPtr))->head))
27269 +
27270 +/*
27271 + * OS specific network buffer access routines
27272 + */
27273 +void *a_netbuf_alloc(int size);
27274 +void *a_netbuf_alloc_raw(int size);
27275 +void a_netbuf_free(void *bufPtr);
27276 +void *a_netbuf_to_data(void *bufPtr);
27277 +A_UINT32 a_netbuf_to_len(void *bufPtr);
27278 +A_STATUS a_netbuf_push(void *bufPtr, A_INT32 len);
27279 +A_STATUS a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len);
27280 +A_STATUS a_netbuf_put(void *bufPtr, A_INT32 len);
27281 +A_STATUS a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len);
27282 +A_STATUS a_netbuf_pull(void *bufPtr, A_INT32 len);
27283 +A_STATUS a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len);
27284 +A_STATUS a_netbuf_trim(void *bufPtr, A_INT32 len);
27285 +A_STATUS a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len);
27286 +A_STATUS a_netbuf_setlen(void *bufPtr, A_INT32 len);
27287 +A_INT32 a_netbuf_headroom(void *bufPtr);
27288 +void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt);
27289 +void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt);
27290 +void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q);
27291 +int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q);
27292 +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q);
27293 +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q);
27294 +void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q);
27295 +
27296 +/*
27297 + * Kernel v.s User space functions
27298 + */
27299 +A_UINT32 a_copy_to_user(void *to, const void *from, A_UINT32 n);
27300 +A_UINT32 a_copy_from_user(void *to, const void *from, A_UINT32 n);
27301 +
27302 +#else /* __KERNEL__ */
27303 +
27304 +#ifdef __GNUC__
27305 +#define __ATTRIB_PACK __attribute__ ((packed))
27306 +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2)))
27307 +#define __ATTRIB_NORETURN __attribute__ ((noreturn))
27308 +#ifndef INLINE
27309 +#define INLINE __inline__
27310 +#endif
27311 +#else /* Not GCC */
27312 +#define __ATTRIB_PACK
27313 +#define __ATTRIB_PRINTF
27314 +#define __ATTRIB_NORETURN
27315 +#ifndef INLINE
27316 +#define INLINE __inline
27317 +#endif
27318 +#endif /* End __GNUC__ */
27319 +
27320 +#define PREPACK
27321 +#define POSTPACK __ATTRIB_PACK
27322 +
27323 +#endif /* __KERNEL__ */
27324 +
27325 +#endif /* _OSAPI_LINUX_H_ */
27326 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/wireless_ext.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/wireless_ext.c
27327 --- linux-2.6.29-rc3.owrt/drivers/ar6000/ar6000/wireless_ext.c 1970-01-01 01:00:00.000000000 +0100
27328 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/ar6000/wireless_ext.c 2009-05-10 22:27:59.000000000 +0200
27329 @@ -0,0 +1,1979 @@
27330 +/*
27331 + *
27332 + * Copyright (c) 2004-2007 Atheros Communications Inc.
27333 + * All rights reserved.
27334 + *
27335 + *
27336 + * This program is free software; you can redistribute it and/or modify
27337 + * it under the terms of the GNU General Public License version 2 as
27338 + * published by the Free Software Foundation;
27339 + *
27340 + * Software distributed under the License is distributed on an "AS
27341 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
27342 + * implied. See the License for the specific language governing
27343 + * rights and limitations under the License.
27344 + *
27345 + *
27346 + *
27347 + */
27348 +
27349 +#include "ar6000_drv.h"
27350 +
27351 +static A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
27352 +static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi);
27353 +extern unsigned int wmitimeout;
27354 +extern A_WAITQUEUE_HEAD arEvent;
27355 +extern wait_queue_head_t ar6000_scan_queue;
27356 +
27357 +/*
27358 + * Encode a WPA or RSN information element as a custom
27359 + * element using the hostap format.
27360 + */
27361 +static u_int
27362 +encode_ie(void *buf, size_t bufsize,
27363 + const u_int8_t *ie, size_t ielen,
27364 + const char *leader, size_t leader_len)
27365 +{
27366 + u_int8_t *p;
27367 + int i;
27368 +
27369 + if (bufsize < leader_len)
27370 + return 0;
27371 + p = buf;
27372 + memcpy(p, leader, leader_len);
27373 + bufsize -= leader_len;
27374 + p += leader_len;
27375 + for (i = 0; i < ielen && bufsize > 2; i++)
27376 + p += sprintf(p, "%02x", ie[i]);
27377 + return (i == ielen ? p - (u_int8_t *)buf : 0);
27378 +}
27379 +
27380 +void
27381 +ar6000_scan_node(void *arg, bss_t *ni)
27382 +{
27383 + struct iw_event iwe;
27384 +#if WIRELESS_EXT > 14
27385 + char buf[64*2 + 30];
27386 +#endif
27387 + struct ar_giwscan_param *param;
27388 + A_CHAR *current_ev;
27389 + A_CHAR *end_buf;
27390 + struct ieee80211_common_ie *cie;
27391 + struct iw_request_info info;
27392 +
27393 + info.cmd = 0;
27394 + info.flags = 0;
27395 +
27396 + param = (struct ar_giwscan_param *)arg;
27397 +
27398 + if (param->current_ev >= param->end_buf) {
27399 + return;
27400 + }
27401 + if ((param->firstPass == TRUE) &&
27402 + ((ni->ni_cie.ie_wpa == NULL) && (ni->ni_cie.ie_rsn == NULL))) {
27403 + /*
27404 + * Only forward wpa bss's in first pass
27405 + */
27406 + return;
27407 + }
27408 +
27409 + if ((param->firstPass == FALSE) &&
27410 + ((ni->ni_cie.ie_wpa != NULL) || (ni->ni_cie.ie_rsn != NULL))) {
27411 + /*
27412 + * Only forward non-wpa bss's in 2nd pass
27413 + */
27414 + return;
27415 + }
27416 +
27417 + current_ev = param->current_ev;
27418 + end_buf = param->end_buf;
27419 +
27420 + cie = &ni->ni_cie;
27421 +
27422 + A_MEMZERO(&iwe, sizeof(iwe));
27423 + iwe.cmd = SIOCGIWAP;
27424 + iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
27425 + A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
27426 + current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
27427 + IW_EV_ADDR_LEN);
27428 +
27429 + A_MEMZERO(&iwe, sizeof(iwe));
27430 + iwe.cmd = SIOCGIWESSID;
27431 + iwe.u.data.flags = 1;
27432 + iwe.u.data.length = cie->ie_ssid[1];
27433 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
27434 + &cie->ie_ssid[2]);
27435 +
27436 + if (cie->ie_capInfo & (IEEE80211_CAPINFO_ESS|IEEE80211_CAPINFO_IBSS)) {
27437 + A_MEMZERO(&iwe, sizeof(iwe));
27438 + iwe.cmd = SIOCGIWMODE;
27439 + iwe.u.mode = cie->ie_capInfo & IEEE80211_CAPINFO_ESS ?
27440 + IW_MODE_MASTER : IW_MODE_ADHOC;
27441 + current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
27442 + IW_EV_UINT_LEN);
27443 + }
27444 +
27445 + A_MEMZERO(&iwe, sizeof(iwe));
27446 + iwe.cmd = SIOCGIWFREQ;
27447 + iwe.u.freq.m = cie->ie_chan * 100000;
27448 + iwe.u.freq.e = 1;
27449 + current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
27450 + IW_EV_FREQ_LEN);
27451 +
27452 + A_MEMZERO(&iwe, sizeof(iwe));
27453 + iwe.cmd = IWEVQUAL;
27454 + ar6000_set_quality(&iwe.u.qual, ni->ni_snr);
27455 + current_ev = iwe_stream_add_event(&info, current_ev, end_buf, &iwe,
27456 + IW_EV_QUAL_LEN);
27457 +
27458 + A_MEMZERO(&iwe, sizeof(iwe));
27459 + iwe.cmd = SIOCGIWENCODE;
27460 + if (cie->ie_capInfo & IEEE80211_CAPINFO_PRIVACY) {
27461 + iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
27462 + } else {
27463 + iwe.u.data.flags = IW_ENCODE_DISABLED;
27464 + }
27465 + iwe.u.data.length = 0;
27466 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, "");
27467 +
27468 + A_MEMZERO(&iwe, sizeof(iwe));
27469 + iwe.cmd = IWEVCUSTOM;
27470 + snprintf(buf, sizeof(buf), "bcn_int=%d", cie->ie_beaconInt);
27471 + iwe.u.data.length = strlen(buf);
27472 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, buf);
27473 +
27474 + if (cie->ie_wpa != NULL) {
27475 + static const char wpa_leader[] = "wpa_ie=";
27476 +
27477 + A_MEMZERO(&iwe, sizeof(iwe));
27478 + iwe.cmd = IWEVCUSTOM;
27479 + iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wpa,
27480 + cie->ie_wpa[1]+2,
27481 + wpa_leader, sizeof(wpa_leader)-1);
27482 +
27483 + if (iwe.u.data.length != 0) {
27484 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
27485 + buf);
27486 + }
27487 + }
27488 +
27489 + if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
27490 + static const char rsn_leader[] = "rsn_ie=";
27491 +
27492 + A_MEMZERO(&iwe, sizeof(iwe));
27493 + iwe.cmd = IWEVCUSTOM;
27494 + iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_rsn,
27495 + cie->ie_rsn[1]+2,
27496 + rsn_leader, sizeof(rsn_leader)-1);
27497 +
27498 + if (iwe.u.data.length != 0) {
27499 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
27500 + buf);
27501 + }
27502 + }
27503 +
27504 + if (cie->ie_wmm != NULL) {
27505 + static const char wmm_leader[] = "wmm_ie=";
27506 +
27507 + A_MEMZERO(&iwe, sizeof(iwe));
27508 + iwe.cmd = IWEVCUSTOM;
27509 + iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_wmm,
27510 + cie->ie_wmm[1]+2,
27511 + wmm_leader, sizeof(wmm_leader)-1);
27512 + if (iwe.u.data.length != 0) {
27513 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
27514 + buf);
27515 + }
27516 + }
27517 +
27518 + if (cie->ie_ath != NULL) {
27519 + static const char ath_leader[] = "ath_ie=";
27520 +
27521 + A_MEMZERO(&iwe, sizeof(iwe));
27522 + iwe.cmd = IWEVCUSTOM;
27523 + iwe.u.data.length = encode_ie(buf, sizeof(buf), cie->ie_ath,
27524 + cie->ie_ath[1]+2,
27525 + ath_leader, sizeof(ath_leader)-1);
27526 + if (iwe.u.data.length != 0) {
27527 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
27528 + buf);
27529 + }
27530 + }
27531 +
27532 + param->current_ev = current_ev;
27533 +}
27534 +
27535 +int
27536 +ar6000_ioctl_giwscan(struct net_device *dev,
27537 + struct iw_request_info *info,
27538 + struct iw_point *data, char *extra)
27539 +{
27540 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27541 + struct ar_giwscan_param param;
27542 + int i;
27543 +
27544 + if (ar->arWlanState == WLAN_DISABLED) {
27545 + return -EIO;
27546 + }
27547 +
27548 + if (ar->arWmiReady == FALSE) {
27549 + return -EIO;
27550 + }
27551 +
27552 + param.current_ev = extra;
27553 + param.end_buf = extra + IW_SCAN_MAX_DATA;
27554 + param.firstPass = TRUE;
27555 +
27556 + /*
27557 + * Do two passes to insure WPA scan candidates
27558 + * are sorted to the front. This is a hack to deal with
27559 + * the wireless extensions capping scan results at
27560 + * IW_SCAN_MAX_DATA bytes. In densely populated environments
27561 + * it's easy to overflow this buffer (especially with WPA/RSN
27562 + * information elements). Note this sorting hack does not
27563 + * guarantee we won't overflow anyway.
27564 + */
27565 + for (i = 0; i < 2; i++) {
27566 + /*
27567 + * Translate data to WE format.
27568 + */
27569 + wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, &param);
27570 + param.firstPass = FALSE;
27571 + if (param.current_ev >= param.end_buf) {
27572 + data->length = param.current_ev - extra;
27573 + return -E2BIG;
27574 + }
27575 + }
27576 +
27577 + data->length = param.current_ev - extra;
27578 + return 0;
27579 +}
27580 +
27581 +extern int reconnect_flag;
27582 +/* SIOCSIWESSID */
27583 +static int
27584 +ar6000_ioctl_siwessid(struct net_device *dev,
27585 + struct iw_request_info *info,
27586 + struct iw_point *data, char *ssid)
27587 +{
27588 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27589 + A_STATUS status;
27590 + A_UINT8 arNetworkType;
27591 +
27592 + if (ar->arWlanState == WLAN_DISABLED) {
27593 + return -EIO;
27594 + }
27595 +
27596 + if (ar->arWmiReady == FALSE) {
27597 + return -EIO;
27598 + }
27599 +
27600 + /*
27601 + * iwconfig passes a string with length excluding any trailing NUL.
27602 + * FIXME: we should be able to set an ESSID of 32 bytes, yet things fall
27603 + * over badly if we do. So we limit the ESSID to 31 bytes.
27604 + */
27605 + if (data->flags && (!data->length || data->length >= sizeof(ar->arSsid))) {
27606 + /*
27607 + * ssid is invalid
27608 + */
27609 + return -EINVAL;
27610 + }
27611 + /* Added for bug 25178, return an IOCTL error instead of target returning
27612 + Illegal parameter error when either the BSSID or channel is missing
27613 + and we cannot scan during connect.
27614 + */
27615 + if (data->flags) {
27616 + if (ar->arSkipScan == TRUE &&
27617 + (ar->arChannelHint == 0 ||
27618 + (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
27619 + !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
27620 + {
27621 + return -EINVAL;
27622 + }
27623 + }
27624 +
27625 + if (down_interruptible(&ar->arSem)) {
27626 + return -ERESTARTSYS;
27627 + }
27628 +
27629 + if (ar->arTxPending[WMI_CONTROL_PRI]) {
27630 + /*
27631 + * sleep until the command queue drains
27632 + */
27633 + wait_event_interruptible_timeout(arEvent,
27634 + ar->arTxPending[WMI_CONTROL_PRI] == 0, wmitimeout * HZ);
27635 + if (signal_pending(current)) {
27636 + return -EINTR;
27637 + }
27638 + }
27639 +
27640 + if (!data->flags) {
27641 + arNetworkType = ar->arNetworkType;
27642 + ar6000_init_profile_info(ar);
27643 + ar->arNetworkType = arNetworkType;
27644 + }
27645 +
27646 + /*
27647 + * The original logic here prevented a disconnect if issuing an "essid off"
27648 + * if no ESSID was set, presumably to prevent sending multiple disconnects
27649 + * to the WMI.
27650 + *
27651 + * Unfortunately, this also meant that no disconnect was sent when we were
27652 + * already connected, but the profile has been changed since (which also
27653 + * clears the ESSID as a reminder that the WMI needs updating.)
27654 + *
27655 + * The "1 ||" makes sure we always disconnect or reconnect. The WMI doesn't
27656 + * seem to mind being sent multiple disconnects.
27657 + */
27658 + if (1 || (ar->arSsidLen) || (!data->flags))
27659 + {
27660 + if ((!data->flags) ||
27661 + (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
27662 + (ar->arSsidLen != (data->length)))
27663 + {
27664 + /*
27665 + * SSID set previously or essid off has been issued.
27666 + *
27667 + * Disconnect Command is issued in two cases after wmi is ready
27668 + * (1) ssid is different from the previous setting
27669 + * (2) essid off has been issued
27670 + *
27671 + */
27672 + if (ar->arWmiReady == TRUE) {
27673 + reconnect_flag = 0;
27674 + status = wmi_disconnect_cmd(ar->arWmi);
27675 + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
27676 + ar->arSsidLen = 0;
27677 + if (ar->arSkipScan == FALSE) {
27678 + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
27679 + }
27680 + if (!data->flags) {
27681 + up(&ar->arSem);
27682 + return 0;
27683 + }
27684 + } else {
27685 + up(&ar->arSem);
27686 + }
27687 + }
27688 + else
27689 + {
27690 + /*
27691 + * SSID is same, so we assume profile hasn't changed.
27692 + * If the interface is up and wmi is ready, we issue
27693 + * a reconnect cmd. Issue a reconnect only we are already
27694 + * connected.
27695 + */
27696 + if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE))
27697 + {
27698 + reconnect_flag = TRUE;
27699 + status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
27700 + ar->arChannelHint);
27701 + up(&ar->arSem);
27702 + if (status != A_OK) {
27703 + return -EIO;
27704 + }
27705 + return 0;
27706 + }
27707 + else{
27708 + /*
27709 + * Dont return if connect is pending.
27710 + */
27711 + if(!(ar->arConnectPending)) {
27712 + up(&ar->arSem);
27713 + return 0;
27714 + }
27715 + }
27716 + }
27717 + }
27718 +
27719 + ar->arSsidLen = data->length;
27720 + A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
27721 +
27722 + /* The ssid length check prevents second "essid off" from the user,
27723 + to be treated as a connect cmd. The second "essid off" is ignored.
27724 + */
27725 + if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) )
27726 + {
27727 + AR6000_SPIN_LOCK(&ar->arLock, 0);
27728 + if (SHARED_AUTH == ar->arDot11AuthMode) {
27729 + ar6000_install_static_wep_keys(ar);
27730 + }
27731 + AR_DEBUG_PRINTF("Connect called with authmode %d dot11 auth %d"\
27732 + " PW crypto %d PW crypto Len %d GRP crypto %d"\
27733 + " GRP crypto Len %d\n",
27734 + ar->arAuthMode, ar->arDot11AuthMode,
27735 + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
27736 + ar->arGroupCrypto, ar->arGroupCryptoLen);
27737 + reconnect_flag = 0;
27738 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
27739 + status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
27740 + ar->arDot11AuthMode, ar->arAuthMode,
27741 + ar->arPairwiseCrypto, ar->arPairwiseCryptoLen,
27742 + ar->arGroupCrypto,ar->arGroupCryptoLen,
27743 + ar->arSsidLen, ar->arSsid,
27744 + ar->arReqBssid, ar->arChannelHint,
27745 + ar->arConnectCtrlFlags);
27746 +
27747 +
27748 + up(&ar->arSem);
27749 +
27750 + if (status != A_OK) {
27751 + return -EIO;
27752 + }
27753 + ar->arConnectPending = TRUE;
27754 + }else{
27755 + up(&ar->arSem);
27756 + }
27757 + return 0;
27758 +}
27759 +
27760 +/* SIOCGIWESSID */
27761 +static int
27762 +ar6000_ioctl_giwessid(struct net_device *dev,
27763 + struct iw_request_info *info,
27764 + struct iw_point *data, char *essid)
27765 +{
27766 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27767 +
27768 + if (ar->arWlanState == WLAN_DISABLED) {
27769 + return -EIO;
27770 + }
27771 +
27772 + data->flags = 1;
27773 + data->length = ar->arSsidLen;
27774 + A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
27775 +
27776 + return 0;
27777 +}
27778 +
27779 +
27780 +void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
27781 +{
27782 + A_UINT8 index;
27783 + A_UINT8 keyUsage;
27784 +
27785 + for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
27786 + if (ar->arWepKeyList[index].arKeyLen) {
27787 + keyUsage = GROUP_USAGE;
27788 + if (index == ar->arDefTxKeyIndex) {
27789 + keyUsage |= TX_USAGE;
27790 + }
27791 + wmi_addKey_cmd(ar->arWmi,
27792 + index,
27793 + WEP_CRYPT,
27794 + keyUsage,
27795 + ar->arWepKeyList[index].arKeyLen,
27796 + NULL,
27797 + ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL,
27798 + NO_SYNC_WMIFLAG);
27799 + }
27800 + }
27801 +}
27802 +
27803 +int
27804 +ar6000_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
27805 + void *w, char *extra)
27806 +{
27807 + return 0;
27808 +}
27809 +
27810 +int
27811 +ar6000_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
27812 + void *w, char *extra)
27813 +{
27814 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27815 + struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra;
27816 +
27817 + if ((ar->arWmiReady == FALSE) || (ar->arConnected != TRUE))
27818 + return -EIO;
27819 +
27820 + switch (mlme->im_op) {
27821 + case IEEE80211_MLME_DISASSOC:
27822 + case IEEE80211_MLME_DEAUTH:
27823 + /* Not Supported */
27824 + break;
27825 + default:
27826 + break;
27827 + }
27828 + return 0;
27829 +}
27830 +
27831 +
27832 +int
27833 +ar6000_ioctl_setwmmparams(struct net_device *dev, struct iw_request_info *info,
27834 + void *w, char *extra)
27835 +{
27836 + return -EIO; /* for now */
27837 +}
27838 +
27839 +int
27840 +ar6000_ioctl_getwmmparams(struct net_device *dev, struct iw_request_info *info,
27841 + void *w, char *extra)
27842 +{
27843 + return -EIO; /* for now */
27844 +}
27845 +
27846 +int ar6000_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info,
27847 + struct iw_point *data, char *extra)
27848 +{
27849 + /* The target generates the WPA/RSN IE */
27850 + return 0;
27851 +}
27852 +
27853 +int
27854 +ar6000_ioctl_setauthalg(struct net_device *dev, struct iw_request_info *info,
27855 + void *w, char *extra)
27856 +{
27857 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27858 + struct ieee80211req_authalg *req = (struct ieee80211req_authalg *)extra;
27859 + int ret = 0;
27860 +
27861 +
27862 + AR6000_SPIN_LOCK(&ar->arLock, 0);
27863 +
27864 + if (req->auth_alg == AUTH_ALG_OPEN_SYSTEM) {
27865 + ar->arDot11AuthMode = OPEN_AUTH;
27866 + } else if (req->auth_alg == AUTH_ALG_LEAP) {
27867 + ar->arDot11AuthMode = LEAP_AUTH;
27868 + ar->arPairwiseCrypto = WEP_CRYPT;
27869 + ar->arGroupCrypto = WEP_CRYPT;
27870 + } else {
27871 + ret = -EIO;
27872 + }
27873 +
27874 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
27875 +
27876 + return ret;
27877 +}
27878 +static int
27879 +ar6000_ioctl_addpmkid(struct net_device *dev, struct iw_request_info *info,
27880 + void *w, char *extra)
27881 +{
27882 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27883 + struct ieee80211req_addpmkid *req = (struct ieee80211req_addpmkid *)extra;
27884 + A_STATUS status;
27885 +
27886 + if (ar->arWlanState == WLAN_DISABLED) {
27887 + return -EIO;
27888 + }
27889 +
27890 + AR_DEBUG_PRINTF("Add pmkid for %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x en=%d\n",
27891 + req->pi_bssid[0], req->pi_bssid[1], req->pi_bssid[2],
27892 + req->pi_bssid[3], req->pi_bssid[4], req->pi_bssid[5],
27893 + req->pi_enable);
27894 +
27895 + status = wmi_setPmkid_cmd(ar->arWmi, req->pi_bssid, req->pi_pmkid,
27896 + req->pi_enable);
27897 +
27898 + if (status != A_OK) {
27899 + return -EIO;
27900 + }
27901 +
27902 + return 0;
27903 +}
27904 +
27905 +/*
27906 + * SIOCSIWRATE
27907 + */
27908 +int
27909 +ar6000_ioctl_siwrate(struct net_device *dev,
27910 + struct iw_request_info *info,
27911 + struct iw_param *rrq, char *extra)
27912 +{
27913 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27914 + A_UINT32 kbps;
27915 +
27916 + if (rrq->fixed) {
27917 + kbps = rrq->value / 1000; /* rrq->value is in bps */
27918 + } else {
27919 + kbps = -1; /* -1 indicates auto rate */
27920 + }
27921 + if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps) == A_EINVAL)
27922 + {
27923 + AR_DEBUG_PRINTF("BitRate is not Valid %d\n", kbps);
27924 + return -EINVAL;
27925 + }
27926 + ar->arBitRate = kbps;
27927 + if(ar->arWmiReady == TRUE)
27928 + {
27929 + if (wmi_set_bitrate_cmd(ar->arWmi, kbps) != A_OK) {
27930 + return -EINVAL;
27931 + }
27932 + }
27933 + return 0;
27934 +}
27935 +
27936 +/*
27937 + * SIOCGIWRATE
27938 + */
27939 +int
27940 +ar6000_ioctl_giwrate(struct net_device *dev,
27941 + struct iw_request_info *info,
27942 + struct iw_param *rrq, char *extra)
27943 +{
27944 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27945 + int ret = 0;
27946 +
27947 + if (down_interruptible(&ar->arSem)) {
27948 + return -ERESTARTSYS;
27949 + }
27950 + if(ar->arWmiReady == TRUE)
27951 + {
27952 + ar->arBitRate = 0xFFFF;
27953 + if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
27954 + up(&ar->arSem);
27955 + return -EIO;
27956 + }
27957 + wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ);
27958 + if (signal_pending(current)) {
27959 + ret = -EINTR;
27960 + }
27961 + }
27962 + /* If the interface is down or wmi is not ready or the target is not
27963 + connected - return the value stored in the device structure */
27964 + if (!ret) {
27965 + if (ar->arBitRate == -1) {
27966 + rrq->fixed = TRUE;
27967 + rrq->value = 0;
27968 + } else {
27969 + rrq->value = ar->arBitRate * 1000;
27970 + }
27971 + }
27972 +
27973 + up(&ar->arSem);
27974 +
27975 + return ret;
27976 +}
27977 +
27978 +/*
27979 + * SIOCSIWTXPOW
27980 + */
27981 +static int
27982 +ar6000_ioctl_siwtxpow(struct net_device *dev,
27983 + struct iw_request_info *info,
27984 + struct iw_param *rrq, char *extra)
27985 +{
27986 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27987 + A_UINT8 dbM;
27988 +
27989 + if (ar->arWlanState == WLAN_DISABLED) {
27990 + return -EIO;
27991 + }
27992 +
27993 + if (ar->arRadioSwitch == WLAN_ENABLED
27994 + && rrq->disabled) {
27995 + if (wmi_switch_radio(ar->arWmi, WLAN_DISABLED) < 0)
27996 + return -EIO;
27997 + ar->arRadioSwitch = WLAN_DISABLED;
27998 + } else if (ar->arRadioSwitch == WLAN_DISABLED
27999 + && !rrq->disabled) {
28000 + if (wmi_switch_radio(ar->arWmi, WLAN_ENABLED) < 0)
28001 + return -EIO;
28002 + ar->arRadioSwitch = WLAN_ENABLED;
28003 + }
28004 +
28005 + if (rrq->fixed) {
28006 + if (rrq->flags != IW_TXPOW_DBM) {
28007 + return -EOPNOTSUPP;
28008 + }
28009 + ar->arTxPwr= dbM = rrq->value;
28010 + ar->arTxPwrSet = TRUE;
28011 + } else {
28012 + ar->arTxPwr = dbM = 0;
28013 + ar->arTxPwrSet = FALSE;
28014 + }
28015 + if(ar->arWmiReady == TRUE)
28016 + {
28017 + AR_DEBUG_PRINTF("Set tx pwr cmd %d dbM\n", dbM);
28018 + wmi_set_txPwr_cmd(ar->arWmi, dbM);
28019 + }
28020 + return 0;
28021 +}
28022 +
28023 +/*
28024 + * SIOCGIWTXPOW
28025 + */
28026 +int
28027 +ar6000_ioctl_giwtxpow(struct net_device *dev,
28028 + struct iw_request_info *info,
28029 + struct iw_param *rrq, char *extra)
28030 +{
28031 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28032 + int ret = 0;
28033 +
28034 + if (ar->arWlanState == WLAN_DISABLED) {
28035 + return -EIO;
28036 + }
28037 +
28038 + if (ar->arRadioSwitch == WLAN_DISABLED) {
28039 + rrq->disabled = 1;
28040 + return 0;
28041 + }
28042 +
28043 + if (down_interruptible(&ar->arSem)) {
28044 + return -ERESTARTSYS;
28045 + }
28046 + if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE))
28047 + {
28048 + ar->arTxPwr = 0;
28049 +
28050 + if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
28051 + up(&ar->arSem);
28052 + return -EIO;
28053 + }
28054 +
28055 + wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ);
28056 +
28057 + if (signal_pending(current)) {
28058 + ret = -EINTR;
28059 + }
28060 + }
28061 + /* If the interace is down or wmi is not ready or target is not connected
28062 + then return value stored in the device structure */
28063 +
28064 + if (!ret) {
28065 + if (ar->arTxPwrSet == TRUE) {
28066 + rrq->fixed = TRUE;
28067 + }
28068 + rrq->value = ar->arTxPwr;
28069 + rrq->flags = IW_TXPOW_DBM;
28070 + }
28071 +
28072 + up(&ar->arSem);
28073 +
28074 + return ret;
28075 +}
28076 +
28077 +/*
28078 + * SIOCSIWRETRY
28079 + * since iwconfig only provides us with one max retry value, we use it
28080 + * to apply to data frames of the BE traffic class.
28081 + */
28082 +static int
28083 +ar6000_ioctl_siwretry(struct net_device *dev,
28084 + struct iw_request_info *info,
28085 + struct iw_param *rrq, char *extra)
28086 +{
28087 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28088 +
28089 + if (ar->arWlanState == WLAN_DISABLED) {
28090 + return -EIO;
28091 + }
28092 +
28093 + if (rrq->disabled) {
28094 + return -EOPNOTSUPP;
28095 + }
28096 +
28097 + if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) {
28098 + return -EOPNOTSUPP;
28099 + }
28100 +
28101 + if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
28102 + return - EINVAL;
28103 + }
28104 + if(ar->arWmiReady == TRUE)
28105 + {
28106 + if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
28107 + rrq->value, 0) != A_OK){
28108 + return -EINVAL;
28109 + }
28110 + }
28111 + ar->arMaxRetries = rrq->value;
28112 + return 0;
28113 +}
28114 +
28115 +/*
28116 + * SIOCGIWRETRY
28117 + */
28118 +static int
28119 +ar6000_ioctl_giwretry(struct net_device *dev,
28120 + struct iw_request_info *info,
28121 + struct iw_param *rrq, char *extra)
28122 +{
28123 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28124 +
28125 + if (ar->arWlanState == WLAN_DISABLED) {
28126 + return -EIO;
28127 + }
28128 +
28129 + rrq->disabled = 0;
28130 + switch (rrq->flags & IW_RETRY_TYPE) {
28131 + case IW_RETRY_LIFETIME:
28132 + return -EOPNOTSUPP;
28133 + break;
28134 + case IW_RETRY_LIMIT:
28135 + rrq->flags = IW_RETRY_LIMIT;
28136 + switch (rrq->flags & IW_RETRY_MODIFIER) {
28137 + case IW_RETRY_MIN:
28138 + rrq->flags |= IW_RETRY_MIN;
28139 + rrq->value = WMI_MIN_RETRIES;
28140 + break;
28141 + case IW_RETRY_MAX:
28142 + rrq->flags |= IW_RETRY_MAX;
28143 + rrq->value = ar->arMaxRetries;
28144 + break;
28145 + }
28146 + break;
28147 + }
28148 + return 0;
28149 +}
28150 +
28151 +/*
28152 + * SIOCSIWENCODE
28153 + */
28154 +static int
28155 +ar6000_ioctl_siwencode(struct net_device *dev,
28156 + struct iw_request_info *info,
28157 + struct iw_point *erq, char *keybuf)
28158 +{
28159 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28160 + int index;
28161 + A_INT32 auth = ar->arDot11AuthMode;
28162 +
28163 + if (ar->arWlanState == WLAN_DISABLED) {
28164 + return -EIO;
28165 + }
28166 +
28167 + index = erq->flags & IW_ENCODE_INDEX;
28168 +
28169 + if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
28170 + ((index - 1) > WMI_MAX_KEY_INDEX)))
28171 + {
28172 + return -EIO;
28173 + }
28174 +
28175 + if (erq->flags & IW_ENCODE_DISABLED) {
28176 + /*
28177 + * Encryption disabled
28178 + */
28179 + if (index) {
28180 + /*
28181 + * If key index was specified then clear the specified key
28182 + */
28183 + index--;
28184 + A_MEMZERO(ar->arWepKeyList[index].arKey,
28185 + sizeof(ar->arWepKeyList[index].arKey));
28186 + ar->arWepKeyList[index].arKeyLen = 0;
28187 + }
28188 + ar->arDot11AuthMode = OPEN_AUTH;
28189 + ar->arPairwiseCrypto = NONE_CRYPT;
28190 + ar->arGroupCrypto = NONE_CRYPT;
28191 + ar->arAuthMode = NONE_AUTH;
28192 + } else {
28193 + /*
28194 + * Enabling WEP encryption
28195 + */
28196 + if (index) {
28197 + index--; /* keyindex is off base 1 in iwconfig */
28198 + }
28199 +
28200 + if (erq->flags & IW_ENCODE_OPEN) {
28201 + auth = OPEN_AUTH;
28202 + } else if (erq->flags & IW_ENCODE_RESTRICTED) {
28203 + auth = SHARED_AUTH;
28204 + }
28205 +
28206 + if (erq->length) {
28207 + if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) {
28208 + return -EIO;
28209 + }
28210 +
28211 + A_MEMZERO(ar->arWepKeyList[index].arKey,
28212 + sizeof(ar->arWepKeyList[index].arKey));
28213 + A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length);
28214 + ar->arWepKeyList[index].arKeyLen = erq->length;
28215 + } else {
28216 + if (ar->arWepKeyList[index].arKeyLen == 0) {
28217 + return -EIO;
28218 + }
28219 + ar->arDefTxKeyIndex = index;
28220 + }
28221 +
28222 + ar->arPairwiseCrypto = WEP_CRYPT;
28223 + ar->arGroupCrypto = WEP_CRYPT;
28224 + ar->arDot11AuthMode = auth;
28225 + ar->arAuthMode = NONE_AUTH;
28226 + }
28227 +
28228 + /*
28229 + * profile has changed. Erase ssid to signal change
28230 + */
28231 + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
28232 + ar->arSsidLen = 0;
28233 +
28234 + return 0;
28235 +}
28236 +
28237 +static int
28238 +ar6000_ioctl_giwencode(struct net_device *dev,
28239 + struct iw_request_info *info,
28240 + struct iw_point *erq, char *key)
28241 +{
28242 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28243 + A_UINT8 keyIndex;
28244 + struct ar_wep_key *wk;
28245 +
28246 + if (ar->arWlanState == WLAN_DISABLED) {
28247 + return -EIO;
28248 + }
28249 +
28250 + if (ar->arPairwiseCrypto == NONE_CRYPT) {
28251 + erq->length = 0;
28252 + erq->flags = IW_ENCODE_DISABLED;
28253 + } else {
28254 + /* get the keyIndex */
28255 + keyIndex = erq->flags & IW_ENCODE_INDEX;
28256 + if (0 == keyIndex) {
28257 + keyIndex = ar->arDefTxKeyIndex;
28258 + } else if ((keyIndex - 1 < WMI_MIN_KEY_INDEX) ||
28259 + (keyIndex - 1 > WMI_MAX_KEY_INDEX))
28260 + {
28261 + keyIndex = WMI_MIN_KEY_INDEX;
28262 + } else {
28263 + keyIndex--;
28264 + }
28265 + erq->flags = keyIndex + 1;
28266 + erq->flags |= IW_ENCODE_ENABLED;
28267 + wk = &ar->arWepKeyList[keyIndex];
28268 + if (erq->length > wk->arKeyLen) {
28269 + erq->length = wk->arKeyLen;
28270 + }
28271 + if (wk->arKeyLen) {
28272 + A_MEMCPY(key, wk->arKey, erq->length);
28273 + }
28274 + if (ar->arDot11AuthMode == OPEN_AUTH) {
28275 + erq->flags |= IW_ENCODE_OPEN;
28276 + } else if (ar->arDot11AuthMode == SHARED_AUTH) {
28277 + erq->flags |= IW_ENCODE_RESTRICTED;
28278 + }
28279 + }
28280 +
28281 + return 0;
28282 +}
28283 +
28284 +static int ar6000_ioctl_siwpower(struct net_device *dev,
28285 + struct iw_request_info *info,
28286 + union iwreq_data *wrqu, char *extra)
28287 +{
28288 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28289 + WMI_POWER_MODE power_mode;
28290 +
28291 + if (wrqu->power.disabled)
28292 + power_mode = MAX_PERF_POWER;
28293 + else
28294 + power_mode = REC_POWER;
28295 +
28296 + if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0)
28297 + return -EIO;
28298 +
28299 + return 0;
28300 +}
28301 +
28302 +static int ar6000_ioctl_giwpower(struct net_device *dev,
28303 + struct iw_request_info *info,
28304 + union iwreq_data *wrqu, char *extra)
28305 +{
28306 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28307 +
28308 + /*
28309 + * FIXME:
28310 + * https://docs.openmoko.org/trac/ticket/2267
28311 + * When starting wpa_supplicant the kernel oopses.
28312 + * The following condition avoids the oops.
28313 + * Remove this comment to bless this solution.
28314 + */
28315 + if (ar->arWlanState == WLAN_DISABLED || ar->arWmiReady == FALSE)
28316 + return -EIO;
28317 +
28318 + return wmi_get_power_mode_cmd(ar->arWmi);
28319 +}
28320 +
28321 +static int ar6000_ioctl_siwgenie(struct net_device *dev,
28322 + struct iw_request_info *info,
28323 + struct iw_point *dwrq,
28324 + char *extra)
28325 +{
28326 + /* The target does that for us */
28327 + return 0;
28328 +}
28329 +
28330 +static int ar6000_ioctl_giwgenie(struct net_device *dev,
28331 + struct iw_request_info *info,
28332 + struct iw_point *dwrq,
28333 + char *extra)
28334 +{
28335 + return 0;
28336 +}
28337 +
28338 +static int ar6000_ioctl_siwauth(struct net_device *dev,
28339 + struct iw_request_info *info,
28340 + struct iw_param *param,
28341 + char *extra)
28342 +{
28343 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28344 + int reset = 0;
28345 +
28346 + switch (param->flags & IW_AUTH_INDEX) {
28347 + case IW_AUTH_WPA_VERSION:
28348 + if (param->value & IW_AUTH_WPA_VERSION_DISABLED) {
28349 + ar->arAuthMode = NONE_AUTH;
28350 + }
28351 + if (param->value & IW_AUTH_WPA_VERSION_WPA) {
28352 + ar->arAuthMode = WPA_AUTH;
28353 + }
28354 + if (param->value & IW_AUTH_WPA_VERSION_WPA2) {
28355 + ar->arAuthMode = WPA2_AUTH;
28356 + }
28357 +
28358 + reset = 1;
28359 + break;
28360 + case IW_AUTH_CIPHER_PAIRWISE:
28361 + if (param->value & IW_AUTH_CIPHER_NONE) {
28362 + ar->arPairwiseCrypto = NONE_CRYPT;
28363 + }
28364 + if (param->value & IW_AUTH_CIPHER_WEP40) {
28365 + ar->arPairwiseCrypto = WEP_CRYPT;
28366 + }
28367 + if (param->value & IW_AUTH_CIPHER_TKIP) {
28368 + ar->arPairwiseCrypto = TKIP_CRYPT;
28369 + }
28370 + if (param->value & IW_AUTH_CIPHER_CCMP) {
28371 + ar->arPairwiseCrypto = AES_CRYPT;
28372 + }
28373 +
28374 + reset = 1;
28375 + break;
28376 + case IW_AUTH_CIPHER_GROUP:
28377 + if (param->value & IW_AUTH_CIPHER_NONE) {
28378 + ar->arGroupCrypto = NONE_CRYPT;
28379 + }
28380 + if (param->value & IW_AUTH_CIPHER_WEP40) {
28381 + ar->arGroupCrypto = WEP_CRYPT;
28382 + }
28383 + if (param->value & IW_AUTH_CIPHER_TKIP) {
28384 + ar->arGroupCrypto = TKIP_CRYPT;
28385 + }
28386 + if (param->value & IW_AUTH_CIPHER_CCMP) {
28387 + ar->arGroupCrypto = AES_CRYPT;
28388 + }
28389 +
28390 + reset = 1;
28391 + break;
28392 + case IW_AUTH_KEY_MGMT:
28393 + if (param->value & IW_AUTH_KEY_MGMT_PSK) {
28394 + if (ar->arAuthMode == WPA_AUTH) {
28395 + ar->arAuthMode = WPA_PSK_AUTH;
28396 + } else if (ar->arAuthMode == WPA2_AUTH) {
28397 + ar->arAuthMode = WPA2_PSK_AUTH;
28398 + }
28399 +
28400 + reset = 1;
28401 + }
28402 + break;
28403 +
28404 + case IW_AUTH_TKIP_COUNTERMEASURES:
28405 + if (ar->arWmiReady == FALSE) {
28406 + return -EIO;
28407 + }
28408 + wmi_set_tkip_countermeasures_cmd(ar->arWmi, param->value);
28409 + break;
28410 +
28411 + case IW_AUTH_DROP_UNENCRYPTED:
28412 + break;
28413 +
28414 + case IW_AUTH_80211_AUTH_ALG:
28415 + if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
28416 + ar->arDot11AuthMode = OPEN_AUTH;
28417 + }
28418 + if (param->value & IW_AUTH_ALG_SHARED_KEY) {
28419 + ar->arDot11AuthMode = SHARED_AUTH;
28420 + }
28421 + if (param->value & IW_AUTH_ALG_LEAP) {
28422 + ar->arDot11AuthMode = LEAP_AUTH;
28423 + ar->arPairwiseCrypto = WEP_CRYPT;
28424 + ar->arGroupCrypto = WEP_CRYPT;
28425 + }
28426 +
28427 + reset = 1;
28428 + break;
28429 +
28430 + case IW_AUTH_WPA_ENABLED:
28431 + reset = 1;
28432 + break;
28433 +
28434 + case IW_AUTH_RX_UNENCRYPTED_EAPOL:
28435 + break;
28436 +
28437 + case IW_AUTH_PRIVACY_INVOKED:
28438 + break;
28439 +
28440 + default:
28441 + printk("%s(): Unknown flag 0x%x\n", __FUNCTION__, param->flags);
28442 + return -EOPNOTSUPP;
28443 + }
28444 +
28445 + if (reset) {
28446 + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
28447 + ar->arSsidLen = 0;
28448 + }
28449 +
28450 + return 0;
28451 +}
28452 +
28453 +static int ar6000_ioctl_giwauth(struct net_device *dev,
28454 + struct iw_request_info *info,
28455 + struct iw_param *dwrq,
28456 + char *extra)
28457 +{
28458 + return 0;
28459 +}
28460 +
28461 +static int ar6000_ioctl_siwencodeext(struct net_device *dev,
28462 + struct iw_request_info *info,
28463 + union iwreq_data *wrqu,
28464 + char *extra)
28465 +{
28466 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28467 + struct iw_point *encoding = &wrqu->encoding;
28468 + struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
28469 + int alg = ext->alg, idx;
28470 +
28471 + if (ar->arWlanState == WLAN_DISABLED) {
28472 + return -EIO;
28473 + }
28474 +
28475 + /* Determine and validate the key index */
28476 + idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
28477 + if (idx) {
28478 + if (idx < 0 || idx > 3)
28479 + return -EINVAL;
28480 + }
28481 +
28482 + if ((alg == IW_ENCODE_ALG_TKIP) || (alg == IW_ENCODE_ALG_CCMP)) {
28483 + struct ieee80211req_key ik;
28484 + KEY_USAGE key_usage;
28485 + CRYPTO_TYPE key_type = NONE_CRYPT;
28486 + int status;
28487 +
28488 + ar->user_saved_keys.keyOk = FALSE;
28489 +
28490 + if (alg == IW_ENCODE_ALG_TKIP) {
28491 + key_type = TKIP_CRYPT;
28492 + ik.ik_type = IEEE80211_CIPHER_TKIP;
28493 + } else {
28494 + key_type = AES_CRYPT;
28495 + ik.ik_type = IEEE80211_CIPHER_AES_CCM;
28496 + }
28497 +
28498 + ik.ik_keyix = idx;
28499 + ik.ik_keylen = ext->key_len;
28500 + ik.ik_flags = IEEE80211_KEY_RECV;
28501 + if (ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
28502 + ik.ik_flags |= IEEE80211_KEY_XMIT
28503 + | IEEE80211_KEY_DEFAULT;
28504 + }
28505 +
28506 + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
28507 + memcpy(&ik.ik_keyrsc, ext->rx_seq, 8);
28508 + }
28509 +
28510 + memcpy(ik.ik_keydata, ext->key, ext->key_len);
28511 +
28512 + ar->user_saved_keys.keyType = key_type;
28513 + if (ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY) {
28514 + key_usage = GROUP_USAGE;
28515 + memset(ik.ik_macaddr, 0, ETH_ALEN);
28516 + memcpy(&ar->user_saved_keys.bcast_ik, &ik,
28517 + sizeof(struct ieee80211req_key));
28518 + } else {
28519 + key_usage = PAIRWISE_USAGE;
28520 + memcpy(ik.ik_macaddr, ext->addr.sa_data, ETH_ALEN);
28521 + memcpy(&ar->user_saved_keys.ucast_ik, &ik,
28522 + sizeof(struct ieee80211req_key));
28523 + }
28524 +
28525 + status = wmi_addKey_cmd(ar->arWmi, ik.ik_keyix, key_type,
28526 + key_usage, ik.ik_keylen,
28527 + (A_UINT8 *)&ik.ik_keyrsc,
28528 + ik.ik_keydata,
28529 + KEY_OP_INIT_VAL, SYNC_BEFORE_WMIFLAG);
28530 +
28531 + if (status < 0)
28532 + return -EIO;
28533 +
28534 + ar->user_saved_keys.keyOk = TRUE;
28535 +
28536 + return 0;
28537 +
28538 + } else {
28539 + /* WEP falls back to SIWENCODE */
28540 + return -EOPNOTSUPP;
28541 + }
28542 +
28543 + return 0;
28544 +}
28545 +
28546 +
28547 +static int ar6000_ioctl_giwencodeext(struct net_device *dev,
28548 + struct iw_request_info *info,
28549 + struct iw_point *dwrq,
28550 + char *extra)
28551 +{
28552 + return 0;
28553 +}
28554 +
28555 +
28556 +static int
28557 +ar6000_ioctl_setparam(struct net_device *dev,
28558 + struct iw_request_info *info,
28559 + void *erq, char *extra)
28560 +{
28561 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28562 + int *i = (int *)extra;
28563 + int param = i[0];
28564 + int value = i[1];
28565 + int ret = 0;
28566 + A_BOOL profChanged = FALSE;
28567 +
28568 + if (ar->arWlanState == WLAN_DISABLED) {
28569 + return -EIO;
28570 + }
28571 +
28572 + switch (param) {
28573 + case IEEE80211_PARAM_WPA:
28574 + switch (value) {
28575 + case WPA_MODE_WPA1:
28576 + ar->arAuthMode = WPA_AUTH;
28577 + profChanged = TRUE;
28578 + break;
28579 + case WPA_MODE_WPA2:
28580 + ar->arAuthMode = WPA2_AUTH;
28581 + profChanged = TRUE;
28582 + break;
28583 + case WPA_MODE_NONE:
28584 + ar->arAuthMode = NONE_AUTH;
28585 + profChanged = TRUE;
28586 + break;
28587 + default:
28588 + printk("IEEE80211_PARAM_WPA: Unknown value %d\n", value);
28589 + }
28590 + break;
28591 + case IEEE80211_PARAM_AUTHMODE:
28592 + switch(value) {
28593 + case IEEE80211_AUTH_WPA_PSK:
28594 + if (WPA_AUTH == ar->arAuthMode) {
28595 + ar->arAuthMode = WPA_PSK_AUTH;
28596 + profChanged = TRUE;
28597 + } else if (WPA2_AUTH == ar->arAuthMode) {
28598 + ar->arAuthMode = WPA2_PSK_AUTH;
28599 + profChanged = TRUE;
28600 + } else {
28601 + AR_DEBUG_PRINTF("Error - Setting PSK mode when WPA "\
28602 + "param was set to %d\n",
28603 + ar->arAuthMode);
28604 + ret = -1;
28605 + }
28606 + break;
28607 + case IEEE80211_AUTH_WPA_CCKM:
28608 + if (WPA2_AUTH == ar->arAuthMode) {
28609 + ar->arAuthMode = WPA2_AUTH_CCKM;
28610 + } else {
28611 + ar->arAuthMode = WPA_AUTH_CCKM;
28612 + }
28613 + break;
28614 + default:
28615 + break;
28616 + }
28617 + break;
28618 + case IEEE80211_PARAM_UCASTCIPHER:
28619 + switch (value) {
28620 + case IEEE80211_CIPHER_AES_CCM:
28621 + ar->arPairwiseCrypto = AES_CRYPT;
28622 + profChanged = TRUE;
28623 + break;
28624 + case IEEE80211_CIPHER_TKIP:
28625 + ar->arPairwiseCrypto = TKIP_CRYPT;
28626 + profChanged = TRUE;
28627 + break;
28628 + case IEEE80211_CIPHER_WEP:
28629 + ar->arPairwiseCrypto = WEP_CRYPT;
28630 + profChanged = TRUE;
28631 + break;
28632 + case IEEE80211_CIPHER_NONE:
28633 + ar->arPairwiseCrypto = NONE_CRYPT;
28634 + profChanged = TRUE;
28635 + break;
28636 + }
28637 + break;
28638 + case IEEE80211_PARAM_UCASTKEYLEN:
28639 + if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
28640 + ret = -EIO;
28641 + } else {
28642 + ar->arPairwiseCryptoLen = value;
28643 + }
28644 + break;
28645 + case IEEE80211_PARAM_MCASTCIPHER:
28646 + switch (value) {
28647 + case IEEE80211_CIPHER_AES_CCM:
28648 + ar->arGroupCrypto = AES_CRYPT;
28649 + profChanged = TRUE;
28650 + break;
28651 + case IEEE80211_CIPHER_TKIP:
28652 + ar->arGroupCrypto = TKIP_CRYPT;
28653 + profChanged = TRUE;
28654 + break;
28655 + case IEEE80211_CIPHER_WEP:
28656 + ar->arGroupCrypto = WEP_CRYPT;
28657 + profChanged = TRUE;
28658 + break;
28659 + case IEEE80211_CIPHER_NONE:
28660 + ar->arGroupCrypto = NONE_CRYPT;
28661 + profChanged = TRUE;
28662 + break;
28663 + }
28664 + break;
28665 + case IEEE80211_PARAM_MCASTKEYLEN:
28666 + if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
28667 + ret = -EIO;
28668 + } else {
28669 + ar->arGroupCryptoLen = value;
28670 + }
28671 + break;
28672 + case IEEE80211_PARAM_COUNTERMEASURES:
28673 + if (ar->arWmiReady == FALSE) {
28674 + return -EIO;
28675 + }
28676 + wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
28677 + break;
28678 + default:
28679 + break;
28680 + }
28681 +
28682 + if (profChanged == TRUE) {
28683 + /*
28684 + * profile has changed. Erase ssid to signal change
28685 + */
28686 + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
28687 + ar->arSsidLen = 0;
28688 + }
28689 +
28690 + return ret;
28691 +}
28692 +
28693 +int
28694 +ar6000_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
28695 + void *w, char *extra)
28696 +{
28697 + return -EIO; /* for now */
28698 +}
28699 +
28700 +int
28701 +ar6000_ioctl_setkey(struct net_device *dev, struct iw_request_info *info,
28702 + void *w, char *extra)
28703 +{
28704 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28705 + struct ieee80211req_key *ik = (struct ieee80211req_key *)extra;
28706 + KEY_USAGE keyUsage;
28707 + A_STATUS status;
28708 + CRYPTO_TYPE keyType = NONE_CRYPT;
28709 +
28710 + if (ar->arWlanState == WLAN_DISABLED) {
28711 + return -EIO;
28712 + }
28713 +
28714 + ar->user_saved_keys.keyOk = FALSE;
28715 +
28716 + if ( 0 == memcmp(ik->ik_macaddr, "\x00\x00\x00\x00\x00\x00",
28717 + IEEE80211_ADDR_LEN)) {
28718 + keyUsage = GROUP_USAGE;
28719 + A_MEMCPY(&ar->user_saved_keys.bcast_ik, ik,
28720 + sizeof(struct ieee80211req_key));
28721 + } else {
28722 + keyUsage = PAIRWISE_USAGE;
28723 + A_MEMCPY(&ar->user_saved_keys.ucast_ik, ik,
28724 + sizeof(struct ieee80211req_key));
28725 + }
28726 +
28727 + switch (ik->ik_type) {
28728 + case IEEE80211_CIPHER_WEP:
28729 + keyType = WEP_CRYPT;
28730 + break;
28731 + case IEEE80211_CIPHER_TKIP:
28732 + keyType = TKIP_CRYPT;
28733 + break;
28734 + case IEEE80211_CIPHER_AES_CCM:
28735 + keyType = AES_CRYPT;
28736 + break;
28737 + default:
28738 + break;
28739 + }
28740 + ar->user_saved_keys.keyType = keyType;
28741 +
28742 + if (IEEE80211_CIPHER_CCKM_KRK != ik->ik_type) {
28743 + if (NONE_CRYPT == keyType) {
28744 + return -EIO;
28745 + }
28746 +
28747 + status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, keyUsage,
28748 + ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc,
28749 + ik->ik_keydata, KEY_OP_INIT_VAL,
28750 + SYNC_BEFORE_WMIFLAG);
28751 +
28752 + if (status != A_OK) {
28753 + return -EIO;
28754 + }
28755 + } else {
28756 + status = wmi_add_krk_cmd(ar->arWmi, ik->ik_keydata);
28757 + }
28758 +
28759 + ar->user_saved_keys.keyOk = TRUE;
28760 +
28761 + return 0;
28762 +}
28763 +
28764 +
28765 +/*
28766 + * SIOCGIWNAME
28767 + */
28768 +int
28769 +ar6000_ioctl_giwname(struct net_device *dev,
28770 + struct iw_request_info *info,
28771 + char *name, char *extra)
28772 +{
28773 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28774 +
28775 + if (ar->arWlanState == WLAN_DISABLED) {
28776 + return -EIO;
28777 + }
28778 +
28779 + switch (ar->arPhyCapability) {
28780 + case (WMI_11A_CAPABILITY):
28781 + strncpy(name, "AR6000 802.11a", IFNAMSIZ);
28782 + break;
28783 + case (WMI_11G_CAPABILITY):
28784 + strncpy(name, "AR6000 802.11g", IFNAMSIZ);
28785 + break;
28786 + case (WMI_11AG_CAPABILITY):
28787 + strncpy(name, "AR6000 802.11ag", IFNAMSIZ);
28788 + break;
28789 + default:
28790 + strncpy(name, "AR6000 802.11", IFNAMSIZ);
28791 + break;
28792 + }
28793 +
28794 + return 0;
28795 +}
28796 +
28797 +/*
28798 + * SIOCSIWFREQ
28799 + */
28800 +int
28801 +ar6000_ioctl_siwfreq(struct net_device *dev,
28802 + struct iw_request_info *info,
28803 + struct iw_freq *freq, char *extra)
28804 +{
28805 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28806 +
28807 + if (ar->arWlanState == WLAN_DISABLED) {
28808 + return -EIO;
28809 + }
28810 +
28811 + /*
28812 + * We support limiting the channels via wmiconfig.
28813 + *
28814 + * We use this command to configure the channel hint for the connect cmd
28815 + * so it is possible the target will end up connecting to a different
28816 + * channel.
28817 + */
28818 + if (freq->e > 1) {
28819 + return -EINVAL;
28820 + } else if (freq->e == 1) {
28821 + ar->arChannelHint = freq->m / 100000;
28822 + } else {
28823 + ar->arChannelHint = wlan_ieee2freq(freq->m);
28824 + }
28825 +
28826 + A_PRINTF("channel hint set to %d\n", ar->arChannelHint);
28827 + return 0;
28828 +}
28829 +
28830 +/*
28831 + * SIOCGIWFREQ
28832 + */
28833 +int
28834 +ar6000_ioctl_giwfreq(struct net_device *dev,
28835 + struct iw_request_info *info,
28836 + struct iw_freq *freq, char *extra)
28837 +{
28838 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28839 +
28840 + if (ar->arWlanState == WLAN_DISABLED) {
28841 + return -EIO;
28842 + }
28843 +
28844 + if (ar->arConnected != TRUE) {
28845 + return -EINVAL;
28846 + }
28847 +
28848 + freq->m = ar->arBssChannel * 100000;
28849 + freq->e = 1;
28850 +
28851 + return 0;
28852 +}
28853 +
28854 +/*
28855 + * SIOCSIWMODE
28856 + */
28857 +int
28858 +ar6000_ioctl_siwmode(struct net_device *dev,
28859 + struct iw_request_info *info,
28860 + __u32 *mode, char *extra)
28861 +{
28862 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28863 +
28864 + if (ar->arWlanState == WLAN_DISABLED) {
28865 + return -EIO;
28866 + }
28867 +
28868 + switch (*mode) {
28869 + case IW_MODE_INFRA:
28870 + ar->arNetworkType = INFRA_NETWORK;
28871 + break;
28872 + case IW_MODE_ADHOC:
28873 + ar->arNetworkType = ADHOC_NETWORK;
28874 + break;
28875 + default:
28876 + return -EINVAL;
28877 + }
28878 +
28879 + return 0;
28880 +}
28881 +
28882 +/*
28883 + * SIOCGIWMODE
28884 + */
28885 +int
28886 +ar6000_ioctl_giwmode(struct net_device *dev,
28887 + struct iw_request_info *info,
28888 + __u32 *mode, char *extra)
28889 +{
28890 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28891 +
28892 + if (ar->arWlanState == WLAN_DISABLED) {
28893 + return -EIO;
28894 + }
28895 +
28896 + switch (ar->arNetworkType) {
28897 + case INFRA_NETWORK:
28898 + *mode = IW_MODE_INFRA;
28899 + break;
28900 + case ADHOC_NETWORK:
28901 + *mode = IW_MODE_ADHOC;
28902 + break;
28903 + default:
28904 + return -EIO;
28905 + }
28906 + return 0;
28907 +}
28908 +
28909 +/*
28910 + * SIOCSIWSENS
28911 + */
28912 +int
28913 +ar6000_ioctl_siwsens(struct net_device *dev,
28914 + struct iw_request_info *info,
28915 + struct iw_param *sens, char *extra)
28916 +{
28917 + return 0;
28918 +}
28919 +
28920 +/*
28921 + * SIOCGIWSENS
28922 + */
28923 +int
28924 +ar6000_ioctl_giwsens(struct net_device *dev,
28925 + struct iw_request_info *info,
28926 + struct iw_param *sens, char *extra)
28927 +{
28928 + sens->value = 0;
28929 + sens->fixed = 1;
28930 +
28931 + return 0;
28932 +}
28933 +
28934 +/*
28935 + * SIOCGIWRANGE
28936 + */
28937 +int
28938 +ar6000_ioctl_giwrange(struct net_device *dev,
28939 + struct iw_request_info *info,
28940 + struct iw_point *data, char *extra)
28941 +{
28942 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28943 + struct iw_range *range = (struct iw_range *) extra;
28944 + int i, ret = 0;
28945 +
28946 + if (ar->arWmiReady == FALSE) {
28947 + return -EIO;
28948 + }
28949 +
28950 + if (ar->arWlanState == WLAN_DISABLED) {
28951 + return -EIO;
28952 + }
28953 +
28954 + if (down_interruptible(&ar->arSem)) {
28955 + return -ERESTARTSYS;
28956 + }
28957 + ar->arNumChannels = -1;
28958 + A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
28959 +
28960 + if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
28961 + up(&ar->arSem);
28962 + return -EIO;
28963 + }
28964 +
28965 + wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ);
28966 +
28967 + if (signal_pending(current)) {
28968 + up(&ar->arSem);
28969 + return -EINTR;
28970 + }
28971 +
28972 + data->length = sizeof(struct iw_range);
28973 + A_MEMZERO(range, sizeof(struct iw_range));
28974 +
28975 + range->txpower_capa = IW_TXPOW_DBM;
28976 +
28977 + range->min_pmp = 1 * 1024;
28978 + range->max_pmp = 65535 * 1024;
28979 + range->min_pmt = 1 * 1024;
28980 + range->max_pmt = 1000 * 1024;
28981 + range->pmp_flags = IW_POWER_PERIOD;
28982 + range->pmt_flags = IW_POWER_TIMEOUT;
28983 + range->pm_capa = 0;
28984 +
28985 + range->we_version_compiled = WIRELESS_EXT;
28986 + range->we_version_source = 13;
28987 +
28988 + range->retry_capa = IW_RETRY_LIMIT;
28989 + range->retry_flags = IW_RETRY_LIMIT;
28990 + range->min_retry = 0;
28991 + range->max_retry = 255;
28992 +
28993 + range->num_frequency = range->num_channels = ar->arNumChannels;
28994 + for (i = 0; i < ar->arNumChannels; i++) {
28995 + range->freq[i].i = wlan_freq2ieee(ar->arChannelList[i]);
28996 + range->freq[i].m = ar->arChannelList[i] * 100000;
28997 + range->freq[i].e = 1;
28998 + /*
28999 + * Linux supports max of 32 channels, bail out once you
29000 + * reach the max.
29001 + */
29002 + if (i == IW_MAX_FREQUENCIES) {
29003 + break;
29004 + }
29005 + }
29006 +
29007 + /* Max quality is max field value minus noise floor */
29008 + range->max_qual.qual = 0xff - 161;
29009 +
29010 + /*
29011 + * In order to use dBm measurements, 'level' must be lower
29012 + * than any possible measurement (see iw_print_stats() in
29013 + * wireless tools). It's unclear how this is meant to be
29014 + * done, but setting zero in these values forces dBm and
29015 + * the actual numbers are not used.
29016 + */
29017 + range->max_qual.level = 0;
29018 + range->max_qual.noise = 0;
29019 +
29020 + range->sensitivity = 3;
29021 +
29022 + range->max_encoding_tokens = 4;
29023 + /* XXX query driver to find out supported key sizes */
29024 + range->num_encoding_sizes = 3;
29025 + range->encoding_size[0] = 5; /* 40-bit */
29026 + range->encoding_size[1] = 13; /* 104-bit */
29027 + range->encoding_size[2] = 16; /* 128-bit */
29028 +
29029 + range->num_bitrates = 0;
29030 +
29031 + /* estimated maximum TCP throughput values (bps) */
29032 + range->throughput = 22000000;
29033 +
29034 + range->min_rts = 0;
29035 + range->max_rts = 2347;
29036 + range->min_frag = 256;
29037 + range->max_frag = 2346;
29038 +
29039 + up(&ar->arSem);
29040 +
29041 + return ret;
29042 +}
29043 +
29044 +
29045 +/*
29046 + * SIOCSIWAP
29047 + * This ioctl is used to set the desired bssid for the connect command.
29048 + */
29049 +int
29050 +ar6000_ioctl_siwap(struct net_device *dev,
29051 + struct iw_request_info *info,
29052 + struct sockaddr *ap_addr, char *extra)
29053 +{
29054 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
29055 +
29056 + if (ar->arWlanState == WLAN_DISABLED) {
29057 + return -EIO;
29058 + }
29059 +
29060 + if (ap_addr->sa_family != ARPHRD_ETHER) {
29061 + return -EIO;
29062 + }
29063 +
29064 + if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
29065 + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
29066 + } else {
29067 + A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid));
29068 + }
29069 +
29070 + return 0;
29071 +}
29072 +
29073 +/*
29074 + * SIOCGIWAP
29075 + */
29076 +int
29077 +ar6000_ioctl_giwap(struct net_device *dev,
29078 + struct iw_request_info *info,
29079 + struct sockaddr *ap_addr, char *extra)
29080 +{
29081 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
29082 +
29083 + if (ar->arWlanState == WLAN_DISABLED) {
29084 + return -EIO;
29085 + }
29086 +
29087 + if (ar->arConnected != TRUE) {
29088 + return -EINVAL;
29089 + }
29090 +
29091 + A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
29092 + ap_addr->sa_family = ARPHRD_ETHER;
29093 +
29094 + return 0;
29095 +}
29096 +
29097 +/*
29098 + * SIOCGIWAPLIST
29099 + */
29100 +int
29101 +ar6000_ioctl_iwaplist(struct net_device *dev,
29102 + struct iw_request_info *info,
29103 + struct iw_point *data, char *extra)
29104 +{
29105 + return -EIO; /* for now */
29106 +}
29107 +
29108 +/*
29109 + * SIOCSIWSCAN
29110 + */
29111 +int
29112 +ar6000_ioctl_siwscan(struct net_device *dev,
29113 + struct iw_request_info *info,
29114 + struct iw_point *data, char *extra)
29115 +{
29116 +#define ACT_DWELLTIME_DEFAULT 105
29117 +#define HOME_TXDRAIN_TIME 100
29118 +#define SCAN_INT HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT
29119 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
29120 + int ret = 0;
29121 +
29122 + if (ar->arWmiReady == FALSE) {
29123 + return -EIO;
29124 + }
29125 +
29126 + if (ar->arWlanState == WLAN_DISABLED) {
29127 + return -EIO;
29128 + }
29129 +
29130 + /* We ask for everything from the target */
29131 + if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
29132 + printk("Couldn't set filtering\n");
29133 + ret = -EIO;
29134 + }
29135 +
29136 + if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \
29137 + HOME_TXDRAIN_TIME, SCAN_INT) != A_OK) {
29138 + ret = -EIO;
29139 + }
29140 +
29141 + ar->scan_complete = 0;
29142 + wait_event_interruptible_timeout(ar6000_scan_queue, ar->scan_complete,
29143 + 5 * HZ);
29144 +
29145 + if (wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0) != A_OK) {
29146 + printk("Couldn't set filtering\n");
29147 + ret = -EIO;
29148 + }
29149 +
29150 + return ret;
29151 +#undef ACT_DWELLTIME_DEFAULT
29152 +#undef HOME_TXDRAIN_TIME
29153 +#undef SCAN_INT
29154 +}
29155 +
29156 +
29157 +/*
29158 + * Units are in db above the noise floor. That means the
29159 + * rssi values reported in the tx/rx descriptors in the
29160 + * driver are the SNR expressed in db.
29161 + *
29162 + * If you assume that the noise floor is -95, which is an
29163 + * excellent assumption 99.5 % of the time, then you can
29164 + * derive the absolute signal level (i.e. -95 + rssi).
29165 + * There are some other slight factors to take into account
29166 + * depending on whether the rssi measurement is from 11b,
29167 + * 11g, or 11a. These differences are at most 2db and
29168 + * can be documented.
29169 + *
29170 + * NB: various calculations are based on the orinoco/wavelan
29171 + * drivers for compatibility
29172 + */
29173 +static void
29174 +ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
29175 +{
29176 + if (rssi < 0) {
29177 + iq->qual = 0;
29178 + } else {
29179 + iq->qual = rssi;
29180 + }
29181 +
29182 + /* NB: max is 94 because noise is hardcoded to 161 */
29183 + if (iq->qual > 94)
29184 + iq->qual = 94;
29185 +
29186 + iq->noise = 161; /* -95dBm */
29187 + iq->level = iq->noise + iq->qual;
29188 + iq->updated = 7;
29189 +}
29190 +
29191 +
29192 +/* Structures to export the Wireless Handlers */
29193 +static const iw_handler ath_handlers[] = {
29194 + (iw_handler) NULL, /* SIOCSIWCOMMIT */
29195 + (iw_handler) ar6000_ioctl_giwname, /* SIOCGIWNAME */
29196 + (iw_handler) NULL, /* SIOCSIWNWID */
29197 + (iw_handler) NULL, /* SIOCGIWNWID */
29198 + (iw_handler) ar6000_ioctl_siwfreq, /* SIOCSIWFREQ */
29199 + (iw_handler) ar6000_ioctl_giwfreq, /* SIOCGIWFREQ */
29200 + (iw_handler) ar6000_ioctl_siwmode, /* SIOCSIWMODE */
29201 + (iw_handler) ar6000_ioctl_giwmode, /* SIOCGIWMODE */
29202 + (iw_handler) ar6000_ioctl_siwsens, /* SIOCSIWSENS */
29203 + (iw_handler) ar6000_ioctl_giwsens, /* SIOCGIWSENS */
29204 + (iw_handler) NULL /* not _used */, /* SIOCSIWRANGE */
29205 + (iw_handler) ar6000_ioctl_giwrange, /* SIOCGIWRANGE */
29206 + (iw_handler) NULL /* not used */, /* SIOCSIWPRIV */
29207 + (iw_handler) NULL /* kernel code */, /* SIOCGIWPRIV */
29208 + (iw_handler) NULL /* not used */, /* SIOCSIWSTATS */
29209 + (iw_handler) NULL /* kernel code */, /* SIOCGIWSTATS */
29210 + (iw_handler) NULL, /* SIOCSIWSPY */
29211 + (iw_handler) NULL, /* SIOCGIWSPY */
29212 + (iw_handler) NULL, /* SIOCSIWTHRSPY */
29213 + (iw_handler) NULL, /* SIOCGIWTHRSPY */
29214 + (iw_handler) ar6000_ioctl_siwap, /* SIOCSIWAP */
29215 + (iw_handler) ar6000_ioctl_giwap, /* SIOCGIWAP */
29216 + (iw_handler) NULL, /* -- hole -- */
29217 + (iw_handler) ar6000_ioctl_iwaplist, /* SIOCGIWAPLIST */
29218 + (iw_handler) ar6000_ioctl_siwscan, /* SIOCSIWSCAN */
29219 + (iw_handler) ar6000_ioctl_giwscan, /* SIOCGIWSCAN */
29220 + (iw_handler) ar6000_ioctl_siwessid, /* SIOCSIWESSID */
29221 + (iw_handler) ar6000_ioctl_giwessid, /* SIOCGIWESSID */
29222 + (iw_handler) NULL, /* SIOCSIWNICKN */
29223 + (iw_handler) NULL, /* SIOCGIWNICKN */
29224 + (iw_handler) NULL, /* -- hole -- */
29225 + (iw_handler) NULL, /* -- hole -- */
29226 + (iw_handler) ar6000_ioctl_siwrate, /* SIOCSIWRATE */
29227 + (iw_handler) ar6000_ioctl_giwrate, /* SIOCGIWRATE */
29228 + (iw_handler) NULL, /* SIOCSIWRTS */
29229 + (iw_handler) NULL, /* SIOCGIWRTS */
29230 + (iw_handler) NULL, /* SIOCSIWFRAG */
29231 + (iw_handler) NULL, /* SIOCGIWFRAG */
29232 + (iw_handler) ar6000_ioctl_siwtxpow, /* SIOCSIWTXPOW */
29233 + (iw_handler) ar6000_ioctl_giwtxpow, /* SIOCGIWTXPOW */
29234 + (iw_handler) ar6000_ioctl_siwretry, /* SIOCSIWRETRY */
29235 + (iw_handler) ar6000_ioctl_giwretry, /* SIOCGIWRETRY */
29236 + (iw_handler) ar6000_ioctl_siwencode, /* SIOCSIWENCODE */
29237 + (iw_handler) ar6000_ioctl_giwencode, /* SIOCGIWENCODE */
29238 + (iw_handler) ar6000_ioctl_siwpower, /* SIOCSIWPOWER */
29239 + (iw_handler) ar6000_ioctl_giwpower, /* SIOCGIWPOWER */
29240 + (iw_handler) NULL, /* -- hole -- */
29241 + (iw_handler) NULL, /* -- hole -- */
29242 + (iw_handler) ar6000_ioctl_siwgenie, /* SIOCSIWGENIE */
29243 + (iw_handler) ar6000_ioctl_giwgenie, /* SIOCGIWGENIE */
29244 + (iw_handler) ar6000_ioctl_siwauth, /* SIOCSIWAUTH */
29245 + (iw_handler) ar6000_ioctl_giwauth, /* SIOCGIWAUTH */
29246 + (iw_handler) ar6000_ioctl_siwencodeext,/* SIOCSIWENCODEEXT */
29247 + (iw_handler) ar6000_ioctl_giwencodeext,/* SIOCGIWENCODEEXT */
29248 + (iw_handler) NULL, /* SIOCSIWPMKSA */
29249 +};
29250 +
29251 +static const iw_handler ath_priv_handlers[] = {
29252 + (iw_handler) ar6000_ioctl_setparam, /* SIOCWFIRSTPRIV+0 */
29253 + (iw_handler) ar6000_ioctl_getparam, /* SIOCWFIRSTPRIV+1 */
29254 + (iw_handler) ar6000_ioctl_setkey, /* SIOCWFIRSTPRIV+2 */
29255 + (iw_handler) ar6000_ioctl_setwmmparams, /* SIOCWFIRSTPRIV+3 */
29256 + (iw_handler) ar6000_ioctl_delkey, /* SIOCWFIRSTPRIV+4 */
29257 + (iw_handler) ar6000_ioctl_getwmmparams, /* SIOCWFIRSTPRIV+5 */
29258 + (iw_handler) ar6000_ioctl_setoptie, /* SIOCWFIRSTPRIV+6 */
29259 + (iw_handler) ar6000_ioctl_setmlme, /* SIOCWFIRSTPRIV+7 */
29260 + (iw_handler) ar6000_ioctl_addpmkid, /* SIOCWFIRSTPRIV+8 */
29261 +};
29262 +
29263 +#define IW_PRIV_TYPE_KEY \
29264 + (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_key))
29265 +#define IW_PRIV_TYPE_DELKEY \
29266 + (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_del_key))
29267 +#define IW_PRIV_TYPE_MLME \
29268 + (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_mlme))
29269 +#define IW_PRIV_TYPE_ADDPMKID \
29270 + (IW_PRIV_TYPE_BYTE | sizeof(struct ieee80211req_addpmkid))
29271 +
29272 +static const struct iw_priv_args ar6000_priv_args[] = {
29273 + { IEEE80211_IOCTL_SETKEY,
29274 + IW_PRIV_TYPE_KEY | IW_PRIV_SIZE_FIXED, 0, "setkey"},
29275 + { IEEE80211_IOCTL_DELKEY,
29276 + IW_PRIV_TYPE_DELKEY | IW_PRIV_SIZE_FIXED, 0, "delkey"},
29277 + { IEEE80211_IOCTL_SETPARAM,
29278 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 2, 0, "setparam"},
29279 + { IEEE80211_IOCTL_GETPARAM,
29280 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1,
29281 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getparam"},
29282 + { IEEE80211_IOCTL_SETWMMPARAMS,
29283 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 4, 0, "setwmmparams"},
29284 + { IEEE80211_IOCTL_GETWMMPARAMS,
29285 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 3,
29286 + IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, "getwmmparams"},
29287 + { IEEE80211_IOCTL_SETOPTIE,
29288 + IW_PRIV_TYPE_BYTE, 0, "setie"},
29289 + { IEEE80211_IOCTL_SETMLME,
29290 + IW_PRIV_TYPE_MLME, 0, "setmlme"},
29291 + { IEEE80211_IOCTL_ADDPMKID,
29292 + IW_PRIV_TYPE_ADDPMKID | IW_PRIV_SIZE_FIXED, 0, "addpmkid"},
29293 +};
29294 +
29295 +void ar6000_ioctl_iwsetup(struct iw_handler_def *def)
29296 +{
29297 + def->private_args = (struct iw_priv_args *)ar6000_priv_args;
29298 + def->num_private_args = ARRAY_SIZE(ar6000_priv_args);
29299 +}
29300 +
29301 +struct iw_handler_def ath_iw_handler_def = {
29302 + .standard = (iw_handler *)ath_handlers,
29303 + .num_standard = ARRAY_SIZE(ath_handlers),
29304 + .private = (iw_handler *)ath_priv_handlers,
29305 + .num_private = ARRAY_SIZE(ath_priv_handlers),
29306 +};
29307 +
29308 +
29309 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/bmi/bmi.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/bmi/bmi.c
29310 --- linux-2.6.29-rc3.owrt/drivers/ar6000/bmi/bmi.c 1970-01-01 01:00:00.000000000 +0100
29311 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/bmi/bmi.c 2009-05-10 22:27:59.000000000 +0200
29312 @@ -0,0 +1,657 @@
29313 +/*
29314 + * Copyright (c) 2004-2007 Atheros Communications Inc.
29315 + * All rights reserved.
29316 + *
29317 + *
29318 + * This program is free software; you can redistribute it and/or modify
29319 + * it under the terms of the GNU General Public License version 2 as
29320 + * published by the Free Software Foundation;
29321 + *
29322 + * Software distributed under the License is distributed on an "AS
29323 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
29324 + * implied. See the License for the specific language governing
29325 + * rights and limitations under the License.
29326 + *
29327 + *
29328 + *
29329 + */
29330 +
29331 +#include "hif.h"
29332 +#include "bmi.h"
29333 +#include "htc_api.h"
29334 +#include "bmi_internal.h"
29335 +
29336 +/*
29337 +Although we had envisioned BMI to run on top of HTC, this is not what the
29338 +final implementation boiled down to on dragon. Its a part of BSP and does
29339 +not use the HTC protocol either. On the host side, however, we were still
29340 +living with the original idea. I think the time has come to accept the truth
29341 +and separate it from HTC which has been carrying BMI's burden all this while.
29342 +It shall make HTC state machine relatively simpler
29343 +*/
29344 +
29345 +/* APIs visible to the driver */
29346 +void
29347 +BMIInit(void)
29348 +{
29349 + bmiDone = FALSE;
29350 +}
29351 +
29352 +A_STATUS
29353 +BMIDone(HIF_DEVICE *device)
29354 +{
29355 + A_STATUS status;
29356 + A_UINT32 cid;
29357 +
29358 + if (bmiDone) {
29359 + AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
29360 + return A_OK;
29361 + }
29362 +
29363 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
29364 + bmiDone = TRUE;
29365 + cid = BMI_DONE;
29366 +
29367 + status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
29368 + if (status != A_OK) {
29369 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29370 + return A_ERROR;
29371 + }
29372 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
29373 +
29374 + return A_OK;
29375 +}
29376 +
29377 +A_STATUS
29378 +BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
29379 +{
29380 + A_STATUS status;
29381 + A_UINT32 cid;
29382 +
29383 + if (bmiDone) {
29384 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29385 + return A_ERROR;
29386 + }
29387 +
29388 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
29389 + cid = BMI_GET_TARGET_INFO;
29390 +
29391 + status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
29392 + if (status != A_OK) {
29393 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29394 + return A_ERROR;
29395 + }
29396 +
29397 + status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_ver,
29398 + sizeof(targ_info->target_ver));
29399 + if (status != A_OK) {
29400 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
29401 + return A_ERROR;
29402 + }
29403 +
29404 + if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
29405 + /* Determine how many bytes are in the Target's targ_info */
29406 + status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_info_byte_count,
29407 + sizeof(targ_info->target_info_byte_count));
29408 + if (status != A_OK) {
29409 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
29410 + return A_ERROR;
29411 + }
29412 +
29413 + /*
29414 + * The Target's targ_info doesn't match the Host's targ_info.
29415 + * We need to do some backwards compatibility work to make this OK.
29416 + */
29417 + A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
29418 +
29419 + /* Read the remainder of the targ_info */
29420 + status = bmiBufferReceive(device,
29421 + ((A_UCHAR *)targ_info)+sizeof(targ_info->target_info_byte_count),
29422 + sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count));
29423 + if (status != A_OK) {
29424 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
29425 + targ_info->target_info_byte_count));
29426 + return A_ERROR;
29427 + }
29428 + } else {
29429 + /*
29430 + * Target must be an AR6001 whose firmware does not
29431 + * support BMI_GET_TARGET_INFO. Construct the data
29432 + * that it would have sent.
29433 + */
29434 + targ_info->target_info_byte_count = sizeof(targ_info);
29435 + targ_info->target_type = TARGET_TYPE_AR6001;
29436 + }
29437 +
29438 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
29439 + targ_info->target_ver, targ_info->target_type));
29440 + printk("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
29441 + targ_info->target_ver, targ_info->target_type);
29442 +
29443 + return A_OK;
29444 +}
29445 +
29446 +A_STATUS
29447 +BMIReadMemory(HIF_DEVICE *device,
29448 + A_UINT32 address,
29449 + A_UCHAR *buffer,
29450 + A_UINT32 length)
29451 +{
29452 + A_UINT32 cid;
29453 + A_STATUS status;
29454 + A_UINT32 offset;
29455 + A_UINT32 remaining, rxlen;
29456 + static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)];
29457 + memset (&data, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
29458 +
29459 + if (bmiDone) {
29460 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29461 + return A_ERROR;
29462 + }
29463 +
29464 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29465 + ("BMI Read Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
29466 + device, address, length));
29467 +
29468 + cid = BMI_READ_MEMORY;
29469 +
29470 + remaining = length;
29471 +
29472 + while (remaining)
29473 + {
29474 + rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
29475 + offset = 0;
29476 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29477 + offset += sizeof(cid);
29478 + A_MEMCPY(&data[offset], &address, sizeof(address));
29479 + offset += sizeof(address);
29480 + A_MEMCPY(&data[offset], &rxlen, sizeof(rxlen));
29481 + offset += sizeof(length);
29482 +
29483 + status = bmiBufferSend(device, data, offset);
29484 + if (status != A_OK) {
29485 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29486 + return A_ERROR;
29487 + }
29488 + status = bmiBufferReceive(device, data, rxlen);
29489 + if (status != A_OK) {
29490 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
29491 + return A_ERROR;
29492 + }
29493 + A_MEMCPY(&buffer[length - remaining], data, rxlen);
29494 + remaining -= rxlen; address += rxlen;
29495 + }
29496 +
29497 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
29498 + return A_OK;
29499 +}
29500 +
29501 +A_STATUS
29502 +BMIWriteMemory(HIF_DEVICE *device,
29503 + A_UINT32 address,
29504 + A_UCHAR *buffer,
29505 + A_UINT32 length)
29506 +{
29507 + A_UINT32 cid;
29508 + A_STATUS status;
29509 + A_UINT32 offset;
29510 + A_UINT32 remaining, txlen;
29511 + const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length);
29512 + static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)];
29513 + memset (&data, 0, header);
29514 +
29515 + if (bmiDone) {
29516 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29517 + return A_ERROR;
29518 + }
29519 +
29520 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29521 + ("BMI Write Memory: Enter (device: 0x%p, address: 0x%x, length: %d)\n",
29522 + device, address, length));
29523 +
29524 + cid = BMI_WRITE_MEMORY;
29525 +
29526 + remaining = length;
29527 + while (remaining)
29528 + {
29529 + txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
29530 + remaining : (BMI_DATASZ_MAX - header);
29531 + offset = 0;
29532 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29533 + offset += sizeof(cid);
29534 + A_MEMCPY(&data[offset], &address, sizeof(address));
29535 + offset += sizeof(address);
29536 + A_MEMCPY(&data[offset], &txlen, sizeof(txlen));
29537 + offset += sizeof(txlen);
29538 + A_MEMCPY(&data[offset], &buffer[length - remaining], txlen);
29539 + offset += txlen;
29540 + status = bmiBufferSend(device, data, offset);
29541 + if (status != A_OK) {
29542 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29543 + return A_ERROR;
29544 + }
29545 + remaining -= txlen; address += txlen;
29546 + }
29547 +
29548 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
29549 +
29550 + return A_OK;
29551 +}
29552 +
29553 +A_STATUS
29554 +BMIExecute(HIF_DEVICE *device,
29555 + A_UINT32 address,
29556 + A_UINT32 *param)
29557 +{
29558 + A_UINT32 cid;
29559 + A_STATUS status;
29560 + A_UINT32 offset;
29561 + static A_UCHAR data[sizeof(cid) + sizeof(address) + sizeof(*param)];
29562 + memset (&data, 0, sizeof(cid) + sizeof(address) + sizeof(*param));
29563 +
29564 + if (bmiDone) {
29565 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29566 + return A_ERROR;
29567 + }
29568 +
29569 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29570 + ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
29571 + device, address, *param));
29572 +
29573 + cid = BMI_EXECUTE;
29574 +
29575 + offset = 0;
29576 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29577 + offset += sizeof(cid);
29578 + A_MEMCPY(&data[offset], &address, sizeof(address));
29579 + offset += sizeof(address);
29580 + A_MEMCPY(&data[offset], param, sizeof(*param));
29581 + offset += sizeof(*param);
29582 + status = bmiBufferSend(device, data, offset);
29583 + if (status != A_OK) {
29584 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29585 + return A_ERROR;
29586 + }
29587 +
29588 + status = bmiBufferReceive(device, data, sizeof(*param));
29589 + if (status != A_OK) {
29590 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
29591 + return A_ERROR;
29592 + }
29593 +
29594 + A_MEMCPY(param, data, sizeof(*param));
29595 +
29596 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
29597 + return A_OK;
29598 +}
29599 +
29600 +A_STATUS
29601 +BMISetAppStart(HIF_DEVICE *device,
29602 + A_UINT32 address)
29603 +{
29604 + A_UINT32 cid;
29605 + A_STATUS status;
29606 + A_UINT32 offset;
29607 + static A_UCHAR data[sizeof(cid) + sizeof(address)];
29608 + memset (&data, 0, sizeof(cid) + sizeof(address));
29609 +
29610 + if (bmiDone) {
29611 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29612 + return A_ERROR;
29613 + }
29614 +
29615 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29616 + ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
29617 + device, address));
29618 +
29619 + cid = BMI_SET_APP_START;
29620 +
29621 + offset = 0;
29622 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29623 + offset += sizeof(cid);
29624 + A_MEMCPY(&data[offset], &address, sizeof(address));
29625 + offset += sizeof(address);
29626 + status = bmiBufferSend(device, data, offset);
29627 + if (status != A_OK) {
29628 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29629 + return A_ERROR;
29630 + }
29631 +
29632 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
29633 + return A_OK;
29634 +}
29635 +
29636 +A_STATUS
29637 +BMIReadSOCRegister(HIF_DEVICE *device,
29638 + A_UINT32 address,
29639 + A_UINT32 *param)
29640 +{
29641 + A_UINT32 cid;
29642 + A_STATUS status;
29643 + A_UINT32 offset;
29644 + static A_UCHAR data[sizeof(cid) + sizeof(address)];
29645 + memset (&data, 0, sizeof(cid) + sizeof(address));
29646 +
29647 + if (bmiDone) {
29648 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29649 + return A_ERROR;
29650 + }
29651 +
29652 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29653 + ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
29654 + device, address));
29655 +
29656 + cid = BMI_READ_SOC_REGISTER;
29657 +
29658 + offset = 0;
29659 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29660 + offset += sizeof(cid);
29661 + A_MEMCPY(&data[offset], &address, sizeof(address));
29662 + offset += sizeof(address);
29663 +
29664 + status = bmiBufferSend(device, data, offset);
29665 + if (status != A_OK) {
29666 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29667 + return A_ERROR;
29668 + }
29669 +
29670 + status = bmiBufferReceive(device, data, sizeof(*param));
29671 + if (status != A_OK) {
29672 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
29673 + return A_ERROR;
29674 + }
29675 + A_MEMCPY(param, data, sizeof(*param));
29676 +
29677 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
29678 + return A_OK;
29679 +}
29680 +
29681 +A_STATUS
29682 +BMIWriteSOCRegister(HIF_DEVICE *device,
29683 + A_UINT32 address,
29684 + A_UINT32 param)
29685 +{
29686 + A_UINT32 cid;
29687 + A_STATUS status;
29688 + A_UINT32 offset;
29689 + static A_UCHAR data[sizeof(cid) + sizeof(address) + sizeof(param)];
29690 +
29691 + memset (&data, 0, sizeof(cid) + sizeof(address) + sizeof(param));
29692 +
29693 + if (bmiDone) {
29694 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29695 + return A_ERROR;
29696 + }
29697 +
29698 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29699 + ("BMI Write SOC Register: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
29700 + device, address, param));
29701 +
29702 + cid = BMI_WRITE_SOC_REGISTER;
29703 +
29704 + offset = 0;
29705 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29706 + offset += sizeof(cid);
29707 + A_MEMCPY(&data[offset], &address, sizeof(address));
29708 + offset += sizeof(address);
29709 + A_MEMCPY(&data[offset], &param, sizeof(param));
29710 + offset += sizeof(param);
29711 + status = bmiBufferSend(device, data, offset);
29712 + if (status != A_OK) {
29713 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29714 + return A_ERROR;
29715 + }
29716 +
29717 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
29718 + return A_OK;
29719 +}
29720 +
29721 +A_STATUS
29722 +BMIrompatchInstall(HIF_DEVICE *device,
29723 + A_UINT32 ROM_addr,
29724 + A_UINT32 RAM_addr,
29725 + A_UINT32 nbytes,
29726 + A_UINT32 do_activate,
29727 + A_UINT32 *rompatch_id)
29728 +{
29729 + A_UINT32 cid;
29730 + A_STATUS status;
29731 + A_UINT32 offset;
29732 + static A_UCHAR data[sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
29733 + sizeof(nbytes) + sizeof(do_activate)];
29734 +
29735 + memset (&data, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
29736 + sizeof(nbytes) + sizeof(do_activate));
29737 +
29738 + if (bmiDone) {
29739 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29740 + return A_ERROR;
29741 + }
29742 +
29743 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29744 + ("BMI rompatch Install: Enter (device: 0x%p, ROMaddr: 0x%x, RAMaddr: 0x%x length: %d activate: %d)\n",
29745 + device, ROM_addr, RAM_addr, nbytes, do_activate));
29746 +
29747 + cid = BMI_ROMPATCH_INSTALL;
29748 +
29749 + offset = 0;
29750 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29751 + offset += sizeof(cid);
29752 + A_MEMCPY(&data[offset], &ROM_addr, sizeof(ROM_addr));
29753 + offset += sizeof(ROM_addr);
29754 + A_MEMCPY(&data[offset], &RAM_addr, sizeof(RAM_addr));
29755 + offset += sizeof(RAM_addr);
29756 + A_MEMCPY(&data[offset], &nbytes, sizeof(nbytes));
29757 + offset += sizeof(nbytes);
29758 + A_MEMCPY(&data[offset], &do_activate, sizeof(do_activate));
29759 + offset += sizeof(do_activate);
29760 + status = bmiBufferSend(device, data, offset);
29761 + if (status != A_OK) {
29762 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29763 + return A_ERROR;
29764 + }
29765 +
29766 + status = bmiBufferReceive(device, (A_UCHAR *)rompatch_id, sizeof(*rompatch_id));
29767 + if (status != A_OK) {
29768 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
29769 + return A_ERROR;
29770 + }
29771 +
29772 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
29773 + return A_OK;
29774 +}
29775 +
29776 +A_STATUS
29777 +BMIrompatchUninstall(HIF_DEVICE *device,
29778 + A_UINT32 rompatch_id)
29779 +{
29780 + A_UINT32 cid;
29781 + A_STATUS status;
29782 + A_UINT32 offset;
29783 + static A_UCHAR data[sizeof(cid) + sizeof(rompatch_id)];
29784 + memset (&data, 0, sizeof(cid) + sizeof(rompatch_id));
29785 +
29786 + if (bmiDone) {
29787 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29788 + return A_ERROR;
29789 + }
29790 +
29791 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29792 + ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
29793 + device, rompatch_id));
29794 +
29795 + cid = BMI_ROMPATCH_UNINSTALL;
29796 +
29797 + offset = 0;
29798 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29799 + offset += sizeof(cid);
29800 + A_MEMCPY(&data[offset], &rompatch_id, sizeof(rompatch_id));
29801 + offset += sizeof(rompatch_id);
29802 + status = bmiBufferSend(device, data, offset);
29803 + if (status != A_OK) {
29804 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29805 + return A_ERROR;
29806 + }
29807 +
29808 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
29809 + return A_OK;
29810 +}
29811 +
29812 +static A_STATUS
29813 +_BMIrompatchChangeActivation(HIF_DEVICE *device,
29814 + A_UINT32 rompatch_count,
29815 + A_UINT32 *rompatch_list,
29816 + A_UINT32 do_activate)
29817 +{
29818 + A_UINT32 cid;
29819 + A_STATUS status;
29820 + A_UINT32 offset;
29821 + static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)];
29822 + A_UINT32 length;
29823 +
29824 + memset (&data, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
29825 +
29826 + if (bmiDone) {
29827 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29828 + return A_ERROR;
29829 + }
29830 +
29831 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29832 + ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
29833 + device, rompatch_count));
29834 +
29835 + cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
29836 +
29837 + offset = 0;
29838 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29839 + offset += sizeof(cid);
29840 + A_MEMCPY(&data[offset], &rompatch_count, sizeof(rompatch_count));
29841 + offset += sizeof(rompatch_count);
29842 + length = rompatch_count * sizeof(*rompatch_list);
29843 + A_MEMCPY(&data[offset], rompatch_list, length);
29844 + offset += length;
29845 + status = bmiBufferSend(device, data, offset);
29846 + if (status != A_OK) {
29847 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
29848 + return A_ERROR;
29849 + }
29850 +
29851 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
29852 +
29853 + return A_OK;
29854 +}
29855 +
29856 +A_STATUS
29857 +BMIrompatchActivate(HIF_DEVICE *device,
29858 + A_UINT32 rompatch_count,
29859 + A_UINT32 *rompatch_list)
29860 +{
29861 + return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
29862 +}
29863 +
29864 +A_STATUS
29865 +BMIrompatchDeactivate(HIF_DEVICE *device,
29866 + A_UINT32 rompatch_count,
29867 + A_UINT32 *rompatch_list)
29868 +{
29869 + return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
29870 +}
29871 +
29872 +/* BMI Access routines */
29873 +A_STATUS
29874 +bmiBufferSend(HIF_DEVICE *device,
29875 + A_UCHAR *buffer,
29876 + A_UINT32 length)
29877 +{
29878 + A_STATUS status;
29879 + A_UINT32 timeout;
29880 + A_UINT32 address;
29881 + static A_UINT32 cmdCredits;
29882 + A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
29883 +
29884 + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
29885 + &mboxAddress, sizeof(mboxAddress));
29886 +
29887 + cmdCredits = 0;
29888 + timeout = BMI_COMMUNICATION_TIMEOUT;
29889 +
29890 + while(timeout-- && !cmdCredits) {
29891 + /* Read the counter register to get the command credits */
29892 + address = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
29893 + /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
29894 + * a decrement, while the remaining 3 bytes has no effect. The rationale behind this is to
29895 + * make all HIF accesses 4-byte aligned */
29896 + status = HIFReadWrite(device, address, (A_UINT8 *)&cmdCredits, 4,
29897 + HIF_RD_SYNC_BYTE_INC, NULL);
29898 + if (status != A_OK) {
29899 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
29900 + return A_ERROR;
29901 + }
29902 + /* the counter is only 8=bits, ignore anything in the upper 3 bytes */
29903 + cmdCredits &= 0xFF;
29904 + }
29905 +
29906 + if (cmdCredits) {
29907 + address = mboxAddress[ENDPOINT1];
29908 + status = HIFReadWrite(device, address, buffer, length,
29909 + HIF_WR_SYNC_BYTE_INC, NULL);
29910 + if (status != A_OK) {
29911 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
29912 + return A_ERROR;
29913 + }
29914 + } else {
29915 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout\n"));
29916 + return A_ERROR;
29917 + }
29918 +
29919 + return status;
29920 +}
29921 +
29922 +A_STATUS
29923 +bmiBufferReceive(HIF_DEVICE *device,
29924 + A_UCHAR *buffer,
29925 + A_UINT32 length)
29926 +{
29927 + A_STATUS status;
29928 + A_UINT32 address;
29929 + A_UINT32 timeout;
29930 + static A_UINT32 cmdCredits;
29931 + A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
29932 +
29933 + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
29934 + &mboxAddress, sizeof(mboxAddress));
29935 +
29936 + cmdCredits = 0;
29937 + timeout = BMI_COMMUNICATION_TIMEOUT;
29938 + while(timeout-- && !cmdCredits) {
29939 + /* Read the counter register to get the command credits */
29940 + address = COUNT_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 1;
29941 + /* read the counter using a 4-byte read. Since the counter is NOT auto-decrementing,
29942 + * we can read this counter multiple times using a non-incrementing address mode.
29943 + * The rationale here is to make all HIF accesses a multiple of 4 bytes */
29944 + status = HIFReadWrite(device, address, (A_UINT8 *)&cmdCredits, sizeof(cmdCredits),
29945 + HIF_RD_SYNC_BYTE_FIX, NULL);
29946 + if (status != A_OK) {
29947 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
29948 + return A_ERROR;
29949 + }
29950 + /* we did a 4-byte read to the same count register so mask off upper bytes */
29951 + cmdCredits &= 0xFF;
29952 + status = A_ERROR;
29953 + }
29954 +
29955 + if (cmdCredits) {
29956 + address = mboxAddress[ENDPOINT1];
29957 + status = HIFReadWrite(device, address, buffer, length,
29958 + HIF_RD_SYNC_BYTE_INC, NULL);
29959 + if (status != A_OK) {
29960 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
29961 + return A_ERROR;
29962 + }
29963 + } else {
29964 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Communication timeout\n"));
29965 + return A_ERROR;
29966 + }
29967 +
29968 + return status;
29969 +}
29970 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/bmi/bmi_internal.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/bmi/bmi_internal.h
29971 --- linux-2.6.29-rc3.owrt/drivers/ar6000/bmi/bmi_internal.h 1970-01-01 01:00:00.000000000 +0100
29972 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/bmi/bmi_internal.h 2009-05-10 22:27:59.000000000 +0200
29973 @@ -0,0 +1,45 @@
29974 +#ifndef BMI_INTERNAL_H
29975 +#define BMI_INTERNAL_H
29976 +/*
29977 + *
29978 + * Copyright (c) 2004-2007 Atheros Communications Inc.
29979 + * All rights reserved.
29980 + *
29981 + *
29982 + * This program is free software; you can redistribute it and/or modify
29983 + * it under the terms of the GNU General Public License version 2 as
29984 + * published by the Free Software Foundation;
29985 + *
29986 + * Software distributed under the License is distributed on an "AS
29987 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
29988 + * implied. See the License for the specific language governing
29989 + * rights and limitations under the License.
29990 + *
29991 + *
29992 + *
29993 + */
29994 +
29995 +#include "a_config.h"
29996 +#include "athdefs.h"
29997 +#include "a_types.h"
29998 +#include "a_osapi.h"
29999 +#include "a_debug.h"
30000 +#include "AR6Khwreg.h"
30001 +#include "bmi_msg.h"
30002 +
30003 +#define BMI_COMMUNICATION_TIMEOUT 100000
30004 +
30005 +/* ------ Global Variable Declarations ------- */
30006 +A_BOOL bmiDone;
30007 +
30008 +A_STATUS
30009 +bmiBufferSend(HIF_DEVICE *device,
30010 + A_UCHAR *buffer,
30011 + A_UINT32 length);
30012 +
30013 +A_STATUS
30014 +bmiBufferReceive(HIF_DEVICE *device,
30015 + A_UCHAR *buffer,
30016 + A_UINT32 length);
30017 +
30018 +#endif
30019 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/hif/hif2.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/hif/hif2.c
30020 --- linux-2.6.29-rc3.owrt/drivers/ar6000/hif/hif2.c 1970-01-01 01:00:00.000000000 +0100
30021 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/hif/hif2.c 2009-05-10 22:27:59.000000000 +0200
30022 @@ -0,0 +1,768 @@
30023 +/*
30024 + * hif2.c - HIF layer re-implementation for the Linux SDIO stack
30025 + *
30026 + * Copyright (C) 2008, 2009 by OpenMoko, Inc.
30027 + * Written by Werner Almesberger <werner@openmoko.org>
30028 + * All Rights Reserved
30029 + *
30030 + * This program is free software; you can redistribute it and/or modify
30031 + * it under the terms of the GNU General Public License version 2 as
30032 + * published by the Free Software Foundation;
30033 + *
30034 + * Based on:
30035 + *
30036 + * @abstract: HIF layer reference implementation for Atheros SDIO stack
30037 + * @notice: Copyright (c) 2004-2006 Atheros Communications Inc.
30038 + */
30039 +
30040 +
30041 +#include <linux/kernel.h>
30042 +#include <linux/kthread.h>
30043 +#include <linux/list.h>
30044 +#include <linux/wait.h>
30045 +#include <linux/spinlock.h>
30046 +#include <linux/mutex.h>
30047 +#include <linux/sched.h>
30048 +#include <linux/mmc/sdio_func.h>
30049 +#include <linux/mmc/sdio.h>
30050 +#include <linux/mmc/sdio_ids.h>
30051 +
30052 +#include "athdefs.h"
30053 +#include "a_types.h"
30054 +#include "hif.h"
30055 +
30056 +
30057 +/* @@@ Hack - this wants cleaning up */
30058 +
30059 +#ifdef CONFIG_MACH_NEO1973_GTA02
30060 +
30061 +#include <mach/gta02-pm-wlan.h>
30062 +
30063 +#else /* CONFIG_MACH_NEO1973_GTA02 */
30064 +
30065 +#define gta02_wlan_query_rfkill_lock() 1
30066 +#define gta02_wlan_set_rfkill_cb(cb, hif) ((void) cb)
30067 +#define gta02_wlan_query_rfkill_unlock()
30068 +#define gta02_wlan_clear_rfkill_cb()
30069 +
30070 +#endif /* !CONFIG_MACH_NEO1973_GTA02 */
30071 +
30072 +
30073 +/*
30074 + * KNOWN BUGS:
30075 + *
30076 + * - HIF_DEVICE_IRQ_ASYNC_SYNC doesn't work yet (gets MMC errors)
30077 + * - latency can reach hundreds of ms, probably because of scheduling delays
30078 + * - packets go through about three queues before finally hitting the network
30079 + */
30080 +
30081 +/*
30082 + * Differences from Atheros' HIFs:
30083 + *
30084 + * - synchronous and asynchronous requests may get reordered with respect to
30085 + * each other, e.g., if HIFReadWrite returns for an asynchronous request and
30086 + * then HIFReadWrite is called for a synchronous request, the synchronous
30087 + * request may be executed before the asynchronous request.
30088 + *
30089 + * - request queue locking seems unnecessarily complex in the Atheros HIFs.
30090 + *
30091 + * - Atheros mask interrupts by calling sdio_claim_irq/sdio_release_irq, which
30092 + * can cause quite a bit of overhead. This HIF has its own light-weight
30093 + * interrupt masking.
30094 + *
30095 + * - Atheros call deviceInsertedHandler from a thread spawned off the probe or
30096 + * device insertion function. The original explanation for the Atheros SDIO
30097 + * stack said that this is done because a delay is needed to let the chip
30098 + * complete initialization. There is indeed a one second delay in the thread.
30099 + *
30100 + * The Atheros Linux SDIO HIF removes the delay and only retains the thread.
30101 + * Experimentally removing the thread didn't show any conflicts, so let's get
30102 + * rid of it for good.
30103 + *
30104 + * - The Atheros SDIO stack with Samuel's driver sets SDIO_CCCR_POWER in
30105 + * SDIO_POWER_EMPC. Atheros' Linux SDIO code apparently doesn't. We don't
30106 + * either, and this seems to work fine.
30107 + * @@@ Need to check this with Atheros.
30108 + */
30109 +
30110 +
30111 +#define MBOXES 4
30112 +
30113 +#define HIF_MBOX_BLOCK_SIZE 128
30114 +#define HIF_MBOX_BASE_ADDR 0x800
30115 +#define HIF_MBOX_WIDTH 0x800
30116 +#define HIF_MBOX_START_ADDR(mbox) \
30117 + (HIF_MBOX_BASE_ADDR+(mbox)*HIF_MBOX_WIDTH)
30118 +
30119 +
30120 +struct hif_device {
30121 + void *htc_handle;
30122 + struct sdio_func *func;
30123 +
30124 + /*
30125 + * @@@ our sweet little bit of bogosity - the mechanism that lets us
30126 + * use the SDIO stack from softirqs. This really wants to use skbs.
30127 + */
30128 + struct list_head queue;
30129 + spinlock_t queue_lock;
30130 + struct task_struct *io_task;
30131 + wait_queue_head_t wait;
30132 +
30133 + /*
30134 + * activate_lock protects "active" and the activation/deactivation
30135 + * process itself.
30136 + *
30137 + * Relation to other locks: The SDIO function can be claimed while
30138 + * activate_lock is being held, but trying to acquire activate_lock
30139 + * while having ownership of the SDIO function could cause a deadlock.
30140 + */
30141 + int active;
30142 + struct mutex activate_lock;
30143 +};
30144 +
30145 +struct hif_request {
30146 + struct list_head list;
30147 + struct sdio_func *func;
30148 + int (*read)(struct sdio_func *func,
30149 + void *dst, unsigned int addr, int count);
30150 + int (*write)(struct sdio_func *func,
30151 + unsigned int addr, void *src, int count);
30152 + void *buf;
30153 + unsigned long addr;
30154 + int len;
30155 + A_STATUS (*completion)(void *context, A_STATUS status);
30156 + void *context;
30157 +};
30158 +
30159 +
30160 +static HTC_CALLBACKS htcCallbacks;
30161 +
30162 +/*
30163 + * shutdown_lock prevents recursion through HIFShutDownDevice
30164 + */
30165 +static DEFINE_MUTEX(shutdown_lock);
30166 +
30167 +
30168 +/* ----- Request processing ------------------------------------------------ */
30169 +
30170 +
30171 +static A_STATUS process_request(struct hif_request *req)
30172 +{
30173 + int ret;
30174 + A_STATUS status;
30175 +
30176 + dev_dbg(&req->func->dev, "process_request(req %p)\n", req);
30177 + sdio_claim_host(req->func);
30178 + if (req->read) {
30179 + ret = req->read(req->func, req->buf, req->addr, req->len);
30180 + } else {
30181 + ret = req->write(req->func, req->addr, req->buf, req->len);
30182 + }
30183 + sdio_release_host(req->func);
30184 + status = ret ? A_ERROR : A_OK;
30185 + if (req->completion)
30186 + req->completion(req->context, status);
30187 + kfree(req);
30188 + return status;
30189 +}
30190 +
30191 +
30192 +static void enqueue_request(struct hif_device *hif, struct hif_request *req)
30193 +{
30194 + unsigned long flags;
30195 +
30196 + dev_dbg(&req->func->dev, "enqueue_request(req %p)\n", req);
30197 + spin_lock_irqsave(&hif->queue_lock, flags);
30198 + list_add_tail(&req->list, &hif->queue);
30199 + spin_unlock_irqrestore(&hif->queue_lock, flags);
30200 + wake_up(&hif->wait);
30201 +}
30202 +
30203 +
30204 +static struct hif_request *dequeue_request(struct hif_device *hif)
30205 +{
30206 + struct hif_request *req;
30207 + unsigned long flags;
30208 +
30209 + spin_lock_irqsave(&hif->queue_lock, flags);
30210 + if (list_empty(&hif->queue))
30211 + req = NULL;
30212 + else {
30213 + req = list_first_entry(&hif->queue,
30214 + struct hif_request, list);
30215 + list_del(&req->list);
30216 + }
30217 + spin_unlock_irqrestore(&hif->queue_lock, flags);
30218 + return req;
30219 +}
30220 +
30221 +
30222 +static void wait_queue_empty(struct hif_device *hif)
30223 +{
30224 + unsigned long flags;
30225 + int empty;
30226 +
30227 + while (1) {
30228 + spin_lock_irqsave(&hif->queue_lock, flags);
30229 + empty = list_empty(&hif->queue);
30230 + spin_unlock_irqrestore(&hif->queue_lock, flags);
30231 + if (empty)
30232 + break;
30233 + else
30234 + yield();
30235 + }
30236 +}
30237 +
30238 +
30239 +static int io(void *data)
30240 +{
30241 + struct hif_device *hif = data;
30242 + struct sched_param param = { .sched_priority = 2 };
30243 + /* one priority level slower than ksdioirqd (which is at 1) */
30244 + DEFINE_WAIT(wait);
30245 + struct hif_request *req;
30246 +
30247 + sched_setscheduler(current, SCHED_FIFO, &param);
30248 +
30249 + while (1) {
30250 + while (1) {
30251 + /*
30252 + * Since we never use signals here, one might think
30253 + * that this ought to be TASK_UNINTERRUPTIBLE. However,
30254 + * such a task would increase the load average and,
30255 + * worse, it would trigger the softlockup check.
30256 + */
30257 + prepare_to_wait(&hif->wait, &wait, TASK_INTERRUPTIBLE);
30258 + if (kthread_should_stop()) {
30259 + finish_wait(&hif->wait, &wait);
30260 + return 0;
30261 + }
30262 + req = dequeue_request(hif);
30263 + if (req)
30264 + break;
30265 + schedule();
30266 + }
30267 + finish_wait(&hif->wait, &wait);
30268 +
30269 + (void) process_request(req);
30270 + }
30271 + return 0;
30272 +}
30273 +
30274 +
30275 +A_STATUS HIFReadWrite(HIF_DEVICE *hif, A_UINT32 address, A_UCHAR *buffer,
30276 + A_UINT32 length, A_UINT32 request, void *context)
30277 +{
30278 + struct device *dev = HIFGetOSDevice(hif);
30279 + struct hif_request *req;
30280 +
30281 + dev_dbg(dev, "HIFReadWrite(device %p, address 0x%x, buffer %p, "
30282 + "length %d, request 0x%x, context %p)\n",
30283 + hif, address, buffer, length, request, context);
30284 +
30285 + BUG_ON(!(request & (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS)));
30286 + BUG_ON(!(request & (HIF_BYTE_BASIS | HIF_BLOCK_BASIS)));
30287 + BUG_ON(!(request & (HIF_READ | HIF_WRITE)));
30288 + BUG_ON(!(request & HIF_EXTENDED_IO));
30289 +
30290 + if (address >= HIF_MBOX_START_ADDR(0) &&
30291 + address < HIF_MBOX_START_ADDR(MBOXES+1)) {
30292 + BUG_ON(length > HIF_MBOX_WIDTH);
30293 + /* Adjust the address so that the last byte falls on the EOM
30294 + address. */
30295 + address += HIF_MBOX_WIDTH-length;
30296 + }
30297 +
30298 + req = kzalloc(sizeof(*req), GFP_ATOMIC);
30299 + if (!req) {
30300 + if (request & HIF_ASYNCHRONOUS)
30301 + htcCallbacks.rwCompletionHandler(context, A_ERROR);
30302 + return A_ERROR;
30303 + }
30304 +
30305 + req->func = hif->func;
30306 + req->addr = address;
30307 + req->buf = buffer;
30308 + req->len = length;
30309 +
30310 + if (request & HIF_READ) {
30311 + if (request & HIF_FIXED_ADDRESS)
30312 + req->read = sdio_readsb;
30313 + else
30314 + req->read = sdio_memcpy_fromio;
30315 + } else {
30316 + if (request & HIF_FIXED_ADDRESS)
30317 + req->write = sdio_writesb;
30318 + else
30319 + req->write = sdio_memcpy_toio;
30320 + }
30321 +
30322 + if (!(request & HIF_ASYNCHRONOUS))
30323 + return process_request(req);
30324 +
30325 + req->completion = htcCallbacks.rwCompletionHandler;
30326 + req->context = context;
30327 + enqueue_request(hif, req);
30328 +
30329 + return A_OK;
30330 +}
30331 +
30332 +
30333 +/* ----- Interrupt handling ------------------------------------------------ */
30334 +
30335 +/*
30336 + * Volatile ought to be good enough to make gcc do the right thing on S3C24xx.
30337 + * No need to use atomic or put barriers, keeping the code more readable.
30338 + *
30339 + * Warning: this story changes if going SMP/SMT.
30340 + */
30341 +
30342 +static volatile int masked = 1;
30343 +static volatile int pending;
30344 +static volatile int in_interrupt;
30345 +
30346 +
30347 +static void ar6000_do_irq(struct sdio_func *func)
30348 +{
30349 + HIF_DEVICE *hif = sdio_get_drvdata(func);
30350 + struct device *dev = HIFGetOSDevice(hif);
30351 + A_STATUS status;
30352 +
30353 + dev_dbg(dev, "ar6000_do_irq -> %p\n", htcCallbacks.dsrHandler);
30354 +
30355 + status = htcCallbacks.dsrHandler(hif->htc_handle);
30356 + BUG_ON(status != A_OK);
30357 +}
30358 +
30359 +
30360 +static void sdio_ar6000_irq(struct sdio_func *func)
30361 +{
30362 + HIF_DEVICE *hif = sdio_get_drvdata(func);
30363 + struct device *dev = HIFGetOSDevice(hif);
30364 +
30365 + dev_dbg(dev, "sdio_ar6000_irq\n");
30366 +
30367 + in_interrupt = 1;
30368 + if (masked) {
30369 + in_interrupt = 0;
30370 + pending++;
30371 + return;
30372 + }
30373 + /*
30374 + * @@@ This is ugly. If we don't drop the lock, we'll deadlock when
30375 + * the handler tries to do SDIO. So there are four choices:
30376 + *
30377 + * 1) Break the call chain by calling the callback from a workqueue.
30378 + * Ugh.
30379 + * 2) Make process_request aware that we already have the lock.
30380 + * 3) Drop the lock. Which is ugly but should be safe as long as we're
30381 + * making sure the device doesn't go away.
30382 + * 4) Change the AR6k driver such that it only issues asynchronous
30383 + * quests when called from an interrupt.
30384 + *
30385 + * Solution 2) is probably the best for now. Will try it later.
30386 + */
30387 + sdio_release_host(func);
30388 + ar6000_do_irq(func);
30389 + sdio_claim_host(func);
30390 + in_interrupt = 0;
30391 +}
30392 +
30393 +
30394 +void HIFAckInterrupt(HIF_DEVICE *hif)
30395 +{
30396 + struct device *dev = HIFGetOSDevice(hif);
30397 +
30398 + dev_dbg(dev, "HIFAckInterrupt\n");
30399 + /* do nothing */
30400 +}
30401 +
30402 +
30403 +void HIFUnMaskInterrupt(HIF_DEVICE *hif)
30404 +{
30405 + struct device *dev = HIFGetOSDevice(hif);
30406 +
30407 + dev_dbg(dev, "HIFUnMaskInterrupt\n");
30408 + do {
30409 + masked = 1;
30410 + if (pending) {
30411 + pending = 0;
30412 + ar6000_do_irq(hif->func);
30413 + /* We may take an interrupt before unmasking and thus
30414 + get it pending. In this case, we just loop back. */
30415 + }
30416 + masked = 0;
30417 + }
30418 + while (pending);
30419 +}
30420 +
30421 +
30422 +void HIFMaskInterrupt(HIF_DEVICE *hif)
30423 +{
30424 + struct device *dev = HIFGetOSDevice(hif);
30425 +
30426 + dev_dbg(dev, "HIFMaskInterrupt\n");
30427 + /*
30428 + * Since sdio_ar6000_irq can also be called from a process context, we
30429 + * may conceivably end up racing with it. Thus, we need to wait until
30430 + * we can be sure that no concurrent interrupt processing is going on
30431 + * before we return.
30432 + *
30433 + * Note: this may be a bit on the paranoid side - the callers may
30434 + * actually be nice enough to disable scheduling. Check later.
30435 + */
30436 + masked = 1;
30437 + while (in_interrupt)
30438 + yield();
30439 +}
30440 +
30441 +
30442 +/* ----- HIF API glue functions -------------------------------------------- */
30443 +
30444 +
30445 +struct device *HIFGetOSDevice(HIF_DEVICE *hif)
30446 +{
30447 + return &hif->func->dev;
30448 +}
30449 +
30450 +
30451 +void HIFSetHandle(void *hif_handle, void *handle)
30452 +{
30453 + HIF_DEVICE *hif = (HIF_DEVICE *) hif_handle;
30454 +
30455 + hif->htc_handle = handle;
30456 +}
30457 +
30458 +
30459 +/* ----- Device configuration (HIF side) ----------------------------------- */
30460 +
30461 +
30462 +A_STATUS HIFConfigureDevice(HIF_DEVICE *hif,
30463 + HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen)
30464 +{
30465 + struct device *dev = HIFGetOSDevice(hif);
30466 + HIF_DEVICE_IRQ_PROCESSING_MODE *ipm_cfg = config;
30467 + A_UINT32 *mbs_cfg = config;
30468 + int i;
30469 +
30470 + dev_dbg(dev, "HIFConfigureDevice\n");
30471 +
30472 + switch (opcode) {
30473 + case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
30474 + for (i = 0; i != MBOXES; i++)
30475 + mbs_cfg[i] = HIF_MBOX_BLOCK_SIZE;
30476 + break;
30477 + case HIF_DEVICE_GET_MBOX_ADDR:
30478 + for (i = 0; i != MBOXES; i++)
30479 + mbs_cfg[i] = HIF_MBOX_START_ADDR(i);
30480 + break;
30481 + case HIF_DEVICE_GET_IRQ_PROC_MODE:
30482 + *ipm_cfg = HIF_DEVICE_IRQ_SYNC_ONLY;
30483 +// *ipm_cfg = HIF_DEVICE_IRQ_ASYNC_SYNC;
30484 + break;
30485 + default:
30486 + return A_ERROR;
30487 + }
30488 + return A_OK;
30489 +}
30490 +
30491 +
30492 +/* ----- Device probe and removal (Linux side) ----------------------------- */
30493 +
30494 +
30495 +static int ar6000_do_activate(struct hif_device *hif)
30496 +{
30497 + struct sdio_func *func = hif->func;
30498 + struct device *dev = &func->dev;
30499 + int ret;
30500 +
30501 + dev_dbg(dev, "ar6000_do_activate\n");
30502 +
30503 + sdio_claim_host(func);
30504 + sdio_enable_func(func);
30505 +
30506 + INIT_LIST_HEAD(&hif->queue);
30507 + init_waitqueue_head(&hif->wait);
30508 + spin_lock_init(&hif->queue_lock);
30509 +
30510 + ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
30511 + if (ret < 0) {
30512 + dev_err(dev, "sdio_set_block_size returns %d\n", ret);
30513 + goto out_enabled;
30514 + }
30515 + ret = sdio_claim_irq(func, sdio_ar6000_irq);
30516 + if (ret) {
30517 + dev_err(dev, "sdio_claim_irq returns %d\n", ret);
30518 + goto out_enabled;
30519 + }
30520 + /* Set SDIO_BUS_CD_DISABLE in SDIO_CCCR_IF ? */
30521 +#if 0
30522 + sdio_f0_writeb(func, SDIO_CCCR_CAP_E4MI, SDIO_CCCR_CAPS, &ret);
30523 + if (ret) {
30524 + dev_err(dev, "sdio_f0_writeb(SDIO_CCCR_CAPS) returns %d\n",
30525 + ret);
30526 + goto out_got_irq;
30527 + }
30528 +#else
30529 + if (0) /* avoid warning */
30530 + goto out_got_irq;
30531 +#endif
30532 +
30533 + sdio_release_host(func);
30534 +
30535 + hif->io_task = kthread_run(io, hif, "ar6000_io");
30536 + ret = IS_ERR(hif->io_task);
30537 + if (ret) {
30538 + dev_err(dev, "kthread_run(ar6000_io): %d\n", ret);
30539 + goto out_func_ready;
30540 + }
30541 +
30542 + ret = htcCallbacks.deviceInsertedHandler(hif);
30543 + if (ret == A_OK)
30544 + return 0;
30545 +
30546 + dev_err(dev, "deviceInsertedHandler: %d\n", ret);
30547 +
30548 + ret = kthread_stop(hif->io_task);
30549 + if (ret)
30550 + dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret);
30551 +
30552 +out_func_ready:
30553 + sdio_claim_host(func);
30554 +
30555 +out_got_irq:
30556 + sdio_release_irq(func);
30557 +
30558 +out_enabled:
30559 + sdio_disable_func(func);
30560 + sdio_release_host(func);
30561 +
30562 + return ret;
30563 +}
30564 +
30565 +
30566 +static void ar6000_do_deactivate(struct hif_device *hif)
30567 +{
30568 + struct sdio_func *func = hif->func;
30569 + struct device *dev = &func->dev;
30570 + int ret;
30571 +
30572 + dev_dbg(dev, "ar6000_do_deactivate\n");
30573 + if (!hif->active)
30574 + return;
30575 +
30576 + if (mutex_trylock(&shutdown_lock)) {
30577 + /*
30578 + * Funny, Atheros' HIF does this call, but this just puts us in
30579 + * a recursion through HTCShutDown/HIFShutDown if unloading the
30580 + * module.
30581 + *
30582 + * However, we need it for suspend/resume. See the comment at
30583 + * HIFShutDown, below.
30584 + */
30585 + ret = htcCallbacks.deviceRemovedHandler(hif->htc_handle, A_OK);
30586 + if (ret != A_OK)
30587 + dev_err(dev, "deviceRemovedHandler: %d\n", ret);
30588 + mutex_unlock(&shutdown_lock);
30589 + }
30590 + wait_queue_empty(hif);
30591 + ret = kthread_stop(hif->io_task);
30592 + if (ret)
30593 + dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret);
30594 + sdio_claim_host(func);
30595 + sdio_release_irq(func);
30596 + sdio_disable_func(func);
30597 + sdio_release_host(func);
30598 +}
30599 +
30600 +
30601 +static int ar6000_activate(struct hif_device *hif)
30602 +{
30603 + int ret = 0;
30604 +
30605 + dev_dbg(&hif->func->dev, "ar6000_activate\n");
30606 + mutex_lock(&hif->activate_lock);
30607 + if (!hif->active) {
30608 + ret = ar6000_do_activate(hif);
30609 + if (ret) {
30610 + printk(KERN_ERR "%s: Failed to activate %d\n",
30611 + __func__, ret);
30612 + goto out;
30613 + }
30614 + hif->active = 1;
30615 + }
30616 +out:
30617 + mutex_unlock(&hif->activate_lock);
30618 + return ret;
30619 +}
30620 +
30621 +
30622 +static void ar6000_deactivate(struct hif_device *hif)
30623 +{
30624 + dev_dbg(&hif->func->dev, "ar6000_deactivate\n");
30625 + mutex_lock(&hif->activate_lock);
30626 + if (hif->active) {
30627 + ar6000_do_deactivate(hif);
30628 + hif->active = 0;
30629 + }
30630 + mutex_unlock(&hif->activate_lock);
30631 +}
30632 +
30633 +
30634 +static int ar6000_rfkill_cb(void *data, int on)
30635 +{
30636 + struct hif_device *hif = data;
30637 + struct sdio_func *func = hif->func;
30638 + struct device *dev = &func->dev;
30639 +
30640 + dev_dbg(dev, "ar6000_rfkill_cb: on %d\n", on);
30641 + if (on)
30642 + return ar6000_activate(hif);
30643 + ar6000_deactivate(hif);
30644 + return 0;
30645 +}
30646 +
30647 +
30648 +static int sdio_ar6000_probe(struct sdio_func *func,
30649 + const struct sdio_device_id *id)
30650 +{
30651 + struct device *dev = &func->dev;
30652 + struct hif_device *hif;
30653 + int ret = 0;
30654 +
30655 + dev_dbg(dev, "sdio_ar6000_probe\n");
30656 + BUG_ON(!htcCallbacks.deviceInsertedHandler);
30657 +
30658 + hif = kzalloc(sizeof(*hif), GFP_KERNEL);
30659 + if (!hif)
30660 + return -ENOMEM;
30661 +
30662 + sdio_set_drvdata(func, hif);
30663 + hif->func = func;
30664 + mutex_init(&hif->activate_lock);
30665 + hif->active = 0;
30666 +
30667 + if (gta02_wlan_query_rfkill_lock())
30668 + ret = ar6000_activate(hif);
30669 + if (!ret) {
30670 + gta02_wlan_set_rfkill_cb(ar6000_rfkill_cb, hif);
30671 + return 0;
30672 + }
30673 + gta02_wlan_query_rfkill_unlock();
30674 + sdio_set_drvdata(func, NULL);
30675 + kfree(hif);
30676 + return ret;
30677 +}
30678 +
30679 +
30680 +static void sdio_ar6000_remove(struct sdio_func *func)
30681 +{
30682 + struct device *dev = &func->dev;
30683 + HIF_DEVICE *hif = sdio_get_drvdata(func);
30684 +
30685 + dev_dbg(dev, "sdio_ar6000_remove\n");
30686 + gta02_wlan_clear_rfkill_cb();
30687 + ar6000_deactivate(hif);
30688 + sdio_set_drvdata(func, NULL);
30689 + kfree(hif);
30690 +}
30691 +
30692 +
30693 +/* ----- Device registration/unregistration (called by HIF) ---------------- */
30694 +
30695 +
30696 +#define ATHEROS_SDIO_DEVICE(id, offset) \
30697 + SDIO_DEVICE(SDIO_VENDOR_ID_ATHEROS, SDIO_DEVICE_ID_ATHEROS_##id | (offset))
30698 +
30699 +static const struct sdio_device_id sdio_ar6000_ids[] = {
30700 + { ATHEROS_SDIO_DEVICE(AR6002, 0) },
30701 + { ATHEROS_SDIO_DEVICE(AR6002, 0x1) },
30702 + { ATHEROS_SDIO_DEVICE(AR6001, 0x8) },
30703 + { ATHEROS_SDIO_DEVICE(AR6001, 0x9) },
30704 + { ATHEROS_SDIO_DEVICE(AR6001, 0xa) },
30705 + { ATHEROS_SDIO_DEVICE(AR6001, 0xb) },
30706 + { /* end: all zeroes */ },
30707 +};
30708 +
30709 +MODULE_DEVICE_TABLE(sdio, sdio_ar6000_ids);
30710 +
30711 +
30712 +static struct sdio_driver sdio_ar6000_driver = {
30713 + .probe = sdio_ar6000_probe,
30714 + .remove = sdio_ar6000_remove,
30715 + .name = "sdio_ar6000",
30716 + .id_table = sdio_ar6000_ids,
30717 +};
30718 +
30719 +
30720 +int HIFInit(HTC_CALLBACKS *callbacks)
30721 +{
30722 + int ret;
30723 +
30724 + BUG_ON(!callbacks);
30725 +
30726 + printk(KERN_DEBUG "HIFInit\n");
30727 + htcCallbacks = *callbacks;
30728 +
30729 + ret = sdio_register_driver(&sdio_ar6000_driver);
30730 + if (ret) {
30731 + printk(KERN_ERR
30732 + "sdio_register_driver(sdio_ar6000_driver): %d\n", ret);
30733 + return A_ERROR;
30734 + }
30735 +
30736 + return 0;
30737 +}
30738 +
30739 +
30740 +/*
30741 + * We have four possible call chains here:
30742 + *
30743 + * System shutdown/reboot:
30744 + *
30745 + * kernel_restart_prepare ...> device_shutdown ... > s3cmci_shutdown ->
30746 + * mmc_remove_host ..> sdio_bus_remove -> sdio_ar6000_remove ->
30747 + * ar6000_deactivate -> ar6000_do_deactivate ->
30748 + * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice
30749 + *
30750 + * This is roughly the same sequence as suspend, described below.
30751 + *
30752 + * Module removal:
30753 + *
30754 + * sys_delete_module -> ar6000_cleanup_module -> HTCShutDown ->
30755 + * HIFShutDownDevice -> sdio_unregister_driver ...> sdio_bus_remove ->
30756 + * sdio_ar6000_remove -> ar6000_deactivate -> ar6000_do_deactivate
30757 + *
30758 + * In this case, HIFShutDownDevice must call sdio_unregister_driver to
30759 + * notify the driver about its removal. ar6000_do_deactivate must not call
30760 + * deviceRemovedHandler, because that would loop back into HIFShutDownDevice.
30761 + *
30762 + * Suspend:
30763 + *
30764 + * device_suspend ...> s3cmci_suspend ...> sdio_bus_remove ->
30765 + * sdio_ar6000_remove -> ar6000_deactivate -> ar6000_do_deactivate ->
30766 + * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice
30767 + *
30768 + * We must call deviceRemovedHandler to inform the ar6k stack that the device
30769 + * has been removed. Since HTCTargetRemovedHandler calls back into
30770 + * HIFShutDownDevice, we must also prevent the call to
30771 + * sdio_unregister_driver, or we'd end up recursing into the SDIO stack,
30772 + * eventually deadlocking somewhere.
30773 + *
30774 + * rfkill:
30775 + *
30776 + * rfkill_state_store -> rfkill_toggle_radio -> gta02_wlan_toggle_radio ->
30777 + * ar6000_rfkill_cb -> ar6000_deactivate -> ar6000_do_deactivate ->
30778 + * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice
30779 + *
30780 + * This is similar to suspend - only the entry point changes.
30781 + */
30782 +
30783 +void HIFShutDownDevice(HIF_DEVICE *hif)
30784 +{
30785 + /* Beware, HTCShutDown calls us with hif == NULL ! */
30786 + if (mutex_trylock(&shutdown_lock)) {
30787 + sdio_unregister_driver(&sdio_ar6000_driver);
30788 + mutex_unlock(&shutdown_lock);
30789 + }
30790 +}
30791 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/hif/hif.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/hif/hif.c
30792 --- linux-2.6.29-rc3.owrt/drivers/ar6000/hif/hif.c 1970-01-01 01:00:00.000000000 +0100
30793 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/hif/hif.c 2009-05-10 22:27:59.000000000 +0200
30794 @@ -0,0 +1,824 @@
30795 +/*
30796 + * @file: hif.c
30797 + *
30798 + * @abstract: HIF layer reference implementation for Atheros SDIO stack
30799 + *
30800 + * @notice: Copyright (c) 2004-2006 Atheros Communications Inc.
30801 + *
30802 + *
30803 + * This program is free software; you can redistribute it and/or modify
30804 + * it under the terms of the GNU General Public License version 2 as
30805 + * published by the Free Software Foundation;
30806 + *
30807 + * Software distributed under the License is distributed on an "AS
30808 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
30809 + * implied. See the License for the specific language governing
30810 + * rights and limitations under the License.
30811 + *
30812 + *
30813 + *
30814 + */
30815 +
30816 +#include "hif_internal.h"
30817 +
30818 +/* ------ Static Variables ------ */
30819 +
30820 +/* ------ Global Variable Declarations ------- */
30821 +SD_PNP_INFO Ids[] = {
30822 + {
30823 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xB,
30824 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30825 + .SDIO_FunctionClass = FUNCTION_CLASS,
30826 + .SDIO_FunctionNo = 1
30827 + },
30828 + {
30829 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xA,
30830 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30831 + .SDIO_FunctionClass = FUNCTION_CLASS,
30832 + .SDIO_FunctionNo = 1
30833 + },
30834 + {
30835 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x9,
30836 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30837 + .SDIO_FunctionClass = FUNCTION_CLASS,
30838 + .SDIO_FunctionNo = 1
30839 + },
30840 + {
30841 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x8,
30842 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30843 + .SDIO_FunctionClass = FUNCTION_CLASS,
30844 + .SDIO_FunctionNo = 1
30845 + },
30846 + {
30847 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x0,
30848 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30849 + .SDIO_FunctionClass = FUNCTION_CLASS,
30850 + .SDIO_FunctionNo = 1
30851 + },
30852 + {
30853 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x1,
30854 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30855 + .SDIO_FunctionClass = FUNCTION_CLASS,
30856 + .SDIO_FunctionNo = 1
30857 + },
30858 + {
30859 + } //list is null termintaed
30860 +};
30861 +
30862 +TARGET_FUNCTION_CONTEXT FunctionContext = {
30863 + .function.Version = CT_SDIO_STACK_VERSION_CODE,
30864 + .function.pName = "sdio_wlan",
30865 + .function.MaxDevices = 1,
30866 + .function.NumDevices = 0,
30867 + .function.pIds = Ids,
30868 + .function.pProbe = hifDeviceInserted,
30869 + .function.pRemove = hifDeviceRemoved,
30870 + .function.pSuspend = NULL,
30871 + .function.pResume = NULL,
30872 + .function.pWake = NULL,
30873 + .function.pContext = &FunctionContext,
30874 +};
30875 +
30876 +HIF_DEVICE hifDevice[HIF_MAX_DEVICES];
30877 +HTC_CALLBACKS htcCallbacks;
30878 +BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM];
30879 +static BUS_REQUEST *s_busRequestFreeQueue = NULL;
30880 +OS_CRITICALSECTION lock;
30881 +extern A_UINT32 onebitmode;
30882 +extern A_UINT32 busspeedlow;
30883 +
30884 +#ifdef DEBUG
30885 +extern A_UINT32 debughif;
30886 +#define ATH_DEBUG_ERROR 1
30887 +#define ATH_DEBUG_WARN 2
30888 +#define ATH_DEBUG_TRACE 3
30889 +#define _AR_DEBUG_PRINTX_ARG(arg...) arg
30890 +#define AR_DEBUG_PRINTF(lvl, args)\
30891 + {if (lvl <= debughif)\
30892 + A_PRINTF(KERN_ALERT _AR_DEBUG_PRINTX_ARG args);\
30893 + }
30894 +#else
30895 +#define AR_DEBUG_PRINTF(lvl, args)
30896 +#endif
30897 +
30898 +static BUS_REQUEST *hifAllocateBusRequest(void);
30899 +static void hifFreeBusRequest(BUS_REQUEST *busrequest);
30900 +static THREAD_RETURN insert_helper_func(POSKERNEL_HELPER pHelper);
30901 +static void ResetAllCards(void);
30902 +
30903 +/* ------ Functions ------ */
30904 +int HIFInit(HTC_CALLBACKS *callbacks)
30905 +{
30906 + SDIO_STATUS status;
30907 + DBG_ASSERT(callbacks != NULL);
30908 +
30909 + /* Store the callback and event handlers */
30910 + htcCallbacks.deviceInsertedHandler = callbacks->deviceInsertedHandler;
30911 + htcCallbacks.deviceRemovedHandler = callbacks->deviceRemovedHandler;
30912 + htcCallbacks.deviceSuspendHandler = callbacks->deviceSuspendHandler;
30913 + htcCallbacks.deviceResumeHandler = callbacks->deviceResumeHandler;
30914 + htcCallbacks.deviceWakeupHandler = callbacks->deviceWakeupHandler;
30915 + htcCallbacks.rwCompletionHandler = callbacks->rwCompletionHandler;
30916 + htcCallbacks.dsrHandler = callbacks->dsrHandler;
30917 +
30918 + CriticalSectionInit(&lock);
30919 +
30920 + /* Register with bus driver core */
30921 + status = SDIO_RegisterFunction(&FunctionContext.function);
30922 + DBG_ASSERT(SDIO_SUCCESS(status));
30923 +
30924 + return(0);
30925 +}
30926 +
30927 +A_STATUS
30928 +HIFReadWrite(HIF_DEVICE *device,
30929 + A_UINT32 address,
30930 + A_UCHAR *buffer,
30931 + A_UINT32 length,
30932 + A_UINT32 request,
30933 + void *context)
30934 +{
30935 + A_UINT8 rw;
30936 + A_UINT8 mode;
30937 + A_UINT8 funcNo;
30938 + A_UINT8 opcode;
30939 + A_UINT16 count;
30940 + SDREQUEST *sdrequest;
30941 + SDIO_STATUS sdiostatus;
30942 + BUS_REQUEST *busrequest;
30943 + A_STATUS status = A_OK;
30944 +
30945 + DBG_ASSERT(device != NULL);
30946 + DBG_ASSERT(device->handle != NULL);
30947 +
30948 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device));
30949 +
30950 + do {
30951 + busrequest = hifAllocateBusRequest();
30952 + if (busrequest == NULL) {
30953 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF Unable to allocate bus request\n"));
30954 + status = A_NO_RESOURCE;
30955 + break;
30956 + }
30957 +
30958 + sdrequest = busrequest->request;
30959 + busrequest->context = context;
30960 +
30961 + sdrequest->pDataBuffer = buffer;
30962 + if (request & HIF_SYNCHRONOUS) {
30963 + sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS;
30964 + sdrequest->pCompleteContext = NULL;
30965 + sdrequest->pCompletion = NULL;
30966 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Synchronous\n"));
30967 + } else if (request & HIF_ASYNCHRONOUS) {
30968 + sdrequest->Flags = SDREQ_FLAGS_RESP_SDIO_R5 | SDREQ_FLAGS_DATA_TRANS |
30969 + SDREQ_FLAGS_TRANS_ASYNC;
30970 + sdrequest->pCompleteContext = busrequest;
30971 + sdrequest->pCompletion = hifRWCompletionHandler;
30972 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Execution mode: Asynchronous\n"));
30973 + } else {
30974 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
30975 + ("Invalid execution mode: 0x%08x\n", request));
30976 + status = A_EINVAL;
30977 + break;
30978 + }
30979 +
30980 + if (request & HIF_EXTENDED_IO) {
30981 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Command type: CMD53\n"));
30982 + sdrequest->Command = CMD53;
30983 + } else {
30984 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
30985 + ("Invalid command type: 0x%08x\n", request));
30986 + status = A_EINVAL;
30987 + break;
30988 + }
30989 +
30990 + if (request & HIF_BLOCK_BASIS) {
30991 + mode = CMD53_BLOCK_BASIS;
30992 + sdrequest->BlockLen = HIF_MBOX_BLOCK_SIZE;
30993 + sdrequest->BlockCount = length / HIF_MBOX_BLOCK_SIZE;
30994 + count = sdrequest->BlockCount;
30995 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
30996 + ("Block mode (BlockLen: %d, BlockCount: %d)\n",
30997 + sdrequest->BlockLen, sdrequest->BlockCount));
30998 + } else if (request & HIF_BYTE_BASIS) {
30999 + mode = CMD53_BYTE_BASIS;
31000 + sdrequest->BlockLen = length;
31001 + sdrequest->BlockCount = 1;
31002 + count = sdrequest->BlockLen;
31003 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31004 + ("Byte mode (BlockLen: %d, BlockCount: %d)\n",
31005 + sdrequest->BlockLen, sdrequest->BlockCount));
31006 + } else {
31007 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31008 + ("Invalid data mode: 0x%08x\n", request));
31009 + status = A_EINVAL;
31010 + break;
31011 + }
31012 +
31013 +#if 0
31014 + /* useful for checking register accesses */
31015 + if (length & 0x3) {
31016 + A_PRINTF(KERN_ALERT"HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n",
31017 + request & HIF_WRITE ? "write":"read", address, length);
31018 + }
31019 +#endif
31020 +
31021 + if ((address >= HIF_MBOX_START_ADDR(0)) &&
31022 + (address <= HIF_MBOX_END_ADDR(3)))
31023 + {
31024 +
31025 + DBG_ASSERT(length <= HIF_MBOX_WIDTH);
31026 +
31027 + /*
31028 + * Mailbox write. Adjust the address so that the last byte
31029 + * falls on the EOM address.
31030 + */
31031 + address += (HIF_MBOX_WIDTH - length);
31032 + }
31033 +
31034 +
31035 +
31036 + if (request & HIF_WRITE) {
31037 + rw = CMD53_WRITE;
31038 + sdrequest->Flags |= SDREQ_FLAGS_DATA_WRITE;
31039 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Write\n"));
31040 + } else if (request & HIF_READ) {
31041 + rw = CMD53_READ;
31042 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Read\n"));
31043 + } else {
31044 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31045 + ("Invalid direction: 0x%08x\n", request));
31046 + status = A_EINVAL;
31047 + break;
31048 + }
31049 +
31050 + if (request & HIF_FIXED_ADDRESS) {
31051 + opcode = CMD53_FIXED_ADDRESS;
31052 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Fixed\n"));
31053 + } else if (request & HIF_INCREMENTAL_ADDRESS) {
31054 + opcode = CMD53_INCR_ADDRESS;
31055 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Address mode: Incremental\n"));
31056 + } else {
31057 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31058 + ("Invalid address mode: 0x%08x\n", request));
31059 + status = A_EINVAL;
31060 + break;
31061 + }
31062 +
31063 + funcNo = SDDEVICE_GET_SDIO_FUNCNO(device->handle);
31064 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Function number: %d\n", funcNo));
31065 + SDIO_SET_CMD53_ARG(sdrequest->Argument, rw, funcNo,
31066 + mode, opcode, address, count);
31067 +
31068 + /* Send the command out */
31069 + sdiostatus = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest);
31070 +
31071 + if (!SDIO_SUCCESS(sdiostatus)) {
31072 + status = A_ERROR;
31073 + }
31074 +
31075 + } while (FALSE);
31076 +
31077 + if (A_FAILED(status) || (request & HIF_SYNCHRONOUS)) {
31078 + if (busrequest != NULL) {
31079 + hifFreeBusRequest(busrequest);
31080 + }
31081 + }
31082 +
31083 + if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
31084 + /* call back async handler on failure */
31085 + htcCallbacks.rwCompletionHandler(context, status);
31086 + }
31087 +
31088 + return status;
31089 +}
31090 +
31091 +A_STATUS
31092 +HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
31093 + void *config, A_UINT32 configLen)
31094 +{
31095 + A_UINT32 count;
31096 +
31097 + switch(opcode) {
31098 + case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
31099 + ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
31100 + ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
31101 + ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
31102 + ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
31103 + break;
31104 +
31105 + case HIF_DEVICE_GET_MBOX_ADDR:
31106 + for (count = 0; count < 4; count ++) {
31107 + ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count);
31108 + }
31109 + break;
31110 + case HIF_DEVICE_GET_IRQ_PROC_MODE:
31111 + /* the SDIO stack allows the interrupts to be processed either way, ASYNC or SYNC */
31112 + *((HIF_DEVICE_IRQ_PROCESSING_MODE *)config) = HIF_DEVICE_IRQ_ASYNC_SYNC;
31113 + break;
31114 + default:
31115 + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
31116 + ("Unsupported configuration opcode: %d\n", opcode));
31117 + return A_ERROR;
31118 + }
31119 +
31120 + return A_OK;
31121 +}
31122 +
31123 +void
31124 +HIFShutDownDevice(HIF_DEVICE *device)
31125 +{
31126 + A_UINT8 data;
31127 + A_UINT32 count;
31128 + SDIO_STATUS status;
31129 + SDCONFIG_BUS_MODE_DATA busSettings;
31130 + SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData;
31131 +
31132 + if (device != NULL) {
31133 + DBG_ASSERT(device->handle != NULL);
31134 +
31135 + /* Remove the allocated current if any */
31136 + status = SDLIB_IssueConfig(device->handle,
31137 + SDCONFIG_FUNC_FREE_SLOT_CURRENT, NULL, 0);
31138 + DBG_ASSERT(SDIO_SUCCESS(status));
31139 +
31140 + /* Disable the card */
31141 + fData.EnableFlags = SDCONFIG_DISABLE_FUNC;
31142 + fData.TimeOut = 1;
31143 + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ENABLE_DISABLE,
31144 + &fData, sizeof(fData));
31145 + DBG_ASSERT(SDIO_SUCCESS(status));
31146 +
31147 + /* Perform a soft I/O reset */
31148 + data = SDIO_IO_RESET;
31149 + status = SDLIB_IssueCMD52(device->handle, 0, SDIO_IO_ABORT_REG,
31150 + &data, 1, 1);
31151 + DBG_ASSERT(SDIO_SUCCESS(status));
31152 +
31153 + /*
31154 + * WAR - Codetelligence driver does not seem to shutdown correctly in 1
31155 + * bit mode. By default it configures the HC in the 4 bit. Its later in
31156 + * our driver that we switch to 1 bit mode. If we try to shutdown, the
31157 + * driver hangs so we revert to 4 bit mode, to be transparent to the
31158 + * underlying bus driver.
31159 + */
31160 + if (onebitmode) {
31161 + ZERO_OBJECT(busSettings);
31162 + busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(device->handle);
31163 + SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags,
31164 + SDCONFIG_BUS_WIDTH_4_BIT);
31165 +
31166 + /* Issue config request to change the bus width to 4 bit */
31167 + status = SDLIB_IssueConfig(device->handle, SDCONFIG_BUS_MODE_CTRL,
31168 + &busSettings,
31169 + sizeof(SDCONFIG_BUS_MODE_DATA));
31170 + DBG_ASSERT(SDIO_SUCCESS(status));
31171 + }
31172 +
31173 + /* Free the bus requests */
31174 + for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
31175 + SDDeviceFreeRequest(device->handle, busRequest[count].request);
31176 + }
31177 + /* Clean up the queue */
31178 + s_busRequestFreeQueue = NULL;
31179 + } else {
31180 + /* since we are unloading the driver anyways, reset all cards in case the SDIO card
31181 + * is externally powered and we are unloading the SDIO stack. This avoids the problem when
31182 + * the SDIO stack is reloaded and attempts are made to re-enumerate a card that is already
31183 + * enumerated */
31184 + ResetAllCards();
31185 + /* Unregister with bus driver core */
31186 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31187 + ("Unregistering with the bus driver\n"));
31188 + status = SDIO_UnregisterFunction(&FunctionContext.function);
31189 + DBG_ASSERT(SDIO_SUCCESS(status));
31190 + }
31191 +}
31192 +
31193 +void
31194 +hifRWCompletionHandler(SDREQUEST *request)
31195 +{
31196 + A_STATUS status;
31197 + void *context;
31198 + BUS_REQUEST *busrequest;
31199 +
31200 + if (SDIO_SUCCESS(request->Status)) {
31201 + status = A_OK;
31202 + } else {
31203 + status = A_ERROR;
31204 + }
31205 +
31206 + DBG_ASSERT(status == A_OK);
31207 + busrequest = (BUS_REQUEST *) request->pCompleteContext;
31208 + context = (void *) busrequest->context;
31209 + /* free the request before calling the callback, in case the
31210 + * callback submits another request, this guarantees that
31211 + * there is at least 1 free request available everytime the callback
31212 + * is invoked */
31213 + hifFreeBusRequest(busrequest);
31214 + htcCallbacks.rwCompletionHandler(context, status);
31215 +}
31216 +
31217 +void
31218 +hifIRQHandler(void *context)
31219 +{
31220 + A_STATUS status;
31221 + HIF_DEVICE *device;
31222 +
31223 + device = (HIF_DEVICE *)context;
31224 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device));
31225 + status = htcCallbacks.dsrHandler(device->htc_handle);
31226 + DBG_ASSERT(status == A_OK);
31227 +}
31228 +
31229 +BOOL
31230 +hifDeviceInserted(SDFUNCTION *function, SDDEVICE *handle)
31231 +{
31232 + BOOL enabled;
31233 + A_UINT8 data;
31234 + A_UINT32 count;
31235 + HIF_DEVICE *device;
31236 + SDIO_STATUS status;
31237 + A_UINT16 maxBlocks;
31238 + A_UINT16 maxBlockSize;
31239 + SDCONFIG_BUS_MODE_DATA busSettings;
31240 + SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData;
31241 + TARGET_FUNCTION_CONTEXT *functionContext;
31242 + SDCONFIG_FUNC_SLOT_CURRENT_DATA slotCurrent;
31243 + SD_BUSCLOCK_RATE currentBusClock;
31244 +
31245 + DBG_ASSERT(function != NULL);
31246 + DBG_ASSERT(handle != NULL);
31247 +
31248 + device = addHifDevice(handle);
31249 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device));
31250 + functionContext = (TARGET_FUNCTION_CONTEXT *)function->pContext;
31251 +
31252 + /*
31253 + * Issue commands to get the manufacturer ID and stuff and compare it
31254 + * against the rev Id derived from the ID registered during the
31255 + * initialization process. Report the device only in the case there
31256 + * is a match. In the case od SDIO, the bus driver has already queried
31257 + * these details so we just need to use their data structures to get the
31258 + * relevant values. Infact, the driver has already matched it against
31259 + * the Ids that we registered with it so we dont need to the step here.
31260 + */
31261 +
31262 + /* Configure the SDIO Bus Width */
31263 + if (onebitmode) {
31264 + data = SDIO_BUS_WIDTH_1_BIT;
31265 + status = SDLIB_IssueCMD52(handle, 0, SDIO_BUS_IF_REG, &data, 1, 1);
31266 + if (!SDIO_SUCCESS(status)) {
31267 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31268 + ("Unable to set the bus width to 1 bit\n"));
31269 + return FALSE;
31270 + }
31271 + }
31272 +
31273 + /* Get current bus flags */
31274 + ZERO_OBJECT(busSettings);
31275 +
31276 + busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(handle);
31277 + if (onebitmode) {
31278 + SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags,
31279 + SDCONFIG_BUS_WIDTH_1_BIT);
31280 + }
31281 +
31282 + /* get the current operating clock, the bus driver sets us up based
31283 + * on what our CIS reports and what the host controller can handle
31284 + * we can use this to determine whether we want to drop our clock rate
31285 + * down */
31286 + currentBusClock = SDDEVICE_GET_OPER_CLOCK(handle);
31287 + busSettings.ClockRate = currentBusClock;
31288 +
31289 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31290 + ("HIF currently running at: %d \n",currentBusClock));
31291 +
31292 + /* see if HIF wants to run at a lower clock speed, we may already be
31293 + * at that lower clock speed */
31294 + if (currentBusClock > (SDIO_CLOCK_FREQUENCY_DEFAULT >> busspeedlow)) {
31295 + busSettings.ClockRate = SDIO_CLOCK_FREQUENCY_DEFAULT >> busspeedlow;
31296 + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
31297 + ("HIF overriding clock to %d \n",busSettings.ClockRate));
31298 + }
31299 +
31300 + /* Issue config request to override clock rate */
31301 + status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_CHANGE_BUS_MODE, &busSettings,
31302 + sizeof(SDCONFIG_BUS_MODE_DATA));
31303 + if (!SDIO_SUCCESS(status)) {
31304 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31305 + ("Unable to configure the host clock\n"));
31306 + return FALSE;
31307 + } else {
31308 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31309 + ("Configured clock: %d, Maximum clock: %d\n",
31310 + busSettings.ActualClockRate,
31311 + SDDEVICE_GET_MAX_CLOCK(handle)));
31312 + }
31313 +
31314 + /*
31315 + * Check if the target supports block mode. This result of this check
31316 + * can be used to implement the HIFReadWrite API.
31317 + */
31318 + if (SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle)) {
31319 + /* Limit block size to operational block limit or card function
31320 + capability */
31321 + maxBlockSize = min(SDDEVICE_GET_OPER_BLOCK_LEN(handle),
31322 + SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle));
31323 +
31324 + /* check if the card support multi-block transfers */
31325 + if (!(SDDEVICE_GET_SDIOCARD_CAPS(handle) & SDIO_CAPS_MULTI_BLOCK)) {
31326 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Byte basis only\n"));
31327 +
31328 + /* Limit block size to max byte basis */
31329 + maxBlockSize = min(maxBlockSize,
31330 + (A_UINT16)SDIO_MAX_LENGTH_BYTE_BASIS);
31331 + maxBlocks = 1;
31332 + } else {
31333 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Multi-block capable\n"));
31334 + maxBlocks = SDDEVICE_GET_OPER_BLOCKS(handle);
31335 + status = SDLIB_SetFunctionBlockSize(handle, HIF_MBOX_BLOCK_SIZE);
31336 + if (!SDIO_SUCCESS(status)) {
31337 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31338 + ("Failed to set block size. Err:%d\n", status));
31339 + return FALSE;
31340 + }
31341 + }
31342 +
31343 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31344 + ("Bytes Per Block: %d bytes, Block Count:%d \n",
31345 + maxBlockSize, maxBlocks));
31346 + } else {
31347 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31348 + ("Function does not support Block Mode!\n"));
31349 + return FALSE;
31350 + }
31351 +
31352 + /* Allocate the slot current */
31353 + status = SDLIB_GetDefaultOpCurrent(handle, &slotCurrent.SlotCurrent);
31354 + if (SDIO_SUCCESS(status)) {
31355 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Allocating Slot current: %d mA\n",
31356 + slotCurrent.SlotCurrent));
31357 + status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ALLOC_SLOT_CURRENT,
31358 + &slotCurrent, sizeof(slotCurrent));
31359 + if (!SDIO_SUCCESS(status)) {
31360 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31361 + ("Failed to allocate slot current %d\n", status));
31362 + return FALSE;
31363 + }
31364 + }
31365 +
31366 + /* Enable the dragon function */
31367 + count = 0;
31368 + enabled = FALSE;
31369 + fData.TimeOut = 1;
31370 + fData.EnableFlags = SDCONFIG_ENABLE_FUNC;
31371 + while ((count++ < SDWLAN_ENABLE_DISABLE_TIMEOUT) && !enabled)
31372 + {
31373 + /* Enable dragon */
31374 + status = SDLIB_IssueConfig(handle, SDCONFIG_FUNC_ENABLE_DISABLE,
31375 + &fData, sizeof(fData));
31376 + if (!SDIO_SUCCESS(status)) {
31377 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31378 + ("Attempting to enable the card again\n"));
31379 + continue;
31380 + }
31381 +
31382 + /* Mark the status as enabled */
31383 + enabled = TRUE;
31384 + }
31385 +
31386 + /* Check if we were succesful in enabling the target */
31387 + if (!enabled) {
31388 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31389 + ("Failed to communicate with the target\n"));
31390 + return FALSE;
31391 + }
31392 +
31393 + /* Allocate the bus requests to be used later */
31394 + A_MEMZERO(busRequest, sizeof(busRequest));
31395 + for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
31396 + if ((busRequest[count].request = SDDeviceAllocRequest(handle)) == NULL){
31397 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("Unable to allocate memory\n"));
31398 + /* TODO: Free the memory that has already been allocated */
31399 + return FALSE;
31400 + }
31401 + hifFreeBusRequest(&busRequest[count]);
31402 +
31403 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31404 + ("0x%08x = busRequest[%d].request = 0x%08x\n",
31405 + (unsigned int) &busRequest[count], count,
31406 + (unsigned int) busRequest[count].request));
31407 + }
31408 +
31409 + /* Schedule a worker to handle device inserted, this is a temporary workaround
31410 + * to fix a deadlock if the device fails to intialize in the insertion handler
31411 + * The failure causes the instance to shutdown the HIF layer and unregister the
31412 + * function driver within the busdriver probe context which can deadlock
31413 + *
31414 + * NOTE: we cannot use the default work queue because that would block
31415 + * SD bus request processing for all synchronous I/O. We must use a kernel
31416 + * thread that is creating using the helper library.
31417 + * */
31418 +
31419 + if (SDIO_SUCCESS(SDLIB_OSCreateHelper(&device->insert_helper,
31420 + insert_helper_func,
31421 + device))) {
31422 + device->helper_started = TRUE;
31423 + }
31424 +
31425 + return TRUE;
31426 +}
31427 +
31428 +static THREAD_RETURN insert_helper_func(POSKERNEL_HELPER pHelper)
31429 +{
31430 +
31431 + /*
31432 + * Adding a wait of around a second before we issue the very first
31433 + * command to dragon. During the process of loading/unloading the
31434 + * driver repeatedly it was observed that we get a data timeout
31435 + * while accessing function 1 registers in the chip. The theory at
31436 + * this point is that some initialization delay in dragon is
31437 + * causing the SDIO state in dragon core to be not ready even after
31438 + * the ready bit indicates that function 1 is ready. Accomodating
31439 + * for this behavior by adding some delay in the driver before it
31440 + * issues the first command after switching on dragon. Need to
31441 + * investigate this a bit more - TODO
31442 + */
31443 +
31444 + A_MDELAY(1000);
31445 + /* Inform HTC */
31446 + if ((htcCallbacks.deviceInsertedHandler(SD_GET_OS_HELPER_CONTEXT(pHelper))) != A_OK) {
31447 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device rejected\n"));
31448 + }
31449 +
31450 + return 0;
31451 +}
31452 +
31453 +void
31454 +HIFAckInterrupt(HIF_DEVICE *device)
31455 +{
31456 + SDIO_STATUS status;
31457 + DBG_ASSERT(device != NULL);
31458 + DBG_ASSERT(device->handle != NULL);
31459 +
31460 + /* Acknowledge our function IRQ */
31461 + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ACK_IRQ,
31462 + NULL, 0);
31463 + DBG_ASSERT(SDIO_SUCCESS(status));
31464 +}
31465 +
31466 +void
31467 +HIFUnMaskInterrupt(HIF_DEVICE *device)
31468 +{
31469 + SDIO_STATUS status;
31470 +
31471 + DBG_ASSERT(device != NULL);
31472 + DBG_ASSERT(device->handle != NULL);
31473 +
31474 + /* Register the IRQ Handler */
31475 + SDDEVICE_SET_IRQ_HANDLER(device->handle, hifIRQHandler, device);
31476 +
31477 + /* Unmask our function IRQ */
31478 + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_UNMASK_IRQ,
31479 + NULL, 0);
31480 + DBG_ASSERT(SDIO_SUCCESS(status));
31481 +}
31482 +
31483 +void HIFMaskInterrupt(HIF_DEVICE *device)
31484 +{
31485 + SDIO_STATUS status;
31486 + DBG_ASSERT(device != NULL);
31487 + DBG_ASSERT(device->handle != NULL);
31488 +
31489 + /* Mask our function IRQ */
31490 + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_MASK_IRQ,
31491 + NULL, 0);
31492 + DBG_ASSERT(SDIO_SUCCESS(status));
31493 +
31494 + /* Unregister the IRQ Handler */
31495 + SDDEVICE_SET_IRQ_HANDLER(device->handle, NULL, NULL);
31496 +}
31497 +
31498 +static BUS_REQUEST *hifAllocateBusRequest(void)
31499 +{
31500 + BUS_REQUEST *busrequest;
31501 +
31502 + /* Acquire lock */
31503 + CriticalSectionAcquire(&lock);
31504 +
31505 + /* Remove first in list */
31506 + if((busrequest = s_busRequestFreeQueue) != NULL)
31507 + {
31508 + s_busRequestFreeQueue = busrequest->next;
31509 + }
31510 +
31511 + /* Release lock */
31512 + CriticalSectionRelease(&lock);
31513 +
31514 + return busrequest;
31515 +}
31516 +
31517 +static void
31518 +hifFreeBusRequest(BUS_REQUEST *busrequest)
31519 +{
31520 + DBG_ASSERT(busrequest != NULL);
31521 +
31522 + /* Acquire lock */
31523 + CriticalSectionAcquire(&lock);
31524 +
31525 + /* Insert first in list */
31526 + busrequest->next = s_busRequestFreeQueue;
31527 + s_busRequestFreeQueue = busrequest;
31528 +
31529 + /* Release lock */
31530 + CriticalSectionRelease(&lock);
31531 +}
31532 +
31533 +void
31534 +hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *handle)
31535 +{
31536 + A_STATUS status;
31537 + HIF_DEVICE *device;
31538 + DBG_ASSERT(function != NULL);
31539 + DBG_ASSERT(handle != NULL);
31540 +
31541 + device = getHifDevice(handle);
31542 + status = htcCallbacks.deviceRemovedHandler(device->htc_handle, A_OK);
31543 +
31544 + /* cleanup the helper thread */
31545 + if (device->helper_started) {
31546 + SDLIB_OSDeleteHelper(&device->insert_helper);
31547 + device->helper_started = FALSE;
31548 + }
31549 +
31550 + delHifDevice(handle);
31551 + DBG_ASSERT(status == A_OK);
31552 +}
31553 +
31554 +HIF_DEVICE *
31555 +addHifDevice(SDDEVICE *handle)
31556 +{
31557 + DBG_ASSERT(handle != NULL);
31558 + hifDevice[0].handle = handle;
31559 + return &hifDevice[0];
31560 +}
31561 +
31562 +HIF_DEVICE *
31563 +getHifDevice(SDDEVICE *handle)
31564 +{
31565 + DBG_ASSERT(handle != NULL);
31566 + return &hifDevice[0];
31567 +}
31568 +
31569 +void
31570 +delHifDevice(SDDEVICE *handle)
31571 +{
31572 + DBG_ASSERT(handle != NULL);
31573 + hifDevice[0].handle = NULL;
31574 +}
31575 +
31576 +struct device*
31577 +HIFGetOSDevice(HIF_DEVICE *device)
31578 +{
31579 + return &device->handle->Device->dev;
31580 +}
31581 +
31582 +static void ResetAllCards(void)
31583 +{
31584 + UINT8 data;
31585 + SDIO_STATUS status;
31586 + int i;
31587 +
31588 + data = SDIO_IO_RESET;
31589 +
31590 + /* set the I/O CARD reset bit:
31591 + * NOTE: we are exploiting a "feature" of the SDIO core that resets the core when you
31592 + * set the RES bit in the SDIO_IO_ABORT register. This bit however "normally" resets the
31593 + * I/O functions leaving the SDIO core in the same state (as per SDIO spec).
31594 + * In this design, this reset can be used to reset the SDIO core itself */
31595 + for (i = 0; i < HIF_MAX_DEVICES; i++) {
31596 + if (hifDevice[i].handle != NULL) {
31597 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31598 + ("Issuing I/O Card reset for instance: %d \n",i));
31599 + /* set the I/O Card reset bit */
31600 + status = SDLIB_IssueCMD52(hifDevice[i].handle,
31601 + 0, /* function 0 space */
31602 + SDIO_IO_ABORT_REG,
31603 + &data,
31604 + 1, /* 1 byte */
31605 + TRUE); /* write */
31606 + }
31607 + }
31608 +
31609 +}
31610 +
31611 +void HIFSetHandle(void *hif_handle, void *handle)
31612 +{
31613 + HIF_DEVICE *device = (HIF_DEVICE *) hif_handle;
31614 +
31615 + device->htc_handle = handle;
31616 +
31617 + return;
31618 +}
31619 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/hif/hif_internal.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/hif/hif_internal.h
31620 --- linux-2.6.29-rc3.owrt/drivers/ar6000/hif/hif_internal.h 1970-01-01 01:00:00.000000000 +0100
31621 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/hif/hif_internal.h 2009-05-10 22:27:59.000000000 +0200
31622 @@ -0,0 +1,102 @@
31623 +/*
31624 + * @file: hif_internal.h
31625 + *
31626 + * @abstract: internal header file for hif layer
31627 + *
31628 + * @notice: Copyright (c) 2004-2006 Atheros Communications Inc.
31629 + *
31630 + *
31631 + * This program is free software; you can redistribute it and/or modify
31632 + * it under the terms of the GNU General Public License version 2 as
31633 + * published by the Free Software Foundation;
31634 + *
31635 + * Software distributed under the License is distributed on an "AS
31636 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
31637 + * implied. See the License for the specific language governing
31638 + * rights and limitations under the License.
31639 + *
31640 + *
31641 + *
31642 + */
31643 +
31644 +#include <linux/sdio/ctsystem.h>
31645 +#include <linux/sdio/sdio_busdriver.h>
31646 +#include <linux/sdio/_sdio_defs.h>
31647 +#include <linux/sdio/sdio_lib.h>
31648 +#include "a_config.h"
31649 +#include "athdefs.h"
31650 +#include "a_types.h"
31651 +#include "a_osapi.h"
31652 +#include "hif.h"
31653 +
31654 +#define MANUFACTURER_ID_AR6001_BASE 0x100
31655 +#define MANUFACTURER_ID_AR6002_BASE 0x200
31656 +#define FUNCTION_CLASS 0x0
31657 +#define MANUFACTURER_CODE 0x271
31658 +
31659 +#define BUS_REQUEST_MAX_NUM 64
31660 +
31661 +#define SDIO_CLOCK_FREQUENCY_DEFAULT 25000000
31662 +#define SDWLAN_ENABLE_DISABLE_TIMEOUT 20
31663 +#define FLAGS_CARD_ENAB 0x02
31664 +#define FLAGS_CARD_IRQ_UNMSK 0x04
31665 +
31666 +#define HIF_MBOX_BLOCK_SIZE 128
31667 +#define HIF_MBOX_BASE_ADDR 0x800
31668 +#define HIF_MBOX_WIDTH 0x800
31669 +#define HIF_MBOX0_BLOCK_SIZE 1
31670 +#define HIF_MBOX1_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
31671 +#define HIF_MBOX2_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
31672 +#define HIF_MBOX3_BLOCK_SIZE HIF_MBOX_BLOCK_SIZE
31673 +
31674 +#define HIF_MBOX_START_ADDR(mbox) \
31675 + HIF_MBOX_BASE_ADDR + mbox * HIF_MBOX_WIDTH
31676 +
31677 +#define HIF_MBOX_END_ADDR(mbox) \
31678 + HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1
31679 +
31680 +struct hif_device {
31681 + SDDEVICE *handle;
31682 + void *htc_handle;
31683 + OSKERNEL_HELPER insert_helper;
31684 + BOOL helper_started;
31685 +};
31686 +
31687 +typedef struct target_function_context {
31688 + SDFUNCTION function; /* function description of the bus driver */
31689 + OS_SEMAPHORE instanceSem; /* instance lock. Unused */
31690 + SDLIST instanceList; /* list of instances. Unused */
31691 +} TARGET_FUNCTION_CONTEXT;
31692 +
31693 +typedef struct bus_request {
31694 + struct bus_request *next;
31695 + SDREQUEST *request;
31696 + void *context;
31697 +} BUS_REQUEST;
31698 +
31699 +BOOL
31700 +hifDeviceInserted(SDFUNCTION *function, SDDEVICE *device);
31701 +
31702 +void
31703 +hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *device);
31704 +
31705 +SDREQUEST *
31706 +hifAllocateDeviceRequest(SDDEVICE *device);
31707 +
31708 +void
31709 +hifFreeDeviceRequest(SDREQUEST *request);
31710 +
31711 +void
31712 +hifRWCompletionHandler(SDREQUEST *request);
31713 +
31714 +void
31715 +hifIRQHandler(void *context);
31716 +
31717 +HIF_DEVICE *
31718 +addHifDevice(SDDEVICE *handle);
31719 +
31720 +HIF_DEVICE *
31721 +getHifDevice(SDDEVICE *handle);
31722 +
31723 +void
31724 +delHifDevice(SDDEVICE *handle);
31725 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/htc/ar6k.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/ar6k.c
31726 --- linux-2.6.29-rc3.owrt/drivers/ar6000/htc/ar6k.c 1970-01-01 01:00:00.000000000 +0100
31727 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/ar6k.c 2009-05-10 22:27:59.000000000 +0200
31728 @@ -0,0 +1,991 @@
31729 +/*
31730 + * AR6K device layer that handles register level I/O
31731 + *
31732 + * Copyright (c) 2007 Atheros Communications Inc.
31733 + * All rights reserved.
31734 + *
31735 + *
31736 + * This program is free software; you can redistribute it and/or modify
31737 + * it under the terms of the GNU General Public License version 2 as
31738 + * published by the Free Software Foundation;
31739 + *
31740 + * Software distributed under the License is distributed on an "AS
31741 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
31742 + * implied. See the License for the specific language governing
31743 + * rights and limitations under the License.
31744 + *
31745 + *
31746 + *
31747 + */
31748 +#include "a_config.h"
31749 +#include "athdefs.h"
31750 +#include "a_types.h"
31751 +#include "AR6Khwreg.h"
31752 +#include "a_osapi.h"
31753 +#include "a_debug.h"
31754 +#include "hif.h"
31755 +#include "htc_packet.h"
31756 +#include "ar6k.h"
31757 +
31758 +#define MAILBOX_FOR_BLOCK_SIZE 1
31759 +
31760 +extern A_UINT32 resetok;
31761 +
31762 +static A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
31763 +static A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
31764 +
31765 +#define LOCK_AR6K(p) A_MUTEX_LOCK(&(p)->Lock);
31766 +#define UNLOCK_AR6K(p) A_MUTEX_UNLOCK(&(p)->Lock);
31767 +
31768 +void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket)
31769 +{
31770 + LOCK_AR6K(pDev);
31771 + HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket);
31772 + UNLOCK_AR6K(pDev);
31773 +}
31774 +
31775 +HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev)
31776 +{
31777 + HTC_PACKET *pPacket;
31778 +
31779 + LOCK_AR6K(pDev);
31780 + pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList);
31781 + UNLOCK_AR6K(pDev);
31782 +
31783 + return pPacket;
31784 +}
31785 +
31786 +A_STATUS DevSetup(AR6K_DEVICE *pDev)
31787 +{
31788 + A_UINT32 mailboxaddrs[AR6K_MAILBOXES];
31789 + A_UINT32 blocksizes[AR6K_MAILBOXES];
31790 + A_STATUS status = A_OK;
31791 + int i;
31792 +
31793 + AR_DEBUG_ASSERT(AR6K_IRQ_PROC_REGS_SIZE == 16);
31794 + AR_DEBUG_ASSERT(AR6K_IRQ_ENABLE_REGS_SIZE == 4);
31795 +
31796 + do {
31797 + /* give a handle to HIF for this target */
31798 + HIFSetHandle(pDev->HIFDevice, (void *)pDev);
31799 + /* initialize our free list of IO packets */
31800 + INIT_HTC_PACKET_QUEUE(&pDev->RegisterIOList);
31801 + A_MUTEX_INIT(&pDev->Lock);
31802 +
31803 + /* get the addresses for all 4 mailboxes */
31804 + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
31805 + mailboxaddrs, sizeof(mailboxaddrs));
31806 +
31807 + if (status != A_OK) {
31808 + AR_DEBUG_ASSERT(FALSE);
31809 + break;
31810 + }
31811 +
31812 + /* carve up register I/O packets (these are for ASYNC register I/O ) */
31813 + for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) {
31814 + HTC_PACKET *pIOPacket;
31815 + pIOPacket = &pDev->RegIOBuffers[i].HtcPacket;
31816 + SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket,
31817 + pDev,
31818 + pDev->RegIOBuffers[i].Buffer,
31819 + AR6K_REG_IO_BUFFER_SIZE,
31820 + 0); /* don't care */
31821 + AR6KFreeIOPacket(pDev,pIOPacket);
31822 + }
31823 +
31824 + /* get the address of the mailbox we are using */
31825 + pDev->MailboxAddress = mailboxaddrs[HTC_MAILBOX];
31826 +
31827 + /* get the block sizes */
31828 + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
31829 + blocksizes, sizeof(blocksizes));
31830 +
31831 + if (status != A_OK) {
31832 + AR_DEBUG_ASSERT(FALSE);
31833 + break;
31834 + }
31835 +
31836 + /* note: we actually get the block size of a mailbox other than 0, for SDIO the block
31837 + * size on mailbox 0 is artificially set to 1. So we use the block size that is set
31838 + * for the other 3 mailboxes */
31839 + pDev->BlockSize = blocksizes[MAILBOX_FOR_BLOCK_SIZE];
31840 + /* must be a power of 2 */
31841 + AR_DEBUG_ASSERT((pDev->BlockSize & (pDev->BlockSize - 1)) == 0);
31842 +
31843 + /* assemble mask, used for padding to a block */
31844 + pDev->BlockMask = pDev->BlockSize - 1;
31845 +
31846 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("BlockSize: %d, MailboxAddress:0x%X \n",
31847 + pDev->BlockSize, pDev->MailboxAddress));
31848 +
31849 + pDev->GetPendingEventsFunc = NULL;
31850 + /* see if the HIF layer implements the get pending events function */
31851 + HIFConfigureDevice(pDev->HIFDevice,
31852 + HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
31853 + &pDev->GetPendingEventsFunc,
31854 + sizeof(pDev->GetPendingEventsFunc));
31855 +
31856 + /* assume we can process HIF interrupt events asynchronously */
31857 + pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC;
31858 +
31859 + /* see if the HIF layer overrides this assumption */
31860 + HIFConfigureDevice(pDev->HIFDevice,
31861 + HIF_DEVICE_GET_IRQ_PROC_MODE,
31862 + &pDev->HifIRQProcessingMode,
31863 + sizeof(pDev->HifIRQProcessingMode));
31864 +
31865 + switch (pDev->HifIRQProcessingMode) {
31866 + case HIF_DEVICE_IRQ_SYNC_ONLY:
31867 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is SYNC ONLY\n"));
31868 + break;
31869 + case HIF_DEVICE_IRQ_ASYNC_SYNC:
31870 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n"));
31871 + break;
31872 + default:
31873 + AR_DEBUG_ASSERT(FALSE);
31874 + }
31875 +
31876 + pDev->HifMaskUmaskRecvEvent = NULL;
31877 +
31878 + /* see if the HIF layer implements the mask/unmask recv events function */
31879 + HIFConfigureDevice(pDev->HIFDevice,
31880 + HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC,
31881 + &pDev->HifMaskUmaskRecvEvent,
31882 + sizeof(pDev->HifMaskUmaskRecvEvent));
31883 +
31884 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%X , 0x%X\n",
31885 + (A_UINT32)pDev->GetPendingEventsFunc, (A_UINT32)pDev->HifMaskUmaskRecvEvent));
31886 +
31887 + status = DevDisableInterrupts(pDev);
31888 +
31889 + } while (FALSE);
31890 +
31891 + if (A_FAILED(status)) {
31892 + /* make sure handle is cleared */
31893 + HIFSetHandle(pDev->HIFDevice, NULL);
31894 + }
31895 +
31896 + return status;
31897 +
31898 +}
31899 +
31900 +static A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev)
31901 +{
31902 + A_STATUS status;
31903 + AR6K_IRQ_ENABLE_REGISTERS regs;
31904 +
31905 + LOCK_AR6K(pDev);
31906 +
31907 + /* Enable all the interrupts except for the dragon interrupt */
31908 + pDev->IrqEnableRegisters.int_status_enable = INT_STATUS_ENABLE_ERROR_SET(0x01) |
31909 + INT_STATUS_ENABLE_CPU_SET(0x01) |
31910 + INT_STATUS_ENABLE_COUNTER_SET(0x01);
31911 +
31912 + if (NULL == pDev->GetPendingEventsFunc) {
31913 + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
31914 + } else {
31915 + /* The HIF layer provided us with a pending events function which means that
31916 + * the detection of pending mbox messages is handled in the HIF layer.
31917 + * This is the case for the SPI2 interface.
31918 + * In the normal case we enable MBOX interrupts, for the case
31919 + * with HIFs that offer this mechanism, we keep these interrupts
31920 + * masked */
31921 + pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
31922 + }
31923 +
31924 +
31925 + /* Set up the CPU Interrupt Status Register */
31926 + pDev->IrqEnableRegisters.cpu_int_status_enable = CPU_INT_STATUS_ENABLE_BIT_SET(0x00);
31927 +
31928 + /* Set up the Error Interrupt Status Register */
31929 + pDev->IrqEnableRegisters.error_status_enable =
31930 + ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(0x01) |
31931 + ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(0x01);
31932 +
31933 + /* Set up the Counter Interrupt Status Register (only for debug interrupt to catch fatal errors) */
31934 + pDev->IrqEnableRegisters.counter_int_status_enable =
31935 + COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK);
31936 +
31937 + /* copy into our temp area */
31938 + A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
31939 +
31940 + UNLOCK_AR6K(pDev);
31941 +
31942 + /* always synchronous */
31943 + status = HIFReadWrite(pDev->HIFDevice,
31944 + INT_STATUS_ENABLE_ADDRESS,
31945 + &regs.int_status_enable,
31946 + AR6K_IRQ_ENABLE_REGS_SIZE,
31947 + HIF_WR_SYNC_BYTE_INC,
31948 + NULL);
31949 +
31950 + if (status != A_OK) {
31951 + /* Can't write it for some reason */
31952 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
31953 + ("Failed to update interrupt control registers err: %d\n", status));
31954 +
31955 + }
31956 +
31957 + return status;
31958 +}
31959 +
31960 +static A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev)
31961 +{
31962 + AR6K_IRQ_ENABLE_REGISTERS regs;
31963 +
31964 + LOCK_AR6K(pDev);
31965 + /* Disable all interrupts */
31966 + pDev->IrqEnableRegisters.int_status_enable = 0;
31967 + pDev->IrqEnableRegisters.cpu_int_status_enable = 0;
31968 + pDev->IrqEnableRegisters.error_status_enable = 0;
31969 + pDev->IrqEnableRegisters.counter_int_status_enable = 0;
31970 + /* copy into our temp area */
31971 + A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
31972 +
31973 + UNLOCK_AR6K(pDev);
31974 +
31975 + /* always synchronous */
31976 + return HIFReadWrite(pDev->HIFDevice,
31977 + INT_STATUS_ENABLE_ADDRESS,
31978 + &regs.int_status_enable,
31979 + AR6K_IRQ_ENABLE_REGS_SIZE,
31980 + HIF_WR_SYNC_BYTE_INC,
31981 + NULL);
31982 +}
31983 +
31984 +/* enable device interrupts */
31985 +A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev)
31986 +{
31987 + /* Unmask the host controller interrupts */
31988 + HIFUnMaskInterrupt(pDev->HIFDevice);
31989 +
31990 + return DevEnableInterrupts(pDev);
31991 +}
31992 +
31993 +/* disable all device interrupts */
31994 +A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev)
31995 +{
31996 + A_STATUS status;
31997 +
31998 + status = DevDisableInterrupts(pDev);
31999 +
32000 + if (A_SUCCESS(status)) {
32001 + /* Disable the interrupt at the HIF layer */
32002 + HIFMaskInterrupt(pDev->HIFDevice);
32003 + }
32004 +
32005 + return status;
32006 +}
32007 +
32008 +/* callback when our fetch to enable/disable completes */
32009 +static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacket)
32010 +{
32011 + AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
32012 +
32013 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev));
32014 +
32015 + if (A_FAILED(pPacket->Status)) {
32016 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
32017 + (" Failed to disable receiver, status:%d \n", pPacket->Status));
32018 + }
32019 + /* free this IO packet */
32020 + AR6KFreeIOPacket(pDev,pPacket);
32021 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDoEnableDisableRecvAsyncHandler \n"));
32022 +}
32023 +
32024 +/* disable packet reception (used in case the host runs out of buffers)
32025 + * this is the "override" method when the HIF reports another methods to
32026 + * disable recv events */
32027 +static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
32028 +{
32029 + A_STATUS status = A_OK;
32030 + HTC_PACKET *pIOPacket = NULL;
32031 +
32032 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n",
32033 + EnableRecv,AsyncMode));
32034 +
32035 + do {
32036 +
32037 + if (AsyncMode) {
32038 +
32039 + pIOPacket = AR6KAllocIOPacket(pDev);
32040 +
32041 + if (NULL == pIOPacket) {
32042 + status = A_NO_MEMORY;
32043 + AR_DEBUG_ASSERT(FALSE);
32044 + break;
32045 + }
32046 +
32047 + /* stick in our completion routine when the I/O operation completes */
32048 + pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
32049 + pIOPacket->pContext = pDev;
32050 +
32051 + /* call the HIF layer override and do this asynchronously */
32052 + status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
32053 + EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
32054 + pIOPacket);
32055 + break;
32056 + }
32057 +
32058 + /* if we get here we are doing it synchronously */
32059 + status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
32060 + EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
32061 + NULL);
32062 +
32063 + } while (FALSE);
32064 +
32065 + if (A_FAILED(status) && (pIOPacket != NULL)) {
32066 + AR6KFreeIOPacket(pDev,pIOPacket);
32067 + }
32068 +
32069 + return status;
32070 +}
32071 +
32072 +/* disable packet reception (used in case the host runs out of buffers)
32073 + * this is the "normal" method using the interrupt enable registers through
32074 + * the host I/F */
32075 +static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
32076 +{
32077 + A_STATUS status = A_OK;
32078 + HTC_PACKET *pIOPacket = NULL;
32079 + AR6K_IRQ_ENABLE_REGISTERS regs;
32080 +
32081 + /* take the lock to protect interrupt enable shadows */
32082 + LOCK_AR6K(pDev);
32083 +
32084 + if (EnableRecv) {
32085 + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
32086 + } else {
32087 + pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
32088 + }
32089 +
32090 + /* copy into our temp area */
32091 + A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
32092 + UNLOCK_AR6K(pDev);
32093 +
32094 + do {
32095 +
32096 + if (AsyncMode) {
32097 +
32098 + pIOPacket = AR6KAllocIOPacket(pDev);
32099 +
32100 + if (NULL == pIOPacket) {
32101 + status = A_NO_MEMORY;
32102 + AR_DEBUG_ASSERT(FALSE);
32103 + break;
32104 + }
32105 +
32106 + /* copy values to write to our async I/O buffer */
32107 + A_MEMCPY(pIOPacket->pBuffer,&regs,AR6K_IRQ_ENABLE_REGS_SIZE);
32108 +
32109 + /* stick in our completion routine when the I/O operation completes */
32110 + pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
32111 + pIOPacket->pContext = pDev;
32112 +
32113 + /* write it out asynchronously */
32114 + HIFReadWrite(pDev->HIFDevice,
32115 + INT_STATUS_ENABLE_ADDRESS,
32116 + pIOPacket->pBuffer,
32117 + AR6K_IRQ_ENABLE_REGS_SIZE,
32118 + HIF_WR_ASYNC_BYTE_INC,
32119 + pIOPacket);
32120 + break;
32121 + }
32122 +
32123 + /* if we get here we are doing it synchronously */
32124 +
32125 + status = HIFReadWrite(pDev->HIFDevice,
32126 + INT_STATUS_ENABLE_ADDRESS,
32127 + &regs.int_status_enable,
32128 + AR6K_IRQ_ENABLE_REGS_SIZE,
32129 + HIF_WR_SYNC_BYTE_INC,
32130 + NULL);
32131 +
32132 + } while (FALSE);
32133 +
32134 + if (A_FAILED(status) && (pIOPacket != NULL)) {
32135 + AR6KFreeIOPacket(pDev,pIOPacket);
32136 + }
32137 +
32138 + return status;
32139 +}
32140 +
32141 +
32142 +A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
32143 +{
32144 + if (NULL == pDev->HifMaskUmaskRecvEvent) {
32145 + return DevDoEnableDisableRecvNormal(pDev,FALSE,AsyncMode);
32146 + } else {
32147 + return DevDoEnableDisableRecvOverride(pDev,FALSE,AsyncMode);
32148 + }
32149 +}
32150 +
32151 +A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
32152 +{
32153 + if (NULL == pDev->HifMaskUmaskRecvEvent) {
32154 + return DevDoEnableDisableRecvNormal(pDev,TRUE,AsyncMode);
32155 + } else {
32156 + return DevDoEnableDisableRecvOverride(pDev,TRUE,AsyncMode);
32157 + }
32158 +}
32159 +
32160 +void DevDumpRegisters(AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs,
32161 + AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs)
32162 +{
32163 +
32164 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, ("\n<------- Register Table -------->\n"));
32165 +
32166 + if (pIrqProcRegs != NULL) {
32167 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32168 + ("Int Status: 0x%x\n",pIrqProcRegs->host_int_status));
32169 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32170 + ("CPU Int Status: 0x%x\n",pIrqProcRegs->cpu_int_status));
32171 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32172 + ("Error Int Status: 0x%x\n",pIrqProcRegs->error_int_status));
32173 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32174 + ("Counter Int Status: 0x%x\n",pIrqProcRegs->counter_int_status));
32175 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32176 + ("Mbox Frame: 0x%x\n",pIrqProcRegs->mbox_frame));
32177 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32178 + ("Rx Lookahead Valid: 0x%x\n",pIrqProcRegs->rx_lookahead_valid));
32179 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32180 + ("Rx Lookahead 0: 0x%x\n",pIrqProcRegs->rx_lookahead[0]));
32181 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32182 + ("Rx Lookahead 1: 0x%x\n",pIrqProcRegs->rx_lookahead[1]));
32183 + }
32184 +
32185 + if (pIrqEnableRegs != NULL) {
32186 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32187 + ("Int Status Enable: 0x%x\n",pIrqEnableRegs->int_status_enable));
32188 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP,
32189 + ("Counter Int Status Enable: 0x%x\n",pIrqEnableRegs->counter_int_status_enable));
32190 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, ("<------------------------------->\n"));
32191 + }
32192 +}
32193 +
32194 +
32195 +#ifdef MBOXHW_UNIT_TEST
32196 +
32197 +
32198 +/* This is a mailbox hardware unit test that must be called in a schedulable context
32199 + * This test is very simple, it will send a list of buffers with a counting pattern
32200 + * and the target will invert the data and send the message back
32201 + *
32202 + * the unit test has the following constraints:
32203 + *
32204 + * The target has at least 8 buffers of 256 bytes each. The host will send
32205 + * the following pattern of buffers in rapid succession :
32206 + *
32207 + * 1 buffer - 128 bytes
32208 + * 1 buffer - 256 bytes
32209 + * 1 buffer - 512 bytes
32210 + * 1 buffer - 1024 bytes
32211 + *
32212 + * The host will send the buffers to one mailbox and wait for buffers to be reflected
32213 + * back from the same mailbox. The target sends the buffers FIFO order.
32214 + * Once the final buffer has been received for a mailbox, the next mailbox is tested.
32215 + *
32216 + *
32217 + * Note: To simplifythe test , we assume that the chosen buffer sizes
32218 + * will fall on a nice block pad
32219 + *
32220 + * It is expected that higher-order tests will be written to stress the mailboxes using
32221 + * a message-based protocol (with some performance timming) that can create more
32222 + * randomness in the packets sent over mailboxes.
32223 + *
32224 + * */
32225 +
32226 +#define A_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1))
32227 +
32228 +#define BUFFER_BLOCK_PAD 128
32229 +
32230 +#if 0
32231 +#define BUFFER1 128
32232 +#define BUFFER2 256
32233 +#define BUFFER3 512
32234 +#define BUFFER4 1024
32235 +#endif
32236 +
32237 +#if 1
32238 +#define BUFFER1 80
32239 +#define BUFFER2 200
32240 +#define BUFFER3 444
32241 +#define BUFFER4 800
32242 +#endif
32243 +
32244 +#define TOTAL_BYTES (A_ROUND_UP_PWR2(BUFFER1,BUFFER_BLOCK_PAD) + \
32245 + A_ROUND_UP_PWR2(BUFFER2,BUFFER_BLOCK_PAD) + \
32246 + A_ROUND_UP_PWR2(BUFFER3,BUFFER_BLOCK_PAD) + \
32247 + A_ROUND_UP_PWR2(BUFFER4,BUFFER_BLOCK_PAD) )
32248 +
32249 +#define TEST_BYTES (BUFFER1 + BUFFER2 + BUFFER3 + BUFFER4)
32250 +
32251 +#define TEST_CREDITS_RECV_TIMEOUT 100
32252 +
32253 +static A_UINT8 g_Buffer[TOTAL_BYTES];
32254 +static A_UINT32 g_MailboxAddrs[AR6K_MAILBOXES];
32255 +static A_UINT32 g_BlockSizes[AR6K_MAILBOXES];
32256 +
32257 +#define BUFFER_PROC_LIST_DEPTH 4
32258 +
32259 +typedef struct _BUFFER_PROC_LIST{
32260 + A_UINT8 *pBuffer;
32261 + A_UINT32 length;
32262 +}BUFFER_PROC_LIST;
32263 +
32264 +
32265 +#define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \
32266 +{ \
32267 + (pList)->pBuffer = (pCurrpos); \
32268 + (pList)->length = (len); \
32269 + (pCurrpos) += (len); \
32270 + (pList)++; \
32271 +}
32272 +
32273 +/* a simple and crude way to send different "message" sizes */
32274 +static void AssembleBufferList(BUFFER_PROC_LIST *pList)
32275 +{
32276 + A_UINT8 *pBuffer = g_Buffer;
32277 +
32278 +#if BUFFER_PROC_LIST_DEPTH < 4
32279 +#error "Buffer processing list depth is not deep enough!!"
32280 +#endif
32281 +
32282 + PUSH_BUFF_PROC_ENTRY(pList,BUFFER1,pBuffer);
32283 + PUSH_BUFF_PROC_ENTRY(pList,BUFFER2,pBuffer);
32284 + PUSH_BUFF_PROC_ENTRY(pList,BUFFER3,pBuffer);
32285 + PUSH_BUFF_PROC_ENTRY(pList,BUFFER4,pBuffer);
32286 +
32287 +}
32288 +
32289 +#define FILL_ZERO TRUE
32290 +#define FILL_COUNTING FALSE
32291 +static void InitBuffers(A_BOOL Zero)
32292 +{
32293 + A_UINT16 *pBuffer16 = (A_UINT16 *)g_Buffer;
32294 + int i;
32295 +
32296 + /* fill buffer with 16 bit counting pattern or zeros */
32297 + for (i = 0; i < (TOTAL_BYTES / 2) ; i++) {
32298 + if (!Zero) {
32299 + pBuffer16[i] = (A_UINT16)i;
32300 + } else {
32301 + pBuffer16[i] = 0;
32302 + }
32303 + }
32304 +}
32305 +
32306 +
32307 +static A_BOOL CheckOneBuffer(A_UINT16 *pBuffer16, int Length)
32308 +{
32309 + int i;
32310 + A_UINT16 startCount;
32311 + A_BOOL success = TRUE;
32312 +
32313 + /* get the starting count */
32314 + startCount = pBuffer16[0];
32315 + /* invert it, this is the expected value */
32316 + startCount = ~startCount;
32317 + /* scan the buffer and verify */
32318 + for (i = 0; i < (Length / 2) ; i++,startCount++) {
32319 + /* target will invert all the data */
32320 + if ((A_UINT16)pBuffer16[i] != (A_UINT16)~startCount) {
32321 + success = FALSE;
32322 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Data Got:0x%X, Expecting:0x%X (offset:%d, total:%d) \n",
32323 + pBuffer16[i], ((A_UINT16)~startCount), i, Length));
32324 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("0x%X 0x%X 0x%X 0x%X \n",
32325 + pBuffer16[i], pBuffer16[i + 1], pBuffer16[i + 2],pBuffer16[i+3]));
32326 + break;
32327 + }
32328 + }
32329 +
32330 + return success;
32331 +}
32332 +
32333 +static A_BOOL CheckBuffers(void)
32334 +{
32335 + int i;
32336 + A_BOOL success = TRUE;
32337 + BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
32338 +
32339 + /* assemble the list */
32340 + AssembleBufferList(checkList);
32341 +
32342 + /* scan the buffers and verify */
32343 + for (i = 0; i < BUFFER_PROC_LIST_DEPTH ; i++) {
32344 + success = CheckOneBuffer((A_UINT16 *)checkList[i].pBuffer, checkList[i].length);
32345 + if (!success) {
32346 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n",
32347 + (A_UINT32)checkList[i].pBuffer, checkList[i].length));
32348 + break;
32349 + }
32350 + }
32351 +
32352 + return success;
32353 +}
32354 +
32355 + /* find the end marker for the last buffer we will be sending */
32356 +static A_UINT16 GetEndMarker(void)
32357 +{
32358 + A_UINT8 *pBuffer;
32359 + BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
32360 +
32361 + /* fill up buffers with the normal counting pattern */
32362 + InitBuffers(FILL_COUNTING);
32363 +
32364 + /* assemble the list we will be sending down */
32365 + AssembleBufferList(checkList);
32366 + /* point to the last 2 bytes of the last buffer */
32367 + pBuffer = &(checkList[BUFFER_PROC_LIST_DEPTH - 1].pBuffer[(checkList[BUFFER_PROC_LIST_DEPTH - 1].length) - 2]);
32368 +
32369 + /* the last count in the last buffer is the marker */
32370 + return (A_UINT16)pBuffer[0] | ((A_UINT16)pBuffer[1] << 8);
32371 +}
32372 +
32373 +#define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR
32374 +
32375 +/* send the ordered buffers to the target */
32376 +static A_STATUS SendBuffers(AR6K_DEVICE *pDev, int mbox)
32377 +{
32378 + A_STATUS status = A_OK;
32379 + A_UINT32 request = HIF_WR_SYNC_BLOCK_INC;
32380 + BUFFER_PROC_LIST sendList[BUFFER_PROC_LIST_DEPTH];
32381 + int i;
32382 + int totalBytes = 0;
32383 + int paddedLength;
32384 + int totalwPadding = 0;
32385 +
32386 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sending buffers on mailbox : %d \n",mbox));
32387 +
32388 + /* fill buffer with counting pattern */
32389 + InitBuffers(FILL_COUNTING);
32390 +
32391 + /* assemble the order in which we send */
32392 + AssembleBufferList(sendList);
32393 +
32394 + for (i = 0; i < BUFFER_PROC_LIST_DEPTH; i++) {
32395 +
32396 + /* we are doing block transfers, so we need to pad everything to a block size */
32397 + paddedLength = (sendList[i].length + (g_BlockSizes[mbox] - 1)) &
32398 + (~(g_BlockSizes[mbox] - 1));
32399 +
32400 + /* send each buffer synchronously */
32401 + status = HIFReadWrite(pDev->HIFDevice,
32402 + g_MailboxAddrs[mbox],
32403 + sendList[i].pBuffer,
32404 + paddedLength,
32405 + request,
32406 + NULL);
32407 + if (status != A_OK) {
32408 + break;
32409 + }
32410 + totalBytes += sendList[i].length;
32411 + totalwPadding += paddedLength;
32412 + }
32413 +
32414 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sent %d bytes (%d padded bytes) to mailbox : %d \n",totalBytes,totalwPadding,mbox));
32415 +
32416 + return status;
32417 +}
32418 +
32419 +/* poll the mailbox credit counter until we get a credit or timeout */
32420 +static A_STATUS GetCredits(AR6K_DEVICE *pDev, int mbox, int *pCredits)
32421 +{
32422 + A_STATUS status = A_OK;
32423 + int timeout = TEST_CREDITS_RECV_TIMEOUT;
32424 + A_UINT8 credits = 0;
32425 + A_UINT32 address;
32426 +
32427 + while (TRUE) {
32428 +
32429 + /* Read the counter register to get credits, this auto-decrements */
32430 + address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4;
32431 + status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits),
32432 + HIF_RD_SYNC_BYTE_FIX, NULL);
32433 + if (status != A_OK) {
32434 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
32435 + ("Unable to decrement the command credit count register (mbox=%d)\n",mbox));
32436 + status = A_ERROR;
32437 + break;
32438 + }
32439 +
32440 + if (credits) {
32441 + break;
32442 + }
32443 +
32444 + timeout--;
32445 +
32446 + if (timeout <= 0) {
32447 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
32448 + (" Timeout reading credit registers (mbox=%d, address:0x%X) \n",mbox,address));
32449 + status = A_ERROR;
32450 + break;
32451 + }
32452 +
32453 + /* delay a little, target may not be ready */
32454 + msleep(1000);
32455 +
32456 + }
32457 +
32458 + if (status == A_OK) {
32459 + *pCredits = credits;
32460 + }
32461 +
32462 + return status;
32463 +}
32464 +
32465 +
32466 +/* wait for the buffers to come back */
32467 +static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
32468 +{
32469 + A_STATUS status = A_OK;
32470 + A_UINT32 request = HIF_RD_SYNC_BLOCK_INC;
32471 + BUFFER_PROC_LIST recvList[BUFFER_PROC_LIST_DEPTH];
32472 + int curBuffer;
32473 + int credits;
32474 + int i;
32475 + int totalBytes = 0;
32476 + int paddedLength;
32477 + int totalwPadding = 0;
32478 +
32479 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for buffers on mailbox : %d \n",mbox));
32480 +
32481 + /* zero the buffers */
32482 + InitBuffers(FILL_ZERO);
32483 +
32484 + /* assemble the order in which we should receive */
32485 + AssembleBufferList(recvList);
32486 +
32487 + curBuffer = 0;
32488 +
32489 + while (curBuffer < BUFFER_PROC_LIST_DEPTH) {
32490 +
32491 + /* get number of buffers that have been completed, this blocks
32492 + * until we get at least 1 credit or it times out */
32493 + status = GetCredits(pDev, mbox, &credits);
32494 +
32495 + if (status != A_OK) {
32496 + break;
32497 + }
32498 +
32499 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got %d messages on mailbox : %d \n",credits, mbox));
32500 +
32501 + /* get all the buffers that are sitting on the queue */
32502 + for (i = 0; i < credits; i++) {
32503 + AR_DEBUG_ASSERT(curBuffer < BUFFER_PROC_LIST_DEPTH);
32504 + /* recv the current buffer synchronously, the buffers should come back in
32505 + * order... with padding applied by the target */
32506 + paddedLength = (recvList[curBuffer].length + (g_BlockSizes[mbox] - 1)) &
32507 + (~(g_BlockSizes[mbox] - 1));
32508 +
32509 + status = HIFReadWrite(pDev->HIFDevice,
32510 + g_MailboxAddrs[mbox],
32511 + recvList[curBuffer].pBuffer,
32512 + paddedLength,
32513 + request,
32514 + NULL);
32515 + if (status != A_OK) {
32516 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to read %d bytes on mailbox:%d : address:0x%X \n",
32517 + recvList[curBuffer].length, mbox, g_MailboxAddrs[mbox]));
32518 + break;
32519 + }
32520 +
32521 + totalwPadding += paddedLength;
32522 + totalBytes += recvList[curBuffer].length;
32523 + curBuffer++;
32524 + }
32525 +
32526 + if (status != A_OK) {
32527 + break;
32528 + }
32529 + /* go back and get some more */
32530 + credits = 0;
32531 + }
32532 +
32533 + if (totalBytes != TEST_BYTES) {
32534 + AR_DEBUG_ASSERT(FALSE);
32535 + } else {
32536 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got all buffers on mbox:%d total recv :%d (w/Padding : %d) \n",
32537 + mbox, totalBytes, totalwPadding));
32538 + }
32539 +
32540 + return status;
32541 +
32542 +
32543 +}
32544 +
32545 +static A_STATUS DoOneMboxHWTest(AR6K_DEVICE *pDev, int mbox)
32546 +{
32547 + A_STATUS status;
32548 +
32549 + do {
32550 + /* send out buffers */
32551 + status = SendBuffers(pDev,mbox);
32552 +
32553 + if (status != A_OK) {
32554 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox));
32555 + break;
32556 + }
32557 +
32558 + /* go get them, this will block */
32559 + status = RecvBuffers(pDev, mbox);
32560 +
32561 + if (status != A_OK) {
32562 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox));
32563 + break;
32564 + }
32565 +
32566 + /* check the returned data patterns */
32567 + if (!CheckBuffers()) {
32568 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer Verify Failed : mbox:%d\n",mbox));
32569 + status = A_ERROR;
32570 + break;
32571 + }
32572 +
32573 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox));
32574 +
32575 + } while (FALSE);
32576 +
32577 + return status;
32578 +}
32579 +
32580 +/* here is where the test starts */
32581 +A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
32582 +{
32583 + int i;
32584 + A_STATUS status;
32585 + int credits = 0;
32586 + A_UINT8 params[4];
32587 + int numBufs;
32588 + int bufferSize;
32589 + A_UINT16 temp;
32590 +
32591 +
32592 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START - \n"));
32593 +
32594 + do {
32595 + /* get the addresses for all 4 mailboxes */
32596 + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
32597 + g_MailboxAddrs, sizeof(g_MailboxAddrs));
32598 +
32599 + if (status != A_OK) {
32600 + AR_DEBUG_ASSERT(FALSE);
32601 + break;
32602 + }
32603 +
32604 + /* get the block sizes */
32605 + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
32606 + g_BlockSizes, sizeof(g_BlockSizes));
32607 +
32608 + if (status != A_OK) {
32609 + AR_DEBUG_ASSERT(FALSE);
32610 + break;
32611 + }
32612 +
32613 + /* note, the HIF layer usually reports mbox 0 to have a block size of
32614 + * 1, but our test wants to run in block-mode for all mailboxes, so we treat all mailboxes
32615 + * the same. */
32616 + g_BlockSizes[0] = g_BlockSizes[1];
32617 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Block Size to use: %d \n",g_BlockSizes[0]));
32618 +
32619 + if (g_BlockSizes[1] > BUFFER_BLOCK_PAD) {
32620 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("%d Block size is too large for buffer pad %d\n",
32621 + g_BlockSizes[1], BUFFER_BLOCK_PAD));
32622 + break;
32623 + }
32624 +
32625 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for target.... \n"));
32626 +
32627 + /* the target lets us know it is ready by giving us 1 credit on
32628 + * mailbox 0 */
32629 + status = GetCredits(pDev, 0, &credits);
32630 +
32631 + if (status != A_OK) {
32632 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n"));
32633 + break;
32634 + }
32635 +
32636 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Target is ready ...\n"));
32637 +
32638 + /* read the first 4 scratch registers */
32639 + status = HIFReadWrite(pDev->HIFDevice,
32640 + SCRATCH_ADDRESS,
32641 + params,
32642 + 4,
32643 + HIF_RD_SYNC_BYTE_INC,
32644 + NULL);
32645 +
32646 + if (status != A_OK) {
32647 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n"));
32648 + break;
32649 + }
32650 +
32651 + numBufs = params[0];
32652 + bufferSize = (int)(((A_UINT16)params[2] << 8) | (A_UINT16)params[1]);
32653 +
32654 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE,
32655 + ("Target parameters: bufs per mailbox:%d, buffer size:%d bytes (total space: %d, minimum required space (w/padding): %d) \n",
32656 + numBufs, bufferSize, (numBufs * bufferSize), TOTAL_BYTES));
32657 +
32658 + if ((numBufs * bufferSize) < TOTAL_BYTES) {
32659 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Not Enough buffer space to run test! need:%d, got:%d \n",
32660 + TOTAL_BYTES, (numBufs*bufferSize)));
32661 + status = A_ERROR;
32662 + break;
32663 + }
32664 +
32665 + temp = GetEndMarker();
32666 +
32667 + status = HIFReadWrite(pDev->HIFDevice,
32668 + SCRATCH_ADDRESS + 4,
32669 + (A_UINT8 *)&temp,
32670 + 2,
32671 + HIF_WR_SYNC_BYTE_INC,
32672 + NULL);
32673 +
32674 + if (status != A_OK) {
32675 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n"));
32676 + break;
32677 + }
32678 +
32679 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp));
32680 +
32681 + temp = (A_UINT16)g_BlockSizes[1];
32682 + /* convert to a mask */
32683 + temp = temp - 1;
32684 + status = HIFReadWrite(pDev->HIFDevice,
32685 + SCRATCH_ADDRESS + 6,
32686 + (A_UINT8 *)&temp,
32687 + 2,
32688 + HIF_WR_SYNC_BYTE_INC,
32689 + NULL);
32690 +
32691 + if (status != A_OK) {
32692 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n"));
32693 + break;
32694 + }
32695 +
32696 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Set Block Mask: 0x%X \n",temp));
32697 +
32698 + /* execute the test on each mailbox */
32699 + for (i = 0; i < AR6K_MAILBOXES; i++) {
32700 + status = DoOneMboxHWTest(pDev, i);
32701 + if (status != A_OK) {
32702 + break;
32703 + }
32704 + }
32705 +
32706 + } while (FALSE);
32707 +
32708 + if (status == A_OK) {
32709 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! - \n"));
32710 + } else {
32711 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! - \n"));
32712 + }
32713 + /* don't let HTC_Start continue, the target is actually not running any HTC code */
32714 + return A_ERROR;
32715 +}
32716 +#endif
32717 +
32718 +
32719 +
32720 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/htc/ar6k_events.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/ar6k_events.c
32721 --- linux-2.6.29-rc3.owrt/drivers/ar6000/htc/ar6k_events.c 1970-01-01 01:00:00.000000000 +0100
32722 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/ar6k_events.c 2009-05-10 22:27:59.000000000 +0200
32723 @@ -0,0 +1,638 @@
32724 +/*
32725 + * AR6K Driver layer event handling (i.e. interrupts, message polling)
32726 + *
32727 + * Copyright (c) 2007 Atheros Communications Inc.
32728 + * All rights reserved.
32729 + *
32730 + *
32731 + * This program is free software; you can redistribute it and/or modify
32732 + * it under the terms of the GNU General Public License version 2 as
32733 + * published by the Free Software Foundation;
32734 + *
32735 + * Software distributed under the License is distributed on an "AS
32736 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
32737 + * implied. See the License for the specific language governing
32738 + * rights and limitations under the License.
32739 + *
32740 + *
32741 + *
32742 + */
32743 +#include "a_config.h"
32744 +#include "athdefs.h"
32745 +#include "a_types.h"
32746 +#include "AR6Khwreg.h"
32747 +#include "a_osapi.h"
32748 +#include "a_debug.h"
32749 +#include "hif.h"
32750 +#include "htc_packet.h"
32751 +#include "ar6k.h"
32752 +
32753 +extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
32754 +extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
32755 +
32756 +static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev);
32757 +
32758 +#define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */
32759 +
32760 +/* completion routine for ALL HIF layer async I/O */
32761 +A_STATUS DevRWCompletionHandler(void *context, A_STATUS status)
32762 +{
32763 + HTC_PACKET *pPacket = (HTC_PACKET *)context;
32764 +
32765 + COMPLETE_HTC_PACKET(pPacket,status);
32766 +
32767 + return A_OK;
32768 +}
32769 +
32770 +/* mailbox recv message polling */
32771 +A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
32772 + A_UINT32 *pLookAhead,
32773 + int TimeoutMS)
32774 +{
32775 + A_STATUS status = A_OK;
32776 + int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS;
32777 +
32778 + AR_DEBUG_ASSERT(timeout > 0);
32779 +
32780 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n"));
32781 +
32782 + while (TRUE) {
32783 +
32784 + if (pDev->GetPendingEventsFunc != NULL)
32785 + {
32786 +
32787 + HIF_PENDING_EVENTS_INFO events;
32788 +
32789 + /* the HIF layer uses a special mechanism to get events, do this
32790 + * synchronously */
32791 + status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
32792 + &events,
32793 + NULL);
32794 + if (A_FAILED(status))
32795 + {
32796 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n"));
32797 + break;
32798 + }
32799 +
32800 + if (events.Events & HIF_RECV_MSG_AVAIL)
32801 + {
32802 + /* there is a message available, the lookahead should be valid now */
32803 + *pLookAhead = events.LookAhead;
32804 +
32805 + break;
32806 + }
32807 + }
32808 + else
32809 + {
32810 +
32811 + /* this is the standard HIF way.... */
32812 + /* load the register table */
32813 + status = HIFReadWrite(pDev->HIFDevice,
32814 + HOST_INT_STATUS_ADDRESS,
32815 + (A_UINT8 *)&pDev->IrqProcRegisters,
32816 + AR6K_IRQ_PROC_REGS_SIZE,
32817 + HIF_RD_SYNC_BYTE_INC,
32818 + NULL);
32819 +
32820 + if (A_FAILED(status))
32821 + {
32822 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n"));
32823 + break;
32824 + }
32825 +
32826 + /* check for MBOX data and valid lookahead */
32827 + if (pDev->IrqProcRegisters.host_int_status & (1 << HTC_MAILBOX))
32828 + {
32829 + if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX))
32830 + {
32831 + /* mailbox has a message and the look ahead is valid */
32832 + *pLookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX];
32833 + break;
32834 + }
32835 + }
32836 +
32837 + }
32838 +
32839 + timeout--;
32840 +
32841 + if (timeout <= 0)
32842 + {
32843 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Timeout waiting for recv message \n"));
32844 + status = A_ERROR;
32845 +
32846 + /* check if the target asserted */
32847 + if ( pDev->IrqProcRegisters.counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) {
32848 + /* target signaled an assert, process this pending interrupt
32849 + * this will call the target failure handler */
32850 + DevServiceDebugInterrupt(pDev);
32851 + }
32852 +
32853 + break;
32854 + }
32855 +
32856 + /* delay a little */
32857 + msleep(DELAY_PER_INTERVAL_MS);
32858 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Retry Mbox Poll : %d \n",timeout));
32859 + }
32860 +
32861 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevPollMboxMsgRecv \n"));
32862 +
32863 + return status;
32864 +}
32865 +
32866 +static A_STATUS DevServiceCPUInterrupt(AR6K_DEVICE *pDev)
32867 +{
32868 + A_STATUS status;
32869 + A_UINT8 cpu_int_status;
32870 + A_UINT8 regBuffer[4];
32871 +
32872 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n"));
32873 + cpu_int_status = pDev->IrqProcRegisters.cpu_int_status &
32874 + pDev->IrqEnableRegisters.cpu_int_status_enable;
32875 + AR_DEBUG_ASSERT(cpu_int_status);
32876 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
32877 + ("Valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
32878 + cpu_int_status));
32879 +
32880 + /* Clear the interrupt */
32881 + pDev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status; /* W1C */
32882 +
32883 + /* set up the register transfer buffer to hit the register 4 times , this is done
32884 + * to make the access 4-byte aligned to mitigate issues with host bus interconnects that
32885 + * restrict bus transfer lengths to be a multiple of 4-bytes */
32886 +
32887 + /* set W1C value to clear the interrupt, this hits the register first */
32888 + regBuffer[0] = cpu_int_status;
32889 + /* the remaining 4 values are set to zero which have no-effect */
32890 + regBuffer[1] = 0;
32891 + regBuffer[2] = 0;
32892 + regBuffer[3] = 0;
32893 +
32894 + status = HIFReadWrite(pDev->HIFDevice,
32895 + CPU_INT_STATUS_ADDRESS,
32896 + regBuffer,
32897 + 4,
32898 + HIF_WR_SYNC_BYTE_FIX,
32899 + NULL);
32900 +
32901 + AR_DEBUG_ASSERT(status == A_OK);
32902 + return status;
32903 +}
32904 +
32905 +
32906 +static A_STATUS DevServiceErrorInterrupt(AR6K_DEVICE *pDev)
32907 +{
32908 + A_STATUS status;
32909 + A_UINT8 error_int_status;
32910 + A_UINT8 regBuffer[4];
32911 +
32912 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n"));
32913 + error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F;
32914 + AR_DEBUG_ASSERT(error_int_status);
32915 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
32916 + ("Valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n",
32917 + error_int_status));
32918 +
32919 + if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) {
32920 + /* Wakeup */
32921 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n"));
32922 + }
32923 +
32924 + if (ERROR_INT_STATUS_RX_UNDERFLOW_GET(error_int_status)) {
32925 + /* Rx Underflow */
32926 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Rx Underflow\n"));
32927 + }
32928 +
32929 + if (ERROR_INT_STATUS_TX_OVERFLOW_GET(error_int_status)) {
32930 + /* Tx Overflow */
32931 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Error : Tx Overflow\n"));
32932 + }
32933 +
32934 + /* Clear the interrupt */
32935 + pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */
32936 +
32937 + /* set up the register transfer buffer to hit the register 4 times , this is done
32938 + * to make the access 4-byte aligned to mitigate issues with host bus interconnects that
32939 + * restrict bus transfer lengths to be a multiple of 4-bytes */
32940 +
32941 + /* set W1C value to clear the interrupt, this hits the register first */
32942 + regBuffer[0] = error_int_status;
32943 + /* the remaining 4 values are set to zero which have no-effect */
32944 + regBuffer[1] = 0;
32945 + regBuffer[2] = 0;
32946 + regBuffer[3] = 0;
32947 +
32948 + status = HIFReadWrite(pDev->HIFDevice,
32949 + ERROR_INT_STATUS_ADDRESS,
32950 + regBuffer,
32951 + 4,
32952 + HIF_WR_SYNC_BYTE_FIX,
32953 + NULL);
32954 +
32955 + AR_DEBUG_ASSERT(status == A_OK);
32956 + return status;
32957 +}
32958 +
32959 +static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev)
32960 +{
32961 + A_UINT32 dummy;
32962 + A_STATUS status;
32963 +
32964 + /* Send a target failure event to the application */
32965 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n"));
32966 +
32967 + if (pDev->TargetFailureCallback != NULL) {
32968 + pDev->TargetFailureCallback(pDev->HTCContext);
32969 + }
32970 +
32971 + /* clear the interrupt , the debug error interrupt is
32972 + * counter 0 */
32973 + /* read counter to clear interrupt */
32974 + status = HIFReadWrite(pDev->HIFDevice,
32975 + COUNT_DEC_ADDRESS,
32976 + (A_UINT8 *)&dummy,
32977 + 4,
32978 + HIF_RD_SYNC_BYTE_INC,
32979 + NULL);
32980 +
32981 + AR_DEBUG_ASSERT(status == A_OK);
32982 + return status;
32983 +}
32984 +
32985 +static A_STATUS DevServiceCounterInterrupt(AR6K_DEVICE *pDev)
32986 +{
32987 + A_UINT8 counter_int_status;
32988 +
32989 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n"));
32990 +
32991 + counter_int_status = pDev->IrqProcRegisters.counter_int_status &
32992 + pDev->IrqEnableRegisters.counter_int_status_enable;
32993 +
32994 + AR_DEBUG_ASSERT(counter_int_status);
32995 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
32996 + ("Valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n",
32997 + counter_int_status));
32998 +
32999 + /* Check if the debug interrupt is pending */
33000 + if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) {
33001 + return DevServiceDebugInterrupt(pDev);
33002 + }
33003 +
33004 + return A_OK;
33005 +}
33006 +
33007 +/* callback when our fetch to get interrupt status registers completes */
33008 +static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
33009 +{
33010 + AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
33011 + A_UINT32 lookAhead = 0;
33012 + A_BOOL otherInts = FALSE;
33013 +
33014 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev));
33015 +
33016 + do {
33017 +
33018 + if (A_FAILED(pPacket->Status)) {
33019 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
33020 + (" GetEvents I/O request failed, status:%d \n", pPacket->Status));
33021 + /* bail out, don't unmask HIF interrupt */
33022 + break;
33023 + }
33024 +
33025 + if (pDev->GetPendingEventsFunc != NULL) {
33026 + /* the HIF layer collected the information for us */
33027 + HIF_PENDING_EVENTS_INFO *pEvents = (HIF_PENDING_EVENTS_INFO *)pPacket->pBuffer;
33028 + if (pEvents->Events & HIF_RECV_MSG_AVAIL) {
33029 + lookAhead = pEvents->LookAhead;
33030 + if (0 == lookAhead) {
33031 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler1, lookAhead is zero! \n"));
33032 + }
33033 + }
33034 + if (pEvents->Events & HIF_OTHER_EVENTS) {
33035 + otherInts = TRUE;
33036 + }
33037 + } else {
33038 + /* standard interrupt table handling.... */
33039 + AR6K_IRQ_PROC_REGISTERS *pReg = (AR6K_IRQ_PROC_REGISTERS *)pPacket->pBuffer;
33040 + A_UINT8 host_int_status;
33041 +
33042 + host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable;
33043 +
33044 + if (host_int_status & (1 << HTC_MAILBOX)) {
33045 + host_int_status &= ~(1 << HTC_MAILBOX);
33046 + if (pReg->rx_lookahead_valid & (1 << HTC_MAILBOX)) {
33047 + /* mailbox has a message and the look ahead is valid */
33048 + lookAhead = pReg->rx_lookahead[HTC_MAILBOX];
33049 + if (0 == lookAhead) {
33050 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" DevGetEventAsyncHandler2, lookAhead is zero! \n"));
33051 + }
33052 + }
33053 + }
33054 +
33055 + if (host_int_status) {
33056 + /* there are other interrupts to handle */
33057 + otherInts = TRUE;
33058 + }
33059 + }
33060 +
33061 + if (otherInts || (lookAhead == 0)) {
33062 + /* if there are other interrupts to process, we cannot do this in the async handler so
33063 + * ack the interrupt which will cause our sync handler to run again
33064 + * if however there are no more messages, we can now ack the interrupt */
33065 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
33066 + (" Acking interrupt from DevGetEventAsyncHandler (otherints:%d, lookahead:0x%X)\n",
33067 + otherInts, lookAhead));
33068 + HIFAckInterrupt(pDev->HIFDevice);
33069 + } else {
33070 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
33071 + (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n",
33072 + lookAhead));
33073 + /* lookahead is non-zero and there are no other interrupts to service,
33074 + * go get the next message */
33075 + pDev->MessagePendingCallback(pDev->HTCContext, lookAhead, NULL);
33076 + }
33077 +
33078 + } while (FALSE);
33079 +
33080 + /* free this IO packet */
33081 + AR6KFreeIOPacket(pDev,pPacket);
33082 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n"));
33083 +}
33084 +
33085 +/* called by the HTC layer when it wants us to check if the device has any more pending
33086 + * recv messages, this starts off a series of async requests to read interrupt registers */
33087 +A_STATUS DevCheckPendingRecvMsgsAsync(void *context)
33088 +{
33089 + AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
33090 + A_STATUS status = A_OK;
33091 + HTC_PACKET *pIOPacket;
33092 +
33093 + /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can
33094 + * cause us to switch contexts */
33095 +
33096 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%X)\n", (A_UINT32)pDev));
33097 +
33098 + do {
33099 +
33100 + if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
33101 + /* break the async processing chain right here, no need to continue.
33102 + * The DevDsrHandler() will handle things in a loop when things are driven
33103 + * synchronously */
33104 + break;
33105 + }
33106 + /* first allocate one of our HTC packets we created for async I/O
33107 + * we reuse HTC packet definitions so that we can use the completion mechanism
33108 + * in DevRWCompletionHandler() */
33109 + pIOPacket = AR6KAllocIOPacket(pDev);
33110 +
33111 + if (NULL == pIOPacket) {
33112 + /* there should be only 1 asynchronous request out at a time to read these registers
33113 + * so this should actually never happen */
33114 + status = A_NO_MEMORY;
33115 + AR_DEBUG_ASSERT(FALSE);
33116 + break;
33117 + }
33118 +
33119 + /* stick in our completion routine when the I/O operation completes */
33120 + pIOPacket->Completion = DevGetEventAsyncHandler;
33121 + pIOPacket->pContext = pDev;
33122 +
33123 + if (pDev->GetPendingEventsFunc) {
33124 + /* HIF layer has it's own mechanism, pass the IO to it.. */
33125 + status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
33126 + (HIF_PENDING_EVENTS_INFO *)pIOPacket->pBuffer,
33127 + pIOPacket);
33128 +
33129 + } else {
33130 + /* standard way, read the interrupt register table asynchronously again */
33131 + status = HIFReadWrite(pDev->HIFDevice,
33132 + HOST_INT_STATUS_ADDRESS,
33133 + pIOPacket->pBuffer,
33134 + AR6K_IRQ_PROC_REGS_SIZE,
33135 + HIF_RD_ASYNC_BYTE_INC,
33136 + pIOPacket);
33137 + }
33138 +
33139 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n"));
33140 + } while (FALSE);
33141 +
33142 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n"));
33143 +
33144 + return status;
33145 +}
33146 +
33147 +/* process pending interrupts synchronously */
33148 +static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pASyncProcessing)
33149 +{
33150 + A_STATUS status = A_OK;
33151 + A_UINT8 host_int_status = 0;
33152 + A_UINT32 lookAhead = 0;
33153 +
33154 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%X)\n", (A_UINT32)pDev));
33155 +
33156 + /*** NOTE: the HIF implementation guarantees that the context of this call allows
33157 + * us to perform SYNCHRONOUS I/O, that is we can block, sleep or call any API that
33158 + * can block or switch thread/task ontexts.
33159 + * This is a fully schedulable context.
33160 + * */
33161 + do {
33162 +
33163 + if (pDev->GetPendingEventsFunc != NULL) {
33164 + HIF_PENDING_EVENTS_INFO events;
33165 +
33166 + /* the HIF layer uses a special mechanism to get events
33167 + * get this synchronously */
33168 + status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
33169 + &events,
33170 + NULL);
33171 +
33172 + if (A_FAILED(status)) {
33173 + break;
33174 + }
33175 +
33176 + if (events.Events & HIF_RECV_MSG_AVAIL) {
33177 + lookAhead = events.LookAhead;
33178 + if (0 == lookAhead) {
33179 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs1 lookAhead is zero! \n"));
33180 + }
33181 + }
33182 +
33183 + if (!(events.Events & HIF_OTHER_EVENTS) ||
33184 + !(pDev->IrqEnableRegisters.int_status_enable & OTHER_INTS_ENABLED)) {
33185 + /* no need to read the register table, no other interesting interrupts.
33186 + * Some interfaces (like SPI) can shadow interrupt sources without
33187 + * requiring the host to do a full table read */
33188 + break;
33189 + }
33190 +
33191 + /* otherwise fall through and read the register table */
33192 + }
33193 +
33194 + /*
33195 + * Read the first 28 bytes of the HTC register table. This will yield us
33196 + * the value of different int status registers and the lookahead
33197 + * registers.
33198 + * length = sizeof(int_status) + sizeof(cpu_int_status) +
33199 + * sizeof(error_int_status) + sizeof(counter_int_status) +
33200 + * sizeof(mbox_frame) + sizeof(rx_lookahead_valid) +
33201 + * sizeof(hole) + sizeof(rx_lookahead) +
33202 + * sizeof(int_status_enable) + sizeof(cpu_int_status_enable) +
33203 + * sizeof(error_status_enable) +
33204 + * sizeof(counter_int_status_enable);
33205 + *
33206 + */
33207 + status = HIFReadWrite(pDev->HIFDevice,
33208 + HOST_INT_STATUS_ADDRESS,
33209 + (A_UINT8 *)&pDev->IrqProcRegisters,
33210 + AR6K_IRQ_PROC_REGS_SIZE,
33211 + HIF_RD_SYNC_BYTE_INC,
33212 + NULL);
33213 +
33214 + if (A_FAILED(status)) {
33215 + break;
33216 + }
33217 +
33218 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) {
33219 + DevDumpRegisters(&pDev->IrqProcRegisters,
33220 + &pDev->IrqEnableRegisters);
33221 + }
33222 +
33223 + /* Update only those registers that are enabled */
33224 + host_int_status = pDev->IrqProcRegisters.host_int_status &
33225 + pDev->IrqEnableRegisters.int_status_enable;
33226 +
33227 + if (NULL == pDev->GetPendingEventsFunc) {
33228 + /* only look at mailbox status if the HIF layer did not provide this function,
33229 + * on some HIF interfaces reading the RX lookahead is not valid to do */
33230 + if (host_int_status & (1 << HTC_MAILBOX)) {
33231 + /* mask out pending mailbox value, we use "lookAhead" as the real flag for
33232 + * mailbox processing below */
33233 + host_int_status &= ~(1 << HTC_MAILBOX);
33234 + if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX)) {
33235 + /* mailbox has a message and the look ahead is valid */
33236 + lookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX];
33237 + if (0 == lookAhead) {
33238 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" ProcessPendingIRQs2, lookAhead is zero! \n"));
33239 + }
33240 + }
33241 + }
33242 + } else {
33243 + /* not valid to check if the HIF has another mechanism for reading mailbox pending status*/
33244 + host_int_status &= ~(1 << HTC_MAILBOX);
33245 + }
33246 +
33247 + } while (FALSE);
33248 +
33249 +
33250 + do {
33251 +
33252 + /* did the interrupt status fetches succeed? */
33253 + if (A_FAILED(status)) {
33254 + break;
33255 + }
33256 +
33257 + if ((0 == host_int_status) && (0 == lookAhead)) {
33258 + /* nothing to process, the caller can use this to break out of a loop */
33259 + *pDone = TRUE;
33260 + break;
33261 + }
33262 +
33263 + if (lookAhead != 0) {
33264 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Pending mailbox message, LookAhead: 0x%X\n",lookAhead));
33265 + /* Mailbox Interrupt, the HTC layer may issue async requests to empty the
33266 + * mailbox...
33267 + * When emptying the recv mailbox we use the async handler above called from the
33268 + * completion routine of the callers read request. This can improve performance
33269 + * by reducing context switching when we rapidly pull packets */
33270 + status = pDev->MessagePendingCallback(pDev->HTCContext, lookAhead, pASyncProcessing);
33271 + if (A_FAILED(status)) {
33272 + break;
33273 + }
33274 + }
33275 +
33276 + /* now handle the rest of them */
33277 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
33278 + (" Valid interrupt source(s) for OTHER interrupts: 0x%x\n",
33279 + host_int_status));
33280 +
33281 + if (HOST_INT_STATUS_CPU_GET(host_int_status)) {
33282 + /* CPU Interrupt */
33283 + status = DevServiceCPUInterrupt(pDev);
33284 + if (A_FAILED(status)){
33285 + break;
33286 + }
33287 + }
33288 +
33289 + if (HOST_INT_STATUS_ERROR_GET(host_int_status)) {
33290 + /* Error Interrupt */
33291 + status = DevServiceErrorInterrupt(pDev);
33292 + if (A_FAILED(status)){
33293 + break;
33294 + }
33295 + }
33296 +
33297 + if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) {
33298 + /* Counter Interrupt */
33299 + status = DevServiceCounterInterrupt(pDev);
33300 + if (A_FAILED(status)){
33301 + break;
33302 + }
33303 + }
33304 +
33305 + } while (FALSE);
33306 +
33307 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n",
33308 + *pDone, *pASyncProcessing, status));
33309 +
33310 + return status;
33311 +}
33312 +
33313 +
33314 +/* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/
33315 +A_STATUS DevDsrHandler(void *context)
33316 +{
33317 + AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
33318 + A_STATUS status = A_OK;
33319 + A_BOOL done = FALSE;
33320 + A_BOOL asyncProc = FALSE;
33321 +
33322 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%X)\n", (A_UINT32)pDev));
33323 +
33324 +
33325 + while (!done) {
33326 + status = ProcessPendingIRQs(pDev, &done, &asyncProc);
33327 + if (A_FAILED(status)) {
33328 + break;
33329 + }
33330 +
33331 + if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
33332 + /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */
33333 + asyncProc = FALSE;
33334 + /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers.
33335 + * this has a nice side effect of blocking us until all async read requests are completed.
33336 + * This behavior is required on some HIF implementations that do not allow ASYNC
33337 + * processing in interrupt handlers (like Windows CE) */
33338 + }
33339 +
33340 + if (asyncProc) {
33341 + /* the function performed some async I/O for performance, we
33342 + need to exit the ISR immediately, the check below will prevent the interrupt from being
33343 + Ack'd while we handle it asynchronously */
33344 + break;
33345 + }
33346 +
33347 + }
33348 +
33349 + if (A_SUCCESS(status) && !asyncProc) {
33350 + /* Ack the interrupt only if :
33351 + * 1. we did not get any errors in processing interrupts
33352 + * 2. there are no outstanding async processing requests */
33353 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Acking interrupt from DevDsrHandler \n"));
33354 + HIFAckInterrupt(pDev->HIFDevice);
33355 + }
33356 +
33357 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n"));
33358 + return A_OK;
33359 +}
33360 +
33361 +
33362 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/htc/ar6k.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/ar6k.h
33363 --- linux-2.6.29-rc3.owrt/drivers/ar6000/htc/ar6k.h 1970-01-01 01:00:00.000000000 +0100
33364 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/ar6k.h 2009-05-10 22:27:59.000000000 +0200
33365 @@ -0,0 +1,191 @@
33366 +/*
33367 + *
33368 + * Copyright (c) 2007 Atheros Communications Inc.
33369 + * All rights reserved.
33370 + *
33371 + *
33372 + * This program is free software; you can redistribute it and/or modify
33373 + * it under the terms of the GNU General Public License version 2 as
33374 + * published by the Free Software Foundation;
33375 + *
33376 + * Software distributed under the License is distributed on an "AS
33377 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
33378 + * implied. See the License for the specific language governing
33379 + * rights and limitations under the License.
33380 + *
33381 + *
33382 + *
33383 + */
33384 +
33385 +#ifndef AR6K_H_
33386 +#define AR6K_H_
33387 +
33388 +#define AR6K_MAILBOXES 4
33389 +
33390 +/* HTC runs over mailbox 0 */
33391 +#define HTC_MAILBOX 0
33392 +
33393 +#define AR6K_TARGET_DEBUG_INTR_MASK 0x01
33394 +
33395 +#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \
33396 + INT_STATUS_ENABLE_CPU_MASK | \
33397 + INT_STATUS_ENABLE_COUNTER_MASK)
33398 +
33399 +//#define MBOXHW_UNIT_TEST 1
33400 +
33401 +#include "athstartpack.h"
33402 +typedef PREPACK struct _AR6K_IRQ_PROC_REGISTERS {
33403 + A_UINT8 host_int_status;
33404 + A_UINT8 cpu_int_status;
33405 + A_UINT8 error_int_status;
33406 + A_UINT8 counter_int_status;
33407 + A_UINT8 mbox_frame;
33408 + A_UINT8 rx_lookahead_valid;
33409 + A_UINT8 hole[2];
33410 + A_UINT32 rx_lookahead[2];
33411 +} POSTPACK AR6K_IRQ_PROC_REGISTERS;
33412 +
33413 +#define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS)
33414 +
33415 +
33416 +
33417 +typedef PREPACK struct _AR6K_IRQ_ENABLE_REGISTERS {
33418 + A_UINT8 int_status_enable;
33419 + A_UINT8 cpu_int_status_enable;
33420 + A_UINT8 error_status_enable;
33421 + A_UINT8 counter_int_status_enable;
33422 +} POSTPACK AR6K_IRQ_ENABLE_REGISTERS;
33423 +
33424 +#include "athendpack.h"
33425 +
33426 +#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(AR6K_IRQ_ENABLE_REGISTERS)
33427 +
33428 +#define AR6K_REG_IO_BUFFER_SIZE 32
33429 +#define AR6K_MAX_REG_IO_BUFFERS 8
33430 +
33431 +/* buffers for ASYNC I/O */
33432 +typedef struct AR6K_ASYNC_REG_IO_BUFFER {
33433 + HTC_PACKET HtcPacket; /* we use an HTC packet as a wrapper for our async register-based I/O */
33434 + A_UINT8 Buffer[AR6K_REG_IO_BUFFER_SIZE];
33435 +} AR6K_ASYNC_REG_IO_BUFFER;
33436 +
33437 +typedef struct _AR6K_DEVICE {
33438 + A_MUTEX_T Lock;
33439 + AR6K_IRQ_PROC_REGISTERS IrqProcRegisters;
33440 + AR6K_IRQ_ENABLE_REGISTERS IrqEnableRegisters;
33441 + void *HIFDevice;
33442 + A_UINT32 BlockSize;
33443 + A_UINT32 BlockMask;
33444 + A_UINT32 MailboxAddress;
33445 + HIF_PENDING_EVENTS_FUNC GetPendingEventsFunc;
33446 + void *HTCContext;
33447 + HTC_PACKET_QUEUE RegisterIOList;
33448 + AR6K_ASYNC_REG_IO_BUFFER RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
33449 + void (*TargetFailureCallback)(void *Context);
33450 + A_STATUS (*MessagePendingCallback)(void *Context, A_UINT32 LookAhead, A_BOOL *pAsyncProc);
33451 + HIF_DEVICE_IRQ_PROCESSING_MODE HifIRQProcessingMode;
33452 + HIF_MASK_UNMASK_RECV_EVENT HifMaskUmaskRecvEvent;
33453 +} AR6K_DEVICE;
33454 +
33455 +#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY)
33456 +
33457 +A_STATUS DevSetup(AR6K_DEVICE *pDev);
33458 +A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev);
33459 +A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev);
33460 +A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
33461 + A_UINT32 *pLookAhead,
33462 + int TimeoutMS);
33463 +A_STATUS DevRWCompletionHandler(void *context, A_STATUS status);
33464 +A_STATUS DevDsrHandler(void *context);
33465 +A_STATUS DevCheckPendingRecvMsgsAsync(void *context);
33466 +void DevDumpRegisters(AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs,
33467 + AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs);
33468 +
33469 +#define DEV_STOP_RECV_ASYNC TRUE
33470 +#define DEV_STOP_RECV_SYNC FALSE
33471 +#define DEV_ENABLE_RECV_ASYNC TRUE
33472 +#define DEV_ENABLE_RECV_SYNC FALSE
33473 +A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
33474 +A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
33475 +
33476 +static INLINE A_STATUS DevSendPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 SendLength) {
33477 + A_UINT32 paddedLength;
33478 + A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
33479 + A_STATUS status;
33480 +
33481 + /* adjust the length to be a multiple of block size if appropriate */
33482 + paddedLength = (SendLength + (pDev->BlockMask)) &
33483 + (~(pDev->BlockMask));
33484 +#if 0 // BufferLength may not be set in , fix this...
33485 + if (paddedLength > pPacket->BufferLength) {
33486 + AR_DEBUG_ASSERT(FALSE);
33487 + if (pPacket->Completion != NULL) {
33488 + COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
33489 + }
33490 + return A_EINVAL;
33491 + }
33492 +#endif
33493 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
33494 + ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n",
33495 + paddedLength,
33496 + pDev->MailboxAddress,
33497 + sync ? "SYNC" : "ASYNC"));
33498 +
33499 + status = HIFReadWrite(pDev->HIFDevice,
33500 + pDev->MailboxAddress,
33501 + pPacket->pBuffer,
33502 + paddedLength, /* the padded length */
33503 + sync ? HIF_WR_SYNC_BLOCK_INC : HIF_WR_ASYNC_BLOCK_INC,
33504 + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
33505 +
33506 + if (sync) {
33507 + pPacket->Status = status;
33508 + }
33509 +
33510 + return status;
33511 +}
33512 +
33513 +static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 RecvLength) {
33514 + A_UINT32 paddedLength;
33515 + A_STATUS status;
33516 + A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
33517 +
33518 + /* adjust the length to be a multiple of block size if appropriate */
33519 + paddedLength = (RecvLength + (pDev->BlockMask)) &
33520 + (~(pDev->BlockMask));
33521 + if (paddedLength > pPacket->BufferLength) {
33522 + AR_DEBUG_ASSERT(FALSE);
33523 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
33524 + ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
33525 + paddedLength,RecvLength,pPacket->BufferLength));
33526 + if (pPacket->Completion != NULL) {
33527 + COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
33528 + }
33529 + return A_EINVAL;
33530 + }
33531 +
33532 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
33533 + ("DevRecvPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n",
33534 + paddedLength,
33535 + pDev->MailboxAddress,
33536 + sync ? "SYNC" : "ASYNC"));
33537 +
33538 + status = HIFReadWrite(pDev->HIFDevice,
33539 + pDev->MailboxAddress,
33540 + pPacket->pBuffer,
33541 + paddedLength,
33542 + sync ? HIF_RD_SYNC_BLOCK_INC : HIF_RD_ASYNC_BLOCK_INC,
33543 + sync ? NULL : pPacket); /* pass the packet as the context to the HIF request */
33544 +
33545 + if (sync) {
33546 + pPacket->Status = status;
33547 + }
33548 +
33549 + return status;
33550 +}
33551 +
33552 +#ifdef MBOXHW_UNIT_TEST
33553 +A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev);
33554 +#endif
33555 +
33556 +#endif /*AR6K_H_*/
33557 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc.c
33558 --- linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc.c 1970-01-01 01:00:00.000000000 +0100
33559 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc.c 2009-05-10 22:27:59.000000000 +0200
33560 @@ -0,0 +1,508 @@
33561 +/*
33562 + *
33563 + * Copyright (c) 2007 Atheros Communications Inc.
33564 + * All rights reserved.
33565 + *
33566 + *
33567 + * This program is free software; you can redistribute it and/or modify
33568 + * it under the terms of the GNU General Public License version 2 as
33569 + * published by the Free Software Foundation;
33570 + *
33571 + * Software distributed under the License is distributed on an "AS
33572 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
33573 + * implied. See the License for the specific language governing
33574 + * rights and limitations under the License.
33575 + *
33576 + *
33577 + *
33578 + */
33579 +
33580 +#include "htc_internal.h"
33581 +
33582 +
33583 +static HTC_INIT_INFO HTCInitInfo = {NULL,NULL,NULL};
33584 +static A_BOOL HTCInitialized = FALSE;
33585 +
33586 +static A_STATUS HTCTargetInsertedHandler(void *hif_handle);
33587 +static A_STATUS HTCTargetRemovedHandler(void *handle, A_STATUS status);
33588 +static void HTCReportFailure(void *Context);
33589 +
33590 +/* Initializes the HTC layer */
33591 +A_STATUS HTCInit(HTC_INIT_INFO *pInitInfo)
33592 +{
33593 + HTC_CALLBACKS htcCallbacks;
33594 +
33595 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Enter\n"));
33596 + if (HTCInitialized) {
33597 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Exit\n"));
33598 + return A_OK;
33599 + }
33600 +
33601 + A_MEMCPY(&HTCInitInfo,pInitInfo,sizeof(HTC_INIT_INFO));
33602 +
33603 + A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS));
33604 +
33605 + /* setup HIF layer callbacks */
33606 + htcCallbacks.deviceInsertedHandler = HTCTargetInsertedHandler;
33607 + htcCallbacks.deviceRemovedHandler = HTCTargetRemovedHandler;
33608 + /* the device layer handles these */
33609 + htcCallbacks.rwCompletionHandler = DevRWCompletionHandler;
33610 + htcCallbacks.dsrHandler = DevDsrHandler;
33611 + HIFInit(&htcCallbacks);
33612 + HTCInitialized = TRUE;
33613 +
33614 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Exit\n"));
33615 + return A_OK;
33616 +}
33617 +
33618 +void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList)
33619 +{
33620 + LOCK_HTC(target);
33621 + HTC_PACKET_ENQUEUE(pList,pPacket);
33622 + UNLOCK_HTC(target);
33623 +}
33624 +
33625 +HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList)
33626 +{
33627 + HTC_PACKET *pPacket;
33628 +
33629 + LOCK_HTC(target);
33630 + pPacket = HTC_PACKET_DEQUEUE(pList);
33631 + UNLOCK_HTC(target);
33632 +
33633 + return pPacket;
33634 +}
33635 +
33636 +/* cleanup the HTC instance */
33637 +static void HTCCleanup(HTC_TARGET *target)
33638 +{
33639 + if (A_IS_MUTEX_VALID(&target->HTCLock)) {
33640 + A_MUTEX_DELETE(&target->HTCLock);
33641 + }
33642 +
33643 + if (A_IS_MUTEX_VALID(&target->HTCRxLock)) {
33644 + A_MUTEX_DELETE(&target->HTCRxLock);
33645 + }
33646 +
33647 + if (A_IS_MUTEX_VALID(&target->HTCTxLock)) {
33648 + A_MUTEX_DELETE(&target->HTCTxLock);
33649 + }
33650 + /* free our instance */
33651 + A_FREE(target);
33652 +}
33653 +
33654 +/* registered target arrival callback from the HIF layer */
33655 +static A_STATUS HTCTargetInsertedHandler(void *hif_handle)
33656 +{
33657 + HTC_TARGET *target = NULL;
33658 + A_STATUS status;
33659 + int i;
33660 +
33661 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Enter\n"));
33662 +
33663 + do {
33664 +
33665 + /* allocate target memory */
33666 + if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) {
33667 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n"));
33668 + status = A_ERROR;
33669 + break;
33670 + }
33671 +
33672 + A_MEMZERO(target, sizeof(HTC_TARGET));
33673 + A_MUTEX_INIT(&target->HTCLock);
33674 + A_MUTEX_INIT(&target->HTCRxLock);
33675 + A_MUTEX_INIT(&target->HTCTxLock);
33676 + INIT_HTC_PACKET_QUEUE(&target->ControlBufferTXFreeList);
33677 + INIT_HTC_PACKET_QUEUE(&target->ControlBufferRXFreeList);
33678 +
33679 + /* give device layer the hif device handle */
33680 + target->Device.HIFDevice = hif_handle;
33681 + /* give the device layer our context (for event processing)
33682 + * the device layer will register it's own context with HIF
33683 + * so we need to set this so we can fetch it in the target remove handler */
33684 + target->Device.HTCContext = target;
33685 + /* set device layer target failure callback */
33686 + target->Device.TargetFailureCallback = HTCReportFailure;
33687 + /* set device layer recv message pending callback */
33688 + target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler;
33689 + target->EpWaitingForBuffers = ENDPOINT_MAX;
33690 +
33691 + /* setup device layer */
33692 + status = DevSetup(&target->Device);
33693 +
33694 + if (A_FAILED(status)) {
33695 + break;
33696 + }
33697 +
33698 + /* carve up buffers/packets for control messages */
33699 + for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) {
33700 + HTC_PACKET *pControlPacket;
33701 + pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
33702 + SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket,
33703 + target,
33704 + target->HTCControlBuffers[i].Buffer,
33705 + HTC_CONTROL_BUFFER_SIZE,
33706 + ENDPOINT_0);
33707 + HTC_FREE_CONTROL_RX(target,pControlPacket);
33708 + }
33709 +
33710 + for (;i < NUM_CONTROL_BUFFERS;i++) {
33711 + HTC_PACKET *pControlPacket;
33712 + pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
33713 + INIT_HTC_PACKET_INFO(pControlPacket,
33714 + target->HTCControlBuffers[i].Buffer,
33715 + HTC_CONTROL_BUFFER_SIZE);
33716 + HTC_FREE_CONTROL_TX(target,pControlPacket);
33717 + }
33718 +
33719 + } while (FALSE);
33720 +
33721 + if (A_SUCCESS(status)) {
33722 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" calling AddInstance callback \n"));
33723 + /* announce ourselves */
33724 + HTCInitInfo.AddInstance((HTC_HANDLE)target);
33725 + } else {
33726 + if (target != NULL) {
33727 + HTCCleanup(target);
33728 + }
33729 + }
33730 +
33731 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Exit\n"));
33732 +
33733 + return status;
33734 +}
33735 +
33736 +/* registered removal callback from the HIF layer */
33737 +static A_STATUS HTCTargetRemovedHandler(void *handle, A_STATUS status)
33738 +{
33739 + HTC_TARGET *target;
33740 +
33741 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCTargetRemovedHandler handle:0x%X \n",(A_UINT32)handle));
33742 +
33743 + if (NULL == handle) {
33744 + /* this could be NULL in the event that target initialization failed */
33745 + return A_OK;
33746 + }
33747 +
33748 + target = ((AR6K_DEVICE *)handle)->HTCContext;
33749 +
33750 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" removing target:0x%X instance:0x%X ... \n",
33751 + (A_UINT32)target, (A_UINT32)target->pInstanceContext));
33752 +
33753 + if (target->pInstanceContext != NULL) {
33754 + /* let upper layer know, it needs to call HTCStop() */
33755 + HTCInitInfo.DeleteInstance(target->pInstanceContext);
33756 + }
33757 +
33758 + HIFShutDownDevice(target->Device.HIFDevice);
33759 +
33760 + HTCCleanup(target);
33761 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCTargetRemovedHandler \n"));
33762 + return A_OK;
33763 +}
33764 +
33765 +/* get the low level HIF device for the caller , the caller may wish to do low level
33766 + * HIF requests */
33767 +void *HTCGetHifDevice(HTC_HANDLE HTCHandle)
33768 +{
33769 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33770 + return target->Device.HIFDevice;
33771 +}
33772 +
33773 +/* set the instance block for this HTC handle, so that on removal, the blob can be
33774 + * returned to the caller */
33775 +void HTCSetInstance(HTC_HANDLE HTCHandle, void *Instance)
33776 +{
33777 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33778 +
33779 + target->pInstanceContext = Instance;
33780 +}
33781 +
33782 +/* wait for the target to arrive (sends HTC Ready message)
33783 + * this operation is fully synchronous and the message is polled for */
33784 +A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
33785 +{
33786 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33787 + A_STATUS status;
33788 + HTC_PACKET *pPacket = NULL;
33789 + HTC_READY_MSG *pRdyMsg;
33790 + HTC_SERVICE_CONNECT_REQ connect;
33791 + HTC_SERVICE_CONNECT_RESP resp;
33792 +
33793 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%X) \n", (A_UINT32)target));
33794 +
33795 + do {
33796 +
33797 +#ifdef MBOXHW_UNIT_TEST
33798 +
33799 + status = DoMboxHWTest(&target->Device);
33800 +
33801 + if (status != A_OK) {
33802 + break;
33803 + }
33804 +
33805 +#endif
33806 +
33807 + /* we should be getting 1 control message that the target is ready */
33808 + status = HTCWaitforControlMessage(target, &pPacket);
33809 +
33810 + if (A_FAILED(status)) {
33811 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n"));
33812 + break;
33813 + }
33814 +
33815 + /* we controlled the buffer creation so it has to be properly aligned */
33816 + pRdyMsg = (HTC_READY_MSG *)pPacket->pBuffer;
33817 +
33818 + if ((pRdyMsg->MessageID != HTC_MSG_READY_ID) ||
33819 + (pPacket->ActualLength < sizeof(HTC_READY_MSG))) {
33820 + /* this message is not valid */
33821 + AR_DEBUG_ASSERT(FALSE);
33822 + status = A_EPROTO;
33823 + break;
33824 + }
33825 +
33826 + if (pRdyMsg->CreditCount == 0 || pRdyMsg->CreditSize == 0) {
33827 + /* this message is not valid */
33828 + AR_DEBUG_ASSERT(FALSE);
33829 + status = A_EPROTO;
33830 + break;
33831 + }
33832 +
33833 + target->TargetCredits = pRdyMsg->CreditCount;
33834 + target->TargetCreditSize = pRdyMsg->CreditSize;
33835 +
33836 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Target Ready: credits: %d credit size: %d\n",
33837 + target->TargetCredits, target->TargetCreditSize));
33838 +
33839 + /* setup our pseudo HTC control endpoint connection */
33840 + A_MEMZERO(&connect,sizeof(connect));
33841 + A_MEMZERO(&resp,sizeof(resp));
33842 + connect.EpCallbacks.pContext = target;
33843 + connect.EpCallbacks.EpTxComplete = HTCControlTxComplete;
33844 + connect.EpCallbacks.EpRecv = HTCControlRecv;
33845 + connect.EpCallbacks.EpRecvRefill = NULL; /* not needed */
33846 + connect.EpCallbacks.EpSendFull = NULL; /* not needed */
33847 + connect.EpCallbacks.EpSendAvail = NULL; /* not needed */
33848 + connect.MaxSendQueueDepth = NUM_CONTROL_BUFFERS;
33849 + connect.ServiceID = HTC_CTRL_RSVD_SVC;
33850 +
33851 + /* connect fake service */
33852 + status = HTCConnectService((HTC_HANDLE)target,
33853 + &connect,
33854 + &resp);
33855 +
33856 + if (!A_FAILED(status)) {
33857 + break;
33858 + }
33859 +
33860 + } while (FALSE);
33861 +
33862 + if (pPacket != NULL) {
33863 + HTC_FREE_CONTROL_RX(target,pPacket);
33864 + }
33865 +
33866 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n"));
33867 +
33868 + return status;
33869 +}
33870 +
33871 +
33872 +
33873 +/* Start HTC, enable interrupts and let the target know host has finished setup */
33874 +A_STATUS HTCStart(HTC_HANDLE HTCHandle)
33875 +{
33876 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33877 + HTC_PACKET *pPacket;
33878 + A_STATUS status;
33879 +
33880 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n"));
33881 +
33882 + /* now that we are starting, push control receive buffers into the
33883 + * HTC control endpoint */
33884 +
33885 + while (1) {
33886 + pPacket = HTC_ALLOC_CONTROL_RX(target);
33887 + if (NULL == pPacket) {
33888 + break;
33889 + }
33890 + HTCAddReceivePkt((HTC_HANDLE)target,pPacket);
33891 + }
33892 +
33893 + do {
33894 +
33895 + AR_DEBUG_ASSERT(target->InitCredits != NULL);
33896 + AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL);
33897 + AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL);
33898 +
33899 + /* call init credits callback to do the distribution ,
33900 + * NOTE: the first entry in the distribution list is ENDPOINT_0, so
33901 + * we pass the start of the list after this one. */
33902 + target->InitCredits(target->pCredDistContext,
33903 + target->EpCreditDistributionListHead->pNext,
33904 + target->TargetCredits);
33905 +
33906 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
33907 + DumpCreditDistStates(target);
33908 + }
33909 +
33910 + /* the caller is done connecting to services, so we can indicate to the
33911 + * target that the setup phase is complete */
33912 + status = HTCSendSetupComplete(target);
33913 +
33914 + if (A_FAILED(status)) {
33915 + break;
33916 + }
33917 +
33918 + /* unmask interrupts */
33919 + status = DevUnmaskInterrupts(&target->Device);
33920 +
33921 + if (A_FAILED(status)) {
33922 + HTCStop(target);
33923 + }
33924 +
33925 + } while (FALSE);
33926 +
33927 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n"));
33928 + return status;
33929 +}
33930 +
33931 +
33932 +/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
33933 +void HTCStop(HTC_HANDLE HTCHandle)
33934 +{
33935 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33936 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n"));
33937 +
33938 + /* mark that we are shutting down .. */
33939 + target->HTCStateFlags |= HTC_STATE_STOPPING;
33940 +
33941 + /* Masking interrupts is a synchronous operation, when this function returns
33942 + * all pending HIF I/O has completed, we can safely flush the queues */
33943 + DevMaskInterrupts(&target->Device);
33944 +
33945 + /* flush all send packets */
33946 + HTCFlushSendPkts(target);
33947 + /* flush all recv buffers */
33948 + HTCFlushRecvBuffers(target);
33949 +
33950 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
33951 +}
33952 +
33953 +/* undo what was done in HTCInit() */
33954 +void HTCShutDown(void)
33955 +{
33956 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCShutDown: \n"));
33957 + HTCInitialized = FALSE;
33958 + /* undo HTCInit */
33959 + HIFShutDownDevice(NULL);
33960 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCShutDown: \n"));
33961 +}
33962 +
33963 +void HTCDumpCreditStates(HTC_HANDLE HTCHandle)
33964 +{
33965 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33966 +
33967 + LOCK_HTC_TX(target);
33968 +
33969 + DumpCreditDistStates(target);
33970 +
33971 + UNLOCK_HTC_TX(target);
33972 +}
33973 +
33974 +/* report a target failure from the device, this is a callback from the device layer
33975 + * which uses a mechanism to report errors from the target (i.e. special interrupts) */
33976 +static void HTCReportFailure(void *Context)
33977 +{
33978 + HTC_TARGET *target = (HTC_TARGET *)Context;
33979 +
33980 + target->TargetFailure = TRUE;
33981 +
33982 + if ((target->pInstanceContext != NULL) && (HTCInitInfo.TargetFailure != NULL)) {
33983 + /* let upper layer know, it needs to call HTCStop() */
33984 + HTCInitInfo.TargetFailure(target->pInstanceContext, A_ERROR);
33985 + }
33986 +}
33987 +
33988 +void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription)
33989 +{
33990 + A_CHAR stream[60];
33991 + A_UINT32 i;
33992 + A_UINT16 offset, count;
33993 +
33994 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<---------Dumping %d Bytes : %s ------>\n", length, pDescription));
33995 +
33996 + count = 0;
33997 + offset = 0;
33998 + for(i = 0; i < length; i++) {
33999 + sprintf(stream + offset, "%2.2X ", buffer[i]);
34000 + count ++;
34001 + offset += 3;
34002 +
34003 + if(count == 16) {
34004 + count = 0;
34005 + offset = 0;
34006 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("[H]: %s\n", stream));
34007 + A_MEMZERO(stream, 60);
34008 + }
34009 + }
34010 +
34011 + if(offset != 0) {
34012 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("[H]: %s\n", stream));
34013 + }
34014 +
34015 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<------------------------------------------------->\n"));
34016 +}
34017 +
34018 +A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle,
34019 + HTC_ENDPOINT_ID Endpoint,
34020 + HTC_ENDPOINT_STAT_ACTION Action,
34021 + HTC_ENDPOINT_STATS *pStats)
34022 +{
34023 +
34024 +#ifdef HTC_EP_STAT_PROFILING
34025 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
34026 + A_BOOL clearStats = FALSE;
34027 + A_BOOL sample = FALSE;
34028 +
34029 + switch (Action) {
34030 + case HTC_EP_STAT_SAMPLE :
34031 + sample = TRUE;
34032 + break;
34033 + case HTC_EP_STAT_SAMPLE_AND_CLEAR :
34034 + sample = TRUE;
34035 + clearStats = TRUE;
34036 + break;
34037 + case HTC_EP_STAT_CLEAR :
34038 + clearStats = TRUE;
34039 + break;
34040 + default:
34041 + break;
34042 + }
34043 +
34044 + A_ASSERT(Endpoint < ENDPOINT_MAX);
34045 +
34046 + /* lock out TX and RX while we sample and/or clear */
34047 + LOCK_HTC_TX(target);
34048 + LOCK_HTC_RX(target);
34049 +
34050 + if (sample) {
34051 + A_ASSERT(pStats != NULL);
34052 + /* return the stats to the caller */
34053 + A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
34054 + }
34055 +
34056 + if (clearStats) {
34057 + /* reset stats */
34058 + A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
34059 + }
34060 +
34061 + UNLOCK_HTC_RX(target);
34062 + UNLOCK_HTC_TX(target);
34063 +
34064 + return TRUE;
34065 +#else
34066 + return FALSE;
34067 +#endif
34068 +}
34069 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_debug.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_debug.h
34070 --- linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_debug.h 1970-01-01 01:00:00.000000000 +0100
34071 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_debug.h 2009-05-10 22:27:59.000000000 +0200
34072 @@ -0,0 +1,65 @@
34073 +#ifndef HTC_DEBUG_H_
34074 +#define HTC_DEBUG_H_
34075 +/*
34076 + *
34077 + * Copyright (c) 2004-2007 Atheros Communications Inc.
34078 + * All rights reserved.
34079 + *
34080 + *
34081 + * This program is free software; you can redistribute it and/or modify
34082 + * it under the terms of the GNU General Public License version 2 as
34083 + * published by the Free Software Foundation;
34084 + *
34085 + * Software distributed under the License is distributed on an "AS
34086 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
34087 + * implied. See the License for the specific language governing
34088 + * rights and limitations under the License.
34089 + *
34090 + *
34091 + *
34092 + */
34093 +
34094 +/* ------- Debug related stuff ------- */
34095 +enum {
34096 + ATH_DEBUG_SEND = 0x0001,
34097 + ATH_DEBUG_RECV = 0x0002,
34098 + ATH_DEBUG_SYNC = 0x0004,
34099 + ATH_DEBUG_DUMP = 0x0008,
34100 + ATH_DEBUG_IRQ = 0x0010,
34101 + ATH_DEBUG_TRC = 0x0020,
34102 + ATH_DEBUG_WARN = 0x0040,
34103 + ATH_DEBUG_ERR = 0x0080,
34104 + ATH_DEBUG_ANY = 0xFFFF,
34105 +};
34106 +
34107 +#ifdef DEBUG
34108 +
34109 +// TODO FIX usage of A_PRINTF!
34110 +#define AR_DEBUG_LVL_CHECK(lvl) (debughtc & (lvl))
34111 +#define AR_DEBUG_PRINTBUF(buffer, length, desc) do { \
34112 + if (debughtc & ATH_DEBUG_DUMP) { \
34113 + DebugDumpBytes(buffer, length,desc); \
34114 + } \
34115 +} while(0)
34116 +#define PRINTX_ARG(arg...) arg
34117 +#define AR_DEBUG_PRINTF(flags, args) do { \
34118 + if (debughtc & (flags)) { \
34119 + A_PRINTF(KERN_ALERT PRINTX_ARG args); \
34120 + } \
34121 +} while (0)
34122 +#define AR_DEBUG_ASSERT(test) do { \
34123 + if (!(test)) { \
34124 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#test)); \
34125 + } \
34126 +} while(0)
34127 +extern int debughtc;
34128 +#else
34129 +#define AR_DEBUG_PRINTF(flags, args)
34130 +#define AR_DEBUG_PRINTBUF(buffer, length, desc)
34131 +#define AR_DEBUG_ASSERT(test)
34132 +#define AR_DEBUG_LVL_CHECK(lvl) 0
34133 +#endif
34134 +
34135 +void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
34136 +
34137 +#endif /*HTC_DEBUG_H_*/
34138 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_internal.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_internal.h
34139 --- linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_internal.h 1970-01-01 01:00:00.000000000 +0100
34140 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_internal.h 2009-05-10 22:27:59.000000000 +0200
34141 @@ -0,0 +1,168 @@
34142 +/*
34143 + *
34144 + * Copyright (c) 2007 Atheros Communications Inc.
34145 + * All rights reserved.
34146 + *
34147 + *
34148 + * This program is free software; you can redistribute it and/or modify
34149 + * it under the terms of the GNU General Public License version 2 as
34150 + * published by the Free Software Foundation;
34151 + *
34152 + * Software distributed under the License is distributed on an "AS
34153 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
34154 + * implied. See the License for the specific language governing
34155 + * rights and limitations under the License.
34156 + *
34157 + *
34158 + *
34159 + */
34160 +
34161 +#ifndef _HTC_INTERNAL_H_
34162 +#define _HTC_INTERNAL_H_
34163 +
34164 +/* for debugging, uncomment this to capture the last frame header, on frame header
34165 + * processing errors, the last frame header is dump for comparison */
34166 +//#define HTC_CAPTURE_LAST_FRAME
34167 +
34168 +//#define HTC_EP_STAT_PROFILING
34169 +
34170 +#ifdef __cplusplus
34171 +extern "C" {
34172 +#endif /* __cplusplus */
34173 +
34174 +/* Header files */
34175 +#include "a_config.h"
34176 +#include "athdefs.h"
34177 +#include "a_types.h"
34178 +#include "a_osapi.h"
34179 +#include "a_debug.h"
34180 +#include "htc.h"
34181 +#include "htc_api.h"
34182 +#include "bmi_msg.h"
34183 +#include "hif.h"
34184 +#include "ar6k.h"
34185 +
34186 +/* HTC operational parameters */
34187 +#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */
34188 +#define HTC_TARGET_DEBUG_INTR_MASK 0x01
34189 +#define HTC_TARGET_CREDIT_INTR_MASK 0xF0
34190 +
34191 +typedef struct _HTC_ENDPOINT {
34192 + HTC_SERVICE_ID ServiceID; /* service ID this endpoint is bound to
34193 + non-zero value means this endpoint is in use */
34194 + HTC_PACKET_QUEUE TxQueue; /* HTC frame buffer TX queue */
34195 + HTC_PACKET_QUEUE RxBuffers; /* HTC frame buffer RX list */
34196 + HTC_ENDPOINT_CREDIT_DIST CreditDist; /* credit distribution structure (exposed to driver layer) */
34197 + HTC_EP_CALLBACKS EpCallBacks; /* callbacks associated with this endpoint */
34198 + int MaxTxQueueDepth; /* max depth of the TX queue before we need to
34199 + call driver's full handler */
34200 + int CurrentTxQueueDepth; /* current TX queue depth */
34201 + int MaxMsgLength; /* max length of endpoint message */
34202 +#ifdef HTC_EP_STAT_PROFILING
34203 + HTC_ENDPOINT_STATS EndPointStats; /* endpoint statistics */
34204 +#endif
34205 +} HTC_ENDPOINT;
34206 +
34207 +#ifdef HTC_EP_STAT_PROFILING
34208 +#define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count);
34209 +#else
34210 +#define INC_HTC_EP_STAT(p,stat,count)
34211 +#endif
34212 +
34213 +#define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL
34214 +
34215 +#define NUM_CONTROL_BUFFERS 8
34216 +#define NUM_CONTROL_TX_BUFFERS 2
34217 +#define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS)
34218 +
34219 +#define HTC_CONTROL_BUFFER_SIZE (HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH)
34220 +
34221 +typedef struct HTC_CONTROL_BUFFER {
34222 + HTC_PACKET HtcPacket;
34223 + A_UINT8 Buffer[HTC_CONTROL_BUFFER_SIZE];
34224 +} HTC_CONTROL_BUFFER;
34225 +
34226 +/* our HTC target state */
34227 +typedef struct _HTC_TARGET {
34228 + HTC_ENDPOINT EndPoint[ENDPOINT_MAX];
34229 + HTC_CONTROL_BUFFER HTCControlBuffers[NUM_CONTROL_BUFFERS];
34230 + HTC_ENDPOINT_CREDIT_DIST *EpCreditDistributionListHead;
34231 + HTC_PACKET_QUEUE ControlBufferTXFreeList;
34232 + HTC_PACKET_QUEUE ControlBufferRXFreeList;
34233 + HTC_CREDIT_DIST_CALLBACK DistributeCredits;
34234 + HTC_CREDIT_INIT_CALLBACK InitCredits;
34235 + void *pCredDistContext;
34236 + int TargetCredits;
34237 + int TargetCreditSize;
34238 + A_MUTEX_T HTCLock;
34239 + A_MUTEX_T HTCRxLock;
34240 + A_MUTEX_T HTCTxLock;
34241 + AR6K_DEVICE Device; /* AR6K - specific state */
34242 + A_UINT32 HTCStateFlags;
34243 + HTC_ENDPOINT_ID EpWaitingForBuffers;
34244 + A_BOOL TargetFailure;
34245 + void *pInstanceContext;
34246 +#define HTC_STATE_WAIT_BUFFERS (1 << 0)
34247 +#define HTC_STATE_STOPPING (1 << 1)
34248 +#ifdef HTC_CAPTURE_LAST_FRAME
34249 + HTC_FRAME_HDR LastFrameHdr; /* useful for debugging */
34250 + A_UINT8 LastTrailer[256];
34251 + A_UINT8 LastTrailerLength;
34252 +#endif
34253 +} HTC_TARGET;
34254 +
34255 +#define HTC_STOPPING(t) ((t)->HTCStateFlags & HTC_STATE_STOPPING)
34256 +#define LOCK_HTC(t) A_MUTEX_LOCK(&(t)->HTCLock);
34257 +#define UNLOCK_HTC(t) A_MUTEX_UNLOCK(&(t)->HTCLock);
34258 +#define LOCK_HTC_RX(t) A_MUTEX_LOCK(&(t)->HTCRxLock);
34259 +#define UNLOCK_HTC_RX(t) A_MUTEX_UNLOCK(&(t)->HTCRxLock);
34260 +#define LOCK_HTC_TX(t) A_MUTEX_LOCK(&(t)->HTCTxLock);
34261 +#define UNLOCK_HTC_TX(t) A_MUTEX_UNLOCK(&(t)->HTCTxLock);
34262 +
34263 +#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd))
34264 +#define HTC_RECYCLE_RX_PKT(target,p) \
34265 +{ \
34266 + HTC_PACKET_RESET_RX(pPacket); \
34267 + HTCAddReceivePkt((HTC_HANDLE)(target),(p)); \
34268 +}
34269 +
34270 +/* internal HTC functions */
34271 +void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket);
34272 +void HTCControlRecv(void *Context, HTC_PACKET *pPacket);
34273 +A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket);
34274 +HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList);
34275 +void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList);
34276 +A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT8 Flags);
34277 +A_STATUS HTCIssueRecv(HTC_TARGET *target, HTC_PACKET *pPacket);
34278 +void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket);
34279 +A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 LookAhead, A_BOOL *pAsyncProc);
34280 +void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint);
34281 +A_STATUS HTCSendSetupComplete(HTC_TARGET *target);
34282 +void HTCFlushRecvBuffers(HTC_TARGET *target);
34283 +void HTCFlushSendPkts(HTC_TARGET *target);
34284 +void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist);
34285 +void DumpCreditDistStates(HTC_TARGET *target);
34286 +void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
34287 +
34288 +static INLINE HTC_PACKET *HTC_ALLOC_CONTROL_TX(HTC_TARGET *target) {
34289 + HTC_PACKET *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList);
34290 + if (pPacket != NULL) {
34291 + /* set payload pointer area with some headroom */
34292 + pPacket->pBuffer = pPacket->pBufferStart + HTC_HDR_LENGTH;
34293 + }
34294 + return pPacket;
34295 +}
34296 +
34297 +#define HTC_FREE_CONTROL_TX(t,p) HTCFreeControlBuffer((t),(p),&(t)->ControlBufferTXFreeList)
34298 +#define HTC_ALLOC_CONTROL_RX(t) HTCAllocControlBuffer((t),&(t)->ControlBufferRXFreeList)
34299 +#define HTC_FREE_CONTROL_RX(t,p) \
34300 +{ \
34301 + HTC_PACKET_RESET_RX(p); \
34302 + HTCFreeControlBuffer((t),(p),&(t)->ControlBufferRXFreeList); \
34303 +}
34304 +
34305 +#ifdef __cplusplus
34306 +}
34307 +#endif
34308 +
34309 +#endif /* _HTC_INTERNAL_H_ */
34310 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_recv.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_recv.c
34311 --- linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_recv.c 1970-01-01 01:00:00.000000000 +0100
34312 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_recv.c 2009-05-10 22:27:59.000000000 +0200
34313 @@ -0,0 +1,703 @@
34314 +/*
34315 + *
34316 + * Copyright (c) 2007 Atheros Communications Inc.
34317 + * All rights reserved.
34318 + *
34319 + *
34320 + * This program is free software; you can redistribute it and/or modify
34321 + * it under the terms of the GNU General Public License version 2 as
34322 + * published by the Free Software Foundation;
34323 + *
34324 + * Software distributed under the License is distributed on an "AS
34325 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
34326 + * implied. See the License for the specific language governing
34327 + * rights and limitations under the License.
34328 + *
34329 + *
34330 + *
34331 + */
34332 +
34333 +#include "htc_internal.h"
34334 +
34335 +#define HTCIssueRecv(t, p) \
34336 + DevRecvPacket(&(t)->Device, \
34337 + (p), \
34338 + (p)->ActualLength)
34339 +
34340 +#define DO_RCV_COMPLETION(t,p,e) \
34341 +{ \
34342 + if ((p)->ActualLength > 0) { \
34343 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" completing packet 0x%X (%d bytes) on ep : %d \n", \
34344 + (A_UINT32)(p), (p)->ActualLength, (p)->Endpoint)); \
34345 + (e)->EpCallBacks.EpRecv((e)->EpCallBacks.pContext, \
34346 + (p)); \
34347 + } else { \
34348 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" recycling empty packet \n")); \
34349 + HTC_RECYCLE_RX_PKT((t), (p)); \
34350 + } \
34351 +}
34352 +
34353 +#ifdef HTC_EP_STAT_PROFILING
34354 +#define HTC_RX_STAT_PROFILE(t,ep,lookAhead) \
34355 +{ \
34356 + LOCK_HTC_RX((t)); \
34357 + INC_HTC_EP_STAT((ep), RxReceived, 1); \
34358 + if ((lookAhead) != 0) { \
34359 + INC_HTC_EP_STAT((ep), RxLookAheads, 1); \
34360 + } \
34361 + UNLOCK_HTC_RX((t)); \
34362 +}
34363 +#else
34364 +#define HTC_RX_STAT_PROFILE(t,ep,lookAhead)
34365 +#endif
34366 +
34367 +static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
34368 + A_UINT8 *pBuffer,
34369 + int Length,
34370 + A_UINT32 *pNextLookAhead,
34371 + HTC_ENDPOINT_ID FromEndpoint)
34372 +{
34373 + HTC_RECORD_HDR *pRecord;
34374 + A_UINT8 *pRecordBuf;
34375 + HTC_LOOKAHEAD_REPORT *pLookAhead;
34376 + A_UINT8 *pOrigBuffer;
34377 + int origLength;
34378 + A_STATUS status;
34379 +
34380 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length));
34381 +
34382 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
34383 + AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer");
34384 + }
34385 +
34386 + pOrigBuffer = pBuffer;
34387 + origLength = Length;
34388 + status = A_OK;
34389 +
34390 + while (Length > 0) {
34391 +
34392 + if (Length < sizeof(HTC_RECORD_HDR)) {
34393 + status = A_EPROTO;
34394 + break;
34395 + }
34396 + /* these are byte aligned structs */
34397 + pRecord = (HTC_RECORD_HDR *)pBuffer;
34398 + Length -= sizeof(HTC_RECORD_HDR);
34399 + pBuffer += sizeof(HTC_RECORD_HDR);
34400 +
34401 + if (pRecord->Length > Length) {
34402 + /* no room left in buffer for record */
34403 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34404 + (" invalid record length: %d (id:%d) buffer has: %d bytes left \n",
34405 + pRecord->Length, pRecord->RecordID, Length));
34406 + status = A_EPROTO;
34407 + break;
34408 + }
34409 + /* start of record follows the header */
34410 + pRecordBuf = pBuffer;
34411 +
34412 + switch (pRecord->RecordID) {
34413 + case HTC_RECORD_CREDITS:
34414 + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_CREDIT_REPORT));
34415 + HTCProcessCreditRpt(target,
34416 + (HTC_CREDIT_REPORT *)pRecordBuf,
34417 + pRecord->Length / (sizeof(HTC_CREDIT_REPORT)),
34418 + FromEndpoint);
34419 + break;
34420 + case HTC_RECORD_LOOKAHEAD:
34421 + AR_DEBUG_ASSERT(pRecord->Length >= sizeof(HTC_LOOKAHEAD_REPORT));
34422 + pLookAhead = (HTC_LOOKAHEAD_REPORT *)pRecordBuf;
34423 + if ((pLookAhead->PreValid == ((~pLookAhead->PostValid) & 0xFF)) &&
34424 + (pNextLookAhead != NULL)) {
34425 +
34426 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
34427 + (" LookAhead Report Found (pre valid:0x%X, post valid:0x%X) \n",
34428 + pLookAhead->PreValid,
34429 + pLookAhead->PostValid));
34430 +
34431 + /* look ahead bytes are valid, copy them over */
34432 + ((A_UINT8 *)pNextLookAhead)[0] = pLookAhead->LookAhead[0];
34433 + ((A_UINT8 *)pNextLookAhead)[1] = pLookAhead->LookAhead[1];
34434 + ((A_UINT8 *)pNextLookAhead)[2] = pLookAhead->LookAhead[2];
34435 + ((A_UINT8 *)pNextLookAhead)[3] = pLookAhead->LookAhead[3];
34436 +
34437 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
34438 + DebugDumpBytes((A_UINT8 *)pNextLookAhead,4,"Next Look Ahead");
34439 + }
34440 + }
34441 + break;
34442 + default:
34443 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n",
34444 + pRecord->RecordID, pRecord->Length));
34445 + break;
34446 + }
34447 +
34448 + if (A_FAILED(status)) {
34449 + break;
34450 + }
34451 +
34452 + /* advance buffer past this record for next time around */
34453 + pBuffer += pRecord->Length;
34454 + Length -= pRecord->Length;
34455 + }
34456 +
34457 + if (A_FAILED(status)) {
34458 + DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer");
34459 + }
34460 +
34461 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n"));
34462 + return status;
34463 +
34464 +}
34465 +
34466 +/* process a received message (i.e. strip off header, process any trailer data)
34467 + * note : locks must be released when this function is called */
34468 +static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT32 *pNextLookAhead)
34469 +{
34470 + A_UINT8 temp;
34471 + A_UINT8 *pBuf;
34472 + A_STATUS status = A_OK;
34473 + A_UINT16 payloadLen;
34474 + A_UINT32 lookAhead;
34475 +
34476 + pBuf = pPacket->pBuffer;
34477 +
34478 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader \n"));
34479 +
34480 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
34481 + AR_DEBUG_PRINTBUF(pBuf,pPacket->ActualLength,"HTC Recv PKT");
34482 + }
34483 +
34484 + do {
34485 + /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to
34486 + * retrieve 16 bit fields */
34487 + payloadLen = A_GET_UINT16_FIELD(pBuf, HTC_FRAME_HDR, PayloadLen);
34488 +
34489 + ((A_UINT8 *)&lookAhead)[0] = pBuf[0];
34490 + ((A_UINT8 *)&lookAhead)[1] = pBuf[1];
34491 + ((A_UINT8 *)&lookAhead)[2] = pBuf[2];
34492 + ((A_UINT8 *)&lookAhead)[3] = pBuf[3];
34493 +
34494 + if (lookAhead != pPacket->HTCReserved) {
34495 + /* somehow the lookahead that gave us the full read length did not
34496 + * reflect the actual header in the pending message */
34497 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34498 + ("HTCProcessRecvHeader, lookahead mismatch! \n"));
34499 + DebugDumpBytes((A_UINT8 *)&pPacket->HTCReserved,4,"Expected Message LookAhead");
34500 + DebugDumpBytes(pBuf,sizeof(HTC_FRAME_HDR),"Current Frame Header");
34501 +#ifdef HTC_CAPTURE_LAST_FRAME
34502 + DebugDumpBytes((A_UINT8 *)&target->LastFrameHdr,sizeof(HTC_FRAME_HDR),"Last Frame Header");
34503 + if (target->LastTrailerLength != 0) {
34504 + DebugDumpBytes(target->LastTrailer,
34505 + target->LastTrailerLength,
34506 + "Last trailer");
34507 + }
34508 +#endif
34509 + status = A_EPROTO;
34510 + break;
34511 + }
34512 +
34513 + /* get flags */
34514 + temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, Flags);
34515 +
34516 + if (temp & HTC_FLAGS_RECV_TRAILER) {
34517 + /* this packet has a trailer */
34518 +
34519 + /* extract the trailer length in control byte 0 */
34520 + temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, ControlBytes[0]);
34521 +
34522 + if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) {
34523 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34524 + ("HTCProcessRecvHeader, invalid header (payloadlength should be :%d, CB[0] is:%d) \n",
34525 + payloadLen, temp));
34526 + status = A_EPROTO;
34527 + break;
34528 + }
34529 +
34530 + /* process trailer data that follows HDR + application payload */
34531 + status = HTCProcessTrailer(target,
34532 + (pBuf + HTC_HDR_LENGTH + payloadLen - temp),
34533 + temp,
34534 + pNextLookAhead,
34535 + pPacket->Endpoint);
34536 +
34537 + if (A_FAILED(status)) {
34538 + break;
34539 + }
34540 +
34541 +#ifdef HTC_CAPTURE_LAST_FRAME
34542 + A_MEMCPY(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp);
34543 + target->LastTrailerLength = temp;
34544 +#endif
34545 + /* trim length by trailer bytes */
34546 + pPacket->ActualLength -= temp;
34547 + }
34548 +#ifdef HTC_CAPTURE_LAST_FRAME
34549 + else {
34550 + target->LastTrailerLength = 0;
34551 + }
34552 +#endif
34553 +
34554 + /* if we get to this point, the packet is good */
34555 + /* remove header and adjust length */
34556 + pPacket->pBuffer += HTC_HDR_LENGTH;
34557 + pPacket->ActualLength -= HTC_HDR_LENGTH;
34558 +
34559 + } while (FALSE);
34560 +
34561 + if (A_FAILED(status)) {
34562 + /* dump the whole packet */
34563 + DebugDumpBytes(pBuf,pPacket->ActualLength,"BAD HTC Recv PKT");
34564 + } else {
34565 +#ifdef HTC_CAPTURE_LAST_FRAME
34566 + A_MEMCPY(&target->LastFrameHdr,pBuf,sizeof(HTC_FRAME_HDR));
34567 +#endif
34568 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
34569 + if (pPacket->ActualLength > 0) {
34570 + AR_DEBUG_PRINTBUF(pPacket->pBuffer,pPacket->ActualLength,"HTC - Application Msg");
34571 + }
34572 + }
34573 + }
34574 +
34575 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessRecvHeader \n"));
34576 + return status;
34577 +}
34578 +
34579 +/* asynchronous completion handler for recv packet fetching, when the device layer
34580 + * completes a read request, it will call this completion handler */
34581 +void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket)
34582 +{
34583 + HTC_TARGET *target = (HTC_TARGET *)Context;
34584 + HTC_ENDPOINT *pEndpoint;
34585 + A_UINT32 nextLookAhead = 0;
34586 + A_STATUS status;
34587 +
34588 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (status:%d, ep:%d) \n",
34589 + pPacket->Status, pPacket->Endpoint));
34590 +
34591 + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
34592 + pEndpoint = &target->EndPoint[pPacket->Endpoint];
34593 + pPacket->Completion = NULL;
34594 +
34595 + /* get completion status */
34596 + status = pPacket->Status;
34597 +
34598 + do {
34599 + if (A_FAILED(status)) {
34600 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRecvCompleteHandler: request failed (status:%d, ep:%d) \n",
34601 + pPacket->Status, pPacket->Endpoint));
34602 + break;
34603 + }
34604 + /* process the header for any trailer data */
34605 + status = HTCProcessRecvHeader(target,pPacket,&nextLookAhead);
34606 +
34607 + if (A_FAILED(status)) {
34608 + break;
34609 + }
34610 + /* was there a lookahead for the next packet? */
34611 + if (nextLookAhead != 0) {
34612 + A_STATUS nextStatus;
34613 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
34614 + ("HTCRecvCompleteHandler - next look ahead was non-zero : 0x%X \n",
34615 + nextLookAhead));
34616 + /* we have another packet, get the next packet fetch started (pipelined) before
34617 + * we call into the endpoint's callback, this will start another async request */
34618 + nextStatus = HTCRecvMessagePendingHandler(target,nextLookAhead,NULL);
34619 + if (A_EPROTO == nextStatus) {
34620 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34621 + ("Next look ahead from recv header was INVALID\n"));
34622 + DebugDumpBytes((A_UINT8 *)&nextLookAhead,
34623 + 4,
34624 + "BAD lookahead from lookahead report");
34625 + }
34626 + } else {
34627 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
34628 + ("HTCRecvCompleteHandler - rechecking for more messages...\n"));
34629 + /* if we did not get anything on the look-ahead,
34630 + * call device layer to asynchronously re-check for messages. If we can keep the async
34631 + * processing going we get better performance. If there is a pending message we will keep processing
34632 + * messages asynchronously which should pipeline things nicely */
34633 + DevCheckPendingRecvMsgsAsync(&target->Device);
34634 + }
34635 +
34636 + HTC_RX_STAT_PROFILE(target,pEndpoint,nextLookAhead);
34637 + DO_RCV_COMPLETION(target,pPacket,pEndpoint);
34638 +
34639 + } while (FALSE);
34640 +
34641 + if (A_FAILED(status)) {
34642 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34643 + ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n",
34644 + status));
34645 + /* recyle this packet */
34646 + HTC_RECYCLE_RX_PKT(target, pPacket);
34647 + }
34648 +
34649 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvCompleteHandler\n"));
34650 +}
34651 +
34652 +/* synchronously wait for a control message from the target,
34653 + * This function is used at initialization time ONLY. At init messages
34654 + * on ENDPOINT 0 are expected. */
34655 +A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket)
34656 +{
34657 + A_STATUS status;
34658 + A_UINT32 lookAhead;
34659 + HTC_PACKET *pPacket = NULL;
34660 + HTC_FRAME_HDR *pHdr;
34661 +
34662 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n"));
34663 +
34664 + do {
34665 +
34666 + *ppControlPacket = NULL;
34667 +
34668 + /* call the polling function to see if we have a message */
34669 + status = DevPollMboxMsgRecv(&target->Device,
34670 + &lookAhead,
34671 + HTC_TARGET_RESPONSE_TIMEOUT);
34672 +
34673 + if (A_FAILED(status)) {
34674 + break;
34675 + }
34676 +
34677 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
34678 + ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead));
34679 +
34680 + /* check the lookahead */
34681 + pHdr = (HTC_FRAME_HDR *)&lookAhead;
34682 +
34683 + if (pHdr->EndpointID != ENDPOINT_0) {
34684 + /* unexpected endpoint number, should be zero */
34685 + AR_DEBUG_ASSERT(FALSE);
34686 + status = A_EPROTO;
34687 + break;
34688 + }
34689 +
34690 + if (A_FAILED(status)) {
34691 + /* bad message */
34692 + AR_DEBUG_ASSERT(FALSE);
34693 + status = A_EPROTO;
34694 + break;
34695 + }
34696 +
34697 + pPacket = HTC_ALLOC_CONTROL_RX(target);
34698 +
34699 + if (pPacket == NULL) {
34700 + AR_DEBUG_ASSERT(FALSE);
34701 + status = A_NO_MEMORY;
34702 + break;
34703 + }
34704 +
34705 + pPacket->HTCReserved = lookAhead;
34706 + pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
34707 +
34708 + if (pPacket->ActualLength > pPacket->BufferLength) {
34709 + AR_DEBUG_ASSERT(FALSE);
34710 + status = A_EPROTO;
34711 + break;
34712 + }
34713 +
34714 + /* we want synchronous operation */
34715 + pPacket->Completion = NULL;
34716 +
34717 + /* get the message from the device, this will block */
34718 + status = HTCIssueRecv(target, pPacket);
34719 +
34720 + if (A_FAILED(status)) {
34721 + break;
34722 + }
34723 +
34724 + /* process receive header */
34725 + status = HTCProcessRecvHeader(target,pPacket,NULL);
34726 +
34727 + pPacket->Status = status;
34728 +
34729 + if (A_FAILED(status)) {
34730 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34731 + ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n",
34732 + status));
34733 + break;
34734 + }
34735 +
34736 + /* give the caller this control message packet, they are responsible to free */
34737 + *ppControlPacket = pPacket;
34738 +
34739 + } while (FALSE);
34740 +
34741 + if (A_FAILED(status)) {
34742 + if (pPacket != NULL) {
34743 + /* cleanup buffer on error */
34744 + HTC_FREE_CONTROL_RX(target,pPacket);
34745 + }
34746 + }
34747 +
34748 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCWaitforControlMessage \n"));
34749 +
34750 + return status;
34751 +}
34752 +
34753 +/* callback when device layer or lookahead report parsing detects a pending message */
34754 +A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 LookAhead, A_BOOL *pAsyncProc)
34755 +{
34756 + HTC_TARGET *target = (HTC_TARGET *)Context;
34757 + A_STATUS status = A_OK;
34758 + HTC_PACKET *pPacket = NULL;
34759 + HTC_FRAME_HDR *pHdr;
34760 + HTC_ENDPOINT *pEndpoint;
34761 + A_BOOL asyncProc = FALSE;
34762 +
34763 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCRecvMessagePendingHandler LookAhead:0x%X \n",LookAhead));
34764 +
34765 + if (IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(&target->Device)) {
34766 + /* We use async mode to get the packets if the device layer supports it.
34767 + * The device layer interfaces with HIF in which HIF may have restrictions on
34768 + * how interrupts are processed */
34769 + asyncProc = TRUE;
34770 + }
34771 +
34772 + if (pAsyncProc != NULL) {
34773 + /* indicate to caller how we decided to process this */
34774 + *pAsyncProc = asyncProc;
34775 + }
34776 +
34777 + while (TRUE) {
34778 +
34779 + pHdr = (HTC_FRAME_HDR *)&LookAhead;
34780 +
34781 + if (pHdr->EndpointID >= ENDPOINT_MAX) {
34782 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID));
34783 + /* invalid endpoint */
34784 + status = A_EPROTO;
34785 + break;
34786 + }
34787 +
34788 + if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
34789 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n",
34790 + pHdr->PayloadLen, HTC_MAX_PAYLOAD_LENGTH));
34791 + status = A_EPROTO;
34792 + break;
34793 + }
34794 +
34795 + pEndpoint = &target->EndPoint[pHdr->EndpointID];
34796 +
34797 + if (0 == pEndpoint->ServiceID) {
34798 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Endpoint %d is not connected !\n",pHdr->EndpointID));
34799 + /* endpoint isn't even connected */
34800 + status = A_EPROTO;
34801 + break;
34802 + }
34803 +
34804 + /* lock RX to get a buffer */
34805 + LOCK_HTC_RX(target);
34806 +
34807 + /* get a packet from the endpoint recv queue */
34808 + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
34809 +
34810 + if (NULL == pPacket) {
34811 + /* check for refill handler */
34812 + if (pEndpoint->EpCallBacks.EpRecvRefill != NULL) {
34813 + UNLOCK_HTC_RX(target);
34814 + /* call the re-fill handler */
34815 + pEndpoint->EpCallBacks.EpRecvRefill(pEndpoint->EpCallBacks.pContext,
34816 + pHdr->EndpointID);
34817 + LOCK_HTC_RX(target);
34818 + /* check if we have more buffers */
34819 + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
34820 + /* fall through */
34821 + }
34822 + }
34823 +
34824 + if (NULL == pPacket) {
34825 + /* this is not an error, we simply need to mark that we are waiting for buffers.*/
34826 + target->HTCStateFlags |= HTC_STATE_WAIT_BUFFERS;
34827 + target->EpWaitingForBuffers = pHdr->EndpointID;
34828 + status = A_NO_MEMORY;
34829 + }
34830 +
34831 + UNLOCK_HTC_RX(target);
34832 +
34833 + if (A_FAILED(status)) {
34834 + /* no buffers */
34835 + break;
34836 + }
34837 +
34838 + AR_DEBUG_ASSERT(pPacket->Endpoint == pHdr->EndpointID);
34839 +
34840 + /* make sure this message can fit in the endpoint buffer */
34841 + if ((pHdr->PayloadLen + HTC_HDR_LENGTH) > pPacket->BufferLength) {
34842 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34843 + ("Payload Length Error : header reports payload of: %d, endpoint buffer size: %d \n",
34844 + pHdr->PayloadLen, pPacket->BufferLength));
34845 + status = A_EPROTO;
34846 + break;
34847 + }
34848 +
34849 + pPacket->HTCReserved = LookAhead; /* set expected look ahead */
34850 + /* set the amount of data to fetch */
34851 + pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
34852 +
34853 + if (asyncProc) {
34854 + /* we use async mode to get the packet if the device layer supports it
34855 + * set our callback and context */
34856 + pPacket->Completion = HTCRecvCompleteHandler;
34857 + pPacket->pContext = target;
34858 + } else {
34859 + /* fully synchronous */
34860 + pPacket->Completion = NULL;
34861 + }
34862 +
34863 + /* go fetch the packet */
34864 + status = HTCIssueRecv(target, pPacket);
34865 +
34866 + if (A_FAILED(status)) {
34867 + break;
34868 + }
34869 +
34870 + if (asyncProc) {
34871 + /* we did this asynchronously so we can get out of the loop, the asynch processing
34872 + * creates a chain of requests to continue processing pending messages in the
34873 + * context of callbacks */
34874 + break;
34875 + }
34876 +
34877 + /* in the sync case, we process the packet, check lookaheads and then repeat */
34878 +
34879 + LookAhead = 0;
34880 + status = HTCProcessRecvHeader(target,pPacket,&LookAhead);
34881 +
34882 + if (A_FAILED(status)) {
34883 + break;
34884 + }
34885 +
34886 + HTC_RX_STAT_PROFILE(target,pEndpoint,LookAhead);
34887 + DO_RCV_COMPLETION(target,pPacket,pEndpoint);
34888 +
34889 + pPacket = NULL;
34890 +
34891 + if (0 == LookAhead) {
34892 + break;
34893 + }
34894 +
34895 + }
34896 +
34897 + if (A_NO_MEMORY == status) {
34898 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34899 + (" Endpoint :%d has no buffers, blocking receiver to prevent overrun.. \n",
34900 + pHdr->EndpointID));
34901 + /* try to stop receive at the device layer */
34902 + DevStopRecv(&target->Device, asyncProc ? DEV_STOP_RECV_ASYNC : DEV_STOP_RECV_SYNC);
34903 + status = A_OK;
34904 + } else if (A_FAILED(status)) {
34905 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34906 + ("Failed to get pending message : LookAhead Value: 0x%X (status = %d) \n",
34907 + LookAhead, status));
34908 + if (pPacket != NULL) {
34909 + /* clean up packet on error */
34910 + HTC_RECYCLE_RX_PKT(target, pPacket);
34911 + }
34912 + }
34913 +
34914 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCRecvMessagePendingHandler \n"));
34915 +
34916 + return status;
34917 +}
34918 +
34919 +/* Makes a buffer available to the HTC module */
34920 +A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
34921 +{
34922 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
34923 + HTC_ENDPOINT *pEndpoint;
34924 + A_BOOL unblockRecv = FALSE;
34925 + A_STATUS status = A_OK;
34926 +
34927 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
34928 + ("+- HTCAddReceivePkt: endPointId: %d, buffer: 0x%X, length: %d\n",
34929 + pPacket->Endpoint, (A_UINT32)pPacket->pBuffer, pPacket->BufferLength));
34930 +
34931 + do {
34932 +
34933 + if (HTC_STOPPING(target)) {
34934 + status = A_ECANCELED;
34935 + break;
34936 + }
34937 +
34938 + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
34939 +
34940 + pEndpoint = &target->EndPoint[pPacket->Endpoint];
34941 +
34942 + LOCK_HTC_RX(target);
34943 +
34944 + /* store receive packet */
34945 + HTC_PACKET_ENQUEUE(&pEndpoint->RxBuffers, pPacket);
34946 +
34947 + /* check if we are blocked waiting for a new buffer */
34948 + if (target->HTCStateFlags & HTC_STATE_WAIT_BUFFERS) {
34949 + if (target->EpWaitingForBuffers == pPacket->Endpoint) {
34950 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" receiver was blocked on ep:%d, unblocking.. \n",
34951 + target->EpWaitingForBuffers));
34952 + target->HTCStateFlags &= ~HTC_STATE_WAIT_BUFFERS;
34953 + target->EpWaitingForBuffers = ENDPOINT_MAX;
34954 + unblockRecv = TRUE;
34955 + }
34956 + }
34957 +
34958 + UNLOCK_HTC_RX(target);
34959 +
34960 + if (unblockRecv && !HTC_STOPPING(target)) {
34961 + /* TODO : implement a buffer threshold count? */
34962 + DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
34963 + }
34964 +
34965 + } while (FALSE);
34966 +
34967 + return status;
34968 +}
34969 +
34970 +static void HTCFlushEndpointRX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
34971 +{
34972 + HTC_PACKET *pPacket;
34973 +
34974 + LOCK_HTC_RX(target);
34975 +
34976 + while (1) {
34977 + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
34978 + if (NULL == pPacket) {
34979 + break;
34980 + }
34981 + UNLOCK_HTC_RX(target);
34982 + pPacket->Status = A_ECANCELED;
34983 + pPacket->ActualLength = 0;
34984 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" Flushing RX packet:0x%X, length:%d, ep:%d \n",
34985 + (A_UINT32)pPacket, pPacket->BufferLength, pPacket->Endpoint));
34986 + /* give the packet back */
34987 + pEndpoint->EpCallBacks.EpRecv(pEndpoint->EpCallBacks.pContext,
34988 + pPacket);
34989 + LOCK_HTC_RX(target);
34990 + }
34991 +
34992 + UNLOCK_HTC_RX(target);
34993 +
34994 +
34995 +}
34996 +
34997 +void HTCFlushRecvBuffers(HTC_TARGET *target)
34998 +{
34999 + HTC_ENDPOINT *pEndpoint;
35000 + int i;
35001 +
35002 + /* NOTE: no need to flush endpoint 0, these buffers were
35003 + * allocated as part of the HTC struct */
35004 + for (i = ENDPOINT_1; i < ENDPOINT_MAX; i++) {
35005 + pEndpoint = &target->EndPoint[i];
35006 + if (pEndpoint->ServiceID == 0) {
35007 + /* not in use.. */
35008 + continue;
35009 + }
35010 + HTCFlushEndpointRX(target,pEndpoint);
35011 + }
35012 +
35013 +
35014 +}
35015 +
35016 +
35017 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_send.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_send.c
35018 --- linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_send.c 1970-01-01 01:00:00.000000000 +0100
35019 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_send.c 2009-05-10 22:27:59.000000000 +0200
35020 @@ -0,0 +1,538 @@
35021 +/*
35022 + *
35023 + * Copyright (c) 2007 Atheros Communications Inc.
35024 + * All rights reserved.
35025 + *
35026 + *
35027 + * This program is free software; you can redistribute it and/or modify
35028 + * it under the terms of the GNU General Public License version 2 as
35029 + * published by the Free Software Foundation;
35030 + *
35031 + * Software distributed under the License is distributed on an "AS
35032 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
35033 + * implied. See the License for the specific language governing
35034 + * rights and limitations under the License.
35035 + *
35036 + *
35037 + *
35038 + */
35039 +
35040 +#include "htc_internal.h"
35041 +
35042 +#define DO_EP_TX_COMPLETION(ep,p) \
35043 +{ \
35044 + (p)->Completion = NULL; \
35045 + (ep)->EpCallBacks.EpTxComplete((ep)->EpCallBacks.pContext,(p)); \
35046 +}
35047 +
35048 +
35049 +/* call the distribute credits callback with the distribution */
35050 +#define DO_DISTRIBUTION(t,reason,description,pList) \
35051 +{ \
35052 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \
35053 + (" calling distribute function (%s) (dfn:0x%X, ctxt:0x%X, dist:0x%X) \n", \
35054 + (description), \
35055 + (A_UINT32)(t)->DistributeCredits, \
35056 + (A_UINT32)(t)->pCredDistContext, \
35057 + (A_UINT32)pList)); \
35058 + (t)->DistributeCredits((t)->pCredDistContext, \
35059 + (pList), \
35060 + (reason)); \
35061 +}
35062 +
35063 +/* our internal send packet completion handler when packets are submited to the AR6K device
35064 + * layer */
35065 +static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket)
35066 +{
35067 + HTC_TARGET *target = (HTC_TARGET *)Context;
35068 + HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint];
35069 +
35070 +
35071 + if (A_FAILED(pPacket->Status)) {
35072 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
35073 + ("HTCSendPktCompletionHandler: request failed (status:%d, ep:%d) \n",
35074 + pPacket->Status, pPacket->Endpoint));
35075 + }
35076 + /* first, fixup the head room we allocated */
35077 + pPacket->pBuffer += HTC_HDR_LENGTH;
35078 + /* do completion */
35079 + DO_EP_TX_COMPLETION(pEndpoint,pPacket);
35080 +}
35081 +
35082 +A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT8 SendFlags)
35083 +{
35084 + A_STATUS status;
35085 + A_UINT8 *pHdrBuf;
35086 + A_BOOL sync = FALSE;
35087 +
35088 + /* caller always provides headrooom */
35089 + pPacket->pBuffer -= HTC_HDR_LENGTH;
35090 + pHdrBuf = pPacket->pBuffer;
35091 + /* setup frame header */
35092 + A_SET_UINT16_FIELD(pHdrBuf,HTC_FRAME_HDR,PayloadLen,(A_UINT16)pPacket->ActualLength);
35093 + A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,Flags,SendFlags);
35094 + A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,EndpointID, (A_UINT8)pPacket->Endpoint);
35095 +
35096 + if (pPacket->Completion == NULL) {
35097 + /* mark that this request was synchronously issued */
35098 + sync = TRUE;
35099 + }
35100 +
35101 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
35102 + ("+-HTCIssueSend: transmit length : %d (%s) \n",
35103 + pPacket->ActualLength + HTC_HDR_LENGTH,
35104 + sync ? "SYNC" : "ASYNC" ));
35105 +
35106 + /* send message to device */
35107 + status = DevSendPacket(&target->Device,
35108 + pPacket,
35109 + pPacket->ActualLength + HTC_HDR_LENGTH);
35110 +
35111 + if (sync) {
35112 + /* use local sync variable. If this was issued asynchronously, pPacket is no longer
35113 + * safe to access. */
35114 + pPacket->pBuffer += HTC_HDR_LENGTH;
35115 + }
35116 +
35117 + /* if this request was asynchronous, the packet completion routine will be invoked by
35118 + * the device layer when the HIF layer completes the request */
35119 +
35120 + return status;
35121 +}
35122 +
35123 +/* try to send the current packet or a packet at the head of the TX queue,
35124 + * if there are no credits, the packet remains in the queue. */
35125 +static void HTCTrySend(HTC_TARGET *target,
35126 + HTC_PACKET *pPacketToSend,
35127 + HTC_ENDPOINT_ID ep)
35128 +{
35129 + HTC_PACKET *pPacket;
35130 + HTC_ENDPOINT *pEndpoint;
35131 + int creditsRequired;
35132 + A_UINT8 sendFlags;
35133 +
35134 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (pPkt:0x%X)\n",(A_UINT32)pPacketToSend));
35135 +
35136 + pEndpoint = &target->EndPoint[ep];
35137 +
35138 + LOCK_HTC_TX(target);
35139 +
35140 + if (pPacketToSend != NULL) {
35141 + /* caller supplied us a packet to queue to the tail of the HTC TX queue before
35142 + * we check the tx queue */
35143 + HTC_PACKET_ENQUEUE(&pEndpoint->TxQueue,pPacketToSend);
35144 + pEndpoint->CurrentTxQueueDepth++;
35145 + }
35146 +
35147 + /* now drain the TX queue for transmission as long as we have enough
35148 + * credits */
35149 +
35150 + while (1) {
35151 +
35152 + if (HTC_QUEUE_EMPTY(&pEndpoint->TxQueue)) {
35153 + /* nothing in the queue */
35154 + break;
35155 + }
35156 +
35157 + sendFlags = 0;
35158 +
35159 + /* get packet at head, but don't remove it */
35160 + pPacket = HTC_GET_PKT_AT_HEAD(&pEndpoint->TxQueue);
35161 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Got head packet:0x%X , Queue Depth: %d\n",
35162 + (A_UINT32)pPacket, pEndpoint->CurrentTxQueueDepth));
35163 +
35164 + /* figure out how many credits this message requires */
35165 + creditsRequired = pPacket->ActualLength + HTC_HDR_LENGTH;
35166 + creditsRequired += target->TargetCreditSize - 1;
35167 + creditsRequired /= target->TargetCreditSize;
35168 +
35169 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n",
35170 + creditsRequired, pEndpoint->CreditDist.TxCredits));
35171 +
35172 + if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
35173 +
35174 + /* not enough credits */
35175 +
35176 + if (pPacket->Endpoint == ENDPOINT_0) {
35177 + /* leave it in the queue */
35178 + break;
35179 + }
35180 + /* invoke the registered distribution function only if this is not
35181 + * endpoint 0, we let the driver layer provide more credits if it can.
35182 + * We pass the credit distribution list starting at the endpoint in question
35183 + * */
35184 +
35185 + /* set how many credits we need */
35186 + pEndpoint->CreditDist.TxCreditsSeek =
35187 + creditsRequired - pEndpoint->CreditDist.TxCredits;
35188 + DO_DISTRIBUTION(target,
35189 + HTC_CREDIT_DIST_SEEK_CREDITS,
35190 + "Seek Credits",
35191 + &pEndpoint->CreditDist);
35192 +
35193 + pEndpoint->CreditDist.TxCreditsSeek = 0;
35194 +
35195 + if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
35196 + /* still not enough credits to send, leave packet in the queue */
35197 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
35198 + (" Not enough credits for ep %d leaving packet in queue..\n",
35199 + pPacket->Endpoint));
35200 + break;
35201 + }
35202 +
35203 + }
35204 +
35205 + pEndpoint->CreditDist.TxCredits -= creditsRequired;
35206 + INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired);
35207 +
35208 + /* check if we need credits */
35209 + if (pEndpoint->CreditDist.TxCredits < pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
35210 + sendFlags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
35211 + INC_HTC_EP_STAT(pEndpoint, TxCreditLowIndications, 1);
35212 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Host Needs Credits \n"));
35213 + }
35214 +
35215 + /* now we can fully dequeue */
35216 + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue);
35217 + pEndpoint->CurrentTxQueueDepth--;
35218 +
35219 + INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
35220 +
35221 + UNLOCK_HTC_TX(target);
35222 +
35223 + HTCIssueSend(target, pPacket, sendFlags);
35224 +
35225 + LOCK_HTC_TX(target);
35226 +
35227 + /* go back and check for more messages */
35228 + }
35229 +
35230 + if (pEndpoint->CurrentTxQueueDepth >= pEndpoint->MaxTxQueueDepth) {
35231 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d, TX queue is full, Depth:%d, Max:%d \n",
35232 + ep, pEndpoint->CurrentTxQueueDepth, pEndpoint->MaxTxQueueDepth));
35233 + UNLOCK_HTC_TX(target);
35234 + /* queue is now full, let caller know */
35235 + if (pEndpoint->EpCallBacks.EpSendFull != NULL) {
35236 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Calling driver's send full callback.... \n"));
35237 + pEndpoint->EpCallBacks.EpSendFull(pEndpoint->EpCallBacks.pContext, ep);
35238 + }
35239 + } else {
35240 + UNLOCK_HTC_TX(target);
35241 + /* queue is now available for new packet, let caller know */
35242 + if (pEndpoint->EpCallBacks.EpSendAvail)
35243 + pEndpoint->EpCallBacks.EpSendAvail(pEndpoint->EpCallBacks.pContext, ep);
35244 + }
35245 +
35246 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
35247 +}
35248 +
35249 +/* HTC API - HTCSendPkt */
35250 +A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
35251 +{
35252 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
35253 + HTC_ENDPOINT *pEndpoint;
35254 + HTC_ENDPOINT_ID ep;
35255 + A_STATUS status = A_OK;
35256 +
35257 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
35258 + ("+HTCSendPkt: Enter endPointId: %d, buffer: 0x%X, length: %d \n",
35259 + pPacket->Endpoint, (A_UINT32)pPacket->pBuffer, pPacket->ActualLength));
35260 +
35261 + ep = pPacket->Endpoint;
35262 + AR_DEBUG_ASSERT(ep < ENDPOINT_MAX);
35263 + pEndpoint = &target->EndPoint[ep];
35264 +
35265 + do {
35266 +
35267 + if (HTC_STOPPING(target)) {
35268 + status = A_ECANCELED;
35269 + pPacket->Status = status;
35270 + DO_EP_TX_COMPLETION(pEndpoint,pPacket);
35271 + break;
35272 + }
35273 + /* everything sent through this interface is asynchronous */
35274 + /* fill in HTC completion routines */
35275 + pPacket->Completion = HTCSendPktCompletionHandler;
35276 + pPacket->pContext = target;
35277 +
35278 + HTCTrySend(target, pPacket, ep);
35279 +
35280 + } while (FALSE);
35281 +
35282 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPkt \n"));
35283 +
35284 + return status;
35285 +}
35286 +
35287 +
35288 +/* check TX queues to drain because of credit distribution update */
35289 +static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
35290 +{
35291 + HTC_ENDPOINT *pEndpoint;
35292 + HTC_ENDPOINT_CREDIT_DIST *pDistItem;
35293 +
35294 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n"));
35295 + pDistItem = target->EpCreditDistributionListHead;
35296 +
35297 + /* run through the credit distribution list to see
35298 + * if there are packets queued
35299 + * NOTE: no locks need to be taken since the distribution list
35300 + * is not dynamic (cannot be re-ordered) and we are not modifying any state */
35301 + while (pDistItem != NULL) {
35302 + pEndpoint = (HTC_ENDPOINT *)pDistItem->pHTCReserved;
35303 +
35304 + if (pEndpoint->CurrentTxQueueDepth > 0) {
35305 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n",
35306 + pDistItem->Endpoint, pEndpoint->CreditDist.TxCredits, pEndpoint->CurrentTxQueueDepth));
35307 + /* try to start the stalled queue, this list is ordered by priority.
35308 + * Highest priority queue get's processed first, if there are credits available the
35309 + * highest priority queue will get a chance to reclaim credits from lower priority
35310 + * ones */
35311 + HTCTrySend(target, NULL, pDistItem->Endpoint);
35312 + }
35313 +
35314 + pDistItem = pDistItem->pNext;
35315 + }
35316 +
35317 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n"));
35318 +}
35319 +
35320 +/* process credit reports and call distribution function */
35321 +void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
35322 +{
35323 + int i;
35324 + HTC_ENDPOINT *pEndpoint;
35325 + int totalCredits = 0;
35326 + A_BOOL doDist = FALSE;
35327 +
35328 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries));
35329 +
35330 + /* lock out TX while we update credits */
35331 + LOCK_HTC_TX(target);
35332 +
35333 + for (i = 0; i < NumEntries; i++, pRpt++) {
35334 + if (pRpt->EndpointID >= ENDPOINT_MAX) {
35335 + AR_DEBUG_ASSERT(FALSE);
35336 + break;
35337 + }
35338 +
35339 + pEndpoint = &target->EndPoint[pRpt->EndpointID];
35340 +
35341 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n",
35342 + pRpt->EndpointID, pRpt->Credits));
35343 +
35344 +
35345 +#ifdef HTC_EP_STAT_PROFILING
35346 +
35347 + INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
35348 + INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits);
35349 +
35350 + if (FromEndpoint == pRpt->EndpointID) {
35351 + /* this credit report arrived on the same endpoint indicating it arrived in an RX
35352 + * packet */
35353 + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromRx, pRpt->Credits);
35354 + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromRx, 1);
35355 + } else if (FromEndpoint == ENDPOINT_0) {
35356 + /* this credit arrived on endpoint 0 as a NULL message */
35357 + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromEp0, pRpt->Credits);
35358 + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromEp0, 1);
35359 + } else {
35360 + /* arrived on another endpoint */
35361 + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits);
35362 + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
35363 + }
35364 +
35365 +#endif
35366 +
35367 + if (ENDPOINT_0 == pRpt->EndpointID) {
35368 + /* always give endpoint 0 credits back */
35369 + pEndpoint->CreditDist.TxCredits += pRpt->Credits;
35370 + } else {
35371 + /* for all other endpoints, update credits to distribute, the distribution function
35372 + * will handle giving out credits back to the endpoints */
35373 + pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits;
35374 + /* flag that we have to do the distribution */
35375 + doDist = TRUE;
35376 + }
35377 +
35378 + totalCredits += pRpt->Credits;
35379 + }
35380 +
35381 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits));
35382 +
35383 + if (doDist) {
35384 + /* this was a credit return based on a completed send operations
35385 + * note, this is done with the lock held */
35386 + DO_DISTRIBUTION(target,
35387 + HTC_CREDIT_DIST_SEND_COMPLETE,
35388 + "Send Complete",
35389 + target->EpCreditDistributionListHead->pNext);
35390 + }
35391 +
35392 + UNLOCK_HTC_TX(target);
35393 +
35394 + if (totalCredits) {
35395 + HTCCheckEndpointTxQueues(target);
35396 + }
35397 +
35398 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n"));
35399 +}
35400 +
35401 +/* flush endpoint TX queue */
35402 +static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag)
35403 +{
35404 + HTC_PACKET *pPacket;
35405 + HTC_PACKET_QUEUE discardQueue;
35406 +
35407 + /* initialize the discard queue */
35408 + INIT_HTC_PACKET_QUEUE(&discardQueue);
35409 +
35410 + LOCK_HTC_TX(target);
35411 +
35412 + /* interate from the front of the TX queue and flush out packets */
35413 + ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue, pPacket, HTC_PACKET, ListLink) {
35414 +
35415 + /* check for removal */
35416 + if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) {
35417 + /* remove from queue */
35418 + HTC_PACKET_REMOVE(pPacket);
35419 + /* add it to the discard pile */
35420 + HTC_PACKET_ENQUEUE(&discardQueue, pPacket);
35421 + pEndpoint->CurrentTxQueueDepth--;
35422 + }
35423 +
35424 + } ITERATE_END;
35425 +
35426 + UNLOCK_HTC_TX(target);
35427 +
35428 + /* empty the discard queue */
35429 + while (1) {
35430 + pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
35431 + if (NULL == pPacket) {
35432 + break;
35433 + }
35434 + pPacket->Status = A_ECANCELED;
35435 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Flushing TX packet:0x%X, length:%d, ep:%d tag:0x%X \n",
35436 + (A_UINT32)pPacket, pPacket->ActualLength, pPacket->Endpoint, pPacket->PktInfo.AsTx.Tag));
35437 + DO_EP_TX_COMPLETION(pEndpoint,pPacket);
35438 + }
35439 +
35440 +}
35441 +
35442 +void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist)
35443 +{
35444 +#ifdef DEBUG
35445 + HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *)pEPDist->pHTCReserved;
35446 +#endif
35447 +
35448 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d ServiceID: 0x%X --------------\n",
35449 + pEPDist->Endpoint, pEPDist->ServiceID));
35450 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" this:0x%X next:0x%X prev:0x%X\n",
35451 + (A_UINT32)pEPDist, (A_UINT32)pEPDist->pNext, (A_UINT32)pEPDist->pPrev));
35452 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" DistFlags : 0x%X \n", pEPDist->DistFlags));
35453 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsNorm : %d \n", pEPDist->TxCreditsNorm));
35454 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsMin : %d \n", pEPDist->TxCreditsMin));
35455 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCredits : %d \n", pEPDist->TxCredits));
35456 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsAssigned : %d \n", pEPDist->TxCreditsAssigned));
35457 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsSeek : %d \n", pEPDist->TxCreditsSeek));
35458 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditSize : %d \n", pEPDist->TxCreditSize));
35459 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg));
35460 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist : %d \n", pEPDist->TxCreditsToDist));
35461 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth : %d \n", pEndpoint->CurrentTxQueueDepth));
35462 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n"));
35463 +}
35464 +
35465 +void DumpCreditDistStates(HTC_TARGET *target)
35466 +{
35467 + HTC_ENDPOINT_CREDIT_DIST *pEPList = target->EpCreditDistributionListHead;
35468 +
35469 + while (pEPList != NULL) {
35470 + DumpCreditDist(pEPList);
35471 + pEPList = pEPList->pNext;
35472 + }
35473 +
35474 + if (target->DistributeCredits != NULL) {
35475 + DO_DISTRIBUTION(target,
35476 + HTC_DUMP_CREDIT_STATE,
35477 + "Dump State",
35478 + NULL);
35479 + }
35480 +}
35481 +
35482 +/* flush all send packets from all endpoint queues */
35483 +void HTCFlushSendPkts(HTC_TARGET *target)
35484 +{
35485 + HTC_ENDPOINT *pEndpoint;
35486 + int i;
35487 +
35488 + DumpCreditDistStates(target);
35489 +
35490 + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
35491 + pEndpoint = &target->EndPoint[i];
35492 + if (pEndpoint->ServiceID == 0) {
35493 + /* not in use.. */
35494 + continue;
35495 + }
35496 + HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL);
35497 + }
35498 +
35499 +}
35500 +
35501 +/* HTC API to flush an endpoint's TX queue*/
35502 +void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag)
35503 +{
35504 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
35505 + HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
35506 +
35507 + if (pEndpoint->ServiceID == 0) {
35508 + AR_DEBUG_ASSERT(FALSE);
35509 + /* not in use.. */
35510 + return;
35511 + }
35512 +
35513 + HTCFlushEndpointTX(target, pEndpoint, Tag);
35514 +}
35515 +
35516 +/* HTC API to indicate activity to the credit distribution function */
35517 +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
35518 + HTC_ENDPOINT_ID Endpoint,
35519 + A_BOOL Active)
35520 +{
35521 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
35522 + HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
35523 + A_BOOL doDist = FALSE;
35524 +
35525 + if (pEndpoint->ServiceID == 0) {
35526 + AR_DEBUG_ASSERT(FALSE);
35527 + /* not in use.. */
35528 + return;
35529 + }
35530 +
35531 + LOCK_HTC_TX(target);
35532 +
35533 + if (Active) {
35534 + if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) {
35535 + /* mark active now */
35536 + pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE;
35537 + doDist = TRUE;
35538 + }
35539 + } else {
35540 + if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
35541 + /* mark inactive now */
35542 + pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE;
35543 + doDist = TRUE;
35544 + }
35545 + }
35546 +
35547 + if (doDist) {
35548 + /* do distribution again based on activity change
35549 + * note, this is done with the lock held */
35550 + DO_DISTRIBUTION(target,
35551 + HTC_CREDIT_DIST_ACTIVITY_CHANGE,
35552 + "Activity Change",
35553 + target->EpCreditDistributionListHead->pNext);
35554 + }
35555 +
35556 + UNLOCK_HTC_TX(target);
35557 +
35558 +}
35559 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_services.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_services.c
35560 --- linux-2.6.29-rc3.owrt/drivers/ar6000/htc/htc_services.c 1970-01-01 01:00:00.000000000 +0100
35561 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/htc/htc_services.c 2009-05-10 22:27:59.000000000 +0200
35562 @@ -0,0 +1,403 @@
35563 +/*
35564 + *
35565 + * Copyright (c) 2007 Atheros Communications Inc.
35566 + * All rights reserved.
35567 + *
35568 + *
35569 + * This program is free software; you can redistribute it and/or modify
35570 + * it under the terms of the GNU General Public License version 2 as
35571 + * published by the Free Software Foundation;
35572 + *
35573 + * Software distributed under the License is distributed on an "AS
35574 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
35575 + * implied. See the License for the specific language governing
35576 + * rights and limitations under the License.
35577 + *
35578 + *
35579 + *
35580 + */
35581 +
35582 +#include "htc_internal.h"
35583 +
35584 +void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket)
35585 +{
35586 + /* not implemented
35587 + * we do not send control TX frames during normal runtime, only during setup */
35588 + AR_DEBUG_ASSERT(FALSE);
35589 +}
35590 +
35591 + /* callback when a control message arrives on this endpoint */
35592 +void HTCControlRecv(void *Context, HTC_PACKET *pPacket)
35593 +{
35594 + AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0);
35595 +
35596 + /* the only control messages we are expecting are NULL messages (credit resports), which should
35597 + * never get here */
35598 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
35599 + ("HTCControlRecv, got message with length:%d \n",
35600 + pPacket->ActualLength + HTC_HDR_LENGTH));
35601 +
35602 + /* dump header and message */
35603 + DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH,
35604 + pPacket->ActualLength + HTC_HDR_LENGTH,
35605 + "Unexpected ENDPOINT 0 Message");
35606 +
35607 + HTC_RECYCLE_RX_PKT((HTC_TARGET*)Context,pPacket);
35608 +}
35609 +
35610 +A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
35611 +{
35612 + HTC_PACKET *pSendPacket = NULL;
35613 + A_STATUS status;
35614 + HTC_SETUP_COMPLETE_MSG *pSetupComplete;
35615 +
35616 + do {
35617 + /* allocate a packet to send to the target */
35618 + pSendPacket = HTC_ALLOC_CONTROL_TX(target);
35619 +
35620 + if (NULL == pSendPacket) {
35621 + status = A_NO_MEMORY;
35622 + break;
35623 + }
35624 +
35625 + /* assemble setup complete message */
35626 + pSetupComplete = (HTC_SETUP_COMPLETE_MSG *)pSendPacket->pBuffer;
35627 + A_MEMZERO(pSetupComplete,sizeof(HTC_SETUP_COMPLETE_MSG));
35628 + pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID;
35629 +
35630 + SET_HTC_PACKET_INFO_TX(pSendPacket,
35631 + NULL,
35632 + (A_UINT8 *)pSetupComplete,
35633 + sizeof(HTC_SETUP_COMPLETE_MSG),
35634 + ENDPOINT_0,
35635 + HTC_SERVICE_TX_PACKET_TAG);
35636 +
35637 + /* we want synchronous operation */
35638 + pSendPacket->Completion = NULL;
35639 + /* send the message */
35640 + status = HTCIssueSend(target,pSendPacket,0);
35641 +
35642 + } while (FALSE);
35643 +
35644 + if (pSendPacket != NULL) {
35645 + HTC_FREE_CONTROL_TX(target,pSendPacket);
35646 + }
35647 +
35648 + return status;
35649 +}
35650 +
35651 +
35652 +A_STATUS HTCConnectService(HTC_HANDLE HTCHandle,
35653 + HTC_SERVICE_CONNECT_REQ *pConnectReq,
35654 + HTC_SERVICE_CONNECT_RESP *pConnectResp)
35655 +{
35656 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
35657 + A_STATUS status = A_OK;
35658 + HTC_PACKET *pRecvPacket = NULL;
35659 + HTC_PACKET *pSendPacket = NULL;
35660 + HTC_CONNECT_SERVICE_RESPONSE_MSG *pResponseMsg;
35661 + HTC_CONNECT_SERVICE_MSG *pConnectMsg;
35662 + HTC_ENDPOINT_ID assignedEndpoint = ENDPOINT_MAX;
35663 + HTC_ENDPOINT *pEndpoint;
35664 + int maxMsgSize = 0;
35665 +
35666 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%X SvcID:0x%X \n",
35667 + (A_UINT32)target, pConnectReq->ServiceID));
35668 +
35669 + do {
35670 +
35671 + AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0);
35672 +
35673 + if (HTC_CTRL_RSVD_SVC == pConnectReq->ServiceID) {
35674 + /* special case for pseudo control service */
35675 + assignedEndpoint = ENDPOINT_0;
35676 + maxMsgSize = HTC_MAX_CONTROL_MESSAGE_LENGTH;
35677 + } else {
35678 + /* allocate a packet to send to the target */
35679 + pSendPacket = HTC_ALLOC_CONTROL_TX(target);
35680 +
35681 + if (NULL == pSendPacket) {
35682 + AR_DEBUG_ASSERT(FALSE);
35683 + status = A_NO_MEMORY;
35684 + break;
35685 + }
35686 + /* assemble connect service message */
35687 + pConnectMsg = (HTC_CONNECT_SERVICE_MSG *)pSendPacket->pBuffer;
35688 + AR_DEBUG_ASSERT(pConnectMsg != NULL);
35689 + A_MEMZERO(pConnectMsg,sizeof(HTC_CONNECT_SERVICE_MSG));
35690 + pConnectMsg->MessageID = HTC_MSG_CONNECT_SERVICE_ID;
35691 + pConnectMsg->ServiceID = pConnectReq->ServiceID;
35692 + pConnectMsg->ConnectionFlags = pConnectReq->ConnectionFlags;
35693 + /* check caller if it wants to transfer meta data */
35694 + if ((pConnectReq->pMetaData != NULL) &&
35695 + (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) {
35696 + /* copy meta data into message buffer (after header ) */
35697 + A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG),
35698 + pConnectReq->pMetaData,
35699 + pConnectReq->MetaDataLength);
35700 + pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength;
35701 + }
35702 +
35703 + SET_HTC_PACKET_INFO_TX(pSendPacket,
35704 + NULL,
35705 + (A_UINT8 *)pConnectMsg,
35706 + sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength,
35707 + ENDPOINT_0,
35708 + HTC_SERVICE_TX_PACKET_TAG);
35709 +
35710 + /* we want synchronous operation */
35711 + pSendPacket->Completion = NULL;
35712 +
35713 + status = HTCIssueSend(target,pSendPacket,0);
35714 +
35715 + if (A_FAILED(status)) {
35716 + break;
35717 + }
35718 +
35719 + /* wait for response */
35720 + status = HTCWaitforControlMessage(target, &pRecvPacket);
35721 +
35722 + if (A_FAILED(status)) {
35723 + break;
35724 + }
35725 + /* we controlled the buffer creation so it has to be properly aligned */
35726 + pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer;
35727 +
35728 + if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) ||
35729 + (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) {
35730 + /* this message is not valid */
35731 + AR_DEBUG_ASSERT(FALSE);
35732 + status = A_EPROTO;
35733 + break;
35734 + }
35735 +
35736 + pConnectResp->ConnectRespCode = pResponseMsg->Status;
35737 + /* check response status */
35738 + if (pResponseMsg->Status != HTC_SERVICE_SUCCESS) {
35739 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
35740 + (" Target failed service 0x%X connect request (status:%d)\n",
35741 + pResponseMsg->ServiceID, pResponseMsg->Status));
35742 + status = A_EPROTO;
35743 + break;
35744 + }
35745 +
35746 + assignedEndpoint = pResponseMsg->EndpointID;
35747 + maxMsgSize = pResponseMsg->MaxMsgSize;
35748 +
35749 + if ((pConnectResp->pMetaData != NULL) &&
35750 + (pResponseMsg->ServiceMetaLength > 0) &&
35751 + (pResponseMsg->ServiceMetaLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) {
35752 + /* caller supplied a buffer and the target responded with data */
35753 + int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength);
35754 + /* copy the meta data */
35755 + A_MEMCPY(pConnectResp->pMetaData,
35756 + ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG),
35757 + copyLength);
35758 + pConnectResp->ActualLength = copyLength;
35759 + }
35760 +
35761 + }
35762 +
35763 + /* the rest of these are parameter checks so set the error status */
35764 + status = A_EPROTO;
35765 +
35766 + if (assignedEndpoint >= ENDPOINT_MAX) {
35767 + AR_DEBUG_ASSERT(FALSE);
35768 + break;
35769 + }
35770 +
35771 + if (0 == maxMsgSize) {
35772 + AR_DEBUG_ASSERT(FALSE);
35773 + break;
35774 + }
35775 +
35776 + pEndpoint = &target->EndPoint[assignedEndpoint];
35777 +
35778 + if (pEndpoint->ServiceID != 0) {
35779 + /* endpoint already in use! */
35780 + AR_DEBUG_ASSERT(FALSE);
35781 + break;
35782 + }
35783 +
35784 + /* return assigned endpoint to caller */
35785 + pConnectResp->Endpoint = assignedEndpoint;
35786 + pConnectResp->MaxMsgLength = maxMsgSize;
35787 +
35788 + /* setup the endpoint */
35789 + pEndpoint->ServiceID = pConnectReq->ServiceID; /* this marks the endpoint in use */
35790 + pEndpoint->MaxTxQueueDepth = pConnectReq->MaxSendQueueDepth;
35791 + pEndpoint->MaxMsgLength = maxMsgSize;
35792 + /* copy all the callbacks */
35793 + pEndpoint->EpCallBacks = pConnectReq->EpCallbacks;
35794 + INIT_HTC_PACKET_QUEUE(&pEndpoint->RxBuffers);
35795 + INIT_HTC_PACKET_QUEUE(&pEndpoint->TxQueue);
35796 + /* set the credit distribution info for this endpoint, this information is
35797 + * passed back to the credit distribution callback function */
35798 + pEndpoint->CreditDist.ServiceID = pConnectReq->ServiceID;
35799 + pEndpoint->CreditDist.pHTCReserved = pEndpoint;
35800 + pEndpoint->CreditDist.Endpoint = assignedEndpoint;
35801 + pEndpoint->CreditDist.TxCreditSize = target->TargetCreditSize;
35802 + pEndpoint->CreditDist.TxCreditsPerMaxMsg = maxMsgSize / target->TargetCreditSize;
35803 +
35804 + if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
35805 + pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1;
35806 + }
35807 +
35808 + status = A_OK;
35809 +
35810 + } while (FALSE);
35811 +
35812 + if (pSendPacket != NULL) {
35813 + HTC_FREE_CONTROL_TX(target,pSendPacket);
35814 + }
35815 +
35816 + if (pRecvPacket != NULL) {
35817 + HTC_FREE_CONTROL_RX(target,pRecvPacket);
35818 + }
35819 +
35820 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n"));
35821 +
35822 + return status;
35823 +}
35824 +
35825 +static void AddToEndpointDistList(HTC_TARGET *target, HTC_ENDPOINT_CREDIT_DIST *pEpDist)
35826 +{
35827 + HTC_ENDPOINT_CREDIT_DIST *pCurEntry,*pLastEntry;
35828 +
35829 + if (NULL == target->EpCreditDistributionListHead) {
35830 + target->EpCreditDistributionListHead = pEpDist;
35831 + pEpDist->pNext = NULL;
35832 + pEpDist->pPrev = NULL;
35833 + return;
35834 + }
35835 +
35836 + /* queue to the end of the list, this does not have to be very
35837 + * fast since this list is built at startup time */
35838 + pCurEntry = target->EpCreditDistributionListHead;
35839 +
35840 + while (pCurEntry) {
35841 + pLastEntry = pCurEntry;
35842 + pCurEntry = pCurEntry->pNext;
35843 + }
35844 +
35845 + pLastEntry->pNext = pEpDist;
35846 + pEpDist->pPrev = pLastEntry;
35847 + pEpDist->pNext = NULL;
35848 +}
35849 +
35850 +
35851 +
35852 +/* default credit init callback */
35853 +static void HTCDefaultCreditInit(void *Context,
35854 + HTC_ENDPOINT_CREDIT_DIST *pEPList,
35855 + int TotalCredits)
35856 +{
35857 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
35858 + int totalEps = 0;
35859 + int creditsPerEndpoint;
35860 +
35861 + pCurEpDist = pEPList;
35862 + /* first run through the list and figure out how many endpoints we are dealing with */
35863 + while (pCurEpDist != NULL) {
35864 + pCurEpDist = pCurEpDist->pNext;
35865 + totalEps++;
35866 + }
35867 +
35868 + /* even distribution */
35869 + creditsPerEndpoint = TotalCredits/totalEps;
35870 +
35871 + pCurEpDist = pEPList;
35872 + /* run through the list and set minimum and normal credits and
35873 + * provide the endpoint with some credits to start */
35874 + while (pCurEpDist != NULL) {
35875 +
35876 + if (creditsPerEndpoint < pCurEpDist->TxCreditsPerMaxMsg) {
35877 + /* too many endpoints and not enough credits */
35878 + AR_DEBUG_ASSERT(FALSE);
35879 + break;
35880 + }
35881 + /* our minimum is set for at least 1 max message */
35882 + pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg;
35883 + /* this value is ignored by our credit alg, since we do
35884 + * not dynamically adjust credits, this is the policy of
35885 + * the "default" credit distribution, something simple and easy */
35886 + pCurEpDist->TxCreditsNorm = 0xFFFF;
35887 + /* give the endpoint minimum credits */
35888 + pCurEpDist->TxCredits = creditsPerEndpoint;
35889 + pCurEpDist->TxCreditsAssigned = creditsPerEndpoint;
35890 + pCurEpDist = pCurEpDist->pNext;
35891 + }
35892 +
35893 +}
35894 +
35895 +/* default credit distribution callback, NOTE, this callback holds the TX lock */
35896 +void HTCDefaultCreditDist(void *Context,
35897 + HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
35898 + HTC_CREDIT_DIST_REASON Reason)
35899 +{
35900 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
35901 +
35902 + if (Reason == HTC_CREDIT_DIST_SEND_COMPLETE) {
35903 + pCurEpDist = pEPDistList;
35904 + /* simple distribution */
35905 + while (pCurEpDist != NULL) {
35906 + if (pCurEpDist->TxCreditsToDist > 0) {
35907 + /* just give the endpoint back the credits */
35908 + pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist;
35909 + pCurEpDist->TxCreditsToDist = 0;
35910 + }
35911 + pCurEpDist = pCurEpDist->pNext;
35912 + }
35913 + }
35914 +
35915 + /* note we do not need to handle the other reason codes as this is a very
35916 + * simple distribution scheme, no need to seek for more credits or handle inactivity */
35917 +}
35918 +
35919 +void HTCSetCreditDistribution(HTC_HANDLE HTCHandle,
35920 + void *pCreditDistContext,
35921 + HTC_CREDIT_DIST_CALLBACK CreditDistFunc,
35922 + HTC_CREDIT_INIT_CALLBACK CreditInitFunc,
35923 + HTC_SERVICE_ID ServicePriorityOrder[],
35924 + int ListLength)
35925 +{
35926 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
35927 + int i;
35928 + int ep;
35929 +
35930 + if (CreditInitFunc != NULL) {
35931 + /* caller has supplied their own distribution functions */
35932 + target->InitCredits = CreditInitFunc;
35933 + AR_DEBUG_ASSERT(CreditDistFunc != NULL);
35934 + target->DistributeCredits = CreditDistFunc;
35935 + target->pCredDistContext = pCreditDistContext;
35936 + } else {
35937 + /* caller wants HTC to do distribution */
35938 + /* if caller wants service to handle distributions then
35939 + * it must set both of these to NULL! */
35940 + AR_DEBUG_ASSERT(CreditDistFunc == NULL);
35941 + target->InitCredits = HTCDefaultCreditInit;
35942 + target->DistributeCredits = HTCDefaultCreditDist;
35943 + target->pCredDistContext = target;
35944 + }
35945 +
35946 + /* always add HTC control endpoint first, we only expose the list after the
35947 + * first one, this is added for TX queue checking */
35948 + AddToEndpointDistList(target, &target->EndPoint[ENDPOINT_0].CreditDist);
35949 +
35950 + /* build the list of credit distribution structures in priority order
35951 + * supplied by the caller, these will follow endpoint 0 */
35952 + for (i = 0; i < ListLength; i++) {
35953 + /* match services with endpoints and add the endpoints to the distribution list
35954 + * in FIFO order */
35955 + for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) {
35956 + if (target->EndPoint[ep].ServiceID == ServicePriorityOrder[i]) {
35957 + /* queue this one to the list */
35958 + AddToEndpointDistList(target, &target->EndPoint[ep].CreditDist);
35959 + break;
35960 + }
35961 + }
35962 + AR_DEBUG_ASSERT(ep < ENDPOINT_MAX);
35963 + }
35964 +
35965 +}
35966 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_config.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_config.h
35967 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_config.h 1970-01-01 01:00:00.000000000 +0100
35968 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_config.h 2009-05-10 22:27:59.000000000 +0200
35969 @@ -0,0 +1,27 @@
35970 +#ifndef _A_CONFIG_H_
35971 +#define _A_CONFIG_H_
35972 +/*
35973 + * Copyright (c) 2004-2005 Atheros Communications Inc.
35974 + * All rights reserved.
35975 + *
35976 + *
35977 + * This program is free software; you can redistribute it and/or modify
35978 + * it under the terms of the GNU General Public License version 2 as
35979 + * published by the Free Software Foundation;
35980 + *
35981 + * Software distributed under the License is distributed on an "AS
35982 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
35983 + * implied. See the License for the specific language governing
35984 + * rights and limitations under the License.
35985 + *
35986 + *
35987 + *
35988 + */
35989 +
35990 +/*
35991 + * This file contains software configuration options that enables
35992 + * specific software "features"
35993 + */
35994 +#include "../ar6000/config_linux.h"
35995 +
35996 +#endif
35997 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_debug.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_debug.h
35998 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_debug.h 1970-01-01 01:00:00.000000000 +0100
35999 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_debug.h 2009-05-10 22:27:59.000000000 +0200
36000 @@ -0,0 +1,41 @@
36001 +#ifndef _A_DEBUG_H_
36002 +#define _A_DEBUG_H_
36003 +/*
36004 + * Copyright (c) 2004-2006 Atheros Communications Inc.
36005 + * All rights reserved.
36006 + *
36007 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36008 + * All rights reserved.
36009 + *
36010 + *
36011 + * This program is free software; you can redistribute it and/or modify
36012 + * it under the terms of the GNU General Public License version 2 as
36013 + * published by the Free Software Foundation;
36014 + *
36015 + * Software distributed under the License is distributed on an "AS
36016 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36017 + * implied. See the License for the specific language governing
36018 + * rights and limitations under the License.
36019 + *
36020 + *
36021 + *
36022 + */
36023 +
36024 +#include <a_types.h>
36025 +#include <a_osapi.h>
36026 +
36027 +#define DBG_INFO 0x00000001
36028 +#define DBG_ERROR 0x00000002
36029 +#define DBG_WARNING 0x00000004
36030 +#define DBG_SDIO 0x00000008
36031 +#define DBG_HIF 0x00000010
36032 +#define DBG_HTC 0x00000020
36033 +#define DBG_WMI 0x00000040
36034 +#define DBG_WMI2 0x00000080
36035 +#define DBG_DRIVER 0x00000100
36036 +
36037 +#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING)
36038 +
36039 +#include "../ar6000/debug_linux.h"
36040 +
36041 +#endif
36042 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_drv_api.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_drv_api.h
36043 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_drv_api.h 1970-01-01 01:00:00.000000000 +0100
36044 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_drv_api.h 2009-05-10 22:27:59.000000000 +0200
36045 @@ -0,0 +1,185 @@
36046 +#ifndef _A_DRV_API_H_
36047 +#define _A_DRV_API_H_
36048 +/*
36049 + * Copyright (c) 2004-2006 Atheros Communications Inc.
36050 + * All rights reserved.
36051 + *
36052 + *
36053 + * This program is free software; you can redistribute it and/or modify
36054 + * it under the terms of the GNU General Public License version 2 as
36055 + * published by the Free Software Foundation;
36056 + *
36057 + * Software distributed under the License is distributed on an "AS
36058 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36059 + * implied. See the License for the specific language governing
36060 + * rights and limitations under the License.
36061 + *
36062 + *
36063 + *
36064 + */
36065 +
36066 +#ifdef __cplusplus
36067 +extern "C" {
36068 +#endif
36069 +
36070 +/****************************************************************************/
36071 +/****************************************************************************/
36072 +/** **/
36073 +/** WMI related hooks **/
36074 +/** **/
36075 +/****************************************************************************/
36076 +/****************************************************************************/
36077 +
36078 +#include <ar6000_api.h>
36079 +
36080 +#define A_WMI_CHANNELLIST_RX(devt, numChan, chanList) \
36081 + ar6000_channelList_rx((devt), (numChan), (chanList))
36082 +
36083 +#define A_WMI_SET_NUMDATAENDPTS(devt, num) \
36084 + ar6000_set_numdataendpts((devt), (num))
36085 +
36086 +#define A_WMI_CONTROL_TX(devt, osbuf, streamID) \
36087 + ar6000_control_tx((devt), (osbuf), (streamID))
36088 +
36089 +#define A_WMI_TARGETSTATS_EVENT(devt, pStats) \
36090 + ar6000_targetStats_event((devt), (pStats))
36091 +
36092 +#define A_WMI_SCANCOMPLETE_EVENT(devt, status) \
36093 + ar6000_scanComplete_event((devt), (status))
36094 +
36095 +#ifdef CONFIG_HOST_DSET_SUPPORT
36096 +
36097 +#define A_WMI_DSET_DATA_REQ(devt, access_cookie, offset, length, targ_buf, targ_reply_fn, targ_reply_arg) \
36098 + ar6000_dset_data_req((devt), (access_cookie), (offset), (length), (targ_buf), (targ_reply_fn), (targ_reply_arg))
36099 +
36100 +#define A_WMI_DSET_CLOSE(devt, access_cookie) \
36101 + ar6000_dset_close((devt), (access_cookie))
36102 +
36103 +#endif
36104 +
36105 +#define A_WMI_DSET_OPEN_REQ(devt, id, targ_handle, targ_reply_fn, targ_reply_arg) \
36106 + ar6000_dset_open_req((devt), (id), (targ_handle), (targ_reply_fn), (targ_reply_arg))
36107 +
36108 +#define A_WMI_CONNECT_EVENT(devt, channel, bssid, listenInterval, beaconInterval, networkType, beaconIeLen, assocReqLen, assocRespLen, assocInfo) \
36109 + ar6000_connect_event((devt), (channel), (bssid), (listenInterval), (beaconInterval), (networkType), (beaconIeLen), (assocReqLen), (assocRespLen), (assocInfo))
36110 +
36111 +#define A_WMI_REGDOMAIN_EVENT(devt, regCode) \
36112 + ar6000_regDomain_event((devt), (regCode))
36113 +
36114 +#define A_WMI_NEIGHBORREPORT_EVENT(devt, numAps, info) \
36115 + ar6000_neighborReport_event((devt), (numAps), (info))
36116 +
36117 +#define A_WMI_DISCONNECT_EVENT(devt, reason, bssid, assocRespLen, assocInfo, protocolReasonStatus) \
36118 + ar6000_disconnect_event((devt), (reason), (bssid), (assocRespLen), (assocInfo), (protocolReasonStatus))
36119 +
36120 +#define A_WMI_TKIP_MICERR_EVENT(devt, keyid, ismcast) \
36121 + ar6000_tkip_micerr_event((devt), (keyid), (ismcast))
36122 +
36123 +#define A_WMI_BITRATE_RX(devt, rateKbps) \
36124 + ar6000_bitrate_rx((devt), (rateKbps))
36125 +
36126 +#define A_WMI_TXPWR_RX(devt, txPwr) \
36127 + ar6000_txPwr_rx((devt), (txPwr))
36128 +
36129 +#define A_WMI_READY_EVENT(devt, datap, phyCap) \
36130 + ar6000_ready_event((devt), (datap), (phyCap))
36131 +
36132 +#define A_WMI_DBGLOG_INIT_DONE(ar) \
36133 + ar6000_dbglog_init_done(ar);
36134 +
36135 +#define A_WMI_RSSI_THRESHOLD_EVENT(devt, newThreshold, rssi) \
36136 + ar6000_rssiThreshold_event((devt), (newThreshold), (rssi))
36137 +
36138 +#define A_WMI_REPORT_ERROR_EVENT(devt, errorVal) \
36139 + ar6000_reportError_event((devt), (errorVal))
36140 +
36141 +#define A_WMI_ROAM_TABLE_EVENT(devt, pTbl) \
36142 + ar6000_roam_tbl_event((devt), (pTbl))
36143 +
36144 +#define A_WMI_ROAM_DATA_EVENT(devt, p) \
36145 + ar6000_roam_data_event((devt), (p))
36146 +
36147 +#define A_WMI_WOW_LIST_EVENT(devt, num_filters, wow_filters) \
36148 + ar6000_wow_list_event((devt), (num_filters), (wow_filters))
36149 +
36150 +#define A_WMI_CAC_EVENT(devt, ac, cac_indication, statusCode, tspecSuggestion) \
36151 + ar6000_cac_event((devt), (ac), (cac_indication), (statusCode), (tspecSuggestion))
36152 +
36153 +#define A_WMI_IPTOS_TO_USERPRIORITY(pkt) \
36154 + ar6000_iptos_to_userPriority((pkt))
36155 +
36156 +#define A_WMI_PMKID_LIST_EVENT(devt, num_pmkid, pmkid_list) \
36157 + ar6000_pmkid_list_event((devt), (num_pmkid), (pmkid_list))
36158 +
36159 +#ifdef CONFIG_HOST_GPIO_SUPPORT
36160 +
36161 +#define A_WMI_GPIO_INTR_RX(intr_mask, input_values) \
36162 + ar6000_gpio_intr_rx((intr_mask), (input_values))
36163 +
36164 +#define A_WMI_GPIO_DATA_RX(reg_id, value) \
36165 + ar6000_gpio_data_rx((reg_id), (value))
36166 +
36167 +#define A_WMI_GPIO_ACK_RX() \
36168 + ar6000_gpio_ack_rx()
36169 +
36170 +#endif
36171 +
36172 +#ifdef SEND_EVENT_TO_APP
36173 +
36174 +#define A_WMI_SEND_EVENT_TO_APP(ar, eventId, datap, len) \
36175 + ar6000_send_event_to_app((ar), (eventId), (datap), (len))
36176 +
36177 +#else
36178 +
36179 +#define A_WMI_SEND_EVENT_TO_APP(ar, eventId, datap, len)
36180 +
36181 +#endif
36182 +
36183 +#ifdef CONFIG_HOST_TCMD_SUPPORT
36184 +#define A_WMI_TCMD_RX_REPORT_EVENT(devt, results, len) \
36185 + ar6000_tcmd_rx_report_event((devt), (results), (len))
36186 +#endif
36187 +
36188 +#define A_WMI_HBCHALLENGERESP_EVENT(devt, cookie, source) \
36189 + ar6000_hbChallengeResp_event((devt), (cookie), (source))
36190 +
36191 +#define A_WMI_TX_RETRY_ERR_EVENT(devt) \
36192 + ar6000_tx_retry_err_event((devt))
36193 +
36194 +#define A_WMI_SNR_THRESHOLD_EVENT_RX(devt, newThreshold, snr) \
36195 + ar6000_snrThresholdEvent_rx((devt), (newThreshold), (snr))
36196 +
36197 +#define A_WMI_LQ_THRESHOLD_EVENT_RX(devt, range, lqVal) \
36198 + ar6000_lqThresholdEvent_rx((devt), (range), (lqVal))
36199 +
36200 +#define A_WMI_RATEMASK_RX(devt, ratemask) \
36201 + ar6000_ratemask_rx((devt), (ratemask))
36202 +
36203 +#define A_WMI_KEEPALIVE_RX(devt, configured) \
36204 + ar6000_keepalive_rx((devt), (configured))
36205 +
36206 +#define A_WMI_BSSINFO_EVENT_RX(ar, datp, len) \
36207 + ar6000_bssInfo_event_rx((ar), (datap), (len))
36208 +
36209 +#define A_WMI_DBGLOG_EVENT(ar, dropped, buffer, length) \
36210 + ar6000_dbglog_event((ar), (dropped), (buffer), (length));
36211 +
36212 +#define A_WMI_STREAM_TX_ACTIVE(devt,trafficClass) \
36213 + ar6000_indicate_tx_activity((devt),(trafficClass), TRUE)
36214 +
36215 +#define A_WMI_STREAM_TX_INACTIVE(devt,trafficClass) \
36216 + ar6000_indicate_tx_activity((devt),(trafficClass), FALSE)
36217 +
36218 +/****************************************************************************/
36219 +/****************************************************************************/
36220 +/** **/
36221 +/** HTC related hooks **/
36222 +/** **/
36223 +/****************************************************************************/
36224 +/****************************************************************************/
36225 +
36226 +#ifdef __cplusplus
36227 +}
36228 +#endif
36229 +
36230 +#endif
36231 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_drv.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_drv.h
36232 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_drv.h 1970-01-01 01:00:00.000000000 +0100
36233 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_drv.h 2009-05-10 22:27:59.000000000 +0200
36234 @@ -0,0 +1,28 @@
36235 +#ifndef _A_DRV_H_
36236 +#define _A_DRV_H_
36237 +/*
36238 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/a_drv.h#1 $
36239 + *
36240 + * This file contains the definitions of the basic atheros data types.
36241 + * It is used to map the data types in atheros files to a platform specific
36242 + * type.
36243 + *
36244 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
36245 + *
36246 + *
36247 + * This program is free software; you can redistribute it and/or modify
36248 + * it under the terms of the GNU General Public License version 2 as
36249 + * published by the Free Software Foundation;
36250 + *
36251 + * Software distributed under the License is distributed on an "AS
36252 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36253 + * implied. See the License for the specific language governing
36254 + * rights and limitations under the License.
36255 + *
36256 + *
36257 + *
36258 + */
36259 +
36260 +#include "../ar6000/athdrv_linux.h"
36261 +
36262 +#endif /* _ADRV_H_ */
36263 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_osapi.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_osapi.h
36264 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_osapi.h 1970-01-01 01:00:00.000000000 +0100
36265 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_osapi.h 2009-05-10 22:27:59.000000000 +0200
36266 @@ -0,0 +1,28 @@
36267 +#ifndef _A_OSAPI_H_
36268 +#define _A_OSAPI_H_
36269 +/*
36270 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/a_osapi.h#1 $
36271 + *
36272 + * This file contains the definitions of the basic atheros data types.
36273 + * It is used to map the data types in atheros files to a platform specific
36274 + * type.
36275 + *
36276 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
36277 + *
36278 + *
36279 + * This program is free software; you can redistribute it and/or modify
36280 + * it under the terms of the GNU General Public License version 2 as
36281 + * published by the Free Software Foundation;
36282 + *
36283 + * Software distributed under the License is distributed on an "AS
36284 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36285 + * implied. See the License for the specific language governing
36286 + * rights and limitations under the License.
36287 + *
36288 + *
36289 + *
36290 + */
36291 +
36292 +#include "../ar6000/osapi_linux.h"
36293 +
36294 +#endif /* _OSAPI_H_ */
36295 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/ar6000_api.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ar6000_api.h
36296 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/ar6000_api.h 1970-01-01 01:00:00.000000000 +0100
36297 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ar6000_api.h 2009-05-10 22:27:59.000000000 +0200
36298 @@ -0,0 +1,29 @@
36299 +#ifndef _AR6000_API_H_
36300 +#define _AR6000_API_H_
36301 +/*
36302 + * Copyright (c) 2004-2005 Atheros Communications Inc.
36303 + * All rights reserved.
36304 + *
36305 + * This file contains the API to access the OS dependent atheros host driver
36306 + * by the WMI or WLAN generic modules.
36307 + *
36308 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/ar6000_api.h#1 $
36309 + *
36310 + *
36311 + * This program is free software; you can redistribute it and/or modify
36312 + * it under the terms of the GNU General Public License version 2 as
36313 + * published by the Free Software Foundation;
36314 + *
36315 + * Software distributed under the License is distributed on an "AS
36316 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36317 + * implied. See the License for the specific language governing
36318 + * rights and limitations under the License.
36319 + *
36320 + *
36321 + *
36322 + */
36323 +
36324 +#include "../ar6000/ar6xapi_linux.h"
36325 +
36326 +#endif /* _AR6000_API_H */
36327 +
36328 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/ar6000_diag.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ar6000_diag.h
36329 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/ar6000_diag.h 1970-01-01 01:00:00.000000000 +0100
36330 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ar6000_diag.h 2009-05-10 22:27:59.000000000 +0200
36331 @@ -0,0 +1,38 @@
36332 +/*
36333 + *
36334 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36335 + * All rights reserved.
36336 + *
36337 + *
36338 + * This program is free software; you can redistribute it and/or modify
36339 + * it under the terms of the GNU General Public License version 2 as
36340 + * published by the Free Software Foundation;
36341 + *
36342 + * Software distributed under the License is distributed on an "AS
36343 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36344 + * implied. See the License for the specific language governing
36345 + * rights and limitations under the License.
36346 + *
36347 + *
36348 + *
36349 + */
36350 +
36351 +#ifndef AR6000_DIAG_H_
36352 +#define AR6000_DIAG_H_
36353 +
36354 +
36355 +A_STATUS
36356 +ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
36357 +
36358 +A_STATUS
36359 +ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
36360 +
36361 +A_STATUS
36362 +ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
36363 + A_UCHAR *data, A_UINT32 length);
36364 +
36365 +A_STATUS
36366 +ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
36367 + A_UCHAR *data, A_UINT32 length);
36368 +
36369 +#endif /*AR6000_DIAG_H_*/
36370 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/AR6001_regdump.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/AR6001_regdump.h
36371 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/AR6001_regdump.h 1970-01-01 01:00:00.000000000 +0100
36372 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/AR6001_regdump.h 2009-05-10 22:27:59.000000000 +0200
36373 @@ -0,0 +1,100 @@
36374 +/*
36375 + * Copyright (c) 2006 Atheros Communications Inc.
36376 + * All rights reserved.
36377 + *
36378 + * $ATH_LICENSE_HOSTSDK0_C$
36379 + *
36380 + */
36381 +
36382 +#ifndef __AR6000_REGDUMP_H__
36383 +#define __AR6000_REGDUMP_H__
36384 +
36385 +#if !defined(__ASSEMBLER__)
36386 +/*
36387 + * Target CPU state at the time of failure is reflected
36388 + * in a register dump, which the Host can fetch through
36389 + * the diagnostic window.
36390 + */
36391 +
36392 +struct MIPS_exception_frame_s {
36393 + A_UINT32 pc; /* Program Counter */
36394 + A_UINT32 at; /* MIPS General Purpose registers */
36395 + A_UINT32 v0;
36396 + A_UINT32 v1;
36397 + A_UINT32 a0;
36398 + A_UINT32 a1;
36399 + A_UINT32 a2;
36400 + A_UINT32 a3;
36401 + A_UINT32 t0;
36402 + A_UINT32 t1;
36403 + A_UINT32 t2;
36404 + A_UINT32 t3;
36405 + A_UINT32 t4;
36406 + A_UINT32 t5;
36407 + A_UINT32 t6;
36408 + A_UINT32 t7;
36409 + A_UINT32 s0;
36410 + A_UINT32 s1;
36411 + A_UINT32 s2;
36412 + A_UINT32 s3;
36413 + A_UINT32 s4;
36414 + A_UINT32 s5;
36415 + A_UINT32 s6;
36416 + A_UINT32 s7;
36417 + A_UINT32 t8;
36418 + A_UINT32 t9;
36419 + A_UINT32 k0;
36420 + A_UINT32 k1;
36421 + A_UINT32 gp;
36422 + A_UINT32 sp;
36423 + A_UINT32 s8;
36424 + A_UINT32 ra;
36425 + A_UINT32 cause; /* Selected coprocessor regs */
36426 + A_UINT32 status;
36427 +};
36428 +typedef struct MIPS_exception_frame_s CPU_exception_frame_t;
36429 +
36430 +#endif
36431 +
36432 +/*
36433 + * Offsets into MIPS_exception_frame structure, for use in assembler code
36434 + * MUST MATCH C STRUCTURE ABOVE
36435 + */
36436 +#define RD_pc 0
36437 +#define RD_at 1
36438 +#define RD_v0 2
36439 +#define RD_v1 3
36440 +#define RD_a0 4
36441 +#define RD_a1 5
36442 +#define RD_a2 6
36443 +#define RD_a3 7
36444 +#define RD_t0 8
36445 +#define RD_t1 9
36446 +#define RD_t2 10
36447 +#define RD_t3 11
36448 +#define RD_t4 12
36449 +#define RD_t5 13
36450 +#define RD_t6 14
36451 +#define RD_t7 15
36452 +#define RD_s0 16
36453 +#define RD_s1 17
36454 +#define RD_s2 18
36455 +#define RD_s3 19
36456 +#define RD_s4 20
36457 +#define RD_s5 21
36458 +#define RD_s6 22
36459 +#define RD_s7 23
36460 +#define RD_t8 24
36461 +#define RD_t9 25
36462 +#define RD_k0 26
36463 +#define RD_k1 27
36464 +#define RD_gp 28
36465 +#define RD_sp 29
36466 +#define RD_s8 30
36467 +#define RD_ra 31
36468 +#define RD_cause 32
36469 +#define RD_status 33
36470 +
36471 +#define RD_SIZE (34*4) /* Space for this number of words */
36472 +
36473 +#endif /* __AR6000_REGDUMP_H__ */
36474 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/AR6Khwreg.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/AR6Khwreg.h
36475 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/AR6Khwreg.h 1970-01-01 01:00:00.000000000 +0100
36476 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/AR6Khwreg.h 2009-05-10 22:27:59.000000000 +0200
36477 @@ -0,0 +1,147 @@
36478 +/*
36479 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36480 + * All rights reserved.
36481 + *
36482 + * $ATH_LICENSE_HOSTSDK0_C$
36483 + *
36484 + * This file contains the definitions for AR6001 registers
36485 + * that may be directly manipulated by Host software.
36486 + */
36487 +
36488 +#ifndef __AR6KHWREG_H__
36489 +#define __AR6KHWREG_H__
36490 +
36491 +#ifdef __cplusplus
36492 +extern "C" {
36493 +#endif
36494 +
36495 +/* Host registers */
36496 +#define HOST_INT_STATUS_ADDRESS 0x00000400
36497 +#define CPU_INT_STATUS_ADDRESS 0x00000401
36498 +#define ERROR_INT_STATUS_ADDRESS 0x00000402
36499 +#define INT_STATUS_ENABLE_ADDRESS 0x00000418
36500 +#define CPU_INT_STATUS_ENABLE_ADDRESS 0x00000419
36501 +#define COUNT_ADDRESS 0x00000420
36502 +#define COUNT_DEC_ADDRESS 0x00000440
36503 +#define WINDOW_DATA_ADDRESS 0x00000474
36504 +#define WINDOW_WRITE_ADDR_ADDRESS 0x00000478
36505 +#define WINDOW_READ_ADDR_ADDRESS 0x0000047c
36506 +
36507 +/* Target addresses */
36508 +#define RESET_CONTROL_ADDRESS 0x0c000000
36509 +#define MC_REMAP_VALID_ADDRESS 0x0c004080
36510 +#define MC_REMAP_SIZE_ADDRESS 0x0c004100
36511 +#define MC_REMAP_COMPARE_ADDRESS 0x0c004180
36512 +#define MC_REMAP_TARGET_ADDRESS 0x0c004200
36513 +#define LOCAL_COUNT_ADDRESS 0x0c014080
36514 +#define LOCAL_SCRATCH_ADDRESS 0x0c0140c0
36515 +
36516 +
36517 +#define INT_STATUS_ENABLE_ERROR_MSB 7
36518 +#define INT_STATUS_ENABLE_ERROR_LSB 7
36519 +#define INT_STATUS_ENABLE_ERROR_MASK 0x00000080
36520 +#define INT_STATUS_ENABLE_ERROR_GET(x) (((x) & INT_STATUS_ENABLE_ERROR_MASK) >> INT_STATUS_ENABLE_ERROR_LSB)
36521 +#define INT_STATUS_ENABLE_ERROR_SET(x) (((x) << INT_STATUS_ENABLE_ERROR_LSB) & INT_STATUS_ENABLE_ERROR_MASK)
36522 +
36523 +#define INT_STATUS_ENABLE_CPU_MSB 6
36524 +#define INT_STATUS_ENABLE_CPU_LSB 6
36525 +#define INT_STATUS_ENABLE_CPU_MASK 0x00000040
36526 +#define INT_STATUS_ENABLE_CPU_GET(x) (((x) & INT_STATUS_ENABLE_CPU_MASK) >> INT_STATUS_ENABLE_CPU_LSB)
36527 +#define INT_STATUS_ENABLE_CPU_SET(x) (((x) << INT_STATUS_ENABLE_CPU_LSB) & INT_STATUS_ENABLE_CPU_MASK)
36528 +
36529 +#define INT_STATUS_ENABLE_COUNTER_MSB 4
36530 +#define INT_STATUS_ENABLE_COUNTER_LSB 4
36531 +#define INT_STATUS_ENABLE_COUNTER_MASK 0x00000010
36532 +#define INT_STATUS_ENABLE_COUNTER_GET(x) (((x) & INT_STATUS_ENABLE_COUNTER_MASK) >> INT_STATUS_ENABLE_COUNTER_LSB)
36533 +#define INT_STATUS_ENABLE_COUNTER_SET(x) (((x) << INT_STATUS_ENABLE_COUNTER_LSB) & INT_STATUS_ENABLE_COUNTER_MASK)
36534 +
36535 +#define INT_STATUS_ENABLE_MBOX_DATA_MSB 3
36536 +#define INT_STATUS_ENABLE_MBOX_DATA_LSB 0
36537 +#define INT_STATUS_ENABLE_MBOX_DATA_MASK 0x0000000f
36538 +#define INT_STATUS_ENABLE_MBOX_DATA_GET(x) (((x) & INT_STATUS_ENABLE_MBOX_DATA_MASK) >> INT_STATUS_ENABLE_MBOX_DATA_LSB)
36539 +#define INT_STATUS_ENABLE_MBOX_DATA_SET(x) (((x) << INT_STATUS_ENABLE_MBOX_DATA_LSB) & INT_STATUS_ENABLE_MBOX_DATA_MASK)
36540 +
36541 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MSB 1
36542 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB 1
36543 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK 0x00000002
36544 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK) >> ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB)
36545 +#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_RX_UNDERFLOW_LSB) & ERROR_STATUS_ENABLE_RX_UNDERFLOW_MASK)
36546 +
36547 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MSB 0
36548 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB 0
36549 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK 0x00000001
36550 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_GET(x) (((x) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK) >> ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB)
36551 +#define ERROR_STATUS_ENABLE_TX_OVERFLOW_SET(x) (((x) << ERROR_STATUS_ENABLE_TX_OVERFLOW_LSB) & ERROR_STATUS_ENABLE_TX_OVERFLOW_MASK)
36552 +
36553 +
36554 +#define CPU_INT_STATUS_ENABLE_BIT_MSB 7
36555 +#define CPU_INT_STATUS_ENABLE_BIT_LSB 0
36556 +#define CPU_INT_STATUS_ENABLE_BIT_MASK 0x000000ff
36557 +#define CPU_INT_STATUS_ENABLE_BIT_GET(x) (((x) & CPU_INT_STATUS_ENABLE_BIT_MASK) >> CPU_INT_STATUS_ENABLE_BIT_LSB)
36558 +#define CPU_INT_STATUS_ENABLE_BIT_SET(x) (((x) << CPU_INT_STATUS_ENABLE_BIT_LSB) & CPU_INT_STATUS_ENABLE_BIT_MASK)
36559 +
36560 +#define COUNTER_INT_STATUS_ENABLE_BIT_MSB 7
36561 +#define COUNTER_INT_STATUS_ENABLE_BIT_LSB 0
36562 +#define COUNTER_INT_STATUS_ENABLE_BIT_MASK 0x000000ff
36563 +#define COUNTER_INT_STATUS_ENABLE_BIT_GET(x) (((x) & COUNTER_INT_STATUS_ENABLE_BIT_MASK) >> COUNTER_INT_STATUS_ENABLE_BIT_LSB)
36564 +#define COUNTER_INT_STATUS_ENABLE_BIT_SET(x) (((x) << COUNTER_INT_STATUS_ENABLE_BIT_LSB) & COUNTER_INT_STATUS_ENABLE_BIT_MASK)
36565 +
36566 +#define ERROR_INT_STATUS_WAKEUP_MSB 2
36567 +#define ERROR_INT_STATUS_WAKEUP_LSB 2
36568 +#define ERROR_INT_STATUS_WAKEUP_MASK 0x00000004
36569 +#define ERROR_INT_STATUS_WAKEUP_GET(x) (((x) & ERROR_INT_STATUS_WAKEUP_MASK) >> ERROR_INT_STATUS_WAKEUP_LSB)
36570 +#define ERROR_INT_STATUS_WAKEUP_SET(x) (((x) << ERROR_INT_STATUS_WAKEUP_LSB) & ERROR_INT_STATUS_WAKEUP_MASK)
36571 +
36572 +#define ERROR_INT_STATUS_RX_UNDERFLOW_MSB 1
36573 +#define ERROR_INT_STATUS_RX_UNDERFLOW_LSB 1
36574 +#define ERROR_INT_STATUS_RX_UNDERFLOW_MASK 0x00000002
36575 +#define ERROR_INT_STATUS_RX_UNDERFLOW_GET(x) (((x) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK) >> ERROR_INT_STATUS_RX_UNDERFLOW_LSB)
36576 +#define ERROR_INT_STATUS_RX_UNDERFLOW_SET(x) (((x) << ERROR_INT_STATUS_RX_UNDERFLOW_LSB) & ERROR_INT_STATUS_RX_UNDERFLOW_MASK)
36577 +
36578 +#define ERROR_INT_STATUS_TX_OVERFLOW_MSB 0
36579 +#define ERROR_INT_STATUS_TX_OVERFLOW_LSB 0
36580 +#define ERROR_INT_STATUS_TX_OVERFLOW_MASK 0x00000001
36581 +#define ERROR_INT_STATUS_TX_OVERFLOW_GET(x) (((x) & ERROR_INT_STATUS_TX_OVERFLOW_MASK) >> ERROR_INT_STATUS_TX_OVERFLOW_LSB)
36582 +#define ERROR_INT_STATUS_TX_OVERFLOW_SET(x) (((x) << ERROR_INT_STATUS_TX_OVERFLOW_LSB) & ERROR_INT_STATUS_TX_OVERFLOW_MASK)
36583 +
36584 +#define HOST_INT_STATUS_ERROR_MSB 7
36585 +#define HOST_INT_STATUS_ERROR_LSB 7
36586 +#define HOST_INT_STATUS_ERROR_MASK 0x00000080
36587 +#define HOST_INT_STATUS_ERROR_GET(x) (((x) & HOST_INT_STATUS_ERROR_MASK) >> HOST_INT_STATUS_ERROR_LSB)
36588 +#define HOST_INT_STATUS_ERROR_SET(x) (((x) << HOST_INT_STATUS_ERROR_LSB) & HOST_INT_STATUS_ERROR_MASK)
36589 +
36590 +#define HOST_INT_STATUS_CPU_MSB 6
36591 +#define HOST_INT_STATUS_CPU_LSB 6
36592 +#define HOST_INT_STATUS_CPU_MASK 0x00000040
36593 +#define HOST_INT_STATUS_CPU_GET(x) (((x) & HOST_INT_STATUS_CPU_MASK) >> HOST_INT_STATUS_CPU_LSB)
36594 +#define HOST_INT_STATUS_CPU_SET(x) (((x) << HOST_INT_STATUS_CPU_LSB) & HOST_INT_STATUS_CPU_MASK)
36595 +
36596 +#define HOST_INT_STATUS_COUNTER_MSB 4
36597 +#define HOST_INT_STATUS_COUNTER_LSB 4
36598 +#define HOST_INT_STATUS_COUNTER_MASK 0x00000010
36599 +#define HOST_INT_STATUS_COUNTER_GET(x) (((x) & HOST_INT_STATUS_COUNTER_MASK) >> HOST_INT_STATUS_COUNTER_LSB)
36600 +#define HOST_INT_STATUS_COUNTER_SET(x) (((x) << HOST_INT_STATUS_COUNTER_LSB) & HOST_INT_STATUS_COUNTER_MASK)
36601 +
36602 +#define RESET_CONTROL_WARM_RST_MSB 7
36603 +#define RESET_CONTROL_WARM_RST_LSB 7
36604 +#define RESET_CONTROL_WARM_RST_MASK 0x00000080
36605 +#define RESET_CONTROL_WARM_RST_GET(x) (((x) & RESET_CONTROL_WARM_RST_MASK) >> RESET_CONTROL_WARM_RST_LSB)
36606 +#define RESET_CONTROL_WARM_RST_SET(x) (((x) << RESET_CONTROL_WARM_RST_LSB) & RESET_CONTROL_WARM_RST_MASK)
36607 +
36608 +#define RESET_CONTROL_COLD_RST_MSB 8
36609 +#define RESET_CONTROL_COLD_RST_LSB 8
36610 +#define RESET_CONTROL_COLD_RST_MASK 0x00000100
36611 +#define RESET_CONTROL_COLD_RST_GET(x) (((x) & RESET_CONTROL_COLD_RST_MASK) >> RESET_CONTROL_COLD_RST_LSB)
36612 +#define RESET_CONTROL_COLD_RST_SET(x) (((x) << RESET_CONTROL_COLD_RST_LSB) & RESET_CONTROL_COLD_RST_MASK)
36613 +
36614 +#define RESET_CAUSE_LAST_MSB 2
36615 +#define RESET_CAUSE_LAST_LSB 0
36616 +#define RESET_CAUSE_LAST_MASK 0x00000007
36617 +#define RESET_CAUSE_LAST_GET(x) (((x) & RESET_CAUSE_LAST_MASK) >> RESET_CAUSE_LAST_LSB)
36618 +#define RESET_CAUSE_LAST_SET(x) (((x) << RESET_CAUSE_LAST_LSB) & RESET_CAUSE_LAST_MASK)
36619 +
36620 +#ifdef __cplusplus
36621 +}
36622 +#endif
36623 +
36624 +#endif /* __AR6KHWREG_H__ */
36625 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/AR6K_version.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/AR6K_version.h
36626 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/AR6K_version.h 1970-01-01 01:00:00.000000000 +0100
36627 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/AR6K_version.h 2009-05-10 22:27:59.000000000 +0200
36628 @@ -0,0 +1,36 @@
36629 +#define __VER_MAJOR_ 2
36630 +#define __VER_MINOR_ 0
36631 +#define __VER_PATCH_ 0
36632 +
36633 +
36634 +/*
36635 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36636 + * All rights reserved.
36637 + *
36638 + * $ATH_LICENSE_HOSTSDK0_C$
36639 + *
36640 + * The makear6ksdk script (used for release builds) modifies the following line.
36641 + */
36642 +#define __BUILD_NUMBER_ 18
36643 +
36644 +
36645 +/* Format of the version number. */
36646 +#define VER_MAJOR_BIT_OFFSET 28
36647 +#define VER_MINOR_BIT_OFFSET 24
36648 +#define VER_PATCH_BIT_OFFSET 16
36649 +#define VER_BUILD_NUM_BIT_OFFSET 0
36650 +
36651 +
36652 +/*
36653 + * The version has the following format:
36654 + * Bits 28-31: Major version
36655 + * Bits 24-27: Minor version
36656 + * Bits 16-23: Patch version
36657 + * Bits 0-15: Build number (automatically generated during build process )
36658 + * E.g. Build 1.1.3.7 would be represented as 0x11030007.
36659 + *
36660 + * DO NOT split the following macro into multiple lines as this may confuse the build scripts.
36661 + */
36662 +#define AR6K_SW_VERSION ( ( __VER_MAJOR_ << VER_MAJOR_BIT_OFFSET ) + ( __VER_MINOR_ << VER_MINOR_BIT_OFFSET ) + ( __VER_PATCH_ << VER_PATCH_BIT_OFFSET ) + ( __BUILD_NUMBER_ << VER_BUILD_NUM_BIT_OFFSET ) )
36663 +
36664 +
36665 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/AR6K_version.h.NEW linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/AR6K_version.h.NEW
36666 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/AR6K_version.h.NEW 1970-01-01 01:00:00.000000000 +0100
36667 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/AR6K_version.h.NEW 2009-05-10 22:27:59.000000000 +0200
36668 @@ -0,0 +1,36 @@
36669 +#define __VER_MAJOR_ 2
36670 +#define __VER_MINOR_ 0
36671 +#define __VER_PATCH_ 0
36672 +
36673 +
36674 +/*
36675 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36676 + * All rights reserved.
36677 + *
36678 + * $ATH_LICENSE_HOSTSDK0_C$
36679 + *
36680 + * The makear6ksdk script (used for release builds) modifies the following line.
36681 + */
36682 +#define __BUILD_NUMBER_ 18
36683 +
36684 +
36685 +/* Format of the version number. */
36686 +#define VER_MAJOR_BIT_OFFSET 28
36687 +#define VER_MINOR_BIT_OFFSET 24
36688 +#define VER_PATCH_BIT_OFFSET 16
36689 +#define VER_BUILD_NUM_BIT_OFFSET 0
36690 +
36691 +
36692 +/*
36693 + * The version has the following format:
36694 + * Bits 28-31: Major version
36695 + * Bits 24-27: Minor version
36696 + * Bits 16-23: Patch version
36697 + * Bits 0-15: Build number (automatically generated during build process )
36698 + * E.g. Build 1.1.3.7 would be represented as 0x11030007.
36699 + *
36700 + * DO NOT split the following macro into multiple lines as this may confuse the build scripts.
36701 + */
36702 +#define AR6K_SW_VERSION ( ( __VER_MAJOR_ << VER_MAJOR_BIT_OFFSET ) + ( __VER_MINOR_ << VER_MINOR_BIT_OFFSET ) + ( __VER_PATCH_ << VER_PATCH_BIT_OFFSET ) + ( __BUILD_NUMBER_ << VER_BUILD_NUM_BIT_OFFSET ) )
36703 +
36704 +
36705 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/athdefs.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/athdefs.h
36706 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/athdefs.h 1970-01-01 01:00:00.000000000 +0100
36707 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/athdefs.h 2009-05-10 22:27:59.000000000 +0200
36708 @@ -0,0 +1,85 @@
36709 +#ifndef __ATHDEFS_H__
36710 +#define __ATHDEFS_H__
36711 +
36712 +/*
36713 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36714 + * All rights reserved.
36715 + *
36716 + * $ATH_LICENSE_HOSTSDK0_C$
36717 + *
36718 + * This file contains definitions that may be used across both
36719 + * Host and Target software. Nothing here is module-dependent
36720 + * or platform-dependent.
36721 + */
36722 +
36723 +/*
36724 + * Generic error codes that can be used by hw, sta, ap, sim, dk
36725 + * and any other environments. Since these are enums, feel free to
36726 + * add any more codes that you need.
36727 + */
36728 +
36729 +typedef enum {
36730 + A_ERROR = -1, /* Generic error return */
36731 + A_OK = 0, /* success */
36732 + /* Following values start at 1 */
36733 + A_DEVICE_NOT_FOUND, /* not able to find PCI device */
36734 + A_NO_MEMORY, /* not able to allocate memory, not available */
36735 + A_MEMORY_NOT_AVAIL, /* memory region is not free for mapping */
36736 + A_NO_FREE_DESC, /* no free descriptors available */
36737 + A_BAD_ADDRESS, /* address does not match descriptor */
36738 + A_WIN_DRIVER_ERROR, /* used in NT_HW version, if problem at init */
36739 + A_REGS_NOT_MAPPED, /* registers not correctly mapped */
36740 + A_EPERM, /* Not superuser */
36741 + A_EACCES, /* Access denied */
36742 + A_ENOENT, /* No such entry, search failed, etc. */
36743 + A_EEXIST, /* The object already exists (can't create) */
36744 + A_EFAULT, /* Bad address fault */
36745 + A_EBUSY, /* Object is busy */
36746 + A_EINVAL, /* Invalid parameter */
36747 + A_EMSGSIZE, /* Inappropriate message buffer length */
36748 + A_ECANCELED, /* Operation canceled */
36749 + A_ENOTSUP, /* Operation not supported */
36750 + A_ECOMM, /* Communication error on send */
36751 + A_EPROTO, /* Protocol error */
36752 + A_ENODEV, /* No such device */
36753 + A_EDEVNOTUP, /* device is not UP */
36754 + A_NO_RESOURCE, /* No resources for requested operation */
36755 + A_HARDWARE, /* Hardware failure */
36756 + A_PENDING, /* Asynchronous routine; will send up results la
36757 +ter (typically in callback) */
36758 + A_EBADCHANNEL, /* The channel cannot be used */
36759 + A_DECRYPT_ERROR, /* Decryption error */
36760 + A_PHY_ERROR, /* RX PHY error */
36761 + A_CONSUMED /* Object was consumed */
36762 +} A_STATUS;
36763 +
36764 +#define A_SUCCESS(x) (x == A_OK)
36765 +#define A_FAILED(x) (!A_SUCCESS(x))
36766 +
36767 +#ifndef TRUE
36768 +#define TRUE 1
36769 +#endif
36770 +
36771 +#ifndef FALSE
36772 +#define FALSE 0
36773 +#endif
36774 +
36775 +/*
36776 + * The following definition is WLAN specific definition
36777 + */
36778 +typedef enum {
36779 + MODE_11A = 0, /* 11a Mode */
36780 + MODE_11G = 1, /* 11g + 11b Mode */
36781 + MODE_11B = 2, /* 11b Mode */
36782 + MODE_11GONLY = 3, /* 11g only Mode */
36783 + MODE_UNKNOWN = 4,
36784 + MODE_MAX = 4
36785 +} WLAN_PHY_MODE;
36786 +
36787 +typedef enum {
36788 + WLAN_11A_CAPABILITY = 1,
36789 + WLAN_11G_CAPABILITY = 2,
36790 + WLAN_11AG_CAPABILITY = 3,
36791 +}WLAN_CAPABILITY;
36792 +
36793 +#endif /* __ATHDEFS_H__ */
36794 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/athdrv.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/athdrv.h
36795 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/athdrv.h 1970-01-01 01:00:00.000000000 +0100
36796 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/athdrv.h 2009-05-10 22:27:59.000000000 +0200
36797 @@ -0,0 +1,32 @@
36798 +/*
36799 + * Copyright (c) 2004-2006 Atheros Communications Inc.
36800 + * All rights reserved.
36801 + *
36802 + *
36803 + *
36804 + * This program is free software; you can redistribute it and/or modify
36805 + * it under the terms of the GNU General Public License version 2 as
36806 + * published by the Free Software Foundation;
36807 + *
36808 + * Software distributed under the License is distributed on an "AS
36809 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36810 + * implied. See the License for the specific language governing
36811 + * rights and limitations under the License.
36812 + *
36813 + *
36814 + *
36815 + */
36816 +
36817 +#ifndef _ATHDRV_H_
36818 +#define _ATHDRV_H_
36819 +
36820 +#ifdef __cplusplus
36821 +extern "C" {
36822 +#endif
36823 +
36824 +
36825 +#ifdef __cplusplus
36826 +}
36827 +#endif
36828 +
36829 +#endif /* _ATHDRV_H_ */
36830 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/athendpack.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/athendpack.h
36831 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/athendpack.h 1970-01-01 01:00:00.000000000 +0100
36832 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/athendpack.h 2009-05-10 22:27:59.000000000 +0200
36833 @@ -0,0 +1,41 @@
36834 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36835 + * @file: athendpack.h
36836 + *
36837 + * @abstract: end compiler-specific structure packing
36838 + *
36839 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36840 + * All rights reserved.
36841 + *
36842 + *
36843 + * This program is free software; you can redistribute it and/or modify
36844 + * it under the terms of the GNU General Public License version 2 as
36845 + * published by the Free Software Foundation;
36846 + *
36847 + * Software distributed under the License is distributed on an "AS
36848 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36849 + * implied. See the License for the specific language governing
36850 + * rights and limitations under the License.
36851 + *
36852 + *
36853 + *
36854 + */
36855 +#ifdef VXWORKS
36856 +#endif /* VXWORKS */
36857 +
36858 +#ifdef LINUX
36859 +#endif /* LINUX */
36860 +
36861 +#ifdef QNX
36862 +#endif /* QNX */
36863 +
36864 +#ifdef INTEGRITY
36865 +#include "integrity/athendpack_integrity.h"
36866 +#endif /* INTEGRITY */
36867 +
36868 +#ifdef NUCLEUS
36869 +#endif /* NUCLEUS */
36870 +
36871 +#ifdef UNDER_CE
36872 +#include "../os/wince/include/athendpack_wince.h"
36873 +#endif /* WINCE */
36874 +
36875 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/athstartpack.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/athstartpack.h
36876 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/athstartpack.h 1970-01-01 01:00:00.000000000 +0100
36877 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/athstartpack.h 2009-05-10 22:27:59.000000000 +0200
36878 @@ -0,0 +1,42 @@
36879 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36880 + * @file: athstartpack.h
36881 + *
36882 + * @abstract: start compiler-specific structure packing
36883 + *
36884 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36885 + * All rights reserved.
36886 + *
36887 + *
36888 + * This program is free software; you can redistribute it and/or modify
36889 + * it under the terms of the GNU General Public License version 2 as
36890 + * published by the Free Software Foundation;
36891 + *
36892 + * Software distributed under the License is distributed on an "AS
36893 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36894 + * implied. See the License for the specific language governing
36895 + * rights and limitations under the License.
36896 + *
36897 + *
36898 + *
36899 + */
36900 +
36901 +#ifdef VXWORKS
36902 +#endif /* VXWORKS */
36903 +
36904 +#ifdef LINUX
36905 +#endif /* LINUX */
36906 +
36907 +#ifdef QNX
36908 +#endif /* QNX */
36909 +
36910 +#ifdef INTEGRITY
36911 +#include "integrity/athstartpack_integrity.h"
36912 +#endif /* INTEGRITY */
36913 +
36914 +#ifdef NUCLEUS
36915 +#endif /* NUCLEUS */
36916 +
36917 +#ifdef UNDER_CE
36918 +#include "../os/wince/include/athstartpack_wince.h"
36919 +#endif /* WINCE */
36920 +
36921 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_types.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_types.h
36922 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/a_types.h 1970-01-01 01:00:00.000000000 +0100
36923 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/a_types.h 2009-05-10 22:27:59.000000000 +0200
36924 @@ -0,0 +1,28 @@
36925 +#ifndef _A_TYPES_H_
36926 +#define _A_TYPES_H_
36927 +/*
36928 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/a_types.h#1 $
36929 + *
36930 + * This file contains the definitions of the basic atheros data types.
36931 + * It is used to map the data types in atheros files to a platform specific
36932 + * type.
36933 + *
36934 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
36935 + *
36936 + *
36937 + * This program is free software; you can redistribute it and/or modify
36938 + * it under the terms of the GNU General Public License version 2 as
36939 + * published by the Free Software Foundation;
36940 + *
36941 + * Software distributed under the License is distributed on an "AS
36942 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36943 + * implied. See the License for the specific language governing
36944 + * rights and limitations under the License.
36945 + *
36946 + *
36947 + *
36948 + */
36949 +
36950 +#include "../ar6000/athtypes_linux.h"
36951 +
36952 +#endif /* _ATHTYPES_H_ */
36953 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/bmi.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/bmi.h
36954 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/bmi.h 1970-01-01 01:00:00.000000000 +0100
36955 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/bmi.h 2009-05-10 22:27:59.000000000 +0200
36956 @@ -0,0 +1,100 @@
36957 +#ifndef _BMI_H_
36958 +#define _BMI_H_
36959 +/*
36960 + * Copyright (c) 2004-2005 Atheros Communications Inc.
36961 + * All rights reserved.
36962 + *
36963 + *
36964 + * This program is free software; you can redistribute it and/or modify
36965 + * it under the terms of the GNU General Public License version 2 as
36966 + * published by the Free Software Foundation;
36967 + *
36968 + * Software distributed under the License is distributed on an "AS
36969 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
36970 + * implied. See the License for the specific language governing
36971 + * rights and limitations under the License.
36972 + *
36973 + *
36974 + *
36975 + * BMI declarations and prototypes
36976 + */
36977 +
36978 +#ifdef __cplusplus
36979 +extern "C" {
36980 +#endif /* __cplusplus */
36981 +
36982 +/* Header files */
36983 +#include "a_config.h"
36984 +#include "athdefs.h"
36985 +#include "a_types.h"
36986 +#include "hif.h"
36987 +#include "a_osapi.h"
36988 +#include "bmi_msg.h"
36989 +
36990 +void
36991 +BMIInit(void);
36992 +
36993 +A_STATUS
36994 +BMIDone(HIF_DEVICE *device);
36995 +
36996 +A_STATUS
36997 +BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info);
36998 +
36999 +A_STATUS
37000 +BMIReadMemory(HIF_DEVICE *device,
37001 + A_UINT32 address,
37002 + A_UCHAR *buffer,
37003 + A_UINT32 length);
37004 +
37005 +A_STATUS
37006 +BMIWriteMemory(HIF_DEVICE *device,
37007 + A_UINT32 address,
37008 + A_UCHAR *buffer,
37009 + A_UINT32 length);
37010 +
37011 +A_STATUS
37012 +BMIExecute(HIF_DEVICE *device,
37013 + A_UINT32 address,
37014 + A_UINT32 *param);
37015 +
37016 +A_STATUS
37017 +BMISetAppStart(HIF_DEVICE *device,
37018 + A_UINT32 address);
37019 +
37020 +A_STATUS
37021 +BMIReadSOCRegister(HIF_DEVICE *device,
37022 + A_UINT32 address,
37023 + A_UINT32 *param);
37024 +
37025 +A_STATUS
37026 +BMIWriteSOCRegister(HIF_DEVICE *device,
37027 + A_UINT32 address,
37028 + A_UINT32 param);
37029 +
37030 +A_STATUS
37031 +BMIrompatchInstall(HIF_DEVICE *device,
37032 + A_UINT32 ROM_addr,
37033 + A_UINT32 RAM_addr,
37034 + A_UINT32 nbytes,
37035 + A_UINT32 do_activate,
37036 + A_UINT32 *patch_id);
37037 +
37038 +A_STATUS
37039 +BMIrompatchUninstall(HIF_DEVICE *device,
37040 + A_UINT32 rompatch_id);
37041 +
37042 +A_STATUS
37043 +BMIrompatchActivate(HIF_DEVICE *device,
37044 + A_UINT32 rompatch_count,
37045 + A_UINT32 *rompatch_list);
37046 +
37047 +A_STATUS
37048 +BMIrompatchDeactivate(HIF_DEVICE *device,
37049 + A_UINT32 rompatch_count,
37050 + A_UINT32 *rompatch_list);
37051 +
37052 +#ifdef __cplusplus
37053 +}
37054 +#endif
37055 +
37056 +#endif /* _BMI_H_ */
37057 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/bmi_msg.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/bmi_msg.h
37058 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/bmi_msg.h 1970-01-01 01:00:00.000000000 +0100
37059 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/bmi_msg.h 2009-05-10 22:27:59.000000000 +0200
37060 @@ -0,0 +1,199 @@
37061 +#ifndef __BMI_MSG_H__
37062 +#define __BMI_MSG_H__
37063 +/*
37064 + *
37065 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37066 + * All rights reserved.
37067 + *
37068 + *
37069 + * This program is free software; you can redistribute it and/or modify
37070 + * it under the terms of the GNU General Public License version 2 as
37071 + * published by the Free Software Foundation;
37072 + *
37073 + * Software distributed under the License is distributed on an "AS
37074 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
37075 + * implied. See the License for the specific language governing
37076 + * rights and limitations under the License.
37077 + *
37078 + *
37079 + *
37080 + */
37081 +
37082 +/*
37083 + * Bootloader Messaging Interface (BMI)
37084 + *
37085 + * BMI is a very simple messaging interface used during initialization
37086 + * to read memory, write memory, execute code, and to define an
37087 + * application entry PC.
37088 + *
37089 + * It is used to download an application to AR6K, to provide
37090 + * patches to code that is already resident on AR6K, and generally
37091 + * to examine and modify state. The Host has an opportunity to use
37092 + * BMI only once during bootup. Once the Host issues a BMI_DONE
37093 + * command, this opportunity ends.
37094 + *
37095 + * The Host writes BMI requests to mailbox0, and reads BMI responses
37096 + * from mailbox0. BMI requests all begin with a command
37097 + * (see below for specific commands), and are followed by
37098 + * command-specific data.
37099 + *
37100 + * Flow control:
37101 + * The Host can only issue a command once the Target gives it a
37102 + * "BMI Command Credit", using AR6K Counter #4. As soon as the
37103 + * Target has completed a command, it issues another BMI Command
37104 + * Credit (so the Host can issue the next command).
37105 + *
37106 + * BMI handles all required Target-side cache flushing.
37107 + */
37108 +
37109 +
37110 +/* Maximum data size used for BMI transfers */
37111 +#define BMI_DATASZ_MAX 32
37112 +
37113 +/* BMI Commands */
37114 +
37115 +#define BMI_NO_COMMAND 0
37116 +
37117 +#define BMI_DONE 1
37118 + /*
37119 + * Semantics: Host is done using BMI
37120 + * Request format:
37121 + * A_UINT32 command (BMI_DONE)
37122 + * Response format: none
37123 + */
37124 +
37125 +#define BMI_READ_MEMORY 2
37126 + /*
37127 + * Semantics: Host reads AR6K memory
37128 + * Request format:
37129 + * A_UINT32 command (BMI_READ_MEMORY)
37130 + * A_UINT32 address
37131 + * A_UINT32 length, at most BMI_DATASZ_MAX
37132 + * Response format:
37133 + * A_UINT8 data[length]
37134 + */
37135 +
37136 +#define BMI_WRITE_MEMORY 3
37137 + /*
37138 + * Semantics: Host writes AR6K memory
37139 + * Request format:
37140 + * A_UINT32 command (BMI_WRITE_MEMORY)
37141 + * A_UINT32 address
37142 + * A_UINT32 length, at most BMI_DATASZ_MAX
37143 + * A_UINT8 data[length]
37144 + * Response format: none
37145 + */
37146 +
37147 +#define BMI_EXECUTE 4
37148 + /*
37149 + * Semantics: Causes AR6K to execute code
37150 + * Request format:
37151 + * A_UINT32 command (BMI_EXECUTE)
37152 + * A_UINT32 address
37153 + * A_UINT32 parameter
37154 + * Response format:
37155 + * A_UINT32 return value
37156 + */
37157 +
37158 +#define BMI_SET_APP_START 5
37159 + /*
37160 + * Semantics: Set Target application starting address
37161 + * Request format:
37162 + * A_UINT32 command (BMI_SET_APP_START)
37163 + * A_UINT32 address
37164 + * Response format: none
37165 + */
37166 +
37167 +#define BMI_READ_SOC_REGISTER 6
37168 + /*
37169 + * Semantics: Read a 32-bit Target SOC register.
37170 + * Request format:
37171 + * A_UINT32 command (BMI_READ_REGISTER)
37172 + * A_UINT32 address
37173 + * Response format:
37174 + * A_UINT32 value
37175 + */
37176 +
37177 +#define BMI_WRITE_SOC_REGISTER 7
37178 + /*
37179 + * Semantics: Write a 32-bit Target SOC register.
37180 + * Request format:
37181 + * A_UINT32 command (BMI_WRITE_REGISTER)
37182 + * A_UINT32 address
37183 + * A_UINT32 value
37184 + *
37185 + * Response format: none
37186 + */
37187 +
37188 +#define BMI_GET_TARGET_ID 8
37189 +#define BMI_GET_TARGET_INFO 8
37190 + /*
37191 + * Semantics: Fetch the 4-byte Target information
37192 + * Request format:
37193 + * A_UINT32 command (BMI_GET_TARGET_ID/INFO)
37194 + * Response format1 (old firmware):
37195 + * A_UINT32 TargetVersionID
37196 + * Response format2 (newer firmware):
37197 + * A_UINT32 TARGET_VERSION_SENTINAL
37198 + * struct bmi_target_info;
37199 + */
37200 +
37201 +struct bmi_target_info {
37202 + A_UINT32 target_info_byte_count; /* size of this structure */
37203 + A_UINT32 target_ver; /* Target Version ID */
37204 + A_UINT32 target_type; /* Target type */
37205 +};
37206 +#define TARGET_VERSION_SENTINAL 0xffffffff
37207 +#define TARGET_TYPE_AR6001 1
37208 +#define TARGET_TYPE_AR6002 2
37209 +
37210 +
37211 +#define BMI_ROMPATCH_INSTALL 9
37212 + /*
37213 + * Semantics: Install a ROM Patch.
37214 + * Request format:
37215 + * A_UINT32 command (BMI_ROMPATCH_INSTALL)
37216 + * A_UINT32 Target ROM Address
37217 + * A_UINT32 Target RAM Address
37218 + * A_UINT32 Size, in bytes
37219 + * A_UINT32 Activate? 1-->activate;
37220 + * 0-->install but do not activate
37221 + * Response format:
37222 + * A_UINT32 PatchID
37223 + */
37224 +
37225 +#define BMI_ROMPATCH_UNINSTALL 10
37226 + /*
37227 + * Semantics: Uninstall a previously-installed ROM Patch,
37228 + * automatically deactivating, if necessary.
37229 + * Request format:
37230 + * A_UINT32 command (BMI_ROMPATCH_UNINSTALL)
37231 + * A_UINT32 PatchID
37232 + *
37233 + * Response format: none
37234 + */
37235 +
37236 +#define BMI_ROMPATCH_ACTIVATE 11
37237 + /*
37238 + * Semantics: Activate a list of previously-installed ROM Patches.
37239 + * Request format:
37240 + * A_UINT32 command (BMI_ROMPATCH_ACTIVATE)
37241 + * A_UINT32 rompatch_count
37242 + * A_UINT32 PatchID[rompatch_count]
37243 + *
37244 + * Response format: none
37245 + */
37246 +
37247 +#define BMI_ROMPATCH_DEACTIVATE 12
37248 + /*
37249 + * Semantics: Deactivate a list of active ROM Patches.
37250 + * Request format:
37251 + * A_UINT32 command (BMI_ROMPATCH_DEACTIVATE)
37252 + * A_UINT32 rompatch_count
37253 + * A_UINT32 PatchID[rompatch_count]
37254 + *
37255 + * Response format: none
37256 + */
37257 +
37258 +
37259 +#endif /* __BMI_MSG_H__ */
37260 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/common_drv.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/common_drv.h
37261 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/common_drv.h 1970-01-01 01:00:00.000000000 +0100
37262 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/common_drv.h 2009-05-10 22:27:59.000000000 +0200
37263 @@ -0,0 +1,61 @@
37264 +/*
37265 + *
37266 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37267 + * All rights reserved.
37268 + *
37269 + *
37270 + * This program is free software; you can redistribute it and/or modify
37271 + * it under the terms of the GNU General Public License version 2 as
37272 + * published by the Free Software Foundation;
37273 + *
37274 + * Software distributed under the License is distributed on an "AS
37275 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
37276 + * implied. See the License for the specific language governing
37277 + * rights and limitations under the License.
37278 + *
37279 + *
37280 + *
37281 + */
37282 +
37283 +
37284 +#ifndef COMMON_DRV_H_
37285 +#define COMMON_DRV_H_
37286 +
37287 +#include "hif.h"
37288 +#include "htc_packet.h"
37289 +
37290 +
37291 +
37292 +/* structure that is the state information for the default credit distribution callback
37293 + * drivers should instantiate (zero-init as well) this structure in their driver instance
37294 + * and pass it as a context to the HTC credit distribution functions */
37295 +typedef struct _COMMON_CREDIT_STATE_INFO {
37296 + int TotalAvailableCredits; /* total credits in the system at startup */
37297 + int CurrentFreeCredits; /* credits available in the pool that have not been
37298 + given out to endpoints */
37299 + HTC_ENDPOINT_CREDIT_DIST *pLowestPriEpDist; /* pointer to the lowest priority endpoint dist struct */
37300 +} COMMON_CREDIT_STATE_INFO;
37301 +
37302 +
37303 +/* HTC TX packet tagging definitions */
37304 +#define AR6K_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED
37305 +#define AR6K_DATA_PKT_TAG (AR6K_CONTROL_PKT_TAG + 1)
37306 +
37307 +#ifdef __cplusplus
37308 +extern "C" {
37309 +#endif
37310 +
37311 +/* OS-independent APIs */
37312 +A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo);
37313 +A_STATUS ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
37314 +A_STATUS ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
37315 +A_STATUS ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address, A_UCHAR *data, A_UINT32 length);
37316 +A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType);
37317 +void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType);
37318 +A_STATUS ar6000_reset_device_skipflash(HIF_DEVICE *hifDevice);
37319 +
37320 +#ifdef __cplusplus
37321 +}
37322 +#endif
37323 +
37324 +#endif /*COMMON_DRV_H_*/
37325 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/dbglog_api.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dbglog_api.h
37326 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/dbglog_api.h 1970-01-01 01:00:00.000000000 +0100
37327 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dbglog_api.h 2009-05-10 22:27:59.000000000 +0200
37328 @@ -0,0 +1,46 @@
37329 +#ifndef _DBGLOG_API_H_
37330 +#define _DBGLOG_API_H_
37331 +/*
37332 + * Copyright (c) 2004-2006 Atheros Communications Inc.
37333 + * All rights reserved.
37334 + *
37335 + *
37336 + * This program is free software; you can redistribute it and/or modify
37337 + * it under the terms of the GNU General Public License version 2 as
37338 + * published by the Free Software Foundation;
37339 + *
37340 + * Software distributed under the License is distributed on an "AS
37341 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
37342 + * implied. See the License for the specific language governing
37343 + * rights and limitations under the License.
37344 + *
37345 + *
37346 + *
37347 + * This file contains host side debug primitives.
37348 + */
37349 +
37350 +#ifdef __cplusplus
37351 +extern "C" {
37352 +#endif
37353 +
37354 +#include "dbglog.h"
37355 +
37356 +#define DBGLOG_HOST_LOG_BUFFER_SIZE DBGLOG_LOG_BUFFER_SIZE
37357 +
37358 +#define DBGLOG_GET_DBGID(arg) \
37359 + ((arg & DBGLOG_DBGID_MASK) >> DBGLOG_DBGID_OFFSET)
37360 +
37361 +#define DBGLOG_GET_MODULEID(arg) \
37362 + ((arg & DBGLOG_MODULEID_MASK) >> DBGLOG_MODULEID_OFFSET)
37363 +
37364 +#define DBGLOG_GET_NUMARGS(arg) \
37365 + ((arg & DBGLOG_NUM_ARGS_MASK) >> DBGLOG_NUM_ARGS_OFFSET)
37366 +
37367 +#define DBGLOG_GET_TIMESTAMP(arg) \
37368 + ((arg & DBGLOG_TIMESTAMP_MASK) >> DBGLOG_TIMESTAMP_OFFSET)
37369 +
37370 +#ifdef __cplusplus
37371 +}
37372 +#endif
37373 +
37374 +#endif /* _DBGLOG_API_H_ */
37375 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/dbglog.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dbglog.h
37376 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/dbglog.h 1970-01-01 01:00:00.000000000 +0100
37377 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dbglog.h 2009-05-10 22:27:59.000000000 +0200
37378 @@ -0,0 +1,107 @@
37379 +/*
37380 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37381 + * All rights reserved.
37382 + *
37383 + * $ATH_LICENSE_HOSTSDK0_C$
37384 + *
37385 + * This file contains the definitions and data structures associated with
37386 + * the log based debug mechanism.
37387 + *
37388 + */
37389 +
37390 +#ifndef _DBGLOG_H_
37391 +#define _DBGLOG_H_
37392 +
37393 +#ifdef __cplusplus
37394 +extern "C" {
37395 +#endif
37396 +
37397 +#define DBGLOG_TIMESTAMP_OFFSET 0
37398 +#define DBGLOG_TIMESTAMP_MASK 0x0000FFFF /* Bit 0-15. Contains bit
37399 + 8-23 of the LF0 timer */
37400 +#define DBGLOG_DBGID_OFFSET 16
37401 +#define DBGLOG_DBGID_MASK 0x03FF0000 /* Bit 16-25 */
37402 +#define DBGLOG_DBGID_NUM_MAX 256 /* Upper limit is width of mask */
37403 +
37404 +#define DBGLOG_MODULEID_OFFSET 26
37405 +#define DBGLOG_MODULEID_MASK 0x3C000000 /* Bit 26-29 */
37406 +#define DBGLOG_MODULEID_NUM_MAX 16 /* Upper limit is width of mask */
37407 +
37408 +/*
37409 + * Please ensure that the definition of any new module intrduced is captured
37410 + * between the DBGLOG_MODULEID_START and DBGLOG_MODULEID_END defines. The
37411 + * structure is required for the parser to correctly pick up the values for
37412 + * different modules.
37413 + */
37414 +#define DBGLOG_MODULEID_START
37415 +#define DBGLOG_MODULEID_INF 0
37416 +#define DBGLOG_MODULEID_WMI 1
37417 +#define DBGLOG_MODULEID_CSERV 2
37418 +#define DBGLOG_MODULEID_PM 3
37419 +#define DBGLOG_MODULEID_TXRX_MGMTBUF 4
37420 +#define DBGLOG_MODULEID_TXRX_TXBUF 5
37421 +#define DBGLOG_MODULEID_TXRX_RXBUF 6
37422 +#define DBGLOG_MODULEID_WOW 7
37423 +#define DBGLOG_MODULEID_WHAL 8
37424 +#define DBGLOG_MODULEID_END
37425 +
37426 +#define DBGLOG_NUM_ARGS_OFFSET 30
37427 +#define DBGLOG_NUM_ARGS_MASK 0xC0000000 /* Bit 30-31 */
37428 +#define DBGLOG_NUM_ARGS_MAX 2 /* Upper limit is width of mask */
37429 +
37430 +#define DBGLOG_MODULE_LOG_ENABLE_OFFSET 0
37431 +#define DBGLOG_MODULE_LOG_ENABLE_MASK 0x0000FFFF
37432 +
37433 +#define DBGLOG_REPORTING_ENABLED_OFFSET 16
37434 +#define DBGLOG_REPORTING_ENABLED_MASK 0x00010000
37435 +
37436 +#define DBGLOG_TIMESTAMP_RESOLUTION_OFFSET 17
37437 +#define DBGLOG_TIMESTAMP_RESOLUTION_MASK 0x000E0000
37438 +
37439 +#define DBGLOG_REPORT_SIZE_OFFSET 20
37440 +#define DBGLOG_REPORT_SIZE_MASK 0x3FF00000
37441 +
37442 +#define DBGLOG_LOG_BUFFER_SIZE 1500
37443 +#define DBGLOG_DBGID_DEFINITION_LEN_MAX 64
37444 +
37445 +struct dbglog_buf_s {
37446 + struct dbglog_buf_s *next;
37447 + A_INT8 *buffer;
37448 + A_UINT32 bufsize;
37449 + A_UINT32 length;
37450 + A_UINT32 count;
37451 + A_UINT32 free;
37452 +};
37453 +
37454 +struct dbglog_hdr_s {
37455 + struct dbglog_buf_s *dbuf;
37456 + A_UINT32 dropped;
37457 +};
37458 +
37459 +struct dbglog_config_s {
37460 + A_UINT32 cfgvalid; /* Mask with valid config bits */
37461 + union {
37462 + /* TODO: Take care of endianness */
37463 + struct {
37464 + A_UINT32 mmask:16; /* Mask of modules with logging on */
37465 + A_UINT32 rep:1; /* Reporting enabled or not */
37466 + A_UINT32 tsr:3; /* Time stamp resolution. Def: 1 ms */
37467 + A_UINT32 size:10; /* Report size in number of messages */
37468 + A_UINT32 reserved:2;
37469 + } dbglog_config;
37470 +
37471 + A_UINT32 value;
37472 + } u;
37473 +};
37474 +
37475 +#define cfgmmask u.dbglog_config.mmask
37476 +#define cfgrep u.dbglog_config.rep
37477 +#define cfgtsr u.dbglog_config.tsr
37478 +#define cfgsize u.dbglog_config.size
37479 +#define cfgvalue u.value
37480 +
37481 +#ifdef __cplusplus
37482 +}
37483 +#endif
37484 +
37485 +#endif /* _DBGLOG_H_ */
37486 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/dbglog_id.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dbglog_id.h
37487 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/dbglog_id.h 1970-01-01 01:00:00.000000000 +0100
37488 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dbglog_id.h 2009-05-10 22:27:59.000000000 +0200
37489 @@ -0,0 +1,307 @@
37490 +/*
37491 + *
37492 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37493 + * All rights reserved.
37494 + *
37495 + * $ATH_LICENSE_HOSTSDK0_C$
37496 + *
37497 + * This file contains the definitions of the debug identifiers for different
37498 + * modules.
37499 + *
37500 + */
37501 +
37502 +#ifndef _DBGLOG_ID_H_
37503 +#define _DBGLOG_ID_H_
37504 +
37505 +#ifdef __cplusplus
37506 +extern "C" {
37507 +#endif
37508 +
37509 +/*
37510 + * The nomenclature for the debug identifiers is MODULE_DESCRIPTION.
37511 + * Please ensure that the definition of any new debugid introduced is captured
37512 + * between the <MODULE>_DBGID_DEFINITION_START and
37513 + * <MODULE>_DBGID_DEFINITION_END defines. The structure is required for the
37514 + * parser to correctly pick up the values for different debug identifiers.
37515 + */
37516 +
37517 +/* INF debug identifier definitions */
37518 +#define INF_DBGID_DEFINITION_START
37519 +#define INF_ASSERTION_FAILED 1
37520 +#define INF_TARGET_ID 2
37521 +#define INF_DBGID_DEFINITION_END
37522 +
37523 +/* WMI debug identifier definitions */
37524 +#define WMI_DBGID_DEFINITION_START
37525 +#define WMI_CMD_RX_XTND_PKT_TOO_SHORT 1
37526 +#define WMI_EXTENDED_CMD_NOT_HANDLED 2
37527 +#define WMI_CMD_RX_PKT_TOO_SHORT 3
37528 +#define WMI_CALLING_WMI_EXTENSION_FN 4
37529 +#define WMI_CMD_NOT_HANDLED 5
37530 +#define WMI_IN_SYNC 6
37531 +#define WMI_TARGET_WMI_SYNC_CMD 7
37532 +#define WMI_SET_SNR_THRESHOLD_PARAMS 8
37533 +#define WMI_SET_RSSI_THRESHOLD_PARAMS 9
37534 +#define WMI_SET_LQ_TRESHOLD_PARAMS 10
37535 +#define WMI_TARGET_CREATE_PSTREAM_CMD 11
37536 +#define WMI_WI_DTM_INUSE 12
37537 +#define WMI_TARGET_DELETE_PSTREAM_CMD 13
37538 +#define WMI_TARGET_IMPLICIT_DELETE_PSTREAM_CMD 14
37539 +#define WMI_TARGET_GET_BIT_RATE_CMD 15
37540 +#define WMI_GET_RATE_MASK_CMD_FIX_RATE_MASK_IS 16
37541 +#define WMI_TARGET_GET_AVAILABLE_CHANNELS_CMD 17
37542 +#define WMI_TARGET_GET_TX_PWR_CMD 18
37543 +#define WMI_FREE_EVBUF_WMIBUF 19
37544 +#define WMI_FREE_EVBUF_DATABUF 20
37545 +#define WMI_FREE_EVBUF_BADFLAG 21
37546 +#define WMI_HTC_RX_ERROR_DATA_PACKET 22
37547 +#define WMI_HTC_RX_SYNC_PAUSING_FOR_MBOX 23
37548 +#define WMI_INCORRECT_WMI_DATA_HDR_DROPPING_PKT 24
37549 +#define WMI_SENDING_READY_EVENT 25
37550 +#define WMI_SETPOWER_MDOE_TO_MAXPERF 26
37551 +#define WMI_SETPOWER_MDOE_TO_REC 27
37552 +#define WMI_BSSINFO_EVENT_FROM 28
37553 +#define WMI_TARGET_GET_STATS_CMD 29
37554 +#define WMI_SENDING_SCAN_COMPLETE_EVENT 30
37555 +#define WMI_SENDING_RSSI_INDB_THRESHOLD_EVENT 31
37556 +#define WMI_SENDING_RSSI_INDBM_THRESHOLD_EVENT 32
37557 +#define WMI_SENDING_LINK_QUALITY_THRESHOLD_EVENT 33
37558 +#define WMI_SENDING_ERROR_REPORT_EVENT 34
37559 +#define WMI_SENDING_CAC_EVENT 35
37560 +#define WMI_TARGET_GET_ROAM_TABLE_CMD 36
37561 +#define WMI_TARGET_GET_ROAM_DATA_CMD 37
37562 +#define WMI_SENDING_GPIO_INTR_EVENT 38
37563 +#define WMI_SENDING_GPIO_ACK_EVENT 39
37564 +#define WMI_SENDING_GPIO_DATA_EVENT 40
37565 +#define WMI_CMD_RX 41
37566 +#define WMI_CMD_RX_XTND 42
37567 +#define WMI_EVENT_SEND 43
37568 +#define WMI_EVENT_SEND_XTND 44
37569 +#define WMI_DBGID_DEFINITION_END
37570 +
37571 +/* CSERV debug identifier definitions */
37572 +#define CSERV_DBGID_DEFINITION_START
37573 +#define CSERV_BEGIN_SCAN1 1
37574 +#define CSERV_BEGIN_SCAN2 2
37575 +#define CSERV_END_SCAN1 3
37576 +#define CSERV_END_SCAN2 4
37577 +#define CSERV_CHAN_SCAN_START 5
37578 +#define CSERV_CHAN_SCAN_STOP 6
37579 +#define CSERV_CHANNEL_OPPPORTUNITY 7
37580 +#define CSERV_NC_TIMEOUT 8
37581 +#define CSERV_BACK_HOME 10
37582 +#define CSERV_CHMGR_CH_CALLBACK1 11
37583 +#define CSERV_CHMGR_CH_CALLBACK2 12
37584 +#define CSERV_CHMGR_CH_CALLBACK3 13
37585 +#define CSERV_SET_SCAN_PARAMS1 14
37586 +#define CSERV_SET_SCAN_PARAMS2 15
37587 +#define CSERV_SET_SCAN_PARAMS3 16
37588 +#define CSERV_SET_SCAN_PARAMS4 17
37589 +#define CSERV_ABORT_SCAN 18
37590 +#define CSERV_NEWSTATE 19
37591 +#define CSERV_MINCHMGR_OP_END 20
37592 +#define CSERV_CHMGR_OP_END 21
37593 +#define CSERV_DISCONNECT_TIMEOUT 22
37594 +#define CSERV_ROAM_TIMEOUT 23
37595 +#define CSERV_FORCE_SCAN1 24
37596 +#define CSERV_FORCE_SCAN2 25
37597 +#define CSERV_FORCE_SCAN3 26
37598 +#define CSERV_UTIL_TIMEOUT 27
37599 +#define CSERV_RSSIPOLLER 28
37600 +#define CSERV_RETRY_CONNECT_TIMEOUT 29
37601 +#define CSERV_RSSIINDBMPOLLER 30
37602 +#define CSERV_BGSCAN_ENABLE 31
37603 +#define CSERV_BGSCAN_DISABLE 32
37604 +#define CSERV_WLAN_START_SCAN_CMD1 33
37605 +#define CSERV_WLAN_START_SCAN_CMD2 34
37606 +#define CSERV_WLAN_START_SCAN_CMD3 35
37607 +#define CSERV_START_SCAN_CMD 36
37608 +#define CSERV_START_FORCE_SCAN 37
37609 +#define CSERV_NEXT_CHAN 38
37610 +#define CSERV_SET_REGCODE 39
37611 +#define CSERV_START_ADHOC 40
37612 +#define CSERV_ADHOC_AT_HOME 41
37613 +#define CSERV_OPT_AT_HOME 42
37614 +#define CSERV_WLAN_CONNECT_CMD 43
37615 +#define CSERV_WLAN_RECONNECT_CMD 44
37616 +#define CSERV_WLAN_DISCONNECT_CMD 45
37617 +#define CSERV_BSS_CHANGE_CHANNEL 46
37618 +#define CSERV_BEACON_RX 47
37619 +#define CSERV_KEEPALIVE_CHECK 48
37620 +#define CSERV_RC_BEGIN_SCAN 49
37621 +#define CSERV_RC_SCAN_START 50
37622 +#define CSERV_RC_SCAN_STOP 51
37623 +#define CSERV_RC_NEXT 52
37624 +#define CSERV_RC_SCAN_END 53
37625 +#define CSERV_PROBE_CALLBACK 54
37626 +#define CSERV_ROAM1 55
37627 +#define CSERV_ROAM2 56
37628 +#define CSERV_ROAM3 57
37629 +#define CSERV_CONNECT_EVENT 58
37630 +#define CSERV_DISCONNECT_EVENT 59
37631 +#define CSERV_BMISS_HANDLER1 60
37632 +#define CSERV_BMISS_HANDLER2 61
37633 +#define CSERV_BMISS_HANDLER3 62
37634 +#define CSERV_LOWRSSI_HANDLER 63
37635 +#define CSERV_WLAN_SET_PMKID_CMD 64
37636 +#define CSERV_RECONNECT_REQUEST 65
37637 +#define CSERV_KEYSPLUMBED_EVENT 66
37638 +#define CSERV_NEW_REG 67
37639 +#define CSERV_SET_RSSI_THOLD 68
37640 +#define CSERV_RSSITHRESHOLDCHECK 69
37641 +#define CSERV_RSSIINDBMTHRESHOLDCHECK 70
37642 +#define CSERV_WLAN_SET_OPT_CMD1 71
37643 +#define CSERV_WLAN_SET_OPT_CMD2 72
37644 +#define CSERV_WLAN_SET_OPT_CMD3 73
37645 +#define CSERV_WLAN_SET_OPT_CMD4 74
37646 +#define CSERV_SCAN_CONNECT_STOP 75
37647 +#define CSERV_BMISS_HANDLER4 76
37648 +#define CSERV_INITIALIZE_TIMER 77
37649 +#define CSERV_ARM_TIMER 78
37650 +#define CSERV_DISARM_TIMER 79
37651 +#define CSERV_UNINITIALIZE_TIMER 80
37652 +#define CSERV_DISCONNECT_EVENT2 81
37653 +#define CSERV_SCAN_CONNECT_START 82
37654 +#define CSERV_BSSINFO_MEMORY_ALLOC_FAILED 83
37655 +#define CSERV_SET_SCAN_PARAMS5 84
37656 +#define CSERV_DBGID_DEFINITION_END
37657 +
37658 +/* TXRX debug identifier definitions */
37659 +#define TXRX_TXBUF_DBGID_DEFINITION_START
37660 +#define TXRX_TXBUF_ALLOCATE_BUF 1
37661 +#define TXRX_TXBUF_QUEUE_BUF_TO_MBOX 2
37662 +#define TXRX_TXBUF_QUEUE_BUF_TO_TXQ 3
37663 +#define TXRX_TXBUF_TXQ_DEPTH 4
37664 +#define TXRX_TXBUF_IBSS_QUEUE_TO_SFQ 5
37665 +#define TXRX_TXBUF_IBSS_QUEUE_TO_TXQ_FRM_SFQ 6
37666 +#define TXRX_TXBUF_INITIALIZE_TIMER 7
37667 +#define TXRX_TXBUF_ARM_TIMER 8
37668 +#define TXRX_TXBUF_DISARM_TIMER 9
37669 +#define TXRX_TXBUF_UNINITIALIZE_TIMER 10
37670 +#define TXRX_TXBUF_DBGID_DEFINITION_END
37671 +
37672 +#define TXRX_RXBUF_DBGID_DEFINITION_START
37673 +#define TXRX_RXBUF_ALLOCATE_BUF 1
37674 +#define TXRX_RXBUF_QUEUE_TO_HOST 2
37675 +#define TXRX_RXBUF_QUEUE_TO_WLAN 3
37676 +#define TXRX_RXBUF_ZERO_LEN_BUF 4
37677 +#define TXRX_RXBUF_QUEUE_TO_HOST_LASTBUF_IN_RXCHAIN 5
37678 +#define TXRX_RXBUF_LASTBUF_IN_RXCHAIN_ZEROBUF 6
37679 +#define TXRX_RXBUF_QUEUE_EMPTY_QUEUE_TO_WLAN 7
37680 +#define TXRX_RXBUF_SEND_TO_RECV_MGMT 8
37681 +#define TXRX_RXBUF_SEND_TO_IEEE_LAYER 9
37682 +#define TXRX_RXBUF_DBGID_DEFINITION_END
37683 +
37684 +#define TXRX_MGMTBUF_DBGID_DEFINITION_START
37685 +#define TXRX_MGMTBUF_ALLOCATE_BUF 1
37686 +#define TXRX_MGMTBUF_ALLOCATE_SM_BUF 2
37687 +#define TXRX_MGMTBUF_ALLOCATE_RMBUF 3
37688 +#define TXRX_MGMTBUF_GET_BUF 4
37689 +#define TXRX_MGMTBUF_GET_SM_BUF 5
37690 +#define TXRX_MGMTBUF_QUEUE_BUF_TO_TXQ 6
37691 +#define TXRX_MGMTBUF_REAPED_BUF 7
37692 +#define TXRX_MGMTBUF_REAPED_SM_BUF 8
37693 +#define TXRX_MGMTBUF_WAIT_FOR_TXQ_DRAIN 9
37694 +#define TXRX_MGMTBUF_WAIT_FOR_TXQ_SFQ_DRAIN 10
37695 +#define TXRX_MGMTBUF_ENQUEUE_INTO_SFQ 11
37696 +#define TXRX_MGMTBUF_DEQUEUE_FROM_SFQ 12
37697 +#define TXRX_MGMTBUF_PAUSE_TXQ 13
37698 +#define TXRX_MGMTBUF_RESUME_TXQ 14
37699 +#define TXRX_MGMTBUF_WAIT_FORTXQ_DRAIN_TIMEOUT 15
37700 +#define TXRX_MGMTBUF_DRAINQ 16
37701 +#define TXRX_MGMTBUF_INDICATE_Q_DRAINED 17
37702 +#define TXRX_MGMTBUF_DBGID_DEFINITION_END
37703 +
37704 +/* PM (Power Module) debug identifier definitions */
37705 +#define PM_DBGID_DEFINITION_START
37706 +#define PM_INIT 1
37707 +#define PM_ENABLE 2
37708 +#define PM_SET_STATE 3
37709 +#define PM_SET_POWERMODE 4
37710 +#define PM_CONN_NOTIFY 5
37711 +#define PM_REF_COUNT_NEGATIVE 6
37712 +#define PM_APSD_ENABLE 7
37713 +#define PM_UPDATE_APSD_STATE 8
37714 +#define PM_CHAN_OP_REQ 9
37715 +#define PM_SET_MY_BEACON_POLICY 10
37716 +#define PM_SET_ALL_BEACON_POLICY 11
37717 +#define PM_SET_PM_PARAMS1 12
37718 +#define PM_SET_PM_PARAMS2 13
37719 +#define PM_ADHOC_SET_PM_CAPS_FAIL 14
37720 +#define PM_ADHOC_UNKNOWN_IBSS_ATTRIB_ID 15
37721 +#define PM_DBGID_DEFINITION_END
37722 +
37723 +/* Wake on Wireless debug identifier definitions */
37724 +#define WOW_DBGID_DEFINITION_START
37725 +#define WOW_INIT 1
37726 +#define WOW_GET_CONFIG_DSET 2
37727 +#define WOW_NO_CONFIG_DSET 3
37728 +#define WOW_INVALID_CONFIG_DSET 4
37729 +#define WOW_USE_DEFAULT_CONFIG 5
37730 +#define WOW_SETUP_GPIO 6
37731 +#define WOW_INIT_DONE 7
37732 +#define WOW_SET_GPIO_PIN 8
37733 +#define WOW_CLEAR_GPIO_PIN 9
37734 +#define WOW_SET_WOW_MODE_CMD 10
37735 +#define WOW_SET_HOST_MODE_CMD 11
37736 +#define WOW_ADD_WOW_PATTERN_CMD 12
37737 +#define WOW_NEW_WOW_PATTERN_AT_INDEX 13
37738 +#define WOW_DEL_WOW_PATTERN_CMD 14
37739 +#define WOW_LIST_CONTAINS_PATTERNS 15
37740 +#define WOW_GET_WOW_LIST_CMD 16
37741 +#define WOW_INVALID_FILTER_ID 17
37742 +#define WOW_INVALID_FILTER_LISTID 18
37743 +#define WOW_NO_VALID_FILTER_AT_ID 19
37744 +#define WOW_NO_VALID_LIST_AT_ID 20
37745 +#define WOW_NUM_PATTERNS_EXCEEDED 21
37746 +#define WOW_NUM_LISTS_EXCEEDED 22
37747 +#define WOW_GET_WOW_STATS 23
37748 +#define WOW_CLEAR_WOW_STATS 24
37749 +#define WOW_WAKEUP_HOST 25
37750 +#define WOW_EVENT_WAKEUP_HOST 26
37751 +#define WOW_EVENT_DISCARD 27
37752 +#define WOW_PATTERN_MATCH 28
37753 +#define WOW_PATTERN_NOT_MATCH 29
37754 +#define WOW_PATTERN_NOT_MATCH_OFFSET 30
37755 +#define WOW_DISABLED_HOST_ASLEEP 31
37756 +#define WOW_ENABLED_HOST_ASLEEP_NO_PATTERNS 32
37757 +#define WOW_ENABLED_HOST_ASLEEP_NO_MATCH_FOUND 33
37758 +#define WOW_DBGID_DEFINITION_END
37759 +
37760 +/* WHAL debug identifier definitions */
37761 +#define WHAL_DBGID_DEFINITION_START
37762 +#define WHAL_ERROR_ANI_CONTROL 1
37763 +#define WHAL_ERROR_CHIP_TEST1 2
37764 +#define WHAL_ERROR_CHIP_TEST2 3
37765 +#define WHAL_ERROR_EEPROM_CHECKSUM 4
37766 +#define WHAL_ERROR_EEPROM_MACADDR 5
37767 +#define WHAL_ERROR_INTERRUPT_HIU 6
37768 +#define WHAL_ERROR_KEYCACHE_RESET 7
37769 +#define WHAL_ERROR_KEYCACHE_SET 8
37770 +#define WHAL_ERROR_KEYCACHE_TYPE 9
37771 +#define WHAL_ERROR_KEYCACHE_TKIPENTRY 10
37772 +#define WHAL_ERROR_KEYCACHE_WEPLENGTH 11
37773 +#define WHAL_ERROR_PHY_INVALID_CHANNEL 12
37774 +#define WHAL_ERROR_POWER_AWAKE 13
37775 +#define WHAL_ERROR_POWER_SET 14
37776 +#define WHAL_ERROR_RECV_STOPDMA 15
37777 +#define WHAL_ERROR_RECV_STOPPCU 16
37778 +#define WHAL_ERROR_RESET_CHANNF1 17
37779 +#define WHAL_ERROR_RESET_CHANNF2 18
37780 +#define WHAL_ERROR_RESET_PM 19
37781 +#define WHAL_ERROR_RESET_OFFSETCAL 20
37782 +#define WHAL_ERROR_RESET_RFGRANT 21
37783 +#define WHAL_ERROR_RESET_RXFRAME 22
37784 +#define WHAL_ERROR_RESET_STOPDMA 23
37785 +#define WHAL_ERROR_RESET_RECOVER 24
37786 +#define WHAL_ERROR_XMIT_COMPUTE 25
37787 +#define WHAL_ERROR_XMIT_NOQUEUE 26
37788 +#define WHAL_ERROR_XMIT_ACTIVEQUEUE 27
37789 +#define WHAL_ERROR_XMIT_BADTYPE 28
37790 +#define WHAL_DBGID_DEFINITION_END
37791 +
37792 +#ifdef __cplusplus
37793 +}
37794 +#endif
37795 +
37796 +#endif /* _DBGLOG_ID_H_ */
37797 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/dl_list.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dl_list.h
37798 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/dl_list.h 1970-01-01 01:00:00.000000000 +0100
37799 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dl_list.h 2009-05-10 22:27:59.000000000 +0200
37800 @@ -0,0 +1,114 @@
37801 +/*
37802 + *
37803 + * Double-link list definitions (adapted from Atheros SDIO stack)
37804 + *
37805 + * Copyright (c) 2007 Atheros Communications Inc.
37806 + * All rights reserved.
37807 + *
37808 + *
37809 + * This program is free software; you can redistribute it and/or modify
37810 + * it under the terms of the GNU General Public License version 2 as
37811 + * published by the Free Software Foundation;
37812 + *
37813 + * Software distributed under the License is distributed on an "AS
37814 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
37815 + * implied. See the License for the specific language governing
37816 + * rights and limitations under the License.
37817 + *
37818 + *
37819 + *
37820 + */
37821 +#ifndef __DL_LIST_H___
37822 +#define __DL_LIST_H___
37823 +
37824 +#define A_CONTAINING_STRUCT(address, struct_type, field_name)\
37825 + ((struct_type *)((A_UINT32)(address) - (A_UINT32)(&((struct_type *)0)->field_name)))
37826 +
37827 +/* list functions */
37828 +/* pointers for the list */
37829 +typedef struct _DL_LIST {
37830 + struct _DL_LIST *pPrev;
37831 + struct _DL_LIST *pNext;
37832 +}DL_LIST, *PDL_LIST;
37833 +/*
37834 + * DL_LIST_INIT , initialize doubly linked list
37835 +*/
37836 +#define DL_LIST_INIT(pList)\
37837 + {(pList)->pPrev = pList; (pList)->pNext = pList;}
37838 +
37839 +#define DL_LIST_IS_EMPTY(pList) (((pList)->pPrev == (pList)) && ((pList)->pNext == (pList)))
37840 +#define DL_LIST_GET_ITEM_AT_HEAD(pList) (pList)->pNext
37841 +#define DL_LIST_GET_ITEM_AT_TAIL(pList) (pList)->pPrev
37842 +/*
37843 + * ITERATE_OVER_LIST pStart is the list, pTemp is a temp list member
37844 + * NOT: do not use this function if the items in the list are deleted inside the
37845 + * iteration loop
37846 +*/
37847 +#define ITERATE_OVER_LIST(pStart, pTemp) \
37848 + for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext)
37849 +
37850 +
37851 +/* safe iterate macro that allows the item to be removed from the list
37852 + * the iteration continues to the next item in the list
37853 + */
37854 +#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \
37855 +{ \
37856 + PDL_LIST pTemp; \
37857 + pTemp = (pStart)->pNext; \
37858 + while (pTemp != (pStart)) { \
37859 + (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset); \
37860 + pTemp = pTemp->pNext; \
37861 +
37862 +#define ITERATE_END }}
37863 +
37864 +/*
37865 + * DL_ListInsertTail - insert pAdd to the end of the list
37866 +*/
37867 +static INLINE PDL_LIST DL_ListInsertTail(PDL_LIST pList, PDL_LIST pAdd) {
37868 + /* insert at tail */
37869 + pAdd->pPrev = pList->pPrev;
37870 + pAdd->pNext = pList;
37871 + pList->pPrev->pNext = pAdd;
37872 + pList->pPrev = pAdd;
37873 + return pAdd;
37874 +}
37875 +
37876 +/*
37877 + * DL_ListInsertHead - insert pAdd into the head of the list
37878 +*/
37879 +static INLINE PDL_LIST DL_ListInsertHead(PDL_LIST pList, PDL_LIST pAdd) {
37880 + /* insert at head */
37881 + pAdd->pPrev = pList;
37882 + pAdd->pNext = pList->pNext;
37883 + pList->pNext->pPrev = pAdd;
37884 + pList->pNext = pAdd;
37885 + return pAdd;
37886 +}
37887 +
37888 +#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem))
37889 +/*
37890 + * DL_ListRemove - remove pDel from list
37891 +*/
37892 +static INLINE PDL_LIST DL_ListRemove(PDL_LIST pDel) {
37893 + pDel->pNext->pPrev = pDel->pPrev;
37894 + pDel->pPrev->pNext = pDel->pNext;
37895 + /* point back to itself just to be safe, incase remove is called again */
37896 + pDel->pNext = pDel;
37897 + pDel->pPrev = pDel;
37898 + return pDel;
37899 +}
37900 +
37901 +/*
37902 + * DL_ListRemoveItemFromHead - get a list item from the head
37903 +*/
37904 +static INLINE PDL_LIST DL_ListRemoveItemFromHead(PDL_LIST pList) {
37905 + PDL_LIST pItem = NULL;
37906 + if (pList->pNext != pList) {
37907 + pItem = pList->pNext;
37908 + /* remove the first item from head */
37909 + DL_ListRemove(pItem);
37910 + }
37911 + return pItem;
37912 +}
37913 +
37914 +#endif /* __DL_LIST_H___ */
37915 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/dset_api.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dset_api.h
37916 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/dset_api.h 1970-01-01 01:00:00.000000000 +0100
37917 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dset_api.h 2009-05-10 22:27:59.000000000 +0200
37918 @@ -0,0 +1,63 @@
37919 +/*
37920 + * Copyright (c) 2004-2006 Atheros Communications Inc.
37921 + * All rights reserved.
37922 + *
37923 + *
37924 + * This program is free software; you can redistribute it and/or modify
37925 + * it under the terms of the GNU General Public License version 2 as
37926 + * published by the Free Software Foundation;
37927 + *
37928 + * Software distributed under the License is distributed on an "AS
37929 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
37930 + * implied. See the License for the specific language governing
37931 + * rights and limitations under the License.
37932 + *
37933 + *
37934 + *
37935 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/dset_api.h#1 $
37936 + *
37937 + * Host-side DataSet API.
37938 + *
37939 + */
37940 +
37941 +#ifndef _DSET_API_H_
37942 +#define _DSET_API_H_
37943 +
37944 +#ifdef __cplusplus
37945 +extern "C" {
37946 +#endif /* __cplusplus */
37947 +
37948 +/*
37949 + * Host-side DataSet support is optional, and is not
37950 + * currently required for correct operation. To disable
37951 + * Host-side DataSet support, set this to 0.
37952 + */
37953 +#ifndef CONFIG_HOST_DSET_SUPPORT
37954 +#define CONFIG_HOST_DSET_SUPPORT 1
37955 +#endif
37956 +
37957 +/* Called to send a DataSet Open Reply back to the Target. */
37958 +A_STATUS wmi_dset_open_reply(struct wmi_t *wmip,
37959 + A_UINT32 status,
37960 + A_UINT32 access_cookie,
37961 + A_UINT32 size,
37962 + A_UINT32 version,
37963 + A_UINT32 targ_handle,
37964 + A_UINT32 targ_reply_fn,
37965 + A_UINT32 targ_reply_arg);
37966 +
37967 +/* Called to send a DataSet Data Reply back to the Target. */
37968 +A_STATUS wmi_dset_data_reply(struct wmi_t *wmip,
37969 + A_UINT32 status,
37970 + A_UINT8 *host_buf,
37971 + A_UINT32 length,
37972 + A_UINT32 targ_buf,
37973 + A_UINT32 targ_reply_fn,
37974 + A_UINT32 targ_reply_arg);
37975 +
37976 +#ifdef __cplusplus
37977 +}
37978 +#endif /* __cplusplus */
37979 +
37980 +
37981 +#endif /* _DSET_API_H_ */
37982 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/dsetid.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dsetid.h
37983 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/dsetid.h 1970-01-01 01:00:00.000000000 +0100
37984 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dsetid.h 2009-05-10 22:27:59.000000000 +0200
37985 @@ -0,0 +1,110 @@
37986 +/*
37987 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37988 + * All rights reserved.
37989 + *
37990 + * $ATH_LICENSE_HOSTSDK0_C$
37991 + *
37992 + */
37993 +
37994 +#ifndef __DSETID_H__
37995 +#define __DSETID_H__
37996 +
37997 +/* Well-known DataSet IDs */
37998 +#define DSETID_UNUSED 0x00000000
37999 +#define DSETID_BOARD_DATA 0x00000001 /* Cal and board data */
38000 +#define DSETID_REGDB 0x00000002 /* Regulatory Database */
38001 +#define DSETID_POWER_CONTROL 0x00000003 /* TX Pwr Lim & Ant Gain */
38002 +#define DSETID_USER_CONFIG 0x00000004 /* User Configuration */
38003 +
38004 +#define DSETID_ANALOG_CONTROL_DATA_START 0x00000005
38005 +#define DSETID_ANALOG_CONTROL_DATA_END 0x00000025
38006 +/*
38007 + * Get DSETID for various reference clock speeds.
38008 + * For each speed there are three DataSets that correspond
38009 + * to the three columns of bank6 data (addr, 11a, 11b/g).
38010 + * This macro returns the dsetid of the first of those
38011 + * three DataSets.
38012 + */
38013 +#define ANALOG_CONTROL_DATA_DSETID(refclk) \
38014 + (DSETID_ANALOG_CONTROL_DATA_START + 3*refclk)
38015 +
38016 +/*
38017 + * There are TWO STARTUP_PATCH DataSets.
38018 + * DSETID_STARTUP_PATCH is historical, and was applied before BMI on
38019 + * earlier systems. On AR6002, it is applied after BMI, just like
38020 + * DSETID_STARTUP_PATCH2.
38021 + */
38022 +#define DSETID_STARTUP_PATCH 0x00000026
38023 +#define DSETID_GPIO_CONFIG_PATCH 0x00000027
38024 +#define DSETID_WLANREGS 0x00000028 /* override wlan regs */
38025 +#define DSETID_STARTUP_PATCH2 0x00000029
38026 +
38027 +#define DSETID_WOW_CONFIG 0x00000090 /* WoW Configuration */
38028 +
38029 +/* Add WHAL_INI_DATA_ID to DSETID_INI_DATA for a specific WHAL INI table. */
38030 +#define DSETID_INI_DATA 0x00000100
38031 +/* Reserved for WHAL INI Tables: 0x100..0x11f */
38032 +#define DSETID_INI_DATA_END 0x0000011f
38033 +
38034 +#define DSETID_VENDOR_START 0x00010000 /* Vendor-defined DataSets */
38035 +
38036 +#define DSETID_INDEX_END 0xfffffffe /* Reserved to indicate the
38037 + end of a memory-based
38038 + DataSet Index */
38039 +#define DSETID_INDEX_FREE 0xffffffff /* An unused index entry */
38040 +
38041 +/*
38042 + * PATCH DataSet format:
38043 + * A list of patches, terminated by a patch with
38044 + * address=PATCH_END.
38045 + *
38046 + * This allows for patches to be stored in flash.
38047 + */
38048 +struct patch_s {
38049 + A_UINT32 *address;
38050 + A_UINT32 data;
38051 +};
38052 +
38053 +/*
38054 + * Skip some patches. Can be used to erase a single patch in a
38055 + * patch DataSet without having to re-write the DataSet. May
38056 + * also be used to embed information for use by subsequent
38057 + * patch code. The "data" in a PATCH_SKIP tells how many
38058 + * bytes of length "patch_s" to skip.
38059 + */
38060 +#define PATCH_SKIP ((A_UINT32 *)0x00000000)
38061 +
38062 +/*
38063 + * Execute code at the address specified by "data".
38064 + * The address of the patch structure is passed as
38065 + * the one parameter.
38066 + */
38067 +#define PATCH_CODE_ABS ((A_UINT32 *)0x00000001)
38068 +
38069 +/*
38070 + * Same as PATCH_CODE_ABS, but treat "data" as an
38071 + * offset from the start of the patch word.
38072 + */
38073 +#define PATCH_CODE_REL ((A_UINT32 *)0x00000002)
38074 +
38075 +/* Mark the end of this patch DataSet. */
38076 +#define PATCH_END ((A_UINT32 *)0xffffffff)
38077 +
38078 +/*
38079 + * A DataSet which contains a Binary Patch to some other DataSet
38080 + * uses the original dsetid with the DSETID_BPATCH_FLAG bit set.
38081 + * Such a BPatch DataSet consists of BPatch metadata followed by
38082 + * the bdiff bytes. BPatch metadata consists of a single 32-bit
38083 + * word that contains the size of the BPatched final image.
38084 + *
38085 + * To create a suitable bdiff DataSet, use bdiff in host/tools/bdiff
38086 + * to create "diffs":
38087 + * bdiff -q -O -nooldmd5 -nonewmd5 -d ORIGfile NEWfile diffs
38088 + * Then add BPatch metadata to the start of "diffs".
38089 + *
38090 + * NB: There are some implementation-induced restrictions
38091 + * on which DataSets can be BPatched.
38092 + */
38093 +#define DSETID_BPATCH_FLAG 0x80000000
38094 +
38095 +#endif /* __DSETID_H__ */
38096 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/dset_internal.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dset_internal.h
38097 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/dset_internal.h 1970-01-01 01:00:00.000000000 +0100
38098 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/dset_internal.h 2009-05-10 22:27:59.000000000 +0200
38099 @@ -0,0 +1,39 @@
38100 +/*
38101 + * Copyright (c) 2007 Atheros Communications Inc.
38102 + * All rights reserved.
38103 + *
38104 + * $ATH_LICENSE_HOSTSDK0_C$
38105 + *
38106 + */
38107 +
38108 +#ifndef __DSET_INTERNAL_H__
38109 +#define __DSET_INTERNAL_H__
38110 +
38111 +/*
38112 + * Internal dset definitions, common for DataSet layer.
38113 + */
38114 +
38115 +#define DSET_TYPE_STANDARD 0
38116 +#define DSET_TYPE_BPATCHED 1
38117 +#define DSET_TYPE_COMPRESSED 2
38118 +
38119 +/* Dataset descriptor */
38120 +
38121 +typedef struct dset_descriptor_s {
38122 + struct dset_descriptor_s *next; /* List link. NULL only at the last
38123 + descriptor */
38124 + A_UINT16 id; /* Dset ID */
38125 + A_UINT16 size; /* Dset size. */
38126 + void *DataPtr; /* Pointer to raw data for standard
38127 + DataSet or pointer to original
38128 + dset_descriptor for patched
38129 + DataSet */
38130 + A_UINT32 data_type; /* DSET_TYPE_*, above */
38131 +
38132 + void *AuxPtr; /* Additional data that might
38133 + needed for data_type. For
38134 + example, pointer to patch
38135 + Dataset descriptor for BPatch. */
38136 +} dset_descriptor_t;
38137 +
38138 +#endif /* __DSET_INTERNAL_H__ */
38139 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/gpio_api.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/gpio_api.h
38140 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/gpio_api.h 1970-01-01 01:00:00.000000000 +0100
38141 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/gpio_api.h 2009-05-10 22:27:59.000000000 +0200
38142 @@ -0,0 +1,57 @@
38143 +#ifndef _GPIO_API_H_
38144 +#define _GPIO_API_H_
38145 +/*
38146 + * Copyright 2005 Atheros Communications, Inc., All Rights Reserved.
38147 + *
38148 + *
38149 + * This program is free software; you can redistribute it and/or modify
38150 + * it under the terms of the GNU General Public License version 2 as
38151 + * published by the Free Software Foundation;
38152 + *
38153 + * Software distributed under the License is distributed on an "AS
38154 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
38155 + * implied. See the License for the specific language governing
38156 + * rights and limitations under the License.
38157 + *
38158 + *
38159 + *
38160 + */
38161 +
38162 +/*
38163 + * Host-side General Purpose I/O API.
38164 + *
38165 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/gpio_api.h#1 $
38166 + */
38167 +
38168 +/*
38169 + * Send a command to the Target in order to change output on GPIO pins.
38170 + */
38171 +A_STATUS wmi_gpio_output_set(struct wmi_t *wmip,
38172 + A_UINT32 set_mask,
38173 + A_UINT32 clear_mask,
38174 + A_UINT32 enable_mask,
38175 + A_UINT32 disable_mask);
38176 +
38177 +/*
38178 + * Send a command to the Target requesting input state of GPIO pins.
38179 + */
38180 +A_STATUS wmi_gpio_input_get(struct wmi_t *wmip);
38181 +
38182 +/*
38183 + * Send a command to the Target to change the value of a GPIO register.
38184 + */
38185 +A_STATUS wmi_gpio_register_set(struct wmi_t *wmip,
38186 + A_UINT32 gpioreg_id,
38187 + A_UINT32 value);
38188 +
38189 +/*
38190 + * Send a command to the Target to fetch the value of a GPIO register.
38191 + */
38192 +A_STATUS wmi_gpio_register_get(struct wmi_t *wmip, A_UINT32 gpioreg_id);
38193 +
38194 +/*
38195 + * Send a command to the Target, acknowledging some GPIO interrupts.
38196 + */
38197 +A_STATUS wmi_gpio_intr_ack(struct wmi_t *wmip, A_UINT32 ack_mask);
38198 +
38199 +#endif /* _GPIO_API_H_ */
38200 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/gpio.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/gpio.h
38201 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/gpio.h 1970-01-01 01:00:00.000000000 +0100
38202 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/gpio.h 2009-05-10 22:27:59.000000000 +0200
38203 @@ -0,0 +1,34 @@
38204 +/*
38205 + * Copyright (c) 2005 Atheros Communications Inc.
38206 + * All rights reserved.
38207 + *
38208 + * $ATH_LICENSE_HOSTSDK0_C$
38209 + *
38210 + */
38211 +
38212 +#if defined(AR6001)
38213 +#define GPIO_PIN_COUNT 18
38214 +#else
38215 +#define GPIO_PIN_COUNT 18
38216 +#endif
38217 +
38218 +/*
38219 + * Possible values for WMIX_GPIO_SET_REGISTER_CMDID.
38220 + * NB: These match hardware order, so that addresses can
38221 + * easily be computed.
38222 + */
38223 +#define GPIO_ID_OUT 0x00000000
38224 +#define GPIO_ID_OUT_W1TS 0x00000001
38225 +#define GPIO_ID_OUT_W1TC 0x00000002
38226 +#define GPIO_ID_ENABLE 0x00000003
38227 +#define GPIO_ID_ENABLE_W1TS 0x00000004
38228 +#define GPIO_ID_ENABLE_W1TC 0x00000005
38229 +#define GPIO_ID_IN 0x00000006
38230 +#define GPIO_ID_STATUS 0x00000007
38231 +#define GPIO_ID_STATUS_W1TS 0x00000008
38232 +#define GPIO_ID_STATUS_W1TC 0x00000009
38233 +#define GPIO_ID_PIN0 0x0000000a
38234 +#define GPIO_ID_PIN(n) (GPIO_ID_PIN0+(n))
38235 +
38236 +#define GPIO_LAST_REGISTER_ID GPIO_ID_PIN(17)
38237 +#define GPIO_ID_NONE 0xffffffff
38238 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/hif.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/hif.h
38239 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/hif.h 1970-01-01 01:00:00.000000000 +0100
38240 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/hif.h 2009-05-10 22:27:59.000000000 +0200
38241 @@ -0,0 +1,296 @@
38242 +/*
38243 + * Copyright (c) 2004-2007 Atheros Communications Inc.
38244 + * All rights reserved.
38245 + *
38246 + *
38247 + * This program is free software; you can redistribute it and/or modify
38248 + * it under the terms of the GNU General Public License version 2 as
38249 + * published by the Free Software Foundation;
38250 + *
38251 + * Software distributed under the License is distributed on an "AS
38252 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
38253 + * implied. See the License for the specific language governing
38254 + * rights and limitations under the License.
38255 + *
38256 + *
38257 + *
38258 + * HIF specific declarations and prototypes
38259 + */
38260 +
38261 +#ifndef _HIF_H_
38262 +#define _HIF_H_
38263 +
38264 +#ifdef __cplusplus
38265 +extern "C" {
38266 +#endif /* __cplusplus */
38267 +
38268 +/* Header files */
38269 +#include "a_config.h"
38270 +#include "athdefs.h"
38271 +#include "a_types.h"
38272 +#include "a_osapi.h"
38273 +
38274 +typedef struct htc_callbacks HTC_CALLBACKS;
38275 +typedef struct hif_device HIF_DEVICE;
38276 +
38277 +/*
38278 + * direction - Direction of transfer (HIF_READ/HIF_WRITE).
38279 + */
38280 +#define HIF_READ 0x00000001
38281 +#define HIF_WRITE 0x00000002
38282 +#define HIF_DIR_MASK (HIF_READ | HIF_WRITE)
38283 +
38284 +/*
38285 + * type - An interface may support different kind of read/write commands.
38286 + * The command type is divided into a basic and an extended command
38287 + * and can be specified using HIF_BASIC_IO/HIF_EXTENDED_IO.
38288 + */
38289 +#define HIF_BASIC_IO 0x00000004
38290 +#define HIF_EXTENDED_IO 0x00000008
38291 +#define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO)
38292 +
38293 +/*
38294 + * emode - This indicates the whether the command is to be executed in a
38295 + * blocking or non-blocking fashion (HIF_SYNCHRONOUS/
38296 + * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been
38297 + * implemented using the asynchronous mode allowing the the bus
38298 + * driver to indicate the completion of operation through the
38299 + * registered callback routine. The requirement primarily comes
38300 + * from the contexts these operations get called from (a driver's
38301 + * transmit context or the ISR context in case of receive).
38302 + * Support for both of these modes is essential.
38303 + */
38304 +#define HIF_SYNCHRONOUS 0x00000010
38305 +#define HIF_ASYNCHRONOUS 0x00000020
38306 +#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS)
38307 +
38308 +/*
38309 + * dmode - An interface may support different kinds of commands based on
38310 + * the tradeoff between the amount of data it can carry and the
38311 + * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/
38312 + * HIF_BLOCK_BASIS). In case of latter, the data is rounded off
38313 + * to the nearest block size by padding. The size of the block is
38314 + * configurable at compile time using the HIF_BLOCK_SIZE and is
38315 + * negotiated with the target during initialization after the
38316 + * dragon interrupts are enabled.
38317 + */
38318 +#define HIF_BYTE_BASIS 0x00000040
38319 +#define HIF_BLOCK_BASIS 0x00000080
38320 +#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS)
38321 +
38322 +/*
38323 + * amode - This indicates if the address has to be incremented on dragon
38324 + * after every read/write operation (HIF?FIXED_ADDRESS/
38325 + * HIF_INCREMENTAL_ADDRESS).
38326 + */
38327 +#define HIF_FIXED_ADDRESS 0x00000100
38328 +#define HIF_INCREMENTAL_ADDRESS 0x00000200
38329 +#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS)
38330 +
38331 +#define HIF_WR_ASYNC_BYTE_FIX \
38332 + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
38333 +#define HIF_WR_ASYNC_BYTE_INC \
38334 + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
38335 +#define HIF_WR_ASYNC_BLOCK_INC \
38336 + (HIF_WRITE | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
38337 +#define HIF_WR_SYNC_BYTE_FIX \
38338 + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
38339 +#define HIF_WR_SYNC_BYTE_INC \
38340 + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
38341 +#define HIF_WR_SYNC_BLOCK_INC \
38342 + (HIF_WRITE | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
38343 +#define HIF_RD_SYNC_BYTE_INC \
38344 + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
38345 +#define HIF_RD_SYNC_BYTE_FIX \
38346 + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
38347 +#define HIF_RD_ASYNC_BYTE_FIX \
38348 + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
38349 +#define HIF_RD_ASYNC_BLOCK_FIX \
38350 + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
38351 +#define HIF_RD_ASYNC_BYTE_INC \
38352 + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
38353 +#define HIF_RD_ASYNC_BLOCK_INC \
38354 + (HIF_READ | HIF_ASYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
38355 +#define HIF_RD_SYNC_BLOCK_INC \
38356 + (HIF_READ | HIF_SYNCHRONOUS | HIF_EXTENDED_IO | HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
38357 +
38358 +
38359 +typedef enum {
38360 + HIF_DEVICE_POWER_STATE = 0,
38361 + HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
38362 + HIF_DEVICE_GET_MBOX_ADDR,
38363 + HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
38364 + HIF_DEVICE_GET_IRQ_PROC_MODE,
38365 + HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC,
38366 +} HIF_DEVICE_CONFIG_OPCODE;
38367 +
38368 +/*
38369 + * HIF CONFIGURE definitions:
38370 + *
38371 + * HIF_DEVICE_GET_MBOX_BLOCK_SIZE
38372 + * input : none
38373 + * output : array of 4 A_UINT32s
38374 + * notes: block size is returned for each mailbox (4)
38375 + *
38376 + * HIF_DEVICE_GET_MBOX_ADDR
38377 + * input : none
38378 + * output : array of 4 A_UINT32
38379 + * notes: address is returned for each mailbox (4) in the array
38380 + *
38381 + * HIF_DEVICE_GET_PENDING_EVENTS_FUNC
38382 + * input : none
38383 + * output: HIF_PENDING_EVENTS_FUNC function pointer
38384 + * notes: this is optional for the HIF layer, if the request is
38385 + * not handled then it indicates that the upper layer can use
38386 + * the standard device methods to get pending events (IRQs, mailbox messages etc..)
38387 + * otherwise it can call the function pointer to check pending events.
38388 + *
38389 + * HIF_DEVICE_GET_IRQ_PROC_MODE
38390 + * input : none
38391 + * output : HIF_DEVICE_IRQ_PROCESSING_MODE (interrupt processing mode)
38392 + * note: the hif layer interfaces with the underlying OS-specific bus driver. The HIF
38393 + * layer can report whether IRQ processing is requires synchronous behavior or
38394 + * can be processed using asynchronous bus requests (typically faster).
38395 + *
38396 + * HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC
38397 + * input :
38398 + * output : HIF_MASK_UNMASK_RECV_EVENT function pointer
38399 + * notes: this is optional for the HIF layer. The HIF layer may require a special mechanism
38400 + * to mask receive message events. The upper layer can call this pointer when it needs
38401 + * to mask/unmask receive events (in case it runs out of buffers).
38402 + *
38403 + *
38404 + */
38405 +
38406 +typedef enum {
38407 + HIF_DEVICE_IRQ_SYNC_ONLY, /* for HIF implementations that require the DSR to process all
38408 + interrupts before returning */
38409 + HIF_DEVICE_IRQ_ASYNC_SYNC, /* for HIF implementations that allow DSR to process interrupts
38410 + using ASYNC I/O (that is HIFAckInterrupt can be called at a
38411 + later time */
38412 +} HIF_DEVICE_IRQ_PROCESSING_MODE;
38413 +
38414 +#define HIF_MAX_DEVICES 1
38415 +
38416 +struct htc_callbacks {
38417 + A_UCHAR *name;
38418 + A_UINT32 id;
38419 + A_STATUS (* deviceInsertedHandler)(void *hif_handle);
38420 + A_STATUS (* deviceRemovedHandler)(void *htc_handle, A_STATUS status);
38421 + A_STATUS (* deviceSuspendHandler)(void *htc_handle);
38422 + A_STATUS (* deviceResumeHandler)(void *htc_handle);
38423 + A_STATUS (* deviceWakeupHandler)(void *htc_handle);
38424 + A_STATUS (* rwCompletionHandler)(void *context, A_STATUS status);
38425 + A_STATUS (* dsrHandler)(void *htc_handle);
38426 +};
38427 +
38428 +
38429 +#define HIF_OTHER_EVENTS (1 << 0) /* other interrupts (non-Recv) are pending, host
38430 + needs to read the register table to figure out what */
38431 +#define HIF_RECV_MSG_AVAIL (1 << 1) /* pending recv packet */
38432 +
38433 +typedef struct _HIF_PENDING_EVENTS_INFO {
38434 + A_UINT32 Events;
38435 + A_UINT32 LookAhead;
38436 +} HIF_PENDING_EVENTS_INFO;
38437 +
38438 + /* function to get pending events , some HIF modules use special mechanisms
38439 + * to detect packet available and other interrupts */
38440 +typedef A_STATUS ( *HIF_PENDING_EVENTS_FUNC)(HIF_DEVICE *device,
38441 + HIF_PENDING_EVENTS_INFO *pEvents,
38442 + void *AsyncContext);
38443 +
38444 +#define HIF_MASK_RECV TRUE
38445 +#define HIF_UNMASK_RECV FALSE
38446 + /* function to mask recv events */
38447 +typedef A_STATUS ( *HIF_MASK_UNMASK_RECV_EVENT)(HIF_DEVICE *device,
38448 + A_BOOL Mask,
38449 + void *AsyncContext);
38450 +
38451 +
38452 +/*
38453 + * This API is used by the HTC layer to initialize the HIF layer and to
38454 + * register different callback routines. Support for following events has
38455 + * been captured - DSR, Read/Write completion, Device insertion/removal,
38456 + * Device suspension/resumption/wakeup. In addition to this, the API is
38457 + * also used to register the name and the revision of the chip. The latter
38458 + * can be used to verify the revision of the chip read from the device
38459 + * before reporting it to HTC.
38460 + */
38461 +int HIFInit(HTC_CALLBACKS *callbacks);
38462 +
38463 +/*
38464 + * This API is used to provide the read/write interface over the specific bus
38465 + * interface.
38466 + * address - Starting address in the dragon's address space. For mailbox
38467 + * writes, it refers to the start of the mbox boundary. It should
38468 + * be ensured that the last byte falls on the mailbox's EOM. For
38469 + * mailbox reads, it refers to the end of the mbox boundary.
38470 + * buffer - Pointer to the buffer containg the data to be transmitted or
38471 + * received.
38472 + * length - Amount of data to be transmitted or received.
38473 + * request - Characterizes the attributes of the command.
38474 + */
38475 +A_STATUS
38476 +HIFReadWrite(HIF_DEVICE *device,
38477 + A_UINT32 address,
38478 + A_UCHAR *buffer,
38479 + A_UINT32 length,
38480 + A_UINT32 request,
38481 + void *context);
38482 +
38483 +/*
38484 + * This can be initiated from the unload driver context ie when the HTCShutdown
38485 + * routine is called.
38486 + */
38487 +void HIFShutDownDevice(HIF_DEVICE *device);
38488 +
38489 +/*
38490 + * This should translate to an acknowledgment to the bus driver indicating that
38491 + * the previous interrupt request has been serviced and the all the relevant
38492 + * sources have been cleared. HTC is ready to process more interrupts.
38493 + * This should prevent the bus driver from raising an interrupt unless the
38494 + * previous one has been serviced and acknowledged using the previous API.
38495 + */
38496 +void HIFAckInterrupt(HIF_DEVICE *device);
38497 +
38498 +void HIFMaskInterrupt(HIF_DEVICE *device);
38499 +
38500 +void HIFUnMaskInterrupt(HIF_DEVICE *device);
38501 +
38502 +/*
38503 + * This set of functions are to be used by the bus driver to notify
38504 + * the HIF module about various events.
38505 + * These are not implemented if the bus driver provides an alternative
38506 + * way for this notification though callbacks for instance.
38507 + */
38508 +int HIFInsertEventNotify(void);
38509 +
38510 +int HIFRemoveEventNotify(void);
38511 +
38512 +int HIFIRQEventNotify(void);
38513 +
38514 +int HIFRWCompleteEventNotify(void);
38515 +
38516 +/*
38517 + * This function associates a opaque handle with the HIF layer
38518 + * to be used in communication with upper layer i.e. HTC.
38519 + * This would normaly be a pointer to htc_target data structure.
38520 + */
38521 +void HIFSetHandle(void *hif_handle, void *handle);
38522 +
38523 +A_STATUS
38524 +HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
38525 + void *config, A_UINT32 configLen);
38526 +
38527 +
38528 +struct device;
38529 +struct device*
38530 +HIFGetOSDevice(HIF_DEVICE *device);
38531 +
38532 +
38533 +#ifdef __cplusplus
38534 +}
38535 +#endif
38536 +
38537 +#endif /* _HIF_H_ */
38538 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/host_version.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/host_version.h
38539 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/host_version.h 1970-01-01 01:00:00.000000000 +0100
38540 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/host_version.h 2009-05-10 22:27:59.000000000 +0200
38541 @@ -0,0 +1,49 @@
38542 +#ifndef _HOST_VERSION_H_
38543 +#define _HOST_VERSION_H_
38544 +/*
38545 + * Copyright (c) 2004-2005 Atheros Communications Inc.
38546 + * All rights reserved.
38547 + *
38548 + * This file contains version information for the sample host driver for the
38549 + * AR6000 chip
38550 + *
38551 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/host_version.h#2 $
38552 + *
38553 + *
38554 + * This program is free software; you can redistribute it and/or modify
38555 + * it under the terms of the GNU General Public License version 2 as
38556 + * published by the Free Software Foundation;
38557 + *
38558 + * Software distributed under the License is distributed on an "AS
38559 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
38560 + * implied. See the License for the specific language governing
38561 + * rights and limitations under the License.
38562 + *
38563 + *
38564 + *
38565 + */
38566 +
38567 +#ifdef __cplusplus
38568 +extern "C" {
38569 +#endif
38570 +
38571 +#include <AR6K_version.h>
38572 +
38573 +/*
38574 + * The version number is made up of major, minor, patch and build
38575 + * numbers. These are 16 bit numbers. The build and release script will
38576 + * set the build number using a Perforce counter. Here the build number is
38577 + * set to 9999 so that builds done without the build-release script are easily
38578 + * identifiable.
38579 + */
38580 +
38581 +#define ATH_SW_VER_MAJOR __VER_MAJOR_
38582 +#define ATH_SW_VER_MINOR __VER_MINOR_
38583 +#define ATH_SW_VER_PATCH __VER_PATCH_
38584 +#define ATH_SW_VER_BUILD 9999
38585 +
38586 +#ifdef __cplusplus
38587 +}
38588 +#endif
38589 +
38590 +#endif /* _HOST_VERSION_H_ */
38591 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/htc_api.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/htc_api.h
38592 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/htc_api.h 1970-01-01 01:00:00.000000000 +0100
38593 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/htc_api.h 2009-05-10 22:27:59.000000000 +0200
38594 @@ -0,0 +1,439 @@
38595 +/*
38596 + *
38597 + * Copyright (c) 2007 Atheros Communications Inc.
38598 + * All rights reserved.
38599 + *
38600 + *
38601 + * This program is free software; you can redistribute it and/or modify
38602 + * it under the terms of the GNU General Public License version 2 as
38603 + * published by the Free Software Foundation;
38604 + *
38605 + * Software distributed under the License is distributed on an "AS
38606 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
38607 + * implied. See the License for the specific language governing
38608 + * rights and limitations under the License.
38609 + *
38610 + *
38611 + *
38612 + */
38613 +
38614 +#ifndef _HTC_API_H_
38615 +#define _HTC_API_H_
38616 +
38617 +#include <htc.h>
38618 +#include <htc_services.h>
38619 +#include "htc_packet.h"
38620 +
38621 +#ifdef __cplusplus
38622 +extern "C" {
38623 +#endif /* __cplusplus */
38624 +
38625 +/* TODO.. for BMI */
38626 +#define ENDPOINT1 0
38627 +// TODO -remove me, but we have to fix BMI first
38628 +#define HTC_MAILBOX_NUM_MAX 4
38629 +
38630 +
38631 +/* ------ Endpoint IDS ------ */
38632 +typedef enum
38633 +{
38634 + ENDPOINT_UNUSED = -1,
38635 + ENDPOINT_0 = 0,
38636 + ENDPOINT_1 = 1,
38637 + ENDPOINT_2 = 2,
38638 + ENDPOINT_3,
38639 + ENDPOINT_4,
38640 + ENDPOINT_5,
38641 + ENDPOINT_6,
38642 + ENDPOINT_7,
38643 + ENDPOINT_8,
38644 + ENDPOINT_MAX,
38645 +} HTC_ENDPOINT_ID;
38646 +
38647 +/* this is the amount of header room required by users of HTC */
38648 +#define HTC_HEADER_LEN HTC_HDR_LENGTH
38649 +
38650 +typedef void *HTC_HANDLE;
38651 +
38652 +typedef A_UINT16 HTC_SERVICE_ID;
38653 +
38654 +typedef struct _HTC_INIT_INFO {
38655 + void (*AddInstance)(HTC_HANDLE);
38656 + void (*DeleteInstance)(void *Instance);
38657 + void (*TargetFailure)(void *Instance, A_STATUS Status);
38658 +} HTC_INIT_INFO;
38659 +
38660 +/* per service connection send completion */
38661 +typedef void (*HTC_EP_SEND_PKT_COMPLETE)(void *,HTC_PACKET *);
38662 +/* per service connection pkt received */
38663 +typedef void (*HTC_EP_RECV_PKT)(void *,HTC_PACKET *);
38664 +
38665 +/* Optional per service connection receive buffer re-fill callback,
38666 + * On some OSes (like Linux) packets are allocated from a global pool and indicated up
38667 + * to the network stack. The driver never gets the packets back from the OS. For these OSes
38668 + * a refill callback can be used to allocate and re-queue buffers into HTC.
38669 + *
38670 + * On other OSes, the network stack can call into the driver's OS-specifc "return_packet" handler and
38671 + * the driver can re-queue these buffers into HTC. In this regard a refill callback is
38672 + * unnecessary */
38673 +typedef void (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint);
38674 +
38675 +/* Optional per service connection callback when a send queue is full. This can occur if the
38676 + * host continues queueing up TX packets faster than credits can arrive
38677 + * To prevent the host (on some Oses like Linux) from continuously queueing packets
38678 + * and consuming resources, this callback is provided so that that the host
38679 + * can disable TX in the subsystem (i.e. network stack)
38680 + * Other OSes require a "per-packet" indication_RAW_STREAM_NUM_MAX for each completed TX packet, this
38681 + * closed loop mechanism will prevent the network stack from overunning the NIC */
38682 +typedef void (*HTC_EP_SEND_QUEUE_FULL)(void *, HTC_ENDPOINT_ID Endpoint);
38683 +/* Optional per service connection callback when a send queue is available for receive new packet. */
38684 +typedef void (*HTC_EP_SEND_QUEUE_AVAIL)(void *, HTC_ENDPOINT_ID Endpoint);
38685 +
38686 +typedef struct _HTC_EP_CALLBACKS {
38687 + void *pContext; /* context for each callback */
38688 + HTC_EP_SEND_PKT_COMPLETE EpTxComplete; /* tx completion callback for connected endpoint */
38689 + HTC_EP_RECV_PKT EpRecv; /* receive callback for connected endpoint */
38690 + HTC_EP_RECV_REFILL EpRecvRefill; /* OPTIONAL receive re-fill callback for connected endpoint */
38691 + HTC_EP_SEND_QUEUE_FULL EpSendFull; /* OPTIONAL send full callback */
38692 + HTC_EP_SEND_QUEUE_AVAIL EpSendAvail; /* OPTIONAL send available callback */
38693 +} HTC_EP_CALLBACKS;
38694 +
38695 +/* service connection information */
38696 +typedef struct _HTC_SERVICE_CONNECT_REQ {
38697 + HTC_SERVICE_ID ServiceID; /* service ID to connect to */
38698 + A_UINT16 ConnectionFlags; /* connection flags, see htc protocol definition */
38699 + A_UINT8 *pMetaData; /* ptr to optional service-specific meta-data */
38700 + A_UINT8 MetaDataLength; /* optional meta data length */
38701 + HTC_EP_CALLBACKS EpCallbacks; /* endpoint callbacks */
38702 + int MaxSendQueueDepth; /* maximum depth of any send queue */
38703 +} HTC_SERVICE_CONNECT_REQ;
38704 +
38705 +/* service connection response information */
38706 +typedef struct _HTC_SERVICE_CONNECT_RESP {
38707 + A_UINT8 *pMetaData; /* caller supplied buffer to optional meta-data */
38708 + A_UINT8 BufferLength; /* length of caller supplied buffer */
38709 + A_UINT8 ActualLength; /* actual length of meta data */
38710 + HTC_ENDPOINT_ID Endpoint; /* endpoint to communicate over */
38711 + int MaxMsgLength; /* max length of all messages over this endpoint */
38712 + A_UINT8 ConnectRespCode; /* connect response code from target */
38713 +} HTC_SERVICE_CONNECT_RESP;
38714 +
38715 +/* endpoint distribution structure */
38716 +typedef struct _HTC_ENDPOINT_CREDIT_DIST {
38717 + struct _HTC_ENDPOINT_CREDIT_DIST *pNext;
38718 + struct _HTC_ENDPOINT_CREDIT_DIST *pPrev;
38719 + HTC_SERVICE_ID ServiceID; /* Service ID (set by HTC) */
38720 + HTC_ENDPOINT_ID Endpoint; /* endpoint for this distribution struct (set by HTC) */
38721 + A_UINT32 DistFlags; /* distribution flags, distribution function can
38722 + set default activity using SET_EP_ACTIVE() macro */
38723 + int TxCreditsNorm; /* credits for normal operation, anything above this
38724 + indicates the endpoint is over-subscribed, this field
38725 + is only relevant to the credit distribution function */
38726 + int TxCreditsMin; /* floor for credit distribution, this field is
38727 + only relevant to the credit distribution function */
38728 + int TxCreditsAssigned; /* number of credits assigned to this EP, this field
38729 + is only relevant to the credit dist function */
38730 + int TxCredits; /* current credits available, this field is used by
38731 + HTC to determine whether a message can be sent or
38732 + must be queued */
38733 + int TxCreditsToDist; /* pending credits to distribute on this endpoint, this
38734 + is set by HTC when credit reports arrive.
38735 + The credit distribution functions sets this to zero
38736 + when it distributes the credits */
38737 + int TxCreditsSeek; /* this is the number of credits that the current pending TX
38738 + packet needs to transmit. This is set by HTC when
38739 + and endpoint needs credits in order to transmit */
38740 + int TxCreditSize; /* size in bytes of each credit (set by HTC) */
38741 + int TxCreditsPerMaxMsg; /* credits required for a maximum sized messages (set by HTC) */
38742 + void *pHTCReserved; /* reserved for HTC use */
38743 +} HTC_ENDPOINT_CREDIT_DIST;
38744 +
38745 +#define HTC_EP_ACTIVE (1 << 31)
38746 +
38747 +/* macro to check if an endpoint has gone active, useful for credit
38748 + * distributions */
38749 +#define IS_EP_ACTIVE(epDist) ((epDist)->DistFlags & HTC_EP_ACTIVE)
38750 +#define SET_EP_ACTIVE(epDist) (epDist)->DistFlags |= HTC_EP_ACTIVE
38751 +
38752 + /* credit distibution code that is passed into the distrbution function,
38753 + * there are mandatory and optional codes that must be handled */
38754 +typedef enum _HTC_CREDIT_DIST_REASON {
38755 + HTC_CREDIT_DIST_SEND_COMPLETE = 0, /* credits available as a result of completed
38756 + send operations (MANDATORY) resulting in credit reports */
38757 + HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1, /* a change in endpoint activity occured (OPTIONAL) */
38758 + HTC_CREDIT_DIST_SEEK_CREDITS, /* an endpoint needs to "seek" credits (OPTIONAL) */
38759 + HTC_DUMP_CREDIT_STATE /* for debugging, dump any state information that is kept by
38760 + the distribution function */
38761 +} HTC_CREDIT_DIST_REASON;
38762 +
38763 +typedef void (*HTC_CREDIT_DIST_CALLBACK)(void *Context,
38764 + HTC_ENDPOINT_CREDIT_DIST *pEPList,
38765 + HTC_CREDIT_DIST_REASON Reason);
38766 +
38767 +typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context,
38768 + HTC_ENDPOINT_CREDIT_DIST *pEPList,
38769 + int TotalCredits);
38770 +
38771 + /* endpoint statistics action */
38772 +typedef enum _HTC_ENDPOINT_STAT_ACTION {
38773 + HTC_EP_STAT_SAMPLE = 0, /* only read statistics */
38774 + HTC_EP_STAT_SAMPLE_AND_CLEAR = 1, /* sample and immediately clear statistics */
38775 + HTC_EP_STAT_CLEAR /* clear only */
38776 +} HTC_ENDPOINT_STAT_ACTION;
38777 +
38778 + /* endpoint statistics */
38779 +typedef struct _HTC_ENDPOINT_STATS {
38780 + A_UINT32 TxCreditLowIndications; /* number of times the host set the credit-low flag in a send message on
38781 + this endpoint */
38782 + A_UINT32 TxIssued; /* running count of TX packets issued */
38783 + A_UINT32 TxCreditRpts; /* running count of total credit reports received for this endpoint */
38784 + A_UINT32 TxCreditRptsFromRx;
38785 + A_UINT32 TxCreditRptsFromOther;
38786 + A_UINT32 TxCreditRptsFromEp0;
38787 + A_UINT32 TxCreditsFromRx; /* count of credits received via Rx packets on this endpoint */
38788 + A_UINT32 TxCreditsFromOther; /* count of credits received via another endpoint */
38789 + A_UINT32 TxCreditsFromEp0; /* count of credits received via another endpoint */
38790 + A_UINT32 TxCreditsConsummed; /* count of consummed credits */
38791 + A_UINT32 TxCreditsReturned; /* count of credits returned */
38792 + A_UINT32 RxReceived; /* count of RX packets received */
38793 + A_UINT32 RxLookAheads; /* count of lookahead records
38794 + found in messages received on this endpoint */
38795 +} HTC_ENDPOINT_STATS;
38796 +
38797 +/* ------ Function Prototypes ------ */
38798 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38799 + @desc: Initialize HTC
38800 + @function name: HTCInit
38801 + @input: pInfo - initialization information
38802 + @output:
38803 + @return: A_OK on success
38804 + @notes: The caller initializes global HTC state and registers various instance
38805 + notification callbacks (see HTC_INIT_INFO).
38806 +
38807 + @example:
38808 + @see also: HTCShutdown
38809 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38810 +A_STATUS HTCInit(HTC_INIT_INFO *pInfo);
38811 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38812 + @desc: Get the underlying HIF device handle
38813 + @function name: HTCGetHifDevice
38814 + @input: HTCHandle - handle passed into the AddInstance callback
38815 + @output:
38816 + @return: opaque HIF device handle usable in HIF API calls.
38817 + @notes:
38818 + @example:
38819 + @see also:
38820 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38821 +void *HTCGetHifDevice(HTC_HANDLE HTCHandle);
38822 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38823 + @desc: Set the associated instance for the HTC handle
38824 + @function name: HTCSetInstance
38825 + @input: HTCHandle - handle passed into the AddInstance callback
38826 + Instance - caller supplied instance object
38827 + @output:
38828 + @return:
38829 + @notes: Caller must set the instance information for the HTC handle in order to receive
38830 + notifications for instance deletion (DeleteInstance callback is called) and for target
38831 + failure notification.
38832 + @example:
38833 + @see also:
38834 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38835 +void HTCSetInstance(HTC_HANDLE HTCHandle, void *Instance);
38836 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38837 + @desc: Set credit distribution parameters
38838 + @function name: HTCSetCreditDistribution
38839 + @input: HTCHandle - HTC handle
38840 + pCreditDistCont - caller supplied context to pass into distribution functions
38841 + CreditDistFunc - Distribution function callback
38842 + CreditDistInit - Credit Distribution initialization callback
38843 + ServicePriorityOrder - Array containing list of service IDs, lowest index is highest
38844 + priority
38845 + ListLength - number of elements in ServicePriorityOrder
38846 + @output:
38847 + @return:
38848 + @notes: The user can set a custom credit distribution function to handle special requirements
38849 + for each endpoint. A default credit distribution routine can be used by setting
38850 + CreditInitFunc to NULL. The default credit distribution is only provided for simple
38851 + "fair" credit distribution without regard to any prioritization.
38852 +
38853 + @example:
38854 + @see also:
38855 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38856 +void HTCSetCreditDistribution(HTC_HANDLE HTCHandle,
38857 + void *pCreditDistContext,
38858 + HTC_CREDIT_DIST_CALLBACK CreditDistFunc,
38859 + HTC_CREDIT_INIT_CALLBACK CreditInitFunc,
38860 + HTC_SERVICE_ID ServicePriorityOrder[],
38861 + int ListLength);
38862 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38863 + @desc: Wait for the target to indicate the HTC layer is ready
38864 + @function name: HTCWaitTarget
38865 + @input: HTCHandle - HTC handle
38866 + @output:
38867 + @return:
38868 + @notes: This API blocks until the target responds with an HTC ready message.
38869 + The caller should not connect services until the target has indicated it is
38870 + ready.
38871 + @example:
38872 + @see also: HTCConnectService
38873 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38874 +A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle);
38875 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38876 + @desc: Start target service communications
38877 + @function name: HTCStart
38878 + @input: HTCHandle - HTC handle
38879 + @output:
38880 + @return:
38881 + @notes: This API indicates to the target that the service connection phase is complete
38882 + and the target can freely start all connected services. This API should only be
38883 + called AFTER all service connections have been made. TCStart will issue a
38884 + SETUP_COMPLETE message to the target to indicate that all service connections
38885 + have been made and the target can start communicating over the endpoints.
38886 + @example:
38887 + @see also: HTCConnectService
38888 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38889 +A_STATUS HTCStart(HTC_HANDLE HTCHandle);
38890 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38891 + @desc: Add receive packet to HTC
38892 + @function name: HTCAddReceivePkt
38893 + @input: HTCHandle - HTC handle
38894 + pPacket - HTC receive packet to add
38895 + @output:
38896 + @return: A_OK on success
38897 + @notes: user must supply HTC packets for capturing incomming HTC frames. The caller
38898 + must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
38899 + macro.
38900 + @example:
38901 + @see also:
38902 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38903 +A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket);
38904 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38905 + @desc: Connect to an HTC service
38906 + @function name: HTCConnectService
38907 + @input: HTCHandle - HTC handle
38908 + pReq - connection details
38909 + @output: pResp - connection response
38910 + @return:
38911 + @notes: Service connections must be performed before HTCStart. User provides callback handlers
38912 + for various endpoint events.
38913 + @example:
38914 + @see also: HTCStart
38915 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38916 +A_STATUS HTCConnectService(HTC_HANDLE HTCHandle,
38917 + HTC_SERVICE_CONNECT_REQ *pReq,
38918 + HTC_SERVICE_CONNECT_RESP *pResp);
38919 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38920 + @desc: Send an HTC packet
38921 + @function name: HTCSendPkt
38922 + @input: HTCHandle - HTC handle
38923 + pPacket - packet to send
38924 + @output:
38925 + @return: A_OK
38926 + @notes: Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro.
38927 + This interface is fully asynchronous. On error, HTC SendPkt will
38928 + call the registered Endpoint callback to cleanup the packet.
38929 + @example:
38930 + @see also: HTCFlushEndpoint
38931 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38932 +A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket);
38933 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38934 + @desc: Stop HTC service communications
38935 + @function name: HTCStop
38936 + @input: HTCHandle - HTC handle
38937 + @output:
38938 + @return:
38939 + @notes: HTC communications is halted. All receive and pending TX packets will
38940 + be flushed.
38941 + @example:
38942 + @see also:
38943 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38944 +void HTCStop(HTC_HANDLE HTCHandle);
38945 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38946 + @desc: Shutdown HTC
38947 + @function name: HTCShutdown
38948 + @input:
38949 + @output:
38950 + @return:
38951 + @notes: This cleans up all resources allocated by HTCInit().
38952 + @example:
38953 + @see also: HTCInit
38954 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38955 +void HTCShutDown(void);
38956 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38957 + @desc: Flush pending TX packets
38958 + @function name: HTCFlushEndpoint
38959 + @input: HTCHandle - HTC handle
38960 + Endpoint - Endpoint to flush
38961 + Tag - flush tag
38962 + @output:
38963 + @return:
38964 + @notes: The Tag parameter is used to selectively flush packets with matching tags.
38965 + The value of 0 forces all packets to be flush regardless of tag.
38966 + @example:
38967 + @see also: HTCSendPkt
38968 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38969 +void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag);
38970 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38971 + @desc: Dump credit distribution state
38972 + @function name: HTCDumpCreditStates
38973 + @input: HTCHandle - HTC handle
38974 + @output:
38975 + @return:
38976 + @notes: This dumps all credit distribution information to the debugger
38977 + @example:
38978 + @see also:
38979 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38980 +void HTCDumpCreditStates(HTC_HANDLE HTCHandle);
38981 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38982 + @desc: Indicate a traffic activity change on an endpoint
38983 + @function name: HTCIndicateActivityChange
38984 + @input: HTCHandle - HTC handle
38985 + Endpoint - endpoint in which activity has changed
38986 + Active - TRUE if active, FALSE if it has become inactive
38987 + @output:
38988 + @return:
38989 + @notes: This triggers the registered credit distribution function to
38990 + re-adjust credits for active/inactive endpoints.
38991 + @example:
38992 + @see also:
38993 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38994 +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
38995 + HTC_ENDPOINT_ID Endpoint,
38996 + A_BOOL Active);
38997 +
38998 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38999 + @desc: Get endpoint statistics
39000 + @function name: HTCGetEndpointStatistics
39001 + @input: HTCHandle - HTC handle
39002 + Endpoint - Endpoint identifier
39003 + Action - action to take with statistics
39004 + @output:
39005 + pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR)
39006 +
39007 + @return: TRUE if statistics profiling is enabled, otherwise FALSE.
39008 +
39009 + @notes: Statistics is a compile-time option and this function may return FALSE
39010 + if HTC is not compiled with profiling.
39011 +
39012 + The caller can specify the statistic "action" to take when sampling
39013 + the statistics. This includes:
39014 +
39015 + HTC_EP_STAT_SAMPLE: The pStats structure is filled with the current values.
39016 + HTC_EP_STAT_SAMPLE_AND_CLEAR: The structure is filled and the current statistics
39017 + are cleared.
39018 + HTC_EP_STAT_CLEA : the statistics are cleared, the called can pass a NULL value for
39019 + pStats
39020 +
39021 + @example:
39022 + @see also:
39023 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
39024 +A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle,
39025 + HTC_ENDPOINT_ID Endpoint,
39026 + HTC_ENDPOINT_STAT_ACTION Action,
39027 + HTC_ENDPOINT_STATS *pStats);
39028 +
39029 +#ifdef __cplusplus
39030 +}
39031 +#endif
39032 +
39033 +#endif /* _HTC_API_H_ */
39034 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/htc.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/htc.h
39035 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/htc.h 1970-01-01 01:00:00.000000000 +0100
39036 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/htc.h 2009-05-10 22:27:59.000000000 +0200
39037 @@ -0,0 +1,190 @@
39038 +/*
39039 + * Copyright (c) 2007 Atheros Communications Inc.
39040 + * All rights reserved.
39041 + *
39042 + * $ATH_LICENSE_HOSTSDK0_C$
39043 + *
39044 + */
39045 +
39046 +
39047 +#ifndef __HTC_H__
39048 +#define __HTC_H__
39049 +
39050 +#ifndef ATH_TARGET
39051 +#include "athstartpack.h"
39052 +#endif
39053 +
39054 +#define A_OFFSETOF(type,field) (int)(&(((type *)NULL)->field))
39055 +
39056 +#define ASSEMBLE_UNALIGNED_UINT16(p,highbyte,lowbyte) \
39057 + (((A_UINT16)(((A_UINT8 *)(p))[(highbyte)])) << 8 | (A_UINT16)(((A_UINT8 *)(p))[(lowbyte)]))
39058 +
39059 +/* alignment independent macros (little-endian) to fetch UINT16s or UINT8s from a
39060 + * structure using only the type and field name.
39061 + * Use these macros if there is the potential for unaligned buffer accesses. */
39062 +#define A_GET_UINT16_FIELD(p,type,field) \
39063 + ASSEMBLE_UNALIGNED_UINT16(p,\
39064 + A_OFFSETOF(type,field) + 1, \
39065 + A_OFFSETOF(type,field))
39066 +
39067 +#define A_SET_UINT16_FIELD(p,type,field,value) \
39068 +{ \
39069 + ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (A_UINT8)(value); \
39070 + ((A_UINT8 *)(p))[A_OFFSETOF(type,field) + 1] = (A_UINT8)((value) >> 8); \
39071 +}
39072 +
39073 +#define A_GET_UINT8_FIELD(p,type,field) \
39074 + ((A_UINT8 *)(p))[A_OFFSETOF(type,field)]
39075 +
39076 +#define A_SET_UINT8_FIELD(p,type,field,value) \
39077 + ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (value)
39078 +
39079 +/****** DANGER DANGER ***************
39080 + *
39081 + * The frame header length and message formats defined herein were
39082 + * selected to accommodate optimal alignment for target processing. This reduces code
39083 + * size and improves performance.
39084 + *
39085 + * Any changes to the header length may alter the alignment and cause exceptions
39086 + * on the target. When adding to the message structures insure that fields are
39087 + * properly aligned.
39088 + *
39089 + */
39090 +
39091 +/* HTC frame header */
39092 +typedef PREPACK struct _HTC_FRAME_HDR{
39093 + /* do not remove or re-arrange these fields, these are minimally required
39094 + * to take advantage of 4-byte lookaheads in some hardware implementations */
39095 + A_UINT8 EndpointID;
39096 + A_UINT8 Flags;
39097 + A_UINT16 PayloadLen; /* length of data (including trailer) that follows the header */
39098 +
39099 + /***** end of 4-byte lookahead ****/
39100 +
39101 + A_UINT8 ControlBytes[2];
39102 +
39103 + /* message payload starts after the header */
39104 +
39105 +} POSTPACK HTC_FRAME_HDR;
39106 +
39107 +/* frame header flags */
39108 +#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0)
39109 +#define HTC_FLAGS_RECV_TRAILER (1 << 1)
39110 +
39111 +
39112 +#define HTC_HDR_LENGTH (sizeof(HTC_FRAME_HDR))
39113 +#define HTC_MAX_TRAILER_LENGTH 255
39114 +#define HTC_MAX_PAYLOAD_LENGTH (2048 - sizeof(HTC_FRAME_HDR))
39115 +
39116 +/* HTC control message IDs */
39117 +typedef enum {
39118 + HTC_MSG_READY_ID = 1,
39119 + HTC_MSG_CONNECT_SERVICE_ID = 2,
39120 + HTC_MSG_CONNECT_SERVICE_RESPONSE_ID = 3,
39121 + HTC_MSG_SETUP_COMPLETE_ID = 4,
39122 +} HTC_MSG_IDS;
39123 +
39124 +#define HTC_MAX_CONTROL_MESSAGE_LENGTH 256
39125 +
39126 +/* base message ID header */
39127 +typedef PREPACK struct {
39128 + A_UINT16 MessageID;
39129 +} POSTPACK HTC_UNKNOWN_MSG;
39130 +
39131 +/* HTC ready message
39132 + * direction : target-to-host */
39133 +typedef PREPACK struct {
39134 + A_UINT16 MessageID; /* ID */
39135 + A_UINT16 CreditCount; /* number of credits the target can offer */
39136 + A_UINT16 CreditSize; /* size of each credit */
39137 + A_UINT8 MaxEndpoints; /* maximum number of endpoints the target has resources for */
39138 + A_UINT8 _Pad1;
39139 +} POSTPACK HTC_READY_MSG;
39140 +
39141 +#define HTC_SERVICE_META_DATA_MAX_LENGTH 128
39142 +
39143 +/* connect service
39144 + * direction : host-to-target */
39145 +typedef PREPACK struct {
39146 + A_UINT16 MessageID;
39147 + A_UINT16 ServiceID; /* service ID of the service to connect to */
39148 + A_UINT16 ConnectionFlags; /* connection flags */
39149 +
39150 +#define HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE (1 << 2) /* reduce credit dribbling when
39151 + the host needs credits */
39152 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK (0x3)
39153 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_FOURTH 0x0
39154 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_ONE_HALF 0x1
39155 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS 0x2
39156 +#define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_UNITY 0x3
39157 +
39158 + A_UINT8 ServiceMetaLength; /* length of meta data that follows */
39159 + A_UINT8 _Pad1;
39160 +
39161 + /* service-specific meta data starts after the header */
39162 +
39163 +} POSTPACK HTC_CONNECT_SERVICE_MSG;
39164 +
39165 +/* connect response
39166 + * direction : target-to-host */
39167 +typedef PREPACK struct {
39168 + A_UINT16 MessageID;
39169 + A_UINT16 ServiceID; /* service ID that the connection request was made */
39170 + A_UINT8 Status; /* service connection status */
39171 + A_UINT8 EndpointID; /* assigned endpoint ID */
39172 + A_UINT16 MaxMsgSize; /* maximum expected message size on this endpoint */
39173 + A_UINT8 ServiceMetaLength; /* length of meta data that follows */
39174 + A_UINT8 _Pad1;
39175 +
39176 + /* service-specific meta data starts after the header */
39177 +
39178 +} POSTPACK HTC_CONNECT_SERVICE_RESPONSE_MSG;
39179 +
39180 +typedef PREPACK struct {
39181 + A_UINT16 MessageID;
39182 + /* currently, no other fields */
39183 +} POSTPACK HTC_SETUP_COMPLETE_MSG;
39184 +
39185 +
39186 +/* connect response status codes */
39187 +#define HTC_SERVICE_SUCCESS 0 /* success */
39188 +#define HTC_SERVICE_NOT_FOUND 1 /* service could not be found */
39189 +#define HTC_SERVICE_FAILED 2 /* specific service failed the connect */
39190 +#define HTC_SERVICE_NO_RESOURCES 3 /* no resources (i.e. no more endpoints) */
39191 +#define HTC_SERVICE_NO_MORE_EP 4 /* specific service is not allowing any more
39192 + endpoints */
39193 +
39194 +/* report record IDs */
39195 +typedef enum {
39196 + HTC_RECORD_NULL = 0,
39197 + HTC_RECORD_CREDITS = 1,
39198 + HTC_RECORD_LOOKAHEAD = 2,
39199 +} HTC_RPT_IDS;
39200 +
39201 +typedef PREPACK struct {
39202 + A_UINT8 RecordID; /* Record ID */
39203 + A_UINT8 Length; /* Length of record */
39204 +} POSTPACK HTC_RECORD_HDR;
39205 +
39206 +typedef PREPACK struct {
39207 + A_UINT8 EndpointID; /* Endpoint that owns these credits */
39208 + A_UINT8 Credits; /* credits to report since last report */
39209 +} POSTPACK HTC_CREDIT_REPORT;
39210 +
39211 +typedef PREPACK struct {
39212 + A_UINT8 PreValid; /* pre valid guard */
39213 + A_UINT8 LookAhead[4]; /* 4 byte lookahead */
39214 + A_UINT8 PostValid; /* post valid guard */
39215 +
39216 + /* NOTE: the LookAhead array is guarded by a PreValid and Post Valid guard bytes.
39217 + * The PreValid bytes must equal the inverse of the PostValid byte */
39218 +
39219 +} POSTPACK HTC_LOOKAHEAD_REPORT;
39220 +
39221 +#ifndef ATH_TARGET
39222 +#include "athendpack.h"
39223 +#endif
39224 +
39225 +
39226 +#endif /* __HTC_H__ */
39227 +
39228 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/htc_packet.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/htc_packet.h
39229 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/htc_packet.h 1970-01-01 01:00:00.000000000 +0100
39230 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/htc_packet.h 2009-05-10 22:27:59.000000000 +0200
39231 @@ -0,0 +1,138 @@
39232 +/*
39233 + *
39234 + * Copyright (c) 2007 Atheros Communications Inc.
39235 + * All rights reserved.
39236 + *
39237 + *
39238 + * This program is free software; you can redistribute it and/or modify
39239 + * it under the terms of the GNU General Public License version 2 as
39240 + * published by the Free Software Foundation;
39241 + *
39242 + * Software distributed under the License is distributed on an "AS
39243 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
39244 + * implied. See the License for the specific language governing
39245 + * rights and limitations under the License.
39246 + *
39247 + *
39248 + *
39249 + */
39250 +
39251 +#ifndef HTC_PACKET_H_
39252 +#define HTC_PACKET_H_
39253 +
39254 +
39255 +#include "dl_list.h"
39256 +
39257 +struct _HTC_PACKET;
39258 +
39259 +typedef void (* HTC_PACKET_COMPLETION)(void *,struct _HTC_PACKET *);
39260 +
39261 +typedef A_UINT16 HTC_TX_TAG;
39262 +
39263 +typedef struct _HTC_TX_PACKET_INFO {
39264 + HTC_TX_TAG Tag; /* tag used to selective flush packets */
39265 +} HTC_TX_PACKET_INFO;
39266 +
39267 +#define HTC_TX_PACKET_TAG_ALL 0 /* a tag of zero is reserved and used to flush ALL packets */
39268 +#define HTC_TX_PACKET_TAG_INTERNAL 1 /* internal tags start here */
39269 +#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */
39270 +
39271 +typedef struct _HTC_RX_PACKET_INFO {
39272 + A_UINT32 Unused; /* for future use and to make compilers happy */
39273 +} HTC_RX_PACKET_INFO;
39274 +
39275 +/* wrapper around endpoint-specific packets */
39276 +typedef struct _HTC_PACKET {
39277 + DL_LIST ListLink; /* double link */
39278 + void *pPktContext; /* caller's per packet specific context */
39279 +
39280 + A_UINT8 *pBufferStart; /* the true buffer start , the caller can
39281 + store the real buffer start here. In
39282 + receive callbacks, the HTC layer sets pBuffer
39283 + to the start of the payload past the header. This
39284 + field allows the caller to reset pBuffer when it
39285 + recycles receive packets back to HTC */
39286 + /*
39287 + * Pointer to the start of the buffer. In the transmit
39288 + * direction this points to the start of the payload. In the
39289 + * receive direction, however, the buffer when queued up
39290 + * points to the start of the HTC header but when returned
39291 + * to the caller points to the start of the payload
39292 + */
39293 + A_UINT8 *pBuffer; /* payload start (RX/TX) */
39294 + A_UINT32 BufferLength; /* length of buffer */
39295 + A_UINT32 ActualLength; /* actual length of payload */
39296 + int Endpoint; /* endpoint that this packet was sent/recv'd from */
39297 + A_STATUS Status; /* completion status */
39298 + union {
39299 + HTC_TX_PACKET_INFO AsTx; /* Tx Packet specific info */
39300 + HTC_RX_PACKET_INFO AsRx; /* Rx Packet specific info */
39301 + } PktInfo;
39302 +
39303 + /* the following fields are for internal HTC use */
39304 + HTC_PACKET_COMPLETION Completion; /* completion */
39305 + void *pContext; /* HTC private completion context */
39306 + A_UINT32 HTCReserved; /* reserved */
39307 +} HTC_PACKET;
39308 +
39309 +
39310 +
39311 +#define COMPLETE_HTC_PACKET(p,status) \
39312 +{ \
39313 + (p)->Status = (status); \
39314 + (p)->Completion((p)->pContext,(p)); \
39315 +}
39316 +
39317 +#define INIT_HTC_PACKET_INFO(p,b,len) \
39318 +{ \
39319 + (p)->pBufferStart = (b); \
39320 + (p)->BufferLength = (len); \
39321 +}
39322 +
39323 +/* macro to set an initial RX packet for refilling HTC */
39324 +#define SET_HTC_PACKET_INFO_RX_REFILL(p,c,b,len,ep) \
39325 +{ \
39326 + (p)->pPktContext = (c); \
39327 + (p)->pBuffer = (b); \
39328 + (p)->pBufferStart = (b); \
39329 + (p)->BufferLength = (len); \
39330 + (p)->Endpoint = (ep); \
39331 +}
39332 +
39333 +/* fast macro to recycle an RX packet that will be re-queued to HTC */
39334 +#define HTC_PACKET_RESET_RX(p) \
39335 + (p)->pBuffer = (p)->pBufferStart
39336 +
39337 +/* macro to set packet parameters for TX */
39338 +#define SET_HTC_PACKET_INFO_TX(p,c,b,len,ep,tag) \
39339 +{ \
39340 + (p)->pPktContext = (c); \
39341 + (p)->pBuffer = (b); \
39342 + (p)->ActualLength = (len); \
39343 + (p)->Endpoint = (ep); \
39344 + (p)->PktInfo.AsTx.Tag = (tag); \
39345 +}
39346 +
39347 +/* HTC Packet Queueing Macros */
39348 +typedef DL_LIST HTC_PACKET_QUEUE;
39349 +/* initialize queue */
39350 +#define INIT_HTC_PACKET_QUEUE(pQ) DL_LIST_INIT((pQ))
39351 +/* enqueue HTC packet to the tail of the queue */
39352 +#define HTC_PACKET_ENQUEUE(pQ,p) DL_ListInsertTail((pQ),&(p)->ListLink)
39353 +/* test if a queue is empty */
39354 +#define HTC_QUEUE_EMPTY(pQ) DL_LIST_IS_EMPTY((pQ))
39355 +/* get packet at head without removing it */
39356 +#define HTC_GET_PKT_AT_HEAD(pQ) A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(pQ)),HTC_PACKET,ListLink);
39357 +/* remove a packet from the current list it is linked to */
39358 +#define HTC_PACKET_REMOVE(p) DL_ListRemove(&(p)->ListLink)
39359 +
39360 +/* dequeue an HTC packet from the head of the queue */
39361 +static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE(HTC_PACKET_QUEUE *queue) {
39362 + DL_LIST *pItem = DL_ListRemoveItemFromHead(queue);
39363 + if (pItem != NULL) {
39364 + return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink);
39365 + }
39366 + return NULL;
39367 +}
39368 +
39369 +#endif /*HTC_PACKET_H_*/
39370 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/htc_services.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/htc_services.h
39371 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/htc_services.h 1970-01-01 01:00:00.000000000 +0100
39372 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/htc_services.h 2009-05-10 22:27:59.000000000 +0200
39373 @@ -0,0 +1,37 @@
39374 +/*
39375 + * Copyright (c) 2007 Atheros Communications Inc.
39376 + * All rights reserved.
39377 + *
39378 + * $ATH_LICENSE_HOSTSDK0_C$
39379 + *
39380 + */
39381 +
39382 +#ifndef __HTC_SERVICES_H__
39383 +#define __HTC_SERVICES_H__
39384 +
39385 +/* Current service IDs */
39386 +
39387 +typedef enum {
39388 + RSVD_SERVICE_GROUP = 0,
39389 + WMI_SERVICE_GROUP = 1,
39390 +
39391 + HTC_TEST_GROUP = 254,
39392 + HTC_SERVICE_GROUP_LAST = 255
39393 +}HTC_SERVICE_GROUP_IDS;
39394 +
39395 +#define MAKE_SERVICE_ID(group,index) \
39396 + (int)(((int)group << 8) | (int)(index))
39397 +
39398 +/* NOTE: service ID of 0x0000 is reserved and should never be used */
39399 +#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP,1)
39400 +#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,0)
39401 +#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,1)
39402 +#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,2)
39403 +#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,3)
39404 +#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP,4)
39405 +#define WMI_MAX_SERVICES 5
39406 +
39407 +/* raw stream service (i.e. flash, tcmd, calibration apps) */
39408 +#define HTC_RAW_STREAMS_SVC MAKE_SERVICE_ID(HTC_TEST_GROUP,0)
39409 +
39410 +#endif /*HTC_SERVICES_H_*/
39411 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/ieee80211.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ieee80211.h
39412 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/ieee80211.h 1970-01-01 01:00:00.000000000 +0100
39413 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ieee80211.h 2009-05-10 22:27:59.000000000 +0200
39414 @@ -0,0 +1,342 @@
39415 +/*-
39416 + * Copyright (c) 2001 Atsushi Onoe
39417 + * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
39418 + * Copyright (c) 2006 Atheros Communications, Inc.
39419 + *
39420 + * Wireless Network driver for Atheros AR6001
39421 + * All rights reserved.
39422 + *
39423 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39424 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39425 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39426 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
39427 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
39428 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
39429 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39430 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39431 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39432 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39433 + *
39434 + */
39435 +#ifndef _NET80211_IEEE80211_H_
39436 +#define _NET80211_IEEE80211_H_
39437 +
39438 +#include "athstartpack.h"
39439 +
39440 +/*
39441 + * 802.11 protocol definitions.
39442 + */
39443 +
39444 +#define IEEE80211_ADDR_LEN 6 /* size of 802.11 address */
39445 +/* is 802.11 address multicast/broadcast? */
39446 +#define IEEE80211_IS_MULTICAST(_a) (*(_a) & 0x01)
39447 +#define IEEE80211_ADDR_EQ(addr1, addr2) \
39448 + (A_MEMCMP(addr1, addr2, IEEE80211_ADDR_LEN) == 0)
39449 +
39450 +#define IEEE80211_KEYBUF_SIZE 16
39451 +#define IEEE80211_MICBUF_SIZE (8+8) /* space for both tx and rx */
39452 +
39453 +/*
39454 + * NB: these values are ordered carefully; there are lots of
39455 + * of implications in any reordering. In particular beware
39456 + * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY.
39457 + */
39458 +#define IEEE80211_CIPHER_WEP 0
39459 +#define IEEE80211_CIPHER_TKIP 1
39460 +#define IEEE80211_CIPHER_AES_OCB 2
39461 +#define IEEE80211_CIPHER_AES_CCM 3
39462 +#define IEEE80211_CIPHER_CKIP 5
39463 +#define IEEE80211_CIPHER_CCKM_KRK 6
39464 +#define IEEE80211_CIPHER_NONE 7 /* pseudo value */
39465 +
39466 +#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1)
39467 +
39468 +#define IEEE80211_IS_VALID_WEP_CIPHER_LEN(len) \
39469 + (((len) == 5) || ((len) == 13) || ((len) == 16))
39470 +
39471 +
39472 +
39473 +/*
39474 + * generic definitions for IEEE 802.11 frames
39475 + */
39476 +PREPACK struct ieee80211_frame {
39477 + A_UINT8 i_fc[2];
39478 + A_UINT8 i_dur[2];
39479 + A_UINT8 i_addr1[IEEE80211_ADDR_LEN];
39480 + A_UINT8 i_addr2[IEEE80211_ADDR_LEN];
39481 + A_UINT8 i_addr3[IEEE80211_ADDR_LEN];
39482 + A_UINT8 i_seq[2];
39483 + /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
39484 + /* see below */
39485 +} POSTPACK;
39486 +
39487 +#define IEEE80211_FC0_VERSION_MASK 0x03
39488 +#define IEEE80211_FC0_VERSION_SHIFT 0
39489 +#define IEEE80211_FC0_VERSION_0 0x00
39490 +#define IEEE80211_FC0_TYPE_MASK 0x0c
39491 +#define IEEE80211_FC0_TYPE_SHIFT 2
39492 +#define IEEE80211_FC0_TYPE_MGT 0x00
39493 +#define IEEE80211_FC0_TYPE_CTL 0x04
39494 +#define IEEE80211_FC0_TYPE_DATA 0x08
39495 +
39496 +#define IEEE80211_FC0_SUBTYPE_MASK 0xf0
39497 +#define IEEE80211_FC0_SUBTYPE_SHIFT 4
39498 +/* for TYPE_MGT */
39499 +#define IEEE80211_FC0_SUBTYPE_ASSOC_REQ 0x00
39500 +#define IEEE80211_FC0_SUBTYPE_ASSOC_RESP 0x10
39501 +#define IEEE80211_FC0_SUBTYPE_REASSOC_REQ 0x20
39502 +#define IEEE80211_FC0_SUBTYPE_REASSOC_RESP 0x30
39503 +#define IEEE80211_FC0_SUBTYPE_PROBE_REQ 0x40
39504 +#define IEEE80211_FC0_SUBTYPE_PROBE_RESP 0x50
39505 +#define IEEE80211_FC0_SUBTYPE_BEACON 0x80
39506 +#define IEEE80211_FC0_SUBTYPE_ATIM 0x90
39507 +#define IEEE80211_FC0_SUBTYPE_DISASSOC 0xa0
39508 +#define IEEE80211_FC0_SUBTYPE_AUTH 0xb0
39509 +#define IEEE80211_FC0_SUBTYPE_DEAUTH 0xc0
39510 +/* for TYPE_CTL */
39511 +#define IEEE80211_FC0_SUBTYPE_PS_POLL 0xa0
39512 +#define IEEE80211_FC0_SUBTYPE_RTS 0xb0
39513 +#define IEEE80211_FC0_SUBTYPE_CTS 0xc0
39514 +#define IEEE80211_FC0_SUBTYPE_ACK 0xd0
39515 +#define IEEE80211_FC0_SUBTYPE_CF_END 0xe0
39516 +#define IEEE80211_FC0_SUBTYPE_CF_END_ACK 0xf0
39517 +/* for TYPE_DATA (bit combination) */
39518 +#define IEEE80211_FC0_SUBTYPE_DATA 0x00
39519 +#define IEEE80211_FC0_SUBTYPE_CF_ACK 0x10
39520 +#define IEEE80211_FC0_SUBTYPE_CF_POLL 0x20
39521 +#define IEEE80211_FC0_SUBTYPE_CF_ACPL 0x30
39522 +#define IEEE80211_FC0_SUBTYPE_NODATA 0x40
39523 +#define IEEE80211_FC0_SUBTYPE_CFACK 0x50
39524 +#define IEEE80211_FC0_SUBTYPE_CFPOLL 0x60
39525 +#define IEEE80211_FC0_SUBTYPE_CF_ACK_CF_ACK 0x70
39526 +#define IEEE80211_FC0_SUBTYPE_QOS 0x80
39527 +#define IEEE80211_FC0_SUBTYPE_QOS_NULL 0xc0
39528 +
39529 +#define IEEE80211_FC1_DIR_MASK 0x03
39530 +#define IEEE80211_FC1_DIR_NODS 0x00 /* STA->STA */
39531 +#define IEEE80211_FC1_DIR_TODS 0x01 /* STA->AP */
39532 +#define IEEE80211_FC1_DIR_FROMDS 0x02 /* AP ->STA */
39533 +#define IEEE80211_FC1_DIR_DSTODS 0x03 /* AP ->AP */
39534 +
39535 +#define IEEE80211_FC1_MORE_FRAG 0x04
39536 +#define IEEE80211_FC1_RETRY 0x08
39537 +#define IEEE80211_FC1_PWR_MGT 0x10
39538 +#define IEEE80211_FC1_MORE_DATA 0x20
39539 +#define IEEE80211_FC1_WEP 0x40
39540 +#define IEEE80211_FC1_ORDER 0x80
39541 +
39542 +#define IEEE80211_SEQ_FRAG_MASK 0x000f
39543 +#define IEEE80211_SEQ_FRAG_SHIFT 0
39544 +#define IEEE80211_SEQ_SEQ_MASK 0xfff0
39545 +#define IEEE80211_SEQ_SEQ_SHIFT 4
39546 +
39547 +#define IEEE80211_NWID_LEN 32
39548 +
39549 +/*
39550 + * 802.11 rate set.
39551 + */
39552 +#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */
39553 +#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */
39554 +
39555 +#define WMM_NUM_AC 4 /* 4 AC categories */
39556 +
39557 +#define WMM_PARAM_ACI_M 0x60 /* Mask for ACI field */
39558 +#define WMM_PARAM_ACI_S 5 /* Shift for ACI field */
39559 +#define WMM_PARAM_ACM_M 0x10 /* Mask for ACM bit */
39560 +#define WMM_PARAM_ACM_S 4 /* Shift for ACM bit */
39561 +#define WMM_PARAM_AIFSN_M 0x0f /* Mask for aifsn field */
39562 +#define WMM_PARAM_LOGCWMIN_M 0x0f /* Mask for CwMin field (in log) */
39563 +#define WMM_PARAM_LOGCWMAX_M 0xf0 /* Mask for CwMax field (in log) */
39564 +#define WMM_PARAM_LOGCWMAX_S 4 /* Shift for CwMax field */
39565 +
39566 +#define WMM_AC_TO_TID(_ac) ( \
39567 + ((_ac) == WMM_AC_VO) ? 6 : \
39568 + ((_ac) == WMM_AC_VI) ? 5 : \
39569 + ((_ac) == WMM_AC_BK) ? 1 : \
39570 + 0)
39571 +
39572 +#define TID_TO_WMM_AC(_tid) ( \
39573 + ((_tid) < 1) ? WMM_AC_BE : \
39574 + ((_tid) < 3) ? WMM_AC_BK : \
39575 + ((_tid) < 6) ? WMM_AC_VI : \
39576 + WMM_AC_VO)
39577 +/*
39578 + * Management information element payloads.
39579 + */
39580 +
39581 +enum {
39582 + IEEE80211_ELEMID_SSID = 0,
39583 + IEEE80211_ELEMID_RATES = 1,
39584 + IEEE80211_ELEMID_FHPARMS = 2,
39585 + IEEE80211_ELEMID_DSPARMS = 3,
39586 + IEEE80211_ELEMID_CFPARMS = 4,
39587 + IEEE80211_ELEMID_TIM = 5,
39588 + IEEE80211_ELEMID_IBSSPARMS = 6,
39589 + IEEE80211_ELEMID_COUNTRY = 7,
39590 + IEEE80211_ELEMID_CHALLENGE = 16,
39591 + /* 17-31 reserved for challenge text extension */
39592 + IEEE80211_ELEMID_PWRCNSTR = 32,
39593 + IEEE80211_ELEMID_PWRCAP = 33,
39594 + IEEE80211_ELEMID_TPCREQ = 34,
39595 + IEEE80211_ELEMID_TPCREP = 35,
39596 + IEEE80211_ELEMID_SUPPCHAN = 36,
39597 + IEEE80211_ELEMID_CHANSWITCH = 37,
39598 + IEEE80211_ELEMID_MEASREQ = 38,
39599 + IEEE80211_ELEMID_MEASREP = 39,
39600 + IEEE80211_ELEMID_QUIET = 40,
39601 + IEEE80211_ELEMID_IBSSDFS = 41,
39602 + IEEE80211_ELEMID_ERP = 42,
39603 + IEEE80211_ELEMID_RSN = 48,
39604 + IEEE80211_ELEMID_XRATES = 50,
39605 + IEEE80211_ELEMID_TPC = 150,
39606 + IEEE80211_ELEMID_CCKM = 156,
39607 + IEEE80211_ELEMID_VENDOR = 221, /* vendor private */
39608 +};
39609 +
39610 +#define ATH_OUI 0x7f0300 /* Atheros OUI */
39611 +#define ATH_OUI_TYPE 0x01
39612 +#define ATH_OUI_SUBTYPE 0x01
39613 +#define ATH_OUI_VERSION 0x00
39614 +
39615 +#define WPA_OUI 0xf25000
39616 +#define WPA_OUI_TYPE 0x01
39617 +#define WPA_VERSION 1 /* current supported version */
39618 +
39619 +#define WPA_CSE_NULL 0x00
39620 +#define WPA_CSE_WEP40 0x01
39621 +#define WPA_CSE_TKIP 0x02
39622 +#define WPA_CSE_CCMP 0x04
39623 +#define WPA_CSE_WEP104 0x05
39624 +
39625 +#define WPA_ASE_NONE 0x00
39626 +#define WPA_ASE_8021X_UNSPEC 0x01
39627 +#define WPA_ASE_8021X_PSK 0x02
39628 +
39629 +#define RSN_OUI 0xac0f00
39630 +#define RSN_VERSION 1 /* current supported version */
39631 +
39632 +#define RSN_CSE_NULL 0x00
39633 +#define RSN_CSE_WEP40 0x01
39634 +#define RSN_CSE_TKIP 0x02
39635 +#define RSN_CSE_WRAP 0x03
39636 +#define RSN_CSE_CCMP 0x04
39637 +#define RSN_CSE_WEP104 0x05
39638 +
39639 +#define RSN_ASE_NONE 0x00
39640 +#define RSN_ASE_8021X_UNSPEC 0x01
39641 +#define RSN_ASE_8021X_PSK 0x02
39642 +
39643 +#define RSN_CAP_PREAUTH 0x01
39644 +
39645 +#define WMM_OUI 0xf25000
39646 +#define WMM_OUI_TYPE 0x02
39647 +#define WMM_INFO_OUI_SUBTYPE 0x00
39648 +#define WMM_PARAM_OUI_SUBTYPE 0x01
39649 +#define WMM_VERSION 1
39650 +
39651 +/* WMM stream classes */
39652 +#define WMM_NUM_AC 4
39653 +#define WMM_AC_BE 0 /* best effort */
39654 +#define WMM_AC_BK 1 /* background */
39655 +#define WMM_AC_VI 2 /* video */
39656 +#define WMM_AC_VO 3 /* voice */
39657 +
39658 +/* TSPEC related */
39659 +#define ACTION_CATEGORY_CODE_TSPEC 17
39660 +#define ACTION_CODE_TSPEC_ADDTS 0
39661 +#define ACTION_CODE_TSPEC_ADDTS_RESP 1
39662 +#define ACTION_CODE_TSPEC_DELTS 2
39663 +
39664 +typedef enum {
39665 + TSPEC_STATUS_CODE_ADMISSION_ACCEPTED = 0,
39666 + TSPEC_STATUS_CODE_ADDTS_INVALID_PARAMS = 0x1,
39667 + TSPEC_STATUS_CODE_ADDTS_REQUEST_REFUSED = 0x3,
39668 + TSPEC_STATUS_CODE_UNSPECIFIED_QOS_RELATED_FAILURE = 0xC8,
39669 + TSPEC_STATUS_CODE_REQUESTED_REFUSED_POLICY_CONFIGURATION = 0xC9,
39670 + TSPEC_STATUS_CODE_INSUFFCIENT_BANDWIDTH = 0xCA,
39671 + TSPEC_STATUS_CODE_INVALID_PARAMS = 0xCB,
39672 + TSPEC_STATUS_CODE_DELTS_SENT = 0x30,
39673 + TSPEC_STATUS_CODE_DELTS_RECV = 0x31,
39674 +} TSPEC_STATUS_CODE;
39675 +
39676 +/*
39677 + * WMM/802.11e Tspec Element
39678 + */
39679 +typedef PREPACK struct wmm_tspec_ie_t {
39680 + A_UINT8 elementId;
39681 + A_UINT8 len;
39682 + A_UINT8 oui[3];
39683 + A_UINT8 ouiType;
39684 + A_UINT8 ouiSubType;
39685 + A_UINT8 version;
39686 + A_UINT16 tsInfo_info;
39687 + A_UINT8 tsInfo_reserved;
39688 + A_UINT16 nominalMSDU;
39689 + A_UINT16 maxMSDU;
39690 + A_UINT32 minServiceInt;
39691 + A_UINT32 maxServiceInt;
39692 + A_UINT32 inactivityInt;
39693 + A_UINT32 suspensionInt;
39694 + A_UINT32 serviceStartTime;
39695 + A_UINT32 minDataRate;
39696 + A_UINT32 meanDataRate;
39697 + A_UINT32 peakDataRate;
39698 + A_UINT32 maxBurstSize;
39699 + A_UINT32 delayBound;
39700 + A_UINT32 minPhyRate;
39701 + A_UINT16 sba;
39702 + A_UINT16 mediumTime;
39703 +} POSTPACK WMM_TSPEC_IE;
39704 +
39705 +
39706 +/*
39707 + * BEACON management packets
39708 + *
39709 + * octet timestamp[8]
39710 + * octet beacon interval[2]
39711 + * octet capability information[2]
39712 + * information element
39713 + * octet elemid
39714 + * octet length
39715 + * octet information[length]
39716 + */
39717 +
39718 +#define IEEE80211_BEACON_INTERVAL(beacon) \
39719 + ((beacon)[8] | ((beacon)[9] << 8))
39720 +#define IEEE80211_BEACON_CAPABILITY(beacon) \
39721 + ((beacon)[10] | ((beacon)[11] << 8))
39722 +
39723 +#define IEEE80211_CAPINFO_ESS 0x0001
39724 +#define IEEE80211_CAPINFO_IBSS 0x0002
39725 +#define IEEE80211_CAPINFO_CF_POLLABLE 0x0004
39726 +#define IEEE80211_CAPINFO_CF_POLLREQ 0x0008
39727 +#define IEEE80211_CAPINFO_PRIVACY 0x0010
39728 +#define IEEE80211_CAPINFO_SHORT_PREAMBLE 0x0020
39729 +#define IEEE80211_CAPINFO_PBCC 0x0040
39730 +#define IEEE80211_CAPINFO_CHNL_AGILITY 0x0080
39731 +/* bits 8-9 are reserved */
39732 +#define IEEE80211_CAPINFO_SHORT_SLOTTIME 0x0400
39733 +#define IEEE80211_CAPINFO_APSD 0x0800
39734 +/* bit 12 is reserved */
39735 +#define IEEE80211_CAPINFO_DSSSOFDM 0x2000
39736 +/* bits 14-15 are reserved */
39737 +
39738 +/*
39739 + * Authentication Modes
39740 + */
39741 +
39742 +enum ieee80211_authmode {
39743 + IEEE80211_AUTH_NONE = 0,
39744 + IEEE80211_AUTH_OPEN = 1,
39745 + IEEE80211_AUTH_SHARED = 2,
39746 + IEEE80211_AUTH_8021X = 3,
39747 + IEEE80211_AUTH_AUTO = 4, /* auto-select/accept */
39748 + /* NB: these are used only for ioctls */
39749 + IEEE80211_AUTH_WPA = 5, /* WPA/RSN w/ 802.1x */
39750 + IEEE80211_AUTH_WPA_PSK = 6, /* WPA/RSN w/ PSK */
39751 + IEEE80211_AUTH_WPA_CCKM = 7, /* WPA/RSN IE w/ CCKM */
39752 +};
39753 +
39754 +#include "athendpack.h"
39755 +
39756 +#endif /* _NET80211_IEEE80211_H_ */
39757 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/ieee80211_ioctl.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ieee80211_ioctl.h
39758 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/ieee80211_ioctl.h 1970-01-01 01:00:00.000000000 +0100
39759 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ieee80211_ioctl.h 2009-05-10 22:27:59.000000000 +0200
39760 @@ -0,0 +1,163 @@
39761 +/*
39762 + * Copyright (c) 2004-2005 Atheros Communications Inc.
39763 + * All rights reserved.
39764 + *
39765 + *
39766 + * This program is free software; you can redistribute it and/or modify
39767 + * it under the terms of the GNU General Public License version 2 as
39768 + * published by the Free Software Foundation;
39769 + *
39770 + * Software distributed under the License is distributed on an "AS
39771 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
39772 + * implied. See the License for the specific language governing
39773 + * rights and limitations under the License.
39774 + *
39775 + *
39776 + *
39777 + *
39778 + * $Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/include/ieee80211_ioctl.h#1 $
39779 + */
39780 +
39781 +#ifndef _IEEE80211_IOCTL_H_
39782 +#define _IEEE80211_IOCTL_H_
39783 +
39784 +#ifdef __cplusplus
39785 +extern "C" {
39786 +#endif
39787 +
39788 +/*
39789 + * Extracted from the MADWIFI net80211/ieee80211_ioctl.h
39790 + */
39791 +
39792 +/*
39793 + * WPA/RSN get/set key request. Specify the key/cipher
39794 + * type and whether the key is to be used for sending and/or
39795 + * receiving. The key index should be set only when working
39796 + * with global keys (use IEEE80211_KEYIX_NONE for ``no index'').
39797 + * Otherwise a unicast/pairwise key is specified by the bssid
39798 + * (on a station) or mac address (on an ap). They key length
39799 + * must include any MIC key data; otherwise it should be no
39800 + more than IEEE80211_KEYBUF_SIZE.
39801 + */
39802 +struct ieee80211req_key {
39803 + u_int8_t ik_type; /* key/cipher type */
39804 + u_int8_t ik_pad;
39805 + u_int16_t ik_keyix; /* key index */
39806 + u_int8_t ik_keylen; /* key length in bytes */
39807 + u_int8_t ik_flags;
39808 +#define IEEE80211_KEY_XMIT 0x01
39809 +#define IEEE80211_KEY_RECV 0x02
39810 +#define IEEE80211_KEY_DEFAULT 0x80 /* default xmit key */
39811 + u_int8_t ik_macaddr[IEEE80211_ADDR_LEN];
39812 + u_int64_t ik_keyrsc; /* key receive sequence counter */
39813 + u_int64_t ik_keytsc; /* key transmit sequence counter */
39814 + u_int8_t ik_keydata[IEEE80211_KEYBUF_SIZE+IEEE80211_MICBUF_SIZE];
39815 +};
39816 +/*
39817 + * Delete a key either by index or address. Set the index
39818 + * to IEEE80211_KEYIX_NONE when deleting a unicast key.
39819 + */
39820 +struct ieee80211req_del_key {
39821 + u_int8_t idk_keyix; /* key index */
39822 + u_int8_t idk_macaddr[IEEE80211_ADDR_LEN];
39823 +};
39824 +/*
39825 + * MLME state manipulation request. IEEE80211_MLME_ASSOC
39826 + * only makes sense when operating as a station. The other
39827 + * requests can be used when operating as a station or an
39828 + * ap (to effect a station).
39829 + */
39830 +struct ieee80211req_mlme {
39831 + u_int8_t im_op; /* operation to perform */
39832 +#define IEEE80211_MLME_ASSOC 1 /* associate station */
39833 +#define IEEE80211_MLME_DISASSOC 2 /* disassociate station */
39834 +#define IEEE80211_MLME_DEAUTH 3 /* deauthenticate station */
39835 +#define IEEE80211_MLME_AUTHORIZE 4 /* authorize station */
39836 +#define IEEE80211_MLME_UNAUTHORIZE 5 /* unauthorize station */
39837 + u_int16_t im_reason; /* 802.11 reason code */
39838 + u_int8_t im_macaddr[IEEE80211_ADDR_LEN];
39839 +};
39840 +
39841 +struct ieee80211req_addpmkid {
39842 + u_int8_t pi_bssid[IEEE80211_ADDR_LEN];
39843 + u_int8_t pi_enable;
39844 + u_int8_t pi_pmkid[16];
39845 +};
39846 +
39847 +#define AUTH_ALG_OPEN_SYSTEM 0x01
39848 +#define AUTH_ALG_SHARED_KEY 0x02
39849 +#define AUTH_ALG_LEAP 0x04
39850 +
39851 +struct ieee80211req_authalg {
39852 + u_int8_t auth_alg;
39853 +};
39854 +
39855 +/*
39856 + * Request to add an IE to a Management Frame
39857 + */
39858 +enum{
39859 + IEEE80211_APPIE_FRAME_BEACON = 0,
39860 + IEEE80211_APPIE_FRAME_PROBE_REQ = 1,
39861 + IEEE80211_APPIE_FRAME_PROBE_RESP = 2,
39862 + IEEE80211_APPIE_FRAME_ASSOC_REQ = 3,
39863 + IEEE80211_APPIE_FRAME_ASSOC_RESP = 4,
39864 + IEEE80211_APPIE_NUM_OF_FRAME = 5
39865 +};
39866 +
39867 +/*
39868 + * The Maximum length of the IE that can be added to a Management frame
39869 + */
39870 +#define IEEE80211_APPIE_FRAME_MAX_LEN 78
39871 +
39872 +struct ieee80211req_getset_appiebuf {
39873 + u_int32_t app_frmtype; /* management frame type for which buffer is added */
39874 + u_int32_t app_buflen; /*application supplied buffer length */
39875 + u_int8_t app_buf[];
39876 +};
39877 +
39878 +/*
39879 + * The following definitions are used by an application to set filter
39880 + * for receiving management frames
39881 + */
39882 +enum {
39883 + IEEE80211_FILTER_TYPE_BEACON = 0x1,
39884 + IEEE80211_FILTER_TYPE_PROBE_REQ = 0x2,
39885 + IEEE80211_FILTER_TYPE_PROBE_RESP = 0x4,
39886 + IEEE80211_FILTER_TYPE_ASSOC_REQ = 0x8,
39887 + IEEE80211_FILTER_TYPE_ASSOC_RESP = 0x10,
39888 + IEEE80211_FILTER_TYPE_AUTH = 0x20,
39889 + IEEE80211_FILTER_TYPE_DEAUTH = 0x40,
39890 + IEEE80211_FILTER_TYPE_DISASSOC = 0x80,
39891 + IEEE80211_FILTER_TYPE_ALL = 0xFF /* used to check the valid filter bits */
39892 +};
39893 +
39894 +struct ieee80211req_set_filter {
39895 + u_int32_t app_filterype; /* management frame filter type */
39896 +};
39897 +
39898 +enum {
39899 + IEEE80211_PARAM_AUTHMODE = 3, /* Authentication Mode */
39900 + IEEE80211_PARAM_MCASTCIPHER = 5,
39901 + IEEE80211_PARAM_MCASTKEYLEN = 6, /* multicast key length */
39902 + IEEE80211_PARAM_UCASTCIPHER = 8,
39903 + IEEE80211_PARAM_UCASTKEYLEN = 9, /* unicast key length */
39904 + IEEE80211_PARAM_WPA = 10, /* WPA mode (0,1,2) */
39905 + IEEE80211_PARAM_ROAMING = 12, /* roaming mode */
39906 + IEEE80211_PARAM_PRIVACY = 13, /* privacy invoked */
39907 + IEEE80211_PARAM_COUNTERMEASURES = 14, /* WPA/TKIP countermeasures */
39908 + IEEE80211_PARAM_DROPUNENCRYPTED = 15, /* discard unencrypted frames */
39909 +};
39910 +
39911 +/*
39912 + * Values for IEEE80211_PARAM_WPA
39913 + */
39914 +#define WPA_MODE_WPA1 1
39915 +#define WPA_MODE_WPA2 2
39916 +#define WPA_MODE_AUTO 3
39917 +#define WPA_MODE_NONE 4
39918 +
39919 +#ifdef __cplusplus
39920 +}
39921 +#endif
39922 +
39923 +#endif /* _IEEE80211_IOCTL_H_ */
39924 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/ieee80211_node.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ieee80211_node.h
39925 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/ieee80211_node.h 1970-01-01 01:00:00.000000000 +0100
39926 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ieee80211_node.h 2009-05-10 22:27:59.000000000 +0200
39927 @@ -0,0 +1,77 @@
39928 +/*-
39929 + * Copyright (c) 2001 Atsushi Onoe
39930 + * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
39931 + * Copyright (c) 2006 Atheros Communications, Inc.
39932 + *
39933 + * Wireless Network driver for Atheros AR6001
39934 + * All rights reserved.
39935 + *
39936 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
39937 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39938 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
39939 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
39940 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
39941 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
39942 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
39943 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
39944 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
39945 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39946 + *
39947 + */
39948 +#ifndef _IEEE80211_NODE_H_
39949 +#define _IEEE80211_NODE_H_
39950 +
39951 +/*
39952 + * Node locking definitions.
39953 + */
39954 +#define IEEE80211_NODE_LOCK_INIT(_nt) A_MUTEX_INIT(&(_nt)->nt_nodelock)
39955 +#define IEEE80211_NODE_LOCK_DESTROY(_nt)
39956 +#define IEEE80211_NODE_LOCK(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock)
39957 +#define IEEE80211_NODE_UNLOCK(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock)
39958 +#define IEEE80211_NODE_LOCK_BH(_nt) A_MUTEX_LOCK(&(_nt)->nt_nodelock)
39959 +#define IEEE80211_NODE_UNLOCK_BH(_nt) A_MUTEX_UNLOCK(&(_nt)->nt_nodelock)
39960 +#define IEEE80211_NODE_LOCK_ASSERT(_nt)
39961 +
39962 +/*
39963 + * Node reference counting definitions.
39964 + *
39965 + * ieee80211_node_initref initialize the reference count to 1
39966 + * ieee80211_node_incref add a reference
39967 + * ieee80211_node_decref remove a reference
39968 + * ieee80211_node_dectestref remove a reference and return 1 if this
39969 + * is the last reference, otherwise 0
39970 + * ieee80211_node_refcnt reference count for printing (only)
39971 + */
39972 +#define ieee80211_node_initref(_ni) ((_ni)->ni_refcnt = 1)
39973 +#define ieee80211_node_incref(_ni) ((_ni)->ni_refcnt++)
39974 +#define ieee80211_node_decref(_ni) ((_ni)->ni_refcnt--)
39975 +#define ieee80211_node_dectestref(_ni) (((_ni)->ni_refcnt--) == 0)
39976 +#define ieee80211_node_refcnt(_ni) ((_ni)->ni_refcnt)
39977 +
39978 +#define IEEE80211_NODE_HASHSIZE 32
39979 +/* simple hash is enough for variation of macaddr */
39980 +#define IEEE80211_NODE_HASH(addr) \
39981 + (((const A_UINT8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \
39982 + IEEE80211_NODE_HASHSIZE)
39983 +
39984 +/*
39985 + * Table of ieee80211_node instances. Each ieee80211com
39986 + * has at least one for holding the scan candidates.
39987 + * When operating as an access point or in ibss mode there
39988 + * is a second table for associated stations or neighbors.
39989 + */
39990 +struct ieee80211_node_table {
39991 + void *nt_wmip; /* back reference */
39992 + A_MUTEX_T nt_nodelock; /* on node table */
39993 + struct bss *nt_node_first; /* information of all nodes */
39994 + struct bss *nt_node_last; /* information of all nodes */
39995 + struct bss *nt_hash[IEEE80211_NODE_HASHSIZE];
39996 + const char *nt_name; /* for debugging */
39997 + A_UINT32 nt_scangen; /* gen# for timeout scan */
39998 + A_TIMER nt_inact_timer;
39999 + A_UINT8 isTimerArmed; /* is the node timer armed */
40000 +};
40001 +
40002 +#define WLAN_NODE_INACT_TIMEOUT_MSEC 10000
40003 +
40004 +#endif /* _IEEE80211_NODE_H_ */
40005 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/ini_dset.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ini_dset.h
40006 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/ini_dset.h 1970-01-01 01:00:00.000000000 +0100
40007 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/ini_dset.h 2009-05-10 22:27:59.000000000 +0200
40008 @@ -0,0 +1,40 @@
40009 +/*
40010 + * Copyright (c) 2004-2007 Atheros Communications Inc.
40011 + * All rights reserved.
40012 + *
40013 + * $ATH_LICENSE_HOSTSDK0_C$
40014 + *
40015 + */
40016 +#ifndef _INI_DSET_H_
40017 +#define _INI_DSET_H_
40018 +
40019 +/*
40020 + * Each of these represents a WHAL INI table, which consists
40021 + * of an "address column" followed by 1 or more "value columns".
40022 + *
40023 + * Software uses the base WHAL_INI_DATA_ID+column to access a
40024 + * DataSet that holds a particular column of data.
40025 + */
40026 +typedef enum {
40027 + WHAL_INI_DATA_ID_NULL =0,
40028 + WHAL_INI_DATA_ID_MODE_SPECIFIC =1, /* 2,3 */
40029 + WHAL_INI_DATA_ID_COMMON =4, /* 5 */
40030 + WHAL_INI_DATA_ID_BB_RFGAIN =6, /* 7,8 */
40031 + WHAL_INI_DATA_ID_ANALOG_BANK1 =9, /* 10 */
40032 + WHAL_INI_DATA_ID_ANALOG_BANK2 =11, /* 12 */
40033 + WHAL_INI_DATA_ID_ANALOG_BANK3 =13, /* 14, 15 */
40034 + WHAL_INI_DATA_ID_ANALOG_BANK6 =16, /* 17, 18 */
40035 + WHAL_INI_DATA_ID_ANALOG_BANK7 =19, /* 20 */
40036 + WHAL_INI_DATA_ID_MODE_OVERRIDES =21, /* 22,23 */
40037 + WHAL_INI_DATA_ID_COMMON_OVERRIDES =24, /* 25 */
40038 +
40039 + WHAL_INI_DATA_ID_MAX =25
40040 +} WHAL_INI_DATA_ID;
40041 +
40042 +typedef PREPACK struct {
40043 + A_UINT16 freqIndex; // 1 - A mode 2 - B or G mode 0 - common
40044 + A_UINT16 offset;
40045 + A_UINT32 newValue;
40046 +} POSTPACK INI_DSET_REG_OVERRIDE;
40047 +
40048 +#endif
40049 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/regDb.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/regDb.h
40050 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/regDb.h 1970-01-01 01:00:00.000000000 +0100
40051 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/regDb.h 2009-05-10 22:27:59.000000000 +0200
40052 @@ -0,0 +1,19 @@
40053 +/*
40054 + * Copyright (c) 2005 Atheros Communications, Inc.
40055 + * All rights reserved.
40056 + *
40057 + *
40058 + * $ATH_LICENSE_HOSTSDK0_C$
40059 + *
40060 + * This module contains the header files for regulatory module,
40061 + * which include the DB schema and DB values.
40062 + * $Id:
40063 + */
40064 +
40065 +#ifndef __REG_DB_H__
40066 +#define __REG_DB_H__
40067 +
40068 +#include "./regulatory/reg_dbschema.h"
40069 +#include "./regulatory/reg_dbvalues.h"
40070 +
40071 +#endif /* __REG_DB_H__ */
40072 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/regdump.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/regdump.h
40073 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/regdump.h 1970-01-01 01:00:00.000000000 +0100
40074 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/regdump.h 2009-05-10 22:27:59.000000000 +0200
40075 @@ -0,0 +1,33 @@
40076 +#ifndef __REGDUMP_H__
40077 +#define __REGDUMP_H__
40078 +/*
40079 + * Copyright (c) 2004-2007 Atheros Communications Inc.
40080 + * All rights reserved.
40081 + *
40082 + * $ATH_LICENSE_HOSTSDK0_C$
40083 + *
40084 + */
40085 +#if defined(AR6001)
40086 +#include "AR6001/AR6001_regdump.h"
40087 +#endif
40088 +#if defined(AR6002)
40089 +#include "AR6002/AR6002_regdump.h"
40090 +#endif
40091 +
40092 +#if !defined(__ASSEMBLER__)
40093 +/*
40094 + * Target CPU state at the time of failure is reflected
40095 + * in a register dump, which the Host can fetch through
40096 + * the diagnostic window.
40097 + */
40098 +struct register_dump_s {
40099 + A_UINT32 target_id; /* Target ID */
40100 + A_UINT32 assline; /* Line number (if assertion failure) */
40101 + A_UINT32 pc; /* Program Counter at time of exception */
40102 + A_UINT32 badvaddr; /* Virtual address causing exception */
40103 + CPU_exception_frame_t exc_frame; /* CPU-specific exception info */
40104 +
40105 + /* Could copy top of stack here, too.... */
40106 +};
40107 +#endif /* __ASSEMBLER__ */
40108 +#endif /* __REGDUMP_H__ */
40109 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/targaddrs.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/targaddrs.h
40110 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/targaddrs.h 1970-01-01 01:00:00.000000000 +0100
40111 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/targaddrs.h 2009-05-10 22:27:59.000000000 +0200
40112 @@ -0,0 +1,158 @@
40113 +/*
40114 + * Copyright (c) 2004-2007 Atheros Communications Inc.
40115 + * All rights reserved.
40116 + *
40117 + * $ATH_LICENSE_HOSTSDK0_C$
40118 + *
40119 + */
40120 +
40121 +#ifndef __TARGADDRS_H__
40122 +#define __TARGADDRS_H__
40123 +#if defined(AR6001)
40124 +#include "AR6001/addrs.h"
40125 +#endif
40126 +#if defined(AR6002)
40127 +#include "AR6002/addrs.h"
40128 +#endif
40129 +
40130 +/*
40131 + * AR6K option bits, to enable/disable various features.
40132 + * By default, all option bits are 0.
40133 + * These bits can be set in LOCAL_SCRATCH register 0.
40134 + */
40135 +#define AR6K_OPTION_BMI_DISABLE 0x01 /* Disable BMI comm with Host */
40136 +#define AR6K_OPTION_SERIAL_ENABLE 0x02 /* Enable serial port msgs */
40137 +#define AR6K_OPTION_WDT_DISABLE 0x04 /* WatchDog Timer override */
40138 +#define AR6K_OPTION_SLEEP_DISABLE 0x08 /* Disable system sleep */
40139 +#define AR6K_OPTION_STOP_BOOT 0x10 /* Stop boot processes (for ATE) */
40140 +#define AR6K_OPTION_ENABLE_NOANI 0x20 /* Operate without ANI */
40141 +#define AR6K_OPTION_DSET_DISABLE 0x40 /* Ignore DataSets */
40142 +#define AR6K_OPTION_IGNORE_FLASH 0x80 /* Ignore flash during bootup */
40143 +
40144 +/*
40145 + * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the
40146 + * host_interest structure. It must match the address of the _host_interest
40147 + * symbol (see linker script).
40148 + *
40149 + * Host Interest is shared between Host and Target in order to coordinate
40150 + * between the two, and is intended to remain constant (with additions only
40151 + * at the end) across software releases.
40152 + */
40153 +#define AR6001_HOST_INTEREST_ADDRESS 0x80000600
40154 +#define AR6002_HOST_INTEREST_ADDRESS 0x00500400
40155 +
40156 +#define HOST_INTEREST_MAX_SIZE 0x100
40157 +
40158 +#if !defined(__ASSEMBLER__)
40159 +struct register_dump_s;
40160 +struct dbglog_hdr_s;
40161 +
40162 +/*
40163 + * These are items that the Host may need to access
40164 + * via BMI or via the Diagnostic Window. The position
40165 + * of items in this structure must remain constant
40166 + * across firmware revisions!
40167 + *
40168 + * Types for each item must be fixed size across
40169 + * target and host platforms.
40170 + *
40171 + * More items may be added at the end.
40172 + */
40173 +struct host_interest_s {
40174 + /*
40175 + * Pointer to application-defined area, if any.
40176 + * Set by Target application during startup.
40177 + */
40178 + A_UINT32 hi_app_host_interest; /* 0x00 */
40179 +
40180 + /* Pointer to register dump area, valid after Target crash. */
40181 + A_UINT32 hi_failure_state; /* 0x04 */
40182 +
40183 + /* Pointer to debug logging header */
40184 + A_UINT32 hi_dbglog_hdr; /* 0x08 */
40185 +
40186 + /* Indicates whether or not flash is present on Target.
40187 + * NB: flash_is_present indicator is here not just
40188 + * because it might be of interest to the Host; but
40189 + * also because it's set early on by Target's startup
40190 + * asm code and we need it to have a special RAM address
40191 + * so that it doesn't get reinitialized with the rest
40192 + * of data.
40193 + */
40194 + A_UINT32 hi_flash_is_present; /* 0x0c */
40195 +
40196 + /*
40197 + * General-purpose flag bits, similar to AR6000_OPTION_* flags.
40198 + * Can be used by application rather than by OS.
40199 + */
40200 + A_UINT32 hi_option_flag; /* 0x10 */
40201 +
40202 + /*
40203 + * Boolean that determines whether or not to
40204 + * display messages on the serial port.
40205 + */
40206 + A_UINT32 hi_serial_enable; /* 0x14 */
40207 +
40208 + /* Start address of Flash DataSet index, if any */
40209 + A_UINT32 hi_dset_list_head; /* 0x18 */
40210 +
40211 + /* Override Target application start address */
40212 + A_UINT32 hi_app_start; /* 0x1c */
40213 +
40214 + /* Clock and voltage tuning */
40215 + A_UINT32 hi_skip_clock_init; /* 0x20 */
40216 + A_UINT32 hi_core_clock_setting; /* 0x24 */
40217 + A_UINT32 hi_cpu_clock_setting; /* 0x28 */
40218 + A_UINT32 hi_system_sleep_setting; /* 0x2c */
40219 + A_UINT32 hi_xtal_control_setting; /* 0x30 */
40220 + A_UINT32 hi_pll_ctrl_setting_24ghz; /* 0x34 */
40221 + A_UINT32 hi_pll_ctrl_setting_5ghz; /* 0x38 */
40222 + A_UINT32 hi_ref_voltage_trim_setting; /* 0x3c */
40223 + A_UINT32 hi_clock_info; /* 0x40 */
40224 +
40225 + /*
40226 + * Flash configuration overrides, used only
40227 + * when firmware is not executing from flash.
40228 + * (When using flash, modify the global variables
40229 + * with equivalent names.)
40230 + */
40231 + A_UINT32 hi_bank0_addr_value; /* 0x44 */
40232 + A_UINT32 hi_bank0_read_value; /* 0x48 */
40233 + A_UINT32 hi_bank0_write_value; /* 0x4c */
40234 + A_UINT32 hi_bank0_config_value; /* 0x50 */
40235 +
40236 + /* Pointer to Board Data */
40237 + A_UINT32 hi_board_data; /* 0x54 */
40238 + A_UINT32 hi_board_data_initialized; /* 0x58 */
40239 +
40240 + A_UINT32 hi_dset_RAM_index_table; /* 0x5c */
40241 +
40242 + A_UINT32 hi_desired_baud_rate; /* 0x60 */
40243 + A_UINT32 hi_dbglog_config; /* 0x64 */
40244 + A_UINT32 hi_end_RAM_reserve_sz; /* 0x68 */
40245 + A_UINT32 hi_mbox_io_block_sz; /* 0x6c */
40246 +
40247 + A_UINT32 hi_num_bpatch_streams; /* 0x70 */
40248 + A_UINT32 hi_mbox_isr_yield_limit; /* 0x74 */
40249 +
40250 + A_UINT32 hi_refclk_hz; /* 0x78 */
40251 +};
40252 +
40253 +/* Bits defined in hi_option_flag */
40254 +#define HI_OPTION_TIMER_WAR 1 /* not really used */
40255 +
40256 +/*
40257 + * Intended for use by Host software, this macro returns the Target RAM
40258 + * address of any item in the host_interest structure.
40259 + * Example: target_addr = AR6001_HOST_INTEREST_ITEM_ADDRESS(hi_board_data);
40260 + */
40261 +#define AR6001_HOST_INTEREST_ITEM_ADDRESS(item) \
40262 + ((A_UINT32)&((((struct host_interest_s *)(AR6001_HOST_INTEREST_ADDRESS))->item)))
40263 +
40264 +#define AR6002_HOST_INTEREST_ITEM_ADDRESS(item) \
40265 + ((A_UINT32)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item)))
40266 +
40267 +
40268 +#endif /* !__ASSEMBLER__ */
40269 +
40270 +#endif /* __TARGADDRS_H__ */
40271 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/testcmd.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/testcmd.h
40272 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/testcmd.h 1970-01-01 01:00:00.000000000 +0100
40273 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/testcmd.h 2009-05-10 22:27:59.000000000 +0200
40274 @@ -0,0 +1,144 @@
40275 +/*
40276 + * Copyright (c) 2004-2005 Atheros Communications Inc.
40277 + * All rights reserved.
40278 + *
40279 + *
40280 + * $ATH_LICENSE_HOSTSDK0_C$
40281 + *
40282 + */
40283 +
40284 +#ifndef TESTCMD_H_
40285 +#define TESTCMD_H_
40286 +
40287 +#ifdef __cplusplus
40288 +extern "C" {
40289 +#endif
40290 +
40291 +typedef enum {
40292 + ZEROES_PATTERN = 0,
40293 + ONES_PATTERN,
40294 + REPEATING_10,
40295 + PN7_PATTERN,
40296 + PN9_PATTERN,
40297 + PN15_PATTERN
40298 +}TX_DATA_PATTERN;
40299 +
40300 +/* Continous tx
40301 + mode : TCMD_CONT_TX_OFF - Disabling continous tx
40302 + TCMD_CONT_TX_SINE - Enable continuous unmodulated tx
40303 + TCMD_CONT_TX_FRAME- Enable continuous modulated tx
40304 + freq : Channel freq in Mhz. (e.g 2412 for channel 1 in 11 g)
40305 +dataRate: 0 - 1 Mbps
40306 + 1 - 2 Mbps
40307 + 2 - 5.5 Mbps
40308 + 3 - 11 Mbps
40309 + 4 - 6 Mbps
40310 + 5 - 9 Mbps
40311 + 6 - 12 Mbps
40312 + 7 - 18 Mbps
40313 + 8 - 24 Mbps
40314 + 9 - 36 Mbps
40315 + 10 - 28 Mbps
40316 + 11 - 54 Mbps
40317 + txPwr: Tx power in dBm[5 -11] for unmod Tx, [5-14] for mod Tx
40318 +antenna: 1 - one antenna
40319 + 2 - two antenna
40320 +Note : Enable/disable continuous tx test cmd works only when target is awake.
40321 +*/
40322 +
40323 +typedef enum {
40324 + TCMD_CONT_TX_OFF = 0,
40325 + TCMD_CONT_TX_SINE,
40326 + TCMD_CONT_TX_FRAME,
40327 + TCMD_CONT_TX_TX99,
40328 + TCMD_CONT_TX_TX100
40329 +} TCMD_CONT_TX_MODE;
40330 +
40331 +typedef PREPACK struct {
40332 + A_UINT32 testCmdId;
40333 + A_UINT32 mode;
40334 + A_UINT32 freq;
40335 + A_UINT32 dataRate;
40336 + A_INT32 txPwr;
40337 + A_UINT32 antenna;
40338 + A_UINT32 enANI;
40339 + A_UINT32 scramblerOff;
40340 + A_UINT32 aifsn;
40341 + A_UINT16 pktSz;
40342 + A_UINT16 txPattern;
40343 +} POSTPACK TCMD_CONT_TX;
40344 +
40345 +#define TCMD_TXPATTERN_ZERONE 0x1
40346 +#define TCMD_TXPATTERN_ZERONE_DIS_SCRAMBLE 0x2
40347 +
40348 +/* Continuous Rx
40349 + act: TCMD_CONT_RX_PROMIS - promiscuous mode (accept all incoming frames)
40350 + TCMD_CONT_RX_FILTER - filter mode (accept only frames with dest
40351 + address equal specified
40352 + mac address (set via act =3)
40353 + TCMD_CONT_RX_REPORT off mode (disable cont rx mode and get the
40354 + report from the last cont
40355 + Rx test)
40356 +
40357 + TCMD_CONT_RX_SETMAC - set MacAddr mode (sets the MAC address for the
40358 + target. This Overrides
40359 + the default MAC address.)
40360 +
40361 +*/
40362 +typedef enum {
40363 + TCMD_CONT_RX_PROMIS =0,
40364 + TCMD_CONT_RX_FILTER,
40365 + TCMD_CONT_RX_REPORT,
40366 + TCMD_CONT_RX_SETMAC
40367 +} TCMD_CONT_RX_ACT;
40368 +
40369 +typedef PREPACK struct {
40370 + A_UINT32 testCmdId;
40371 + A_UINT32 act;
40372 + A_UINT32 enANI;
40373 + PREPACK union {
40374 + struct PREPACK TCMD_CONT_RX_PARA {
40375 + A_UINT32 freq;
40376 + A_UINT32 antenna;
40377 + } POSTPACK para;
40378 + struct PREPACK TCMD_CONT_RX_REPORT {
40379 + A_UINT32 totalPkt;
40380 + A_INT32 rssiInDBm;
40381 + } POSTPACK report;
40382 + struct PREPACK TCMD_CONT_RX_MAC {
40383 + A_UCHAR addr[ATH_MAC_LEN];
40384 + } POSTPACK mac;
40385 + } POSTPACK u;
40386 +} POSTPACK TCMD_CONT_RX;
40387 +
40388 +/* Force sleep/wake test cmd
40389 + mode: TCMD_PM_WAKEUP - Wakeup the target
40390 + TCMD_PM_SLEEP - Force the target to sleep.
40391 + */
40392 +typedef enum {
40393 + TCMD_PM_WAKEUP = 1, /* be consistent with target */
40394 + TCMD_PM_SLEEP
40395 +} TCMD_PM_MODE;
40396 +
40397 +typedef PREPACK struct {
40398 + A_UINT32 testCmdId;
40399 + A_UINT32 mode;
40400 +} POSTPACK TCMD_PM;
40401 +
40402 +typedef enum{
40403 + TCMD_CONT_TX_ID,
40404 + TCMD_CONT_RX_ID,
40405 + TCMD_PM_ID
40406 + } TCMD_ID;
40407 +
40408 +typedef PREPACK union {
40409 + TCMD_CONT_TX contTx;
40410 + TCMD_CONT_RX contRx;
40411 + TCMD_PM pm ;
40412 +} POSTPACK TEST_CMD;
40413 +
40414 +#ifdef __cplusplus
40415 +}
40416 +#endif
40417 +
40418 +#endif /* TESTCMD_H_ */
40419 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/wlan_api.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wlan_api.h
40420 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/wlan_api.h 1970-01-01 01:00:00.000000000 +0100
40421 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wlan_api.h 2009-05-10 22:27:59.000000000 +0200
40422 @@ -0,0 +1,101 @@
40423 +#ifndef _HOST_WLAN_API_H_
40424 +#define _HOST_WLAN_API_H_
40425 +/*
40426 + * Copyright (c) 2004-2005 Atheros Communications Inc.
40427 + * All rights reserved.
40428 + *
40429 + * This file contains the API for the host wlan module
40430 + *
40431 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/wlan_api.h#1 $
40432 + *
40433 + *
40434 + * This program is free software; you can redistribute it and/or modify
40435 + * it under the terms of the GNU General Public License version 2 as
40436 + * published by the Free Software Foundation;
40437 + *
40438 + * Software distributed under the License is distributed on an "AS
40439 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
40440 + * implied. See the License for the specific language governing
40441 + * rights and limitations under the License.
40442 + *
40443 + *
40444 + *
40445 + */
40446 +
40447 +#ifdef __cplusplus
40448 +extern "C" {
40449 +#endif
40450 +
40451 +struct ieee80211_node_table;
40452 +struct ieee80211_frame;
40453 +
40454 +struct ieee80211_common_ie {
40455 + A_UINT16 ie_chan;
40456 + A_UINT8 *ie_tstamp;
40457 + A_UINT8 *ie_ssid;
40458 + A_UINT8 *ie_rates;
40459 + A_UINT8 *ie_xrates;
40460 + A_UINT8 *ie_country;
40461 + A_UINT8 *ie_wpa;
40462 + A_UINT8 *ie_rsn;
40463 + A_UINT8 *ie_wmm;
40464 + A_UINT8 *ie_ath;
40465 + A_UINT16 ie_capInfo;
40466 + A_UINT16 ie_beaconInt;
40467 + A_UINT8 *ie_tim;
40468 + A_UINT8 *ie_chswitch;
40469 + A_UINT8 ie_erp;
40470 + A_UINT8 *ie_wsc;
40471 +};
40472 +
40473 +typedef struct bss {
40474 + A_UINT8 ni_macaddr[6];
40475 + A_UINT8 ni_snr;
40476 + A_INT16 ni_rssi;
40477 + struct bss *ni_list_next;
40478 + struct bss *ni_list_prev;
40479 + struct bss *ni_hash_next;
40480 + struct bss *ni_hash_prev;
40481 + struct ieee80211_common_ie ni_cie;
40482 + A_UINT8 *ni_buf;
40483 + struct ieee80211_node_table *ni_table;
40484 + A_UINT32 ni_refcnt;
40485 + int ni_scangen;
40486 + A_UINT32 ni_tstamp;
40487 +} bss_t;
40488 +
40489 +typedef void wlan_node_iter_func(void *arg, bss_t *);
40490 +
40491 +bss_t *wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size);
40492 +void wlan_node_free(bss_t *ni);
40493 +void wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
40494 + const A_UINT8 *macaddr);
40495 +bss_t *wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr);
40496 +void wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni);
40497 +void wlan_free_allnodes(struct ieee80211_node_table *nt);
40498 +void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
40499 + void *arg);
40500 +
40501 +void wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt);
40502 +void wlan_node_table_reset(struct ieee80211_node_table *nt);
40503 +void wlan_node_table_cleanup(struct ieee80211_node_table *nt);
40504 +
40505 +A_STATUS wlan_parse_beacon(A_UINT8 *buf, int framelen,
40506 + struct ieee80211_common_ie *cie);
40507 +
40508 +A_UINT16 wlan_ieee2freq(int chan);
40509 +A_UINT32 wlan_freq2ieee(A_UINT16 freq);
40510 +
40511 +
40512 +bss_t *
40513 +wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
40514 + A_UINT32 ssidLength, A_BOOL bIsWPA2);
40515 +
40516 +void
40517 +wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni);
40518 +
40519 +#ifdef __cplusplus
40520 +}
40521 +#endif
40522 +
40523 +#endif /* _HOST_WLAN_API_H_ */
40524 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/wlan_dset.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wlan_dset.h
40525 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/wlan_dset.h 1970-01-01 01:00:00.000000000 +0100
40526 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wlan_dset.h 2009-05-10 22:27:59.000000000 +0200
40527 @@ -0,0 +1,20 @@
40528 +/*
40529 + * Copyright (c) 2007 Atheros Communications, Inc.
40530 + * All rights reserved.
40531 + *
40532 + *
40533 + * $ATH_LICENSE_HOSTSDK0_C$
40534 + *
40535 + */
40536 +
40537 +#ifndef __WLAN_DSET_H__
40538 +#define __WKAN_DSET_H__
40539 +
40540 +typedef PREPACK struct wow_config_dset {
40541 +
40542 + A_UINT8 valid_dset;
40543 + A_UINT8 gpio_enable;
40544 + A_UINT16 gpio_pin;
40545 +} POSTPACK WOW_CONFIG_DSET;
40546 +
40547 +#endif
40548 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/wmi_api.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wmi_api.h
40549 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/wmi_api.h 1970-01-01 01:00:00.000000000 +0100
40550 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wmi_api.h 2009-05-10 22:27:59.000000000 +0200
40551 @@ -0,0 +1,260 @@
40552 +#ifndef _WMI_API_H_
40553 +#define _WMI_API_H_
40554 +/*
40555 + * Copyright (c) 2004-2006 Atheros Communications Inc.
40556 + * All rights reserved.
40557 + *
40558 + * This file contains the definitions for the Wireless Module Interface (WMI).
40559 + *
40560 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/wmi_api.h#2 $
40561 + *
40562 + *
40563 + * This program is free software; you can redistribute it and/or modify
40564 + * it under the terms of the GNU General Public License version 2 as
40565 + * published by the Free Software Foundation;
40566 + *
40567 + * Software distributed under the License is distributed on an "AS
40568 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
40569 + * implied. See the License for the specific language governing
40570 + * rights and limitations under the License.
40571 + *
40572 + *
40573 + *
40574 + */
40575 +
40576 +#ifdef __cplusplus
40577 +extern "C" {
40578 +#endif
40579 +
40580 +/*
40581 + * IP QoS Field definitions according to 802.1p
40582 + */
40583 +#define BEST_EFFORT_PRI 0
40584 +#define BACKGROUND_PRI 1
40585 +#define EXCELLENT_EFFORT_PRI 3
40586 +#define CONTROLLED_LOAD_PRI 4
40587 +#define VIDEO_PRI 5
40588 +#define VOICE_PRI 6
40589 +#define NETWORK_CONTROL_PRI 7
40590 +#define MAX_NUM_PRI 8
40591 +
40592 +#define UNDEFINED_PRI (0xff)
40593 +
40594 +/* simple mapping of IP TOS field to a WMI priority stream
40595 + * this mapping was taken from the original linux driver implementation
40596 + * The operation maps the following
40597 + *
40598 + * */
40599 +#define IP_TOS_TO_WMI_PRI(tos) \
40600 + ((WMI_PRI_STREAM_ID)(((tos) >> 1) & 0x03))
40601 +
40602 +#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000 /* 5 seconds */
40603 +
40604 +
40605 +struct wmi_t;
40606 +
40607 +void *wmi_init(void *devt);
40608 +
40609 +void wmi_qos_state_init(struct wmi_t *wmip);
40610 +void wmi_shutdown(struct wmi_t *wmip);
40611 +A_UINT16 wmi_get_mapped_qos_queue(struct wmi_t *, A_UINT8);
40612 +A_STATUS wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf);
40613 +A_STATUS wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType);
40614 +A_STATUS wmi_dot3_2_dix(struct wmi_t *wmip, void *osbuf);
40615 +A_STATUS wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf);
40616 +A_STATUS wmi_syncpoint(struct wmi_t *wmip);
40617 +A_STATUS wmi_syncpoint_reset(struct wmi_t *wmip);
40618 +WMI_PRI_STREAM_ID wmi_get_stream_id(struct wmi_t *wmip, A_UINT8 trafficClass);
40619 +A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT8 dir, A_UINT8 up);
40620 +
40621 +A_STATUS wmi_control_rx(struct wmi_t *wmip, void *osbuf);
40622 +void wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg);
40623 +void wmi_free_allnodes(struct wmi_t *wmip);
40624 +bss_t *wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr);
40625 +
40626 +
40627 +typedef enum {
40628 + NO_SYNC_WMIFLAG = 0,
40629 + SYNC_BEFORE_WMIFLAG, /* transmit all queued data before cmd */
40630 + SYNC_AFTER_WMIFLAG, /* any new data waits until cmd execs */
40631 + SYNC_BOTH_WMIFLAG,
40632 + END_WMIFLAG /* end marker */
40633 +} WMI_SYNC_FLAG;
40634 +
40635 +A_STATUS wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
40636 + WMI_SYNC_FLAG flag);
40637 +A_STATUS wmi_connect_cmd(struct wmi_t *wmip,
40638 + NETWORK_TYPE netType,
40639 + DOT11_AUTH_MODE dot11AuthMode,
40640 + AUTH_MODE authMode,
40641 + CRYPTO_TYPE pairwiseCrypto,
40642 + A_UINT8 pairwiseCryptoLen,
40643 + CRYPTO_TYPE groupCrypto,
40644 + A_UINT8 groupCryptoLen,
40645 + int ssidLength,
40646 + A_UCHAR *ssid,
40647 + A_UINT8 *bssid,
40648 + A_UINT16 channel,
40649 + A_UINT32 ctrl_flags);
40650 +A_STATUS wmi_reconnect_cmd(struct wmi_t *wmip,
40651 + A_UINT8 *bssid,
40652 + A_UINT16 channel);
40653 +A_STATUS wmi_disconnect_cmd(struct wmi_t *wmip);
40654 +A_STATUS wmi_getrev_cmd(struct wmi_t *wmip);
40655 +A_STATUS wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
40656 + A_BOOL forceFgScan, A_BOOL isLegacy,
40657 + A_UINT32 homeDwellTime, A_UINT32 forceScanInterval);
40658 +A_STATUS wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec,
40659 + A_UINT16 fg_end_sec, A_UINT16 bg_sec,
40660 + A_UINT16 minact_chdw_msec,
40661 + A_UINT16 maxact_chdw_msec, A_UINT16 pas_chdw_msec,
40662 + A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags,
40663 + A_UINT32 max_dfsch_act_time);
40664 +A_STATUS wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask);
40665 +A_STATUS wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
40666 + A_UINT8 ssidLength, A_UCHAR *ssid);
40667 +A_STATUS wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons);
40668 +A_STATUS wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmisstime, A_UINT16 bmissbeacons);
40669 +A_STATUS wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
40670 + A_UINT8 ieLen, A_UINT8 *ieInfo);
40671 +A_STATUS wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode);
40672 +A_STATUS wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
40673 + A_UINT16 atim_windows, A_UINT16 timeout_value);
40674 +A_STATUS wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
40675 + A_UINT16 psPollNum, A_UINT16 dtimPolicy);
40676 +A_STATUS wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout);
40677 +A_STATUS wmi_sync_cmd(struct wmi_t *wmip, A_UINT8 syncNumber);
40678 +A_STATUS wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream);
40679 +A_STATUS wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 streamID);
40680 +A_STATUS wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 rate);
40681 +A_STATUS wmi_get_bitrate_cmd(struct wmi_t *wmip);
40682 +A_INT8 wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate);
40683 +A_STATUS wmi_get_regDomain_cmd(struct wmi_t *wmip);
40684 +A_STATUS wmi_get_channelList_cmd(struct wmi_t *wmip);
40685 +A_STATUS wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
40686 + WMI_PHY_MODE mode, A_INT8 numChan,
40687 + A_UINT16 *channelList);
40688 +
40689 +A_STATUS wmi_set_snr_threshold_params(struct wmi_t *wmip,
40690 + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
40691 +A_STATUS wmi_set_rssi_threshold_params(struct wmi_t *wmip,
40692 + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
40693 +A_STATUS wmi_clr_rssi_snr(struct wmi_t *wmip);
40694 +A_STATUS wmi_set_lq_threshold_params(struct wmi_t *wmip,
40695 + WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd);
40696 +A_STATUS wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold);
40697 +A_STATUS wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status);
40698 +
40699 +A_STATUS wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 bitmask);
40700 +
40701 +A_STATUS wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie,
40702 + A_UINT32 source);
40703 +A_STATUS wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
40704 + A_UINT16 tsr, A_BOOL rep, A_UINT16 size,
40705 + A_UINT32 valid);
40706 +A_STATUS wmi_get_stats_cmd(struct wmi_t *wmip);
40707 +A_STATUS wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex,
40708 + CRYPTO_TYPE keyType, A_UINT8 keyUsage,
40709 + A_UINT8 keyLength,A_UINT8 *keyRSC,
40710 + A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl,
40711 + WMI_SYNC_FLAG sync_flag);
40712 +A_STATUS wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk);
40713 +A_STATUS wmi_delete_krk_cmd(struct wmi_t *wmip);
40714 +A_STATUS wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex);
40715 +A_STATUS wmi_set_akmp_params_cmd(struct wmi_t *wmip,
40716 + WMI_SET_AKMP_PARAMS_CMD *akmpParams);
40717 +A_STATUS wmi_get_pmkid_list_cmd(struct wmi_t *wmip);
40718 +A_STATUS wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
40719 + WMI_SET_PMKID_LIST_CMD *pmkInfo);
40720 +A_STATUS wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM);
40721 +A_STATUS wmi_get_txPwr_cmd(struct wmi_t *wmip);
40722 +A_STATUS wmi_switch_radio(struct wmi_t *wmip, A_UINT8 on);
40723 +A_STATUS wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid);
40724 +A_STATUS wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex);
40725 +A_STATUS wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en);
40726 +A_STATUS wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
40727 + A_BOOL set);
40728 +A_STATUS wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT16 txop,
40729 + A_UINT8 eCWmin, A_UINT8 eCWmax,
40730 + A_UINT8 aifsn);
40731 +A_STATUS wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
40732 + A_UINT8 trafficClass, A_UINT8 maxRetries,
40733 + A_UINT8 enableNotify);
40734 +
40735 +void wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid);
40736 +
40737 +A_STATUS wmi_get_roam_tbl_cmd(struct wmi_t *wmip);
40738 +A_STATUS wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType);
40739 +A_STATUS wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
40740 + A_UINT8 size);
40741 +A_STATUS wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
40742 + WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
40743 + A_UINT8 size);
40744 +
40745 +A_STATUS wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode);
40746 +A_STATUS wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
40747 + A_UINT8 frmType,
40748 + A_UINT8 *dstMacAddr,
40749 + A_UINT8 *bssid,
40750 + A_UINT16 optIEDataLen,
40751 + A_UINT8 *optIEData);
40752 +
40753 +A_STATUS wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl);
40754 +A_STATUS wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize);
40755 +A_STATUS wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSpLen);
40756 +A_UINT8 convert_userPriority_to_trafficClass(A_UINT8 userPriority);
40757 +A_UINT8 wmi_get_power_mode_cmd(struct wmi_t *wmip);
40758 +A_STATUS wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance);
40759 +
40760 +#ifdef CONFIG_HOST_TCMD_SUPPORT
40761 +A_STATUS wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32 len);
40762 +#endif
40763 +
40764 +A_STATUS wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status);
40765 +A_STATUS wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd);
40766 +
40767 +
40768 +/*
40769 + * This function is used to configure the fix rates mask to the target.
40770 + */
40771 +A_STATUS wmi_set_fixrates_cmd(struct wmi_t *wmip, A_INT16 fixRatesMask);
40772 +A_STATUS wmi_get_ratemask_cmd(struct wmi_t *wmip);
40773 +
40774 +A_STATUS wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
40775 +
40776 +A_STATUS wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
40777 +
40778 +A_STATUS wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status);
40779 +A_STATUS wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable);
40780 +
40781 +A_STATUS wmi_get_keepalive_configured(struct wmi_t *wmip);
40782 +A_UINT8 wmi_get_keepalive_cmd(struct wmi_t *wmip);
40783 +A_STATUS wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval);
40784 +
40785 +A_STATUS wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType,
40786 + A_UINT8 ieLen,A_UINT8 *ieInfo);
40787 +
40788 +A_STATUS wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen);
40789 +A_INT32 wmi_get_rate(A_INT8 rateindex);
40790 +
40791 +/*Wake on Wireless WMI commands*/
40792 +A_STATUS wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd);
40793 +A_STATUS wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd);
40794 +A_STATUS wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd);
40795 +A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
40796 + WMI_ADD_WOW_PATTERN_CMD *cmd, A_UINT8* pattern, A_UINT8* mask, A_UINT8 pattern_size);
40797 +A_STATUS wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
40798 + WMI_DEL_WOW_PATTERN_CMD *cmd);
40799 +A_STATUS wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status);
40800 +
40801 +bss_t *
40802 +wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
40803 + A_UINT32 ssidLength, A_BOOL bIsWPA2);
40804 +
40805 +void
40806 +wmi_node_return (struct wmi_t *wmip, bss_t *bss);
40807 +#ifdef __cplusplus
40808 +}
40809 +#endif
40810 +
40811 +#endif /* _WMI_API_H_ */
40812 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/wmi.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wmi.h
40813 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/wmi.h 1970-01-01 01:00:00.000000000 +0100
40814 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wmi.h 2009-05-10 22:27:59.000000000 +0200
40815 @@ -0,0 +1,1743 @@
40816 +/*
40817 + * Copyright (c) 2004-2006 Atheros Communications Inc.
40818 + * All rights reserved.
40819 + *
40820 + *
40821 + * $ATH_LICENSE_HOSTSDK0_C$
40822 + *
40823 + * This file contains the definitions of the WMI protocol specified in the
40824 + * Wireless Module Interface (WMI). It includes definitions of all the
40825 + * commands and events. Commands are messages from the host to the WM.
40826 + * Events and Replies are messages from the WM to the host.
40827 + *
40828 + * Ownership of correctness in regards to WMI commands
40829 + * belongs to the host driver and the WM is not required to validate
40830 + * parameters for value, proper range, or any other checking.
40831 + *
40832 + */
40833 +
40834 +#ifndef _WMI_H_
40835 +#define _WMI_H_
40836 +
40837 +#ifndef ATH_TARGET
40838 +#include "athstartpack.h"
40839 +#endif
40840 +
40841 +#include "wmix.h"
40842 +
40843 +#ifdef __cplusplus
40844 +extern "C" {
40845 +#endif
40846 +
40847 +#define WMI_PROTOCOL_VERSION 0x0002
40848 +#define WMI_PROTOCOL_REVISION 0x0000
40849 +
40850 +#define ATH_MAC_LEN 6 /* length of mac in bytes */
40851 +#define WMI_CMD_MAX_LEN 100
40852 +#define WMI_CONTROL_MSG_MAX_LEN 256
40853 +#define WMI_OPT_CONTROL_MSG_MAX_LEN 1536
40854 +#define IS_ETHERTYPE(_typeOrLen) ((_typeOrLen) >= 0x0600)
40855 +#define RFC1042OUI {0x00, 0x00, 0x00}
40856 +
40857 +#define IP_ETHERTYPE 0x0800
40858 +
40859 +#define WMI_IMPLICIT_PSTREAM 0xFF
40860 +#define WMI_MAX_THINSTREAM 15
40861 +
40862 +struct host_app_area_s {
40863 + A_UINT32 wmi_protocol_ver;
40864 +};
40865 +
40866 +/*
40867 + * Data Path
40868 + */
40869 +typedef PREPACK struct {
40870 + A_UINT8 dstMac[ATH_MAC_LEN];
40871 + A_UINT8 srcMac[ATH_MAC_LEN];
40872 + A_UINT16 typeOrLen;
40873 +} POSTPACK ATH_MAC_HDR;
40874 +
40875 +typedef PREPACK struct {
40876 + A_UINT8 dsap;
40877 + A_UINT8 ssap;
40878 + A_UINT8 cntl;
40879 + A_UINT8 orgCode[3];
40880 + A_UINT16 etherType;
40881 +} POSTPACK ATH_LLC_SNAP_HDR;
40882 +
40883 +typedef enum {
40884 + DATA_MSGTYPE = 0x0,
40885 + CNTL_MSGTYPE,
40886 + SYNC_MSGTYPE
40887 +} WMI_MSG_TYPE;
40888 +
40889 +
40890 +typedef PREPACK struct {
40891 + A_INT8 rssi;
40892 + A_UINT8 info; /* WMI_MSG_TYPE in lower 2 bits - b1b0 */
40893 + /* UP in next 3 bits - b4b3b2 */
40894 +#define WMI_DATA_HDR_MSG_TYPE_MASK 0x03
40895 +#define WMI_DATA_HDR_MSG_TYPE_SHIFT 0
40896 +#define WMI_DATA_HDR_UP_MASK 0x07
40897 +#define WMI_DATA_HDR_UP_SHIFT 2
40898 +#define WMI_DATA_HDR_IS_MSG_TYPE(h, t) (((h)->info & (WMI_DATA_HDR_MSG_TYPE_MASK)) == (t))
40899 +} POSTPACK WMI_DATA_HDR;
40900 +
40901 +
40902 +#define WMI_DATA_HDR_SET_MSG_TYPE(h, t) (h)->info = (((h)->info & ~(WMI_DATA_HDR_MSG_TYPE_MASK << WMI_DATA_HDR_MSG_TYPE_SHIFT)) | (t << WMI_DATA_HDR_MSG_TYPE_SHIFT))
40903 +#define WMI_DATA_HDR_SET_UP(h, p) (h)->info = (((h)->info & ~(WMI_DATA_HDR_UP_MASK << WMI_DATA_HDR_UP_SHIFT)) | (p << WMI_DATA_HDR_UP_SHIFT))
40904 +
40905 +/*
40906 + * Control Path
40907 + */
40908 +typedef PREPACK struct {
40909 + A_UINT16 commandId;
40910 +} POSTPACK WMI_CMD_HDR; /* used for commands and events */
40911 +
40912 +/*
40913 + * List of Commnands
40914 + */
40915 +typedef enum {
40916 + WMI_CONNECT_CMDID = 0x0001,
40917 + WMI_RECONNECT_CMDID,
40918 + WMI_DISCONNECT_CMDID,
40919 + WMI_SYNCHRONIZE_CMDID,
40920 + WMI_CREATE_PSTREAM_CMDID,
40921 + WMI_DELETE_PSTREAM_CMDID,
40922 + WMI_START_SCAN_CMDID,
40923 + WMI_SET_SCAN_PARAMS_CMDID,
40924 + WMI_SET_BSS_FILTER_CMDID,
40925 + WMI_SET_PROBED_SSID_CMDID,
40926 + WMI_SET_LISTEN_INT_CMDID,
40927 + WMI_SET_BMISS_TIME_CMDID,
40928 + WMI_SET_DISC_TIMEOUT_CMDID,
40929 + WMI_GET_CHANNEL_LIST_CMDID,
40930 + WMI_SET_BEACON_INT_CMDID,
40931 + WMI_GET_STATISTICS_CMDID,
40932 + WMI_SET_CHANNEL_PARAMS_CMDID,
40933 + WMI_SET_POWER_MODE_CMDID,
40934 + WMI_SET_IBSS_PM_CAPS_CMDID,
40935 + WMI_SET_POWER_PARAMS_CMDID,
40936 + WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
40937 + WMI_ADD_CIPHER_KEY_CMDID,
40938 + WMI_DELETE_CIPHER_KEY_CMDID,
40939 + WMI_ADD_KRK_CMDID,
40940 + WMI_DELETE_KRK_CMDID,
40941 + WMI_SET_PMKID_CMDID,
40942 + WMI_SET_TX_PWR_CMDID,
40943 + WMI_GET_TX_PWR_CMDID,
40944 + WMI_SET_ASSOC_INFO_CMDID,
40945 + WMI_ADD_BAD_AP_CMDID,
40946 + WMI_DELETE_BAD_AP_CMDID,
40947 + WMI_SET_TKIP_COUNTERMEASURES_CMDID,
40948 + WMI_RSSI_THRESHOLD_PARAMS_CMDID,
40949 + WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
40950 + WMI_SET_ACCESS_PARAMS_CMDID,
40951 + WMI_SET_RETRY_LIMITS_CMDID,
40952 + WMI_SET_OPT_MODE_CMDID,
40953 + WMI_OPT_TX_FRAME_CMDID,
40954 + WMI_SET_VOICE_PKT_SIZE_CMDID,
40955 + WMI_SET_MAX_SP_LEN_CMDID,
40956 + WMI_SET_ROAM_CTRL_CMDID,
40957 + WMI_GET_ROAM_TBL_CMDID,
40958 + WMI_GET_ROAM_DATA_CMDID,
40959 + WMI_ENABLE_RM_CMDID,
40960 + WMI_SET_MAX_OFFHOME_DURATION_CMDID,
40961 + WMI_EXTENSION_CMDID, /* Non-wireless extensions */
40962 + WMI_SNR_THRESHOLD_PARAMS_CMDID,
40963 + WMI_LQ_THRESHOLD_PARAMS_CMDID,
40964 + WMI_SET_LPREAMBLE_CMDID,
40965 + WMI_SET_RTS_CMDID,
40966 + WMI_CLR_RSSI_SNR_CMDID,
40967 + WMI_SET_FIXRATES_CMDID,
40968 + WMI_GET_FIXRATES_CMDID,
40969 + WMI_SET_AUTH_MODE_CMDID,
40970 + WMI_SET_REASSOC_MODE_CMDID,
40971 + WMI_SET_WMM_CMDID,
40972 + WMI_SET_WMM_TXOP_CMDID,
40973 + WMI_TEST_CMDID,
40974 + WMI_SET_BT_STATUS_CMDID,
40975 + WMI_SET_BT_PARAMS_CMDID,
40976 +
40977 + WMI_SET_KEEPALIVE_CMDID,
40978 + WMI_GET_KEEPALIVE_CMDID,
40979 + WMI_SET_APPIE_CMDID,
40980 + WMI_GET_APPIE_CMDID,
40981 + WMI_SET_WSC_STATUS_CMDID,
40982 +
40983 + /* Wake on Wireless */
40984 + WMI_SET_HOST_SLEEP_MODE_CMDID,
40985 + WMI_SET_WOW_MODE_CMDID,
40986 + WMI_GET_WOW_LIST_CMDID,
40987 + WMI_ADD_WOW_PATTERN_CMDID,
40988 + WMI_DEL_WOW_PATTERN_CMDID,
40989 + WMI_SET_MAC_ADDRESS_CMDID,
40990 + WMI_SET_AKMP_PARAMS_CMDID,
40991 + WMI_SET_PMKID_LIST_CMDID,
40992 + WMI_GET_PMKID_LIST_CMDID,
40993 +
40994 + /*
40995 + * Developer commands starts at 0xF000
40996 + */
40997 + WMI_SET_BITRATE_CMDID = 0xF000,
40998 + WMI_GET_BITRATE_CMDID,
40999 + WMI_SET_WHALPARAM_CMDID,
41000 +
41001 +} WMI_COMMAND_ID;
41002 +
41003 +/*
41004 + * Frame Types
41005 + */
41006 +typedef enum {
41007 + WMI_FRAME_BEACON = 0,
41008 + WMI_FRAME_PROBE_REQ,
41009 + WMI_FRAME_PROBE_RESP,
41010 + WMI_FRAME_ASSOC_REQ,
41011 + WMI_FRAME_ASSOC_RESP,
41012 + WMI_NUM_MGMT_FRAME
41013 +} WMI_MGMT_FRAME_TYPE;
41014 +
41015 +/*
41016 + * Connect Command
41017 + */
41018 +typedef enum {
41019 + INFRA_NETWORK = 0x01,
41020 + ADHOC_NETWORK = 0x02,
41021 + ADHOC_CREATOR = 0x04,
41022 +} NETWORK_TYPE;
41023 +
41024 +typedef enum {
41025 + OPEN_AUTH = 0x01,
41026 + SHARED_AUTH = 0x02,
41027 + LEAP_AUTH = 0x04, /* different from IEEE_AUTH_MODE definitions */
41028 +} DOT11_AUTH_MODE;
41029 +
41030 +typedef enum {
41031 + NONE_AUTH = 0x01,
41032 + WPA_AUTH = 0x02,
41033 + WPA_PSK_AUTH = 0x03,
41034 + WPA2_AUTH = 0x04,
41035 + WPA2_PSK_AUTH = 0x05,
41036 + WPA_AUTH_CCKM = 0x06,
41037 + WPA2_AUTH_CCKM = 0x07,
41038 +} AUTH_MODE;
41039 +
41040 +typedef enum {
41041 + NONE_CRYPT = 0x01,
41042 + WEP_CRYPT = 0x02,
41043 + TKIP_CRYPT = 0x03,
41044 + AES_CRYPT = 0x04,
41045 +} CRYPTO_TYPE;
41046 +
41047 +#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT
41048 +#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1)
41049 +
41050 +#define WMI_MIN_KEY_INDEX 0
41051 +#define WMI_MAX_KEY_INDEX 3
41052 +
41053 +#define WMI_MAX_KEY_LEN 32
41054 +
41055 +#define WMI_MAX_SSID_LEN 32
41056 +
41057 +typedef enum {
41058 + CONNECT_ASSOC_POLICY_USER = 0x0001,
41059 + CONNECT_SEND_REASSOC = 0x0002,
41060 + CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004,
41061 + CONNECT_PROFILE_MATCH_DONE = 0x0008,
41062 + CONNECT_IGNORE_AAC_BEACON = 0x0010,
41063 + CONNECT_CSA_FOLLOW_BSS = 0x0020,
41064 +} WMI_CONNECT_CTRL_FLAGS_BITS;
41065 +
41066 +#define DEFAULT_CONNECT_CTRL_FLAGS (CONNECT_CSA_FOLLOW_BSS)
41067 +
41068 +typedef PREPACK struct {
41069 + A_UINT8 networkType;
41070 + A_UINT8 dot11AuthMode;
41071 + A_UINT8 authMode;
41072 + A_UINT8 pairwiseCryptoType;
41073 + A_UINT8 pairwiseCryptoLen;
41074 + A_UINT8 groupCryptoType;
41075 + A_UINT8 groupCryptoLen;
41076 + A_UINT8 ssidLength;
41077 + A_UCHAR ssid[WMI_MAX_SSID_LEN];
41078 + A_UINT16 channel;
41079 + A_UINT8 bssid[ATH_MAC_LEN];
41080 + A_UINT32 ctrl_flags;
41081 +} POSTPACK WMI_CONNECT_CMD;
41082 +
41083 +/*
41084 + * WMI_RECONNECT_CMDID
41085 + */
41086 +typedef PREPACK struct {
41087 + A_UINT16 channel; /* hint */
41088 + A_UINT8 bssid[ATH_MAC_LEN]; /* mandatory if set */
41089 +} POSTPACK WMI_RECONNECT_CMD;
41090 +
41091 +/*
41092 + * WMI_ADD_CIPHER_KEY_CMDID
41093 + */
41094 +typedef enum {
41095 + PAIRWISE_USAGE = 0x00,
41096 + GROUP_USAGE = 0x01,
41097 + TX_USAGE = 0x02, /* default Tx Key - Static WEP only */
41098 +} KEY_USAGE;
41099 +
41100 +/*
41101 + * Bit Flag
41102 + * Bit 0 - Initialise TSC - default is Initialize
41103 + */
41104 +#define KEY_OP_INIT_TSC 0x01
41105 +#define KEY_OP_INIT_RSC 0x02
41106 +
41107 +#define KEY_OP_INIT_VAL 0x03 /* Default Initialise the TSC & RSC */
41108 +#define KEY_OP_VALID_MASK 0x03
41109 +
41110 +typedef PREPACK struct {
41111 + A_UINT8 keyIndex;
41112 + A_UINT8 keyType;
41113 + A_UINT8 keyUsage; /* KEY_USAGE */
41114 + A_UINT8 keyLength;
41115 + A_UINT8 keyRSC[8]; /* key replay sequence counter */
41116 + A_UINT8 key[WMI_MAX_KEY_LEN];
41117 + A_UINT8 key_op_ctrl; /* Additional Key Control information */
41118 +} POSTPACK WMI_ADD_CIPHER_KEY_CMD;
41119 +
41120 +/*
41121 + * WMI_DELETE_CIPHER_KEY_CMDID
41122 + */
41123 +typedef PREPACK struct {
41124 + A_UINT8 keyIndex;
41125 +} POSTPACK WMI_DELETE_CIPHER_KEY_CMD;
41126 +
41127 +#define WMI_KRK_LEN 16
41128 +/*
41129 + * WMI_ADD_KRK_CMDID
41130 + */
41131 +typedef PREPACK struct {
41132 + A_UINT8 krk[WMI_KRK_LEN];
41133 +} POSTPACK WMI_ADD_KRK_CMD;
41134 +
41135 +/*
41136 + * WMI_SET_TKIP_COUNTERMEASURES_CMDID
41137 + */
41138 +typedef enum {
41139 + WMI_TKIP_CM_DISABLE = 0x0,
41140 + WMI_TKIP_CM_ENABLE = 0x1,
41141 +} WMI_TKIP_CM_CONTROL;
41142 +
41143 +typedef PREPACK struct {
41144 + A_UINT8 cm_en; /* WMI_TKIP_CM_CONTROL */
41145 +} POSTPACK WMI_SET_TKIP_COUNTERMEASURES_CMD;
41146 +
41147 +/*
41148 + * WMI_SET_PMKID_CMDID
41149 + */
41150 +
41151 +#define WMI_PMKID_LEN 16
41152 +
41153 +typedef enum {
41154 + PMKID_DISABLE = 0,
41155 + PMKID_ENABLE = 1,
41156 +} PMKID_ENABLE_FLG;
41157 +
41158 +typedef PREPACK struct {
41159 + A_UINT8 bssid[ATH_MAC_LEN];
41160 + A_UINT8 enable; /* PMKID_ENABLE_FLG */
41161 + A_UINT8 pmkid[WMI_PMKID_LEN];
41162 +} POSTPACK WMI_SET_PMKID_CMD;
41163 +
41164 +/*
41165 + * WMI_START_SCAN_CMD
41166 + */
41167 +typedef enum {
41168 + WMI_LONG_SCAN = 0,
41169 + WMI_SHORT_SCAN = 1,
41170 +} WMI_SCAN_TYPE;
41171 +
41172 +typedef PREPACK struct {
41173 + A_BOOL forceFgScan;
41174 + A_BOOL isLegacy; /* For Legacy Cisco AP compatibility */
41175 + A_UINT32 homeDwellTime; /* Maximum duration in the home channel(milliseconds) */
41176 + A_UINT32 forceScanInterval; /* Time interval between scans (milliseconds)*/
41177 + A_UINT8 scanType; /* WMI_SCAN_TYPE */
41178 +} POSTPACK WMI_START_SCAN_CMD;
41179 +
41180 +/*
41181 + * WMI_SET_SCAN_PARAMS_CMDID
41182 + */
41183 +#define WMI_SHORTSCANRATIO_DEFAULT 3
41184 +typedef enum {
41185 + CONNECT_SCAN_CTRL_FLAGS = 0x01, /* set if can scan in the Connect cmd */
41186 + SCAN_CONNECTED_CTRL_FLAGS = 0x02, /* set if scan for the SSID it is */
41187 + /* already connected to */
41188 + ACTIVE_SCAN_CTRL_FLAGS = 0x04, /* set if enable active scan */
41189 + ROAM_SCAN_CTRL_FLAGS = 0x08, /* set if enable roam scan when bmiss and lowrssi */
41190 + REPORT_BSSINFO_CTRL_FLAGS = 0x10, /* set if follows customer BSSINFO reporting rule */
41191 + ENABLE_AUTO_CTRL_FLAGS = 0x20, /* if disabled, target doesn't
41192 + scan after a disconnect event */
41193 + ENABLE_SCAN_ABORT_EVENT = 0x40 /* Scan complete event with canceled status will be generated when a scan is prempted before it gets completed */
41194 +
41195 +} WMI_SCAN_CTRL_FLAGS_BITS;
41196 +
41197 +#define CAN_SCAN_IN_CONNECT(flags) (flags & CONNECT_SCAN_CTRL_FLAGS)
41198 +#define CAN_SCAN_CONNECTED(flags) (flags & SCAN_CONNECTED_CTRL_FLAGS)
41199 +#define ENABLE_ACTIVE_SCAN(flags) (flags & ACTIVE_SCAN_CTRL_FLAGS)
41200 +#define ENABLE_ROAM_SCAN(flags) (flags & ROAM_SCAN_CTRL_FLAGS)
41201 +#define CONFIG_REPORT_BSSINFO(flags) (flags & REPORT_BSSINFO_CTRL_FLAGS)
41202 +#define IS_AUTO_SCAN_ENABLED(flags) (flags & ENABLE_AUTO_CTRL_FLAGS)
41203 +#define SCAN_ABORT_EVENT_ENABLED(flags) (flags & ENABLE_SCAN_ABORT_EVENT)
41204 +
41205 +#define DEFAULT_SCAN_CTRL_FLAGS (CONNECT_SCAN_CTRL_FLAGS| SCAN_CONNECTED_CTRL_FLAGS| ACTIVE_SCAN_CTRL_FLAGS| ROAM_SCAN_CTRL_FLAGS | ENABLE_AUTO_CTRL_FLAGS)
41206 +
41207 +
41208 +typedef PREPACK struct {
41209 + A_UINT16 fg_start_period; /* seconds */
41210 + A_UINT16 fg_end_period; /* seconds */
41211 + A_UINT16 bg_period; /* seconds */
41212 + A_UINT16 maxact_chdwell_time; /* msec */
41213 + A_UINT16 pas_chdwell_time; /* msec */
41214 + A_UINT8 shortScanRatio; /* how many shorts scan for one long */
41215 + A_UINT8 scanCtrlFlags;
41216 + A_UINT16 minact_chdwell_time; /* msec */
41217 + A_UINT32 max_dfsch_act_time; /* msecs */
41218 +} POSTPACK WMI_SCAN_PARAMS_CMD;
41219 +
41220 +/*
41221 + * WMI_SET_BSS_FILTER_CMDID
41222 + */
41223 +typedef enum {
41224 + NONE_BSS_FILTER = 0x0, /* no beacons forwarded */
41225 + ALL_BSS_FILTER, /* all beacons forwarded */
41226 + PROFILE_FILTER, /* only beacons matching profile */
41227 + ALL_BUT_PROFILE_FILTER, /* all but beacons matching profile */
41228 + CURRENT_BSS_FILTER, /* only beacons matching current BSS */
41229 + ALL_BUT_BSS_FILTER, /* all but beacons matching BSS */
41230 + PROBED_SSID_FILTER, /* beacons matching probed ssid */
41231 + LAST_BSS_FILTER, /* marker only */
41232 +} WMI_BSS_FILTER;
41233 +
41234 +typedef PREPACK struct {
41235 + A_UINT8 bssFilter; /* see WMI_BSS_FILTER */
41236 + A_UINT32 ieMask;
41237 +} POSTPACK WMI_BSS_FILTER_CMD;
41238 +
41239 +/*
41240 + * WMI_SET_PROBED_SSID_CMDID
41241 + */
41242 +#define MAX_PROBED_SSID_INDEX 5
41243 +
41244 +typedef enum {
41245 + DISABLE_SSID_FLAG = 0, /* disables entry */
41246 + SPECIFIC_SSID_FLAG = 0x01, /* probes specified ssid */
41247 + ANY_SSID_FLAG = 0x02, /* probes for any ssid */
41248 +} WMI_SSID_FLAG;
41249 +
41250 +typedef PREPACK struct {
41251 + A_UINT8 entryIndex; /* 0 to MAX_PROBED_SSID_INDEX */
41252 + A_UINT8 flag; /* WMI_SSID_FLG */
41253 + A_UINT8 ssidLength;
41254 + A_UINT8 ssid[32];
41255 +} POSTPACK WMI_PROBED_SSID_CMD;
41256 +
41257 +/*
41258 + * WMI_SET_LISTEN_INT_CMDID
41259 + * The Listen interval is between 15 and 3000 TUs
41260 + */
41261 +#define MIN_LISTEN_INTERVAL 15
41262 +#define MAX_LISTEN_INTERVAL 5000
41263 +#define MIN_LISTEN_BEACONS 1
41264 +#define MAX_LISTEN_BEACONS 50
41265 +
41266 +typedef PREPACK struct {
41267 + A_UINT16 listenInterval;
41268 + A_UINT16 numBeacons;
41269 +} POSTPACK WMI_LISTEN_INT_CMD;
41270 +
41271 +/*
41272 + * WMI_SET_BEACON_INT_CMDID
41273 + */
41274 +typedef PREPACK struct {
41275 + A_UINT16 beaconInterval;
41276 +} POSTPACK WMI_BEACON_INT_CMD;
41277 +
41278 +/*
41279 + * WMI_SET_BMISS_TIME_CMDID
41280 + * valid values are between 1000 and 5000 TUs
41281 + */
41282 +
41283 +#define MIN_BMISS_TIME 1000
41284 +#define MAX_BMISS_TIME 5000
41285 +#define MIN_BMISS_BEACONS 1
41286 +#define MAX_BMISS_BEACONS 50
41287 +
41288 +typedef PREPACK struct {
41289 + A_UINT16 bmissTime;
41290 + A_UINT16 numBeacons;
41291 +} POSTPACK WMI_BMISS_TIME_CMD;
41292 +
41293 +/*
41294 + * WMI_SET_POWER_MODE_CMDID
41295 + */
41296 +typedef enum {
41297 + REC_POWER = 0x01,
41298 + MAX_PERF_POWER,
41299 +} WMI_POWER_MODE;
41300 +
41301 +typedef PREPACK struct {
41302 + A_UINT8 powerMode; /* WMI_POWER_MODE */
41303 +} POSTPACK WMI_POWER_MODE_CMD;
41304 +
41305 +/*
41306 + * WMI_SET_POWER_PARAMS_CMDID
41307 + */
41308 +typedef enum {
41309 + IGNORE_DTIM = 0x01,
41310 + NORMAL_DTIM = 0x02,
41311 + STICK_DTIM = 0x03,
41312 +} WMI_DTIM_POLICY;
41313 +
41314 +typedef PREPACK struct {
41315 + A_UINT16 idle_period; /* msec */
41316 + A_UINT16 pspoll_number;
41317 + A_UINT16 dtim_policy;
41318 +} POSTPACK WMI_POWER_PARAMS_CMD;
41319 +
41320 +typedef PREPACK struct {
41321 + A_UINT8 power_saving;
41322 + A_UINT8 ttl; /* number of beacon periods */
41323 + A_UINT16 atim_windows; /* msec */
41324 + A_UINT16 timeout_value; /* msec */
41325 +} POSTPACK WMI_IBSS_PM_CAPS_CMD;
41326 +
41327 +/*
41328 + * WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID
41329 + */
41330 +typedef enum {
41331 + IGNORE_TIM_ALL_QUEUES_APSD = 0,
41332 + PROCESS_TIM_ALL_QUEUES_APSD = 1,
41333 + IGNORE_TIM_SIMULATED_APSD = 2,
41334 + PROCESS_TIM_SIMULATED_APSD = 3,
41335 +} APSD_TIM_POLICY;
41336 +
41337 +typedef PREPACK struct {
41338 + A_UINT16 psPollTimeout; /* msec */
41339 + A_UINT16 triggerTimeout; /* msec */
41340 + A_UINT32 apsdTimPolicy; /* TIM behavior with ques APSD enabled. Default is IGNORE_TIM_ALL_QUEUES_APSD */
41341 + A_UINT32 simulatedAPSDTimPolicy; /* TIM behavior with simulated APSD enabled. Default is PROCESS_TIM_SIMULATED_APSD */
41342 +} POSTPACK WMI_POWERSAVE_TIMERS_POLICY_CMD;
41343 +
41344 +/*
41345 + * WMI_SET_VOICE_PKT_SIZE_CMDID
41346 + */
41347 +typedef PREPACK struct {
41348 + A_UINT16 voicePktSize;
41349 +} POSTPACK WMI_SET_VOICE_PKT_SIZE_CMD;
41350 +
41351 +/*
41352 + * WMI_SET_MAX_SP_LEN_CMDID
41353 + */
41354 +typedef enum {
41355 + DELIVER_ALL_PKT = 0x0,
41356 + DELIVER_2_PKT = 0x1,
41357 + DELIVER_4_PKT = 0x2,
41358 + DELIVER_6_PKT = 0x3,
41359 +} APSD_SP_LEN_TYPE;
41360 +
41361 +typedef PREPACK struct {
41362 + A_UINT8 maxSPLen;
41363 +} POSTPACK WMI_SET_MAX_SP_LEN_CMD;
41364 +
41365 +/*
41366 + * WMI_SET_DISC_TIMEOUT_CMDID
41367 + */
41368 +typedef PREPACK struct {
41369 + A_UINT8 disconnectTimeout; /* seconds */
41370 +} POSTPACK WMI_DISC_TIMEOUT_CMD;
41371 +
41372 +typedef enum {
41373 + UPLINK_TRAFFIC = 0,
41374 + DNLINK_TRAFFIC = 1,
41375 + BIDIR_TRAFFIC = 2,
41376 +} DIR_TYPE;
41377 +
41378 +typedef enum {
41379 + DISABLE_FOR_THIS_AC = 0,
41380 + ENABLE_FOR_THIS_AC = 1,
41381 + ENABLE_FOR_ALL_AC = 2,
41382 +} VOICEPS_CAP_TYPE;
41383 +
41384 +typedef enum {
41385 + TRAFFIC_TYPE_APERIODIC = 0,
41386 + TRAFFIC_TYPE_PERIODIC = 1,
41387 +}TRAFFIC_TYPE;
41388 +
41389 +/*
41390 + * WMI_CREATE_PSTREAM_CMDID
41391 + */
41392 +typedef PREPACK struct {
41393 + A_UINT32 minServiceInt; /* in milli-sec */
41394 + A_UINT32 maxServiceInt; /* in milli-sec */
41395 + A_UINT32 inactivityInt; /* in milli-sec */
41396 + A_UINT32 suspensionInt; /* in milli-sec */
41397 + A_UINT32 serviceStartTime;
41398 + A_UINT32 minDataRate; /* in bps */
41399 + A_UINT32 meanDataRate; /* in bps */
41400 + A_UINT32 peakDataRate; /* in bps */
41401 + A_UINT32 maxBurstSize;
41402 + A_UINT32 delayBound;
41403 + A_UINT32 minPhyRate; /* in bps */
41404 + A_UINT32 sba;
41405 + A_UINT32 mediumTime;
41406 + A_UINT16 nominalMSDU; /* in octects */
41407 + A_UINT16 maxMSDU; /* in octects */
41408 + A_UINT8 trafficClass;
41409 + A_UINT8 trafficType; /* TRAFFIC_TYPE */
41410 + A_UINT8 trafficDirection; /* TRAFFIC_DIR */
41411 + A_UINT8 voicePSCapability; /* VOICEPS_CAP_TYPE */
41412 + A_UINT8 tsid;
41413 + A_UINT8 userPriority; /* 802.1D user priority */
41414 +} POSTPACK WMI_CREATE_PSTREAM_CMD;
41415 +
41416 +/*
41417 + * WMI_DELETE_PSTREAM_CMDID
41418 + */
41419 +typedef PREPACK struct {
41420 + A_UINT8 trafficClass;
41421 + A_UINT8 tsid;
41422 +} POSTPACK WMI_DELETE_PSTREAM_CMD;
41423 +
41424 +/*
41425 + * WMI_SET_CHANNEL_PARAMS_CMDID
41426 + */
41427 +typedef enum {
41428 + WMI_11A_MODE = 0x1,
41429 + WMI_11G_MODE = 0x2,
41430 + WMI_11AG_MODE = 0x3,
41431 + WMI_11B_MODE = 0x4,
41432 + WMI_11GONLY_MODE = 0x5,
41433 +} WMI_PHY_MODE;
41434 +
41435 +#define WMI_MAX_CHANNELS 32
41436 +
41437 +typedef PREPACK struct {
41438 + A_UINT8 reserved1;
41439 + A_UINT8 scanParam; /* set if enable scan */
41440 + A_UINT8 phyMode; /* see WMI_PHY_MODE */
41441 + A_UINT8 numChannels; /* how many channels follow */
41442 + A_UINT16 channelList[1]; /* channels in Mhz */
41443 +} POSTPACK WMI_CHANNEL_PARAMS_CMD;
41444 +
41445 +
41446 +/*
41447 + * WMI_RSSI_THRESHOLD_PARAMS_CMDID
41448 + * Setting the polltime to 0 would disable polling.
41449 + * Threshold values are in the ascending order, and should agree to:
41450 + * (lowThreshold_lowerVal < lowThreshold_upperVal < highThreshold_lowerVal
41451 + * < highThreshold_upperVal)
41452 + */
41453 +
41454 +typedef PREPACK struct WMI_RSSI_THRESHOLD_PARAMS{
41455 + A_UINT32 pollTime; /* Polling time as a factor of LI */
41456 + A_INT16 thresholdAbove1_Val; /* lowest of upper */
41457 + A_INT16 thresholdAbove2_Val;
41458 + A_INT16 thresholdAbove3_Val;
41459 + A_INT16 thresholdAbove4_Val;
41460 + A_INT16 thresholdAbove5_Val;
41461 + A_INT16 thresholdAbove6_Val; /* highest of upper */
41462 + A_INT16 thresholdBelow1_Val; /* lowest of bellow */
41463 + A_INT16 thresholdBelow2_Val;
41464 + A_INT16 thresholdBelow3_Val;
41465 + A_INT16 thresholdBelow4_Val;
41466 + A_INT16 thresholdBelow5_Val;
41467 + A_INT16 thresholdBelow6_Val; /* highest of bellow */
41468 + A_UINT8 weight; /* "alpha" */
41469 + A_UINT8 reserved[3];
41470 +} POSTPACK WMI_RSSI_THRESHOLD_PARAMS_CMD;
41471 +
41472 +/*
41473 + * WMI_SNR_THRESHOLD_PARAMS_CMDID
41474 + * Setting the polltime to 0 would disable polling.
41475 + */
41476 +
41477 +typedef PREPACK struct WMI_SNR_THRESHOLD_PARAMS{
41478 + A_UINT32 pollTime; /* Polling time as a factor of LI */
41479 + A_UINT8 weight; /* "alpha" */
41480 + A_UINT8 thresholdAbove1_Val; /* lowest of uppper*/
41481 + A_UINT8 thresholdAbove2_Val;
41482 + A_UINT8 thresholdAbove3_Val;
41483 + A_UINT8 thresholdAbove4_Val; /* highest of upper */
41484 + A_UINT8 thresholdBelow1_Val; /* lowest of bellow */
41485 + A_UINT8 thresholdBelow2_Val;
41486 + A_UINT8 thresholdBelow3_Val;
41487 + A_UINT8 thresholdBelow4_Val; /* highest of bellow */
41488 + A_UINT8 reserved[3];
41489 +} POSTPACK WMI_SNR_THRESHOLD_PARAMS_CMD;
41490 +
41491 +/*
41492 + * WMI_LQ_THRESHOLD_PARAMS_CMDID
41493 + */
41494 +typedef PREPACK struct WMI_LQ_THRESHOLD_PARAMS {
41495 + A_UINT8 enable;
41496 + A_UINT8 thresholdAbove1_Val;
41497 + A_UINT8 thresholdAbove2_Val;
41498 + A_UINT8 thresholdAbove3_Val;
41499 + A_UINT8 thresholdAbove4_Val;
41500 + A_UINT8 thresholdBelow1_Val;
41501 + A_UINT8 thresholdBelow2_Val;
41502 + A_UINT8 thresholdBelow3_Val;
41503 + A_UINT8 thresholdBelow4_Val;
41504 + A_UINT8 reserved[3];
41505 +} POSTPACK WMI_LQ_THRESHOLD_PARAMS_CMD;
41506 +
41507 +typedef enum {
41508 + WMI_LPREAMBLE_DISABLED = 0,
41509 + WMI_LPREAMBLE_ENABLED
41510 +} WMI_LPREAMBLE_STATUS;
41511 +
41512 +typedef PREPACK struct {
41513 + A_UINT8 status;
41514 +}POSTPACK WMI_SET_LPREAMBLE_CMD;
41515 +
41516 +typedef PREPACK struct {
41517 + A_UINT16 threshold;
41518 +}POSTPACK WMI_SET_RTS_CMD;
41519 +
41520 +/*
41521 + * WMI_TARGET_ERROR_REPORT_BITMASK_CMDID
41522 + * Sets the error reporting event bitmask in target. Target clears it
41523 + * upon an error. Subsequent errors are counted, but not reported
41524 + * via event, unless the bitmask is set again.
41525 + */
41526 +typedef PREPACK struct {
41527 + A_UINT32 bitmask;
41528 +} POSTPACK WMI_TARGET_ERROR_REPORT_BITMASK;
41529 +
41530 +/*
41531 + * WMI_SET_TX_PWR_CMDID
41532 + */
41533 +typedef PREPACK struct {
41534 + A_UINT8 dbM; /* in dbM units */
41535 +} POSTPACK WMI_SET_TX_PWR_CMD, WMI_TX_PWR_REPLY;
41536 +
41537 +/*
41538 + * WMI_SET_ASSOC_INFO_CMDID
41539 + *
41540 + * A maximum of 2 private IEs can be sent in the [Re]Assoc request.
41541 + * A 3rd one, the CCX version IE can also be set from the host.
41542 + */
41543 +#define WMI_MAX_ASSOC_INFO_TYPE 2
41544 +#define WMI_CCX_VER_IE 2 /* ieType to set CCX Version IE */
41545 +
41546 +#define WMI_MAX_ASSOC_INFO_LEN 240
41547 +
41548 +typedef PREPACK struct {
41549 + A_UINT8 ieType;
41550 + A_UINT8 bufferSize;
41551 + A_UINT8 assocInfo[1]; /* up to WMI_MAX_ASSOC_INFO_LEN */
41552 +} POSTPACK WMI_SET_ASSOC_INFO_CMD;
41553 +
41554 +
41555 +/*
41556 + * WMI_GET_TX_PWR_CMDID does not take any parameters
41557 + */
41558 +
41559 +/*
41560 + * WMI_ADD_BAD_AP_CMDID
41561 + */
41562 +#define WMI_MAX_BAD_AP_INDEX 1
41563 +
41564 +typedef PREPACK struct {
41565 + A_UINT8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */
41566 + A_UINT8 bssid[ATH_MAC_LEN];
41567 +} POSTPACK WMI_ADD_BAD_AP_CMD;
41568 +
41569 +/*
41570 + * WMI_DELETE_BAD_AP_CMDID
41571 + */
41572 +typedef PREPACK struct {
41573 + A_UINT8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */
41574 +} POSTPACK WMI_DELETE_BAD_AP_CMD;
41575 +
41576 +/*
41577 + * WMI_SET_ACCESS_PARAMS_CMDID
41578 + */
41579 +#define WMI_DEFAULT_TXOP_ACPARAM 0 /* implies one MSDU */
41580 +#define WMI_DEFAULT_ECWMIN_ACPARAM 4 /* corresponds to CWmin of 15 */
41581 +#define WMI_DEFAULT_ECWMAX_ACPARAM 10 /* corresponds to CWmax of 1023 */
41582 +#define WMI_MAX_CW_ACPARAM 15 /* maximum eCWmin or eCWmax */
41583 +#define WMI_DEFAULT_AIFSN_ACPARAM 2
41584 +#define WMI_MAX_AIFSN_ACPARAM 15
41585 +typedef PREPACK struct {
41586 + A_UINT16 txop; /* in units of 32 usec */
41587 + A_UINT8 eCWmin;
41588 + A_UINT8 eCWmax;
41589 + A_UINT8 aifsn;
41590 +} POSTPACK WMI_SET_ACCESS_PARAMS_CMD;
41591 +
41592 +
41593 +/*
41594 + * WMI_SET_RETRY_LIMITS_CMDID
41595 + *
41596 + * This command is used to customize the number of retries the
41597 + * wlan device will perform on a given frame.
41598 + */
41599 +#define WMI_MIN_RETRIES 2
41600 +#define WMI_MAX_RETRIES 13
41601 +typedef enum {
41602 + MGMT_FRAMETYPE = 0,
41603 + CONTROL_FRAMETYPE = 1,
41604 + DATA_FRAMETYPE = 2
41605 +} WMI_FRAMETYPE;
41606 +
41607 +typedef PREPACK struct {
41608 + A_UINT8 frameType; /* WMI_FRAMETYPE */
41609 + A_UINT8 trafficClass; /* applies only to DATA_FRAMETYPE */
41610 + A_UINT8 maxRetries;
41611 + A_UINT8 enableNotify;
41612 +} POSTPACK WMI_SET_RETRY_LIMITS_CMD;
41613 +
41614 +/*
41615 + * WMI_SET_ROAM_CTRL_CMDID
41616 + *
41617 + * This command is used to influence the Roaming behaviour
41618 + * Set the host biases of the BSSs before setting the roam mode as bias
41619 + * based.
41620 + */
41621 +
41622 +/*
41623 + * Different types of Roam Control
41624 + */
41625 +
41626 +typedef enum {
41627 + WMI_FORCE_ROAM = 1, /* Roam to the specified BSSID */
41628 + WMI_SET_ROAM_MODE = 2, /* default ,progd bias, no roam */
41629 + WMI_SET_HOST_BIAS = 3, /* Set the Host Bias */
41630 + WMI_SET_LOWRSSI_SCAN_PARAMS = 4, /* Set lowrssi Scan parameters */
41631 +} WMI_ROAM_CTRL_TYPE;
41632 +
41633 +#define WMI_MIN_ROAM_CTRL_TYPE WMI_FORCE_ROAM
41634 +#define WMI_MAX_ROAM_CTRL_TYPE WMI_SET_LOWRSSI_SCAN_PARAMS
41635 +
41636 +/*
41637 + * ROAM MODES
41638 + */
41639 +
41640 +typedef enum {
41641 + WMI_DEFAULT_ROAM_MODE = 1, /* RSSI based ROAM */
41642 + WMI_HOST_BIAS_ROAM_MODE = 2, /* HOST BIAS based ROAM */
41643 + WMI_LOCK_BSS_MODE = 3 /* Lock to the Current BSS - no Roam */
41644 +} WMI_ROAM_MODE;
41645 +
41646 +/*
41647 + * BSS HOST BIAS INFO
41648 + */
41649 +
41650 +typedef PREPACK struct {
41651 + A_UINT8 bssid[ATH_MAC_LEN];
41652 + A_INT8 bias;
41653 +} POSTPACK WMI_BSS_BIAS;
41654 +
41655 +typedef PREPACK struct {
41656 + A_UINT8 numBss;
41657 + WMI_BSS_BIAS bssBias[1];
41658 +} POSTPACK WMI_BSS_BIAS_INFO;
41659 +
41660 +typedef PREPACK struct WMI_LOWRSSI_SCAN_PARAMS {
41661 + A_UINT16 lowrssi_scan_period;
41662 + A_INT16 lowrssi_scan_threshold;
41663 + A_INT16 lowrssi_roam_threshold;
41664 + A_UINT8 roam_rssi_floor;
41665 + A_UINT8 reserved[1]; /* For alignment */
41666 +} POSTPACK WMI_LOWRSSI_SCAN_PARAMS;
41667 +
41668 +typedef PREPACK struct {
41669 + PREPACK union {
41670 + A_UINT8 bssid[ATH_MAC_LEN]; /* WMI_FORCE_ROAM */
41671 + A_UINT8 roamMode; /* WMI_SET_ROAM_MODE */
41672 + WMI_BSS_BIAS_INFO bssBiasInfo; /* WMI_SET_HOST_BIAS */
41673 + WMI_LOWRSSI_SCAN_PARAMS lrScanParams;
41674 + } POSTPACK info;
41675 + A_UINT8 roamCtrlType ;
41676 +} POSTPACK WMI_SET_ROAM_CTRL_CMD;
41677 +
41678 +/*
41679 + * WMI_ENABLE_RM_CMDID
41680 + */
41681 +typedef PREPACK struct {
41682 + A_BOOL enable_radio_measurements;
41683 +} POSTPACK WMI_ENABLE_RM_CMD;
41684 +
41685 +/*
41686 + * WMI_SET_MAX_OFFHOME_DURATION_CMDID
41687 + */
41688 +typedef PREPACK struct {
41689 + A_UINT8 max_offhome_duration;
41690 +} POSTPACK WMI_SET_MAX_OFFHOME_DURATION_CMD;
41691 +
41692 +typedef PREPACK struct {
41693 + A_UINT32 frequency;
41694 + A_UINT8 threshold;
41695 +} POSTPACK WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD;
41696 +
41697 +typedef enum {
41698 + BT_STREAM_UNDEF = 0,
41699 + BT_STREAM_SCO, /* SCO stream */
41700 + BT_STREAM_A2DP, /* A2DP stream */
41701 + BT_STREAM_MAX
41702 +} BT_STREAM_TYPE;
41703 +
41704 +typedef enum {
41705 + BT_PARAM_SCO = 1, /* SCO stream parameters */
41706 + BT_PARAM_A2DP, /* A2DP stream parameters */
41707 + BT_PARAM_MISC, /* miscellaneous parameters */
41708 + BT_PARAM_REGS, /* co-existence register parameters */
41709 + BT_PARAM_MAX
41710 +} BT_PARAM_TYPE;
41711 +
41712 +typedef enum {
41713 + BT_STATUS_UNDEF = 0,
41714 + BT_STATUS_START,
41715 + BT_STATUS_STOP,
41716 + BT_STATUS_RESUME,
41717 + BT_STATUS_SUSPEND,
41718 + BT_STATUS_MAX
41719 +} BT_STREAM_STATUS;
41720 +
41721 +typedef PREPACK struct {
41722 + A_UINT8 streamType;
41723 + A_UINT8 status;
41724 +} POSTPACK WMI_SET_BT_STATUS_CMD;
41725 +
41726 +typedef PREPACK struct {
41727 + A_UINT8 noSCOPkts;
41728 + A_UINT8 pspollTimeout;
41729 + A_UINT8 stompbt;
41730 +} POSTPACK BT_PARAMS_SCO;
41731 +
41732 +typedef PREPACK struct {
41733 + A_UINT32 period;
41734 + A_UINT32 dutycycle;
41735 + A_UINT8 stompbt;
41736 +} POSTPACK BT_PARAMS_A2DP;
41737 +
41738 +typedef PREPACK struct {
41739 + A_UINT32 mode;
41740 + A_UINT32 scoWghts;
41741 + A_UINT32 a2dpWghts;
41742 + A_UINT32 genWghts;
41743 + A_UINT32 mode2;
41744 + A_UINT8 setVal;
41745 +} POSTPACK BT_COEX_REGS;
41746 +
41747 +typedef enum {
41748 + WLAN_PROTECT_POLICY = 1,
41749 + WLAN_COEX_CTRL_FLAGS
41750 +} BT_PARAMS_MISC_TYPE;
41751 +
41752 +typedef enum {
41753 + WLAN_PROTECT_PER_STREAM = 0x01, /* default */
41754 + WLAN_PROTECT_ANY_TX = 0x02
41755 +} WLAN_PROTECT_FLAGS;
41756 +
41757 +
41758 +#define WLAN_DISABLE_COEX_IN_DISCONNECT 0x01 /* default */
41759 +#define WLAN_KEEP_COEX_IN_DISCONNECT 0x02
41760 +#define WLAN_STOMPBT_IN_DISCONNECT 0x04
41761 +
41762 +#define WLAN_DISABLE_COEX_IN_ROAM 0x10 /* default */
41763 +#define WLAN_KEEP_COEX_IN_ROAM 0x20
41764 +#define WLAN_STOMPBT_IN_ROAM 0x40
41765 +
41766 +#define WLAN_DISABLE_COEX_IN_SCAN 0x100 /* default */
41767 +#define WLAN_KEEP_COEX_IN_SCAN 0x200
41768 +#define WLAN_STOMPBT_IN_SCAN 0x400
41769 +
41770 +#define WLAN_DISABLE_COEX_BT_OFF 0x1000 /* default */
41771 +#define WLAN_KEEP_COEX_BT_OFF 0x2000
41772 +#define WLAN_STOMPBT_BT_OFF 0x4000
41773 +
41774 +typedef PREPACK struct {
41775 + A_UINT32 period;
41776 + A_UINT32 dutycycle;
41777 + A_UINT8 stompbt;
41778 + A_UINT8 policy;
41779 +} POSTPACK WLAN_PROTECT_POLICY_TYPE;
41780 +
41781 +typedef PREPACK struct {
41782 + PREPACK union {
41783 + WLAN_PROTECT_POLICY_TYPE protectParams;
41784 + A_UINT16 wlanCtrlFlags;
41785 + } POSTPACK info;
41786 + A_UINT8 paramType;
41787 +} POSTPACK BT_PARAMS_MISC;
41788 +
41789 +typedef PREPACK struct {
41790 + PREPACK union {
41791 + BT_PARAMS_SCO scoParams;
41792 + BT_PARAMS_A2DP a2dpParams;
41793 + BT_PARAMS_MISC miscParams;
41794 + BT_COEX_REGS regs;
41795 + } POSTPACK info;
41796 + A_UINT8 paramType;
41797 +} POSTPACK WMI_SET_BT_PARAMS_CMD;
41798 +
41799 +/*
41800 + * Command Replies
41801 + */
41802 +
41803 +/*
41804 + * WMI_GET_CHANNEL_LIST_CMDID reply
41805 + */
41806 +typedef PREPACK struct {
41807 + A_UINT8 reserved1;
41808 + A_UINT8 numChannels; /* number of channels in reply */
41809 + A_UINT16 channelList[1]; /* channel in Mhz */
41810 +} POSTPACK WMI_CHANNEL_LIST_REPLY;
41811 +
41812 +typedef enum {
41813 + A_SUCCEEDED = A_OK,
41814 + A_FAILED_DELETE_STREAM_DOESNOT_EXIST=250,
41815 + A_SUCCEEDED_MODIFY_STREAM=251,
41816 + A_FAILED_INVALID_STREAM = 252,
41817 + A_FAILED_MAX_THINSTREAMS = 253,
41818 + A_FAILED_CREATE_REMOVE_PSTREAM_FIRST = 254,
41819 +} PSTREAM_REPLY_STATUS;
41820 +
41821 +/*
41822 + * List of Events (target to host)
41823 + */
41824 +typedef enum {
41825 + WMI_READY_EVENTID = 0x1001,
41826 + WMI_CONNECT_EVENTID,
41827 + WMI_DISCONNECT_EVENTID,
41828 + WMI_BSSINFO_EVENTID,
41829 + WMI_CMDERROR_EVENTID,
41830 + WMI_REGDOMAIN_EVENTID,
41831 + WMI_PSTREAM_TIMEOUT_EVENTID,
41832 + WMI_NEIGHBOR_REPORT_EVENTID,
41833 + WMI_TKIP_MICERR_EVENTID,
41834 + WMI_SCAN_COMPLETE_EVENTID,
41835 + WMI_REPORT_STATISTICS_EVENTID,
41836 + WMI_RSSI_THRESHOLD_EVENTID,
41837 + WMI_ERROR_REPORT_EVENTID,
41838 + WMI_OPT_RX_FRAME_EVENTID,
41839 + WMI_REPORT_ROAM_TBL_EVENTID,
41840 + WMI_EXTENSION_EVENTID,
41841 + WMI_CAC_EVENTID,
41842 + WMI_SNR_THRESHOLD_EVENTID,
41843 + WMI_LQ_THRESHOLD_EVENTID,
41844 + WMI_TX_RETRY_ERR_EVENTID,
41845 + WMI_REPORT_ROAM_DATA_EVENTID,
41846 + WMI_TEST_EVENTID,
41847 + WMI_APLIST_EVENTID,
41848 + WMI_GET_WOW_LIST_EVENTID,
41849 + WMI_GET_PMKID_LIST_EVENTID
41850 +} WMI_EVENT_ID;
41851 +
41852 +typedef enum {
41853 + WMI_11A_CAPABILITY = 1,
41854 + WMI_11G_CAPABILITY = 2,
41855 + WMI_11AG_CAPABILITY = 3,
41856 +} WMI_PHY_CAPABILITY;
41857 +
41858 +typedef PREPACK struct {
41859 + A_UINT8 macaddr[ATH_MAC_LEN];
41860 + A_UINT8 phyCapability; /* WMI_PHY_CAPABILITY */
41861 +} POSTPACK WMI_READY_EVENT;
41862 +
41863 +/*
41864 + * Connect Event
41865 + */
41866 +typedef PREPACK struct {
41867 + A_UINT16 channel;
41868 + A_UINT8 bssid[ATH_MAC_LEN];
41869 + A_UINT16 listenInterval;
41870 + A_UINT16 beaconInterval;
41871 + A_UINT32 networkType;
41872 + A_UINT8 beaconIeLen;
41873 + A_UINT8 assocReqLen;
41874 + A_UINT8 assocRespLen;
41875 + A_UINT8 assocInfo[1];
41876 +} POSTPACK WMI_CONNECT_EVENT;
41877 +
41878 +/*
41879 + * Disconnect Event
41880 + */
41881 +typedef enum {
41882 + NO_NETWORK_AVAIL = 0x01,
41883 + LOST_LINK = 0x02, /* bmiss */
41884 + DISCONNECT_CMD = 0x03,
41885 + BSS_DISCONNECTED = 0x04,
41886 + AUTH_FAILED = 0x05,
41887 + ASSOC_FAILED = 0x06,
41888 + NO_RESOURCES_AVAIL = 0x07,
41889 + CSERV_DISCONNECT = 0x08,
41890 + INVALID_PROFILE = 0x0a,
41891 + DOT11H_CHANNEL_SWITCH = 0x0b,
41892 +} WMI_DISCONNECT_REASON;
41893 +
41894 +typedef PREPACK struct {
41895 + A_UINT16 protocolReasonStatus; /* reason code, see 802.11 spec. */
41896 + A_UINT8 bssid[ATH_MAC_LEN]; /* set if known */
41897 + A_UINT8 disconnectReason ; /* see WMI_DISCONNECT_REASON */
41898 + A_UINT8 assocRespLen;
41899 + A_UINT8 assocInfo[1];
41900 +} POSTPACK WMI_DISCONNECT_EVENT;
41901 +
41902 +/*
41903 + * BSS Info Event.
41904 + * Mechanism used to inform host of the presence and characteristic of
41905 + * wireless networks present. Consists of bss info header followed by
41906 + * the beacon or probe-response frame body. The 802.11 header is not included.
41907 + */
41908 +typedef enum {
41909 + BEACON_FTYPE = 0x1,
41910 + PROBERESP_FTYPE,
41911 + ACTION_MGMT_FTYPE,
41912 +} WMI_BI_FTYPE;
41913 +
41914 +enum {
41915 + BSS_ELEMID_CHANSWITCH = 0x01,
41916 + BSS_ELEMID_ATHEROS = 0x02,
41917 +};
41918 +
41919 +typedef PREPACK struct {
41920 + A_UINT16 channel;
41921 + A_UINT8 frameType; /* see WMI_BI_FTYPE */
41922 + A_UINT8 snr;
41923 + A_INT16 rssi;
41924 + A_UINT8 bssid[ATH_MAC_LEN];
41925 + A_UINT32 ieMask;
41926 +} POSTPACK WMI_BSS_INFO_HDR;
41927 +
41928 +/*
41929 + * Command Error Event
41930 + */
41931 +typedef enum {
41932 + INVALID_PARAM = 0x01,
41933 + ILLEGAL_STATE = 0x02,
41934 + INTERNAL_ERROR = 0x03,
41935 +} WMI_ERROR_CODE;
41936 +
41937 +typedef PREPACK struct {
41938 + A_UINT16 commandId;
41939 + A_UINT8 errorCode;
41940 +} POSTPACK WMI_CMD_ERROR_EVENT;
41941 +
41942 +/*
41943 + * New Regulatory Domain Event
41944 + */
41945 +typedef PREPACK struct {
41946 + A_UINT32 regDomain;
41947 +} POSTPACK WMI_REG_DOMAIN_EVENT;
41948 +
41949 +typedef PREPACK struct {
41950 + A_UINT8 trafficClass;
41951 +} POSTPACK WMI_PSTREAM_TIMEOUT_EVENT;
41952 +
41953 +/*
41954 + * The WMI_NEIGHBOR_REPORT Event is generated by the target to inform
41955 + * the host of BSS's it has found that matches the current profile.
41956 + * It can be used by the host to cache PMKs and/to initiate pre-authentication
41957 + * if the BSS supports it. The first bssid is always the current associated
41958 + * BSS.
41959 + * The bssid and bssFlags information repeats according to the number
41960 + * or APs reported.
41961 + */
41962 +typedef enum {
41963 + WMI_DEFAULT_BSS_FLAGS = 0x00,
41964 + WMI_PREAUTH_CAPABLE_BSS = 0x01,
41965 + WMI_PMKID_VALID_BSS = 0x02,
41966 +} WMI_BSS_FLAGS;
41967 +
41968 +typedef PREPACK struct {
41969 + A_UINT8 bssid[ATH_MAC_LEN];
41970 + A_UINT8 bssFlags; /* see WMI_BSS_FLAGS */
41971 +} POSTPACK WMI_NEIGHBOR_INFO;
41972 +
41973 +typedef PREPACK struct {
41974 + A_INT8 numberOfAps;
41975 + WMI_NEIGHBOR_INFO neighbor[1];
41976 +} POSTPACK WMI_NEIGHBOR_REPORT_EVENT;
41977 +
41978 +/*
41979 + * TKIP MIC Error Event
41980 + */
41981 +typedef PREPACK struct {
41982 + A_UINT8 keyid;
41983 + A_UINT8 ismcast;
41984 +} POSTPACK WMI_TKIP_MICERR_EVENT;
41985 +
41986 +/*
41987 + * WMI_SCAN_COMPLETE_EVENTID - no parameters (old), staus parameter (new)
41988 + */
41989 +typedef PREPACK struct {
41990 + A_STATUS status;
41991 +} POSTPACK WMI_SCAN_COMPLETE_EVENT;
41992 +
41993 +#define MAX_OPT_DATA_LEN 1400
41994 +
41995 +/*
41996 + * WMI_SET_ADHOC_BSSID_CMDID
41997 + */
41998 +typedef PREPACK struct {
41999 + A_UINT8 bssid[ATH_MAC_LEN];
42000 +} POSTPACK WMI_SET_ADHOC_BSSID_CMD;
42001 +
42002 +/*
42003 + * WMI_SET_OPT_MODE_CMDID
42004 + */
42005 +typedef enum {
42006 + SPECIAL_OFF,
42007 + SPECIAL_ON,
42008 +} OPT_MODE_TYPE;
42009 +
42010 +typedef PREPACK struct {
42011 + A_UINT8 optMode;
42012 +} POSTPACK WMI_SET_OPT_MODE_CMD;
42013 +
42014 +/*
42015 + * WMI_TX_OPT_FRAME_CMDID
42016 + */
42017 +typedef enum {
42018 + OPT_PROBE_REQ = 0x01,
42019 + OPT_PROBE_RESP = 0x02,
42020 + OPT_CPPP_START = 0x03,
42021 + OPT_CPPP_STOP = 0x04,
42022 +} WMI_OPT_FTYPE;
42023 +
42024 +typedef PREPACK struct {
42025 + A_UINT16 optIEDataLen;
42026 + A_UINT8 frmType;
42027 + A_UINT8 dstAddr[ATH_MAC_LEN];
42028 + A_UINT8 bssid[ATH_MAC_LEN];
42029 + A_UINT8 reserved; /* For alignment */
42030 + A_UINT8 optIEData[1];
42031 +} POSTPACK WMI_OPT_TX_FRAME_CMD;
42032 +
42033 +/*
42034 + * Special frame receive Event.
42035 + * Mechanism used to inform host of the receiption of the special frames.
42036 + * Consists of special frame info header followed by special frame body.
42037 + * The 802.11 header is not included.
42038 + */
42039 +typedef PREPACK struct {
42040 + A_UINT16 channel;
42041 + A_UINT8 frameType; /* see WMI_OPT_FTYPE */
42042 + A_INT8 snr;
42043 + A_UINT8 srcAddr[ATH_MAC_LEN];
42044 + A_UINT8 bssid[ATH_MAC_LEN];
42045 +} POSTPACK WMI_OPT_RX_INFO_HDR;
42046 +
42047 +/*
42048 + * Reporting statistics.
42049 + */
42050 +typedef PREPACK struct {
42051 + A_UINT32 tx_packets;
42052 + A_UINT32 tx_bytes;
42053 + A_UINT32 tx_unicast_pkts;
42054 + A_UINT32 tx_unicast_bytes;
42055 + A_UINT32 tx_multicast_pkts;
42056 + A_UINT32 tx_multicast_bytes;
42057 + A_UINT32 tx_broadcast_pkts;
42058 + A_UINT32 tx_broadcast_bytes;
42059 + A_UINT32 tx_rts_success_cnt;
42060 + A_UINT32 tx_packet_per_ac[4];
42061 + A_UINT32 tx_errors_per_ac[4];
42062 +
42063 + A_UINT32 tx_errors;
42064 + A_UINT32 tx_failed_cnt;
42065 + A_UINT32 tx_retry_cnt;
42066 + A_UINT32 tx_rts_fail_cnt;
42067 + A_INT32 tx_unicast_rate;
42068 +}POSTPACK tx_stats_t;
42069 +
42070 +typedef PREPACK struct {
42071 + A_UINT32 rx_packets;
42072 + A_UINT32 rx_bytes;
42073 + A_UINT32 rx_unicast_pkts;
42074 + A_UINT32 rx_unicast_bytes;
42075 + A_UINT32 rx_multicast_pkts;
42076 + A_UINT32 rx_multicast_bytes;
42077 + A_UINT32 rx_broadcast_pkts;
42078 + A_UINT32 rx_broadcast_bytes;
42079 + A_UINT32 rx_fragment_pkt;
42080 +
42081 + A_UINT32 rx_errors;
42082 + A_UINT32 rx_crcerr;
42083 + A_UINT32 rx_key_cache_miss;
42084 + A_UINT32 rx_decrypt_err;
42085 + A_UINT32 rx_duplicate_frames;
42086 + A_INT32 rx_unicast_rate;
42087 +}POSTPACK rx_stats_t;
42088 +
42089 +typedef PREPACK struct {
42090 + A_UINT32 tkip_local_mic_failure;
42091 + A_UINT32 tkip_counter_measures_invoked;
42092 + A_UINT32 tkip_replays;
42093 + A_UINT32 tkip_format_errors;
42094 + A_UINT32 ccmp_format_errors;
42095 + A_UINT32 ccmp_replays;
42096 +}POSTPACK tkip_ccmp_stats_t;
42097 +
42098 +typedef PREPACK struct {
42099 + A_UINT32 power_save_failure_cnt;
42100 +}POSTPACK pm_stats_t;
42101 +
42102 +typedef PREPACK struct {
42103 + A_UINT32 cs_bmiss_cnt;
42104 + A_UINT32 cs_lowRssi_cnt;
42105 + A_UINT16 cs_connect_cnt;
42106 + A_UINT16 cs_disconnect_cnt;
42107 + A_INT16 cs_aveBeacon_rssi;
42108 + A_UINT16 cs_roam_count;
42109 + A_UINT16 cs_rssi;
42110 + A_UINT8 cs_snr;
42111 + A_UINT8 cs_aveBeacon_snr;
42112 + A_UINT8 cs_lastRoam_msec;
42113 +} POSTPACK cserv_stats_t;
42114 +
42115 +typedef PREPACK struct {
42116 + tx_stats_t tx_stats;
42117 + rx_stats_t rx_stats;
42118 + tkip_ccmp_stats_t tkipCcmpStats;
42119 +}POSTPACK wlan_net_stats_t;
42120 +
42121 +typedef PREPACK struct {
42122 + A_UINT32 wow_num_pkts_dropped;
42123 + A_UINT16 wow_num_events_discarded;
42124 + A_UINT8 wow_num_host_pkt_wakeups;
42125 + A_UINT8 wow_num_host_event_wakeups;
42126 +} POSTPACK wlan_wow_stats_t;
42127 +
42128 +typedef PREPACK struct {
42129 + A_UINT32 lqVal;
42130 + A_INT32 noise_floor_calibation;
42131 + pm_stats_t pmStats;
42132 + wlan_net_stats_t txrxStats;
42133 + wlan_wow_stats_t wowStats;
42134 + cserv_stats_t cservStats;
42135 +} POSTPACK WMI_TARGET_STATS;
42136 +
42137 +/*
42138 + * WMI_RSSI_THRESHOLD_EVENTID.
42139 + * Indicate the RSSI events to host. Events are indicated when we breach a
42140 + * thresold value.
42141 + */
42142 +typedef enum{
42143 + WMI_RSSI_THRESHOLD1_ABOVE = 0,
42144 + WMI_RSSI_THRESHOLD2_ABOVE,
42145 + WMI_RSSI_THRESHOLD3_ABOVE,
42146 + WMI_RSSI_THRESHOLD4_ABOVE,
42147 + WMI_RSSI_THRESHOLD5_ABOVE,
42148 + WMI_RSSI_THRESHOLD6_ABOVE,
42149 + WMI_RSSI_THRESHOLD1_BELOW,
42150 + WMI_RSSI_THRESHOLD2_BELOW,
42151 + WMI_RSSI_THRESHOLD3_BELOW,
42152 + WMI_RSSI_THRESHOLD4_BELOW,
42153 + WMI_RSSI_THRESHOLD5_BELOW,
42154 + WMI_RSSI_THRESHOLD6_BELOW
42155 +}WMI_RSSI_THRESHOLD_VAL;
42156 +
42157 +typedef PREPACK struct {
42158 + A_INT16 rssi;
42159 + A_UINT8 range;
42160 +}POSTPACK WMI_RSSI_THRESHOLD_EVENT;
42161 +
42162 +/*
42163 + * WMI_ERROR_REPORT_EVENTID
42164 + */
42165 +typedef enum{
42166 + WMI_TARGET_PM_ERR_FAIL = 0x00000001,
42167 + WMI_TARGET_KEY_NOT_FOUND = 0x00000002,
42168 + WMI_TARGET_DECRYPTION_ERR = 0x00000004,
42169 + WMI_TARGET_BMISS = 0x00000008,
42170 + WMI_PSDISABLE_NODE_JOIN = 0x00000010,
42171 + WMI_TARGET_COM_ERR = 0x00000020,
42172 + WMI_TARGET_FATAL_ERR = 0x00000040
42173 +} WMI_TARGET_ERROR_VAL;
42174 +
42175 +typedef PREPACK struct {
42176 + A_UINT32 errorVal;
42177 +}POSTPACK WMI_TARGET_ERROR_REPORT_EVENT;
42178 +
42179 +typedef PREPACK struct {
42180 + A_UINT8 retrys;
42181 +}POSTPACK WMI_TX_RETRY_ERR_EVENT;
42182 +
42183 +typedef enum{
42184 + WMI_SNR_THRESHOLD1_ABOVE = 1,
42185 + WMI_SNR_THRESHOLD1_BELOW,
42186 + WMI_SNR_THRESHOLD2_ABOVE,
42187 + WMI_SNR_THRESHOLD2_BELOW,
42188 + WMI_SNR_THRESHOLD3_ABOVE,
42189 + WMI_SNR_THRESHOLD3_BELOW,
42190 + WMI_SNR_THRESHOLD4_ABOVE,
42191 + WMI_SNR_THRESHOLD4_BELOW
42192 +} WMI_SNR_THRESHOLD_VAL;
42193 +
42194 +typedef PREPACK struct {
42195 + A_UINT8 range; /* WMI_SNR_THRESHOLD_VAL */
42196 + A_UINT8 snr;
42197 +}POSTPACK WMI_SNR_THRESHOLD_EVENT;
42198 +
42199 +typedef enum{
42200 + WMI_LQ_THRESHOLD1_ABOVE = 1,
42201 + WMI_LQ_THRESHOLD1_BELOW,
42202 + WMI_LQ_THRESHOLD2_ABOVE,
42203 + WMI_LQ_THRESHOLD2_BELOW,
42204 + WMI_LQ_THRESHOLD3_ABOVE,
42205 + WMI_LQ_THRESHOLD3_BELOW,
42206 + WMI_LQ_THRESHOLD4_ABOVE,
42207 + WMI_LQ_THRESHOLD4_BELOW
42208 +} WMI_LQ_THRESHOLD_VAL;
42209 +
42210 +typedef PREPACK struct {
42211 + A_INT32 lq;
42212 + A_UINT8 range; /* WMI_LQ_THRESHOLD_VAL */
42213 +}POSTPACK WMI_LQ_THRESHOLD_EVENT;
42214 +/*
42215 + * WMI_REPORT_ROAM_TBL_EVENTID
42216 + */
42217 +#define MAX_ROAM_TBL_CAND 5
42218 +
42219 +typedef PREPACK struct {
42220 + A_INT32 roam_util;
42221 + A_UINT8 bssid[ATH_MAC_LEN];
42222 + A_INT8 rssi;
42223 + A_INT8 rssidt;
42224 + A_INT8 last_rssi;
42225 + A_INT8 util;
42226 + A_INT8 bias;
42227 + A_UINT8 reserved; /* For alignment */
42228 +} POSTPACK WMI_BSS_ROAM_INFO;
42229 +
42230 +
42231 +typedef PREPACK struct {
42232 + A_UINT16 roamMode;
42233 + A_UINT16 numEntries;
42234 + WMI_BSS_ROAM_INFO bssRoamInfo[1];
42235 +} POSTPACK WMI_TARGET_ROAM_TBL;
42236 +
42237 +/*
42238 + * WMI_CAC_EVENTID
42239 + */
42240 +typedef enum {
42241 + CAC_INDICATION_ADMISSION = 0x00,
42242 + CAC_INDICATION_ADMISSION_RESP = 0x01,
42243 + CAC_INDICATION_DELETE = 0x02,
42244 + CAC_INDICATION_NO_RESP = 0x03,
42245 +}CAC_INDICATION;
42246 +
42247 +#define WMM_TSPEC_IE_LEN 63
42248 +
42249 +typedef PREPACK struct {
42250 + A_UINT8 ac;
42251 + A_UINT8 cac_indication;
42252 + A_UINT8 statusCode;
42253 + A_UINT8 tspecSuggestion[WMM_TSPEC_IE_LEN];
42254 +}POSTPACK WMI_CAC_EVENT;
42255 +
42256 +/*
42257 + * WMI_APLIST_EVENTID
42258 + */
42259 +
42260 +typedef enum {
42261 + APLIST_VER1 = 1,
42262 +} APLIST_VER;
42263 +
42264 +typedef PREPACK struct {
42265 + A_UINT8 bssid[ATH_MAC_LEN];
42266 + A_UINT16 channel;
42267 +} POSTPACK WMI_AP_INFO_V1;
42268 +
42269 +typedef PREPACK union {
42270 + WMI_AP_INFO_V1 apInfoV1;
42271 +} POSTPACK WMI_AP_INFO;
42272 +
42273 +typedef PREPACK struct {
42274 + A_UINT8 apListVer;
42275 + A_UINT8 numAP;
42276 + WMI_AP_INFO apList[1];
42277 +} POSTPACK WMI_APLIST_EVENT;
42278 +
42279 +/*
42280 + * developer commands
42281 + */
42282 +
42283 +/*
42284 + * WMI_SET_BITRATE_CMDID
42285 + *
42286 + * Get bit rate cmd uses same definition as set bit rate cmd
42287 + */
42288 +typedef enum {
42289 + RATE_AUTO = -1,
42290 + RATE_1Mb = 0,
42291 + RATE_2Mb = 1,
42292 + RATE_5_5Mb = 2,
42293 + RATE_11Mb = 3,
42294 + RATE_6Mb = 4,
42295 + RATE_9Mb = 5,
42296 + RATE_12Mb = 6,
42297 + RATE_18Mb = 7,
42298 + RATE_24Mb = 8,
42299 + RATE_36Mb = 9,
42300 + RATE_48Mb = 10,
42301 + RATE_54Mb = 11,
42302 +} WMI_BIT_RATE;
42303 +
42304 +typedef PREPACK struct {
42305 + A_INT8 rateIndex; /* see WMI_BIT_RATE */
42306 +} POSTPACK WMI_BIT_RATE_CMD, WMI_BIT_RATE_REPLY;
42307 +
42308 +/*
42309 + * WMI_SET_FIXRATES_CMDID
42310 + *
42311 + * Get fix rates cmd uses same definition as set fix rates cmd
42312 + */
42313 +typedef enum {
42314 + FIX_RATE_1Mb = 0x1,
42315 + FIX_RATE_2Mb = 0x2,
42316 + FIX_RATE_5_5Mb = 0x4,
42317 + FIX_RATE_11Mb = 0x8,
42318 + FIX_RATE_6Mb = 0x10,
42319 + FIX_RATE_9Mb = 0x20,
42320 + FIX_RATE_12Mb = 0x40,
42321 + FIX_RATE_18Mb = 0x80,
42322 + FIX_RATE_24Mb = 0x100,
42323 + FIX_RATE_36Mb = 0x200,
42324 + FIX_RATE_48Mb = 0x400,
42325 + FIX_RATE_54Mb = 0x800,
42326 +} WMI_FIX_RATES_MASK;
42327 +
42328 +typedef PREPACK struct {
42329 + A_UINT16 fixRateMask; /* see WMI_BIT_RATE */
42330 +} POSTPACK WMI_FIX_RATES_CMD, WMI_FIX_RATES_REPLY;
42331 +
42332 +/*
42333 + * WMI_SET_RECONNECT_AUTH_MODE_CMDID
42334 + *
42335 + * Set authentication mode
42336 + */
42337 +typedef enum {
42338 + RECONN_DO_AUTH = 0x00,
42339 + RECONN_NOT_AUTH = 0x01
42340 +} WMI_AUTH_MODE;
42341 +
42342 +typedef PREPACK struct {
42343 + A_UINT8 mode;
42344 +} POSTPACK WMI_SET_AUTH_MODE_CMD;
42345 +
42346 +/*
42347 + * WMI_SET_REASSOC_MODE_CMDID
42348 + *
42349 + * Set authentication mode
42350 + */
42351 +typedef enum {
42352 + REASSOC_DO_DISASSOC = 0x00,
42353 + REASSOC_DONOT_DISASSOC = 0x01
42354 +} WMI_REASSOC_MODE;
42355 +
42356 +typedef PREPACK struct {
42357 + A_UINT8 mode;
42358 +}POSTPACK WMI_SET_REASSOC_MODE_CMD;
42359 +
42360 +typedef enum {
42361 + ROAM_DATA_TIME = 1, /* Get The Roam Time Data */
42362 +} ROAM_DATA_TYPE;
42363 +
42364 +typedef PREPACK struct {
42365 + A_UINT32 disassoc_time;
42366 + A_UINT32 no_txrx_time;
42367 + A_UINT32 assoc_time;
42368 + A_UINT32 allow_txrx_time;
42369 + A_UINT32 last_data_txrx_time;
42370 + A_UINT32 first_data_txrx_time;
42371 + A_UINT8 disassoc_bssid[ATH_MAC_LEN];
42372 + A_INT8 disassoc_bss_rssi;
42373 + A_UINT8 assoc_bssid[ATH_MAC_LEN];
42374 + A_INT8 assoc_bss_rssi;
42375 +} POSTPACK WMI_TARGET_ROAM_TIME;
42376 +
42377 +typedef PREPACK struct {
42378 + PREPACK union {
42379 + WMI_TARGET_ROAM_TIME roamTime;
42380 + } POSTPACK u;
42381 + A_UINT8 roamDataType ;
42382 +} POSTPACK WMI_TARGET_ROAM_DATA;
42383 +
42384 +typedef enum {
42385 + WMI_WMM_DISABLED = 0,
42386 + WMI_WMM_ENABLED
42387 +} WMI_WMM_STATUS;
42388 +
42389 +typedef PREPACK struct {
42390 + A_UINT8 status;
42391 +}POSTPACK WMI_SET_WMM_CMD;
42392 +
42393 +typedef enum {
42394 + WMI_TXOP_DISABLED = 0,
42395 + WMI_TXOP_ENABLED
42396 +} WMI_TXOP_CFG;
42397 +
42398 +typedef PREPACK struct {
42399 + A_UINT8 txopEnable;
42400 +}POSTPACK WMI_SET_WMM_TXOP_CMD;
42401 +
42402 +typedef PREPACK struct {
42403 + A_UINT8 keepaliveInterval;
42404 +} POSTPACK WMI_SET_KEEPALIVE_CMD;
42405 +
42406 +typedef PREPACK struct {
42407 + A_BOOL configured;
42408 + A_UINT8 keepaliveInterval;
42409 +} POSTPACK WMI_GET_KEEPALIVE_CMD;
42410 +
42411 +/*
42412 + * Add Application specified IE to a management frame
42413 + */
42414 +#define WMI_MAX_IE_LEN 78
42415 +
42416 +typedef PREPACK struct {
42417 + A_UINT8 mgmtFrmType; /* one of WMI_MGMT_FRAME_TYPE */
42418 + A_UINT8 ieLen; /* Length of the IE that should be added to the MGMT frame */
42419 + A_UINT8 ieInfo[1];
42420 +} POSTPACK WMI_SET_APPIE_CMD;
42421 +
42422 +/*
42423 + * Notify the WSC registration status to the target
42424 + */
42425 +#define WSC_REG_ACTIVE 1
42426 +#define WSC_REG_INACTIVE 0
42427 +/* Generic Hal Interface for setting hal paramters. */
42428 +/* Add new Set HAL Param cmdIds here for newer params */
42429 +typedef enum {
42430 + WHAL_SETCABTO_CMDID = 1,
42431 +}WHAL_CMDID;
42432 +
42433 +typedef PREPACK struct {
42434 + A_UINT8 cabTimeOut;
42435 +} POSTPACK WHAL_SETCABTO_PARAM;
42436 +
42437 +typedef PREPACK struct {
42438 + A_UINT8 whalCmdId;
42439 + A_UINT8 data[1];
42440 +} POSTPACK WHAL_PARAMCMD;
42441 +
42442 +
42443 +#define WOW_MAX_FILTER_LISTS 1 /*4*/
42444 +#define WOW_MAX_FILTERS_PER_LIST 4
42445 +#define WOW_PATTERN_SIZE 64
42446 +#define WOW_MASK_SIZE 64
42447 +
42448 +typedef PREPACK struct {
42449 + A_UINT8 wow_valid_filter;
42450 + A_UINT8 wow_filter_id;
42451 + A_UINT8 wow_filter_size;
42452 + A_UINT8 wow_filter_offset;
42453 + A_UINT8 wow_filter_mask[WOW_MASK_SIZE];
42454 + A_UINT8 wow_filter_pattern[WOW_PATTERN_SIZE];
42455 +} POSTPACK WOW_FILTER;
42456 +
42457 +
42458 +typedef PREPACK struct {
42459 + A_UINT8 wow_valid_list;
42460 + A_UINT8 wow_list_id;
42461 + A_UINT8 wow_num_filters;
42462 + A_UINT8 wow_total_list_size;
42463 + WOW_FILTER list[WOW_MAX_FILTERS_PER_LIST];
42464 +} POSTPACK WOW_FILTER_LIST;
42465 +
42466 +typedef PREPACK struct {
42467 + A_BOOL awake;
42468 + A_BOOL asleep;
42469 +} POSTPACK WMI_SET_HOST_SLEEP_MODE_CMD;
42470 +
42471 +typedef PREPACK struct {
42472 + A_BOOL enable_wow;
42473 +} POSTPACK WMI_SET_WOW_MODE_CMD;
42474 +
42475 +typedef PREPACK struct {
42476 + A_UINT8 filter_list_id;
42477 +} POSTPACK WMI_GET_WOW_LIST_CMD;
42478 +
42479 +/*
42480 + * WMI_GET_WOW_LIST_CMD reply
42481 + */
42482 +typedef PREPACK struct {
42483 + A_UINT8 num_filters; /* number of patterns in reply */
42484 + A_UINT8 this_filter_num; /* this is filter # x of total num_filters */
42485 + A_UINT8 wow_mode;
42486 + A_UINT8 host_mode;
42487 + WOW_FILTER wow_filters[1];
42488 +} POSTPACK WMI_GET_WOW_LIST_REPLY;
42489 +
42490 +typedef PREPACK struct {
42491 + A_UINT8 filter_list_id;
42492 + A_UINT8 filter_size;
42493 + A_UINT8 filter_offset;
42494 + A_UINT8 filter[1];
42495 +} POSTPACK WMI_ADD_WOW_PATTERN_CMD;
42496 +
42497 +typedef PREPACK struct {
42498 + A_UINT16 filter_list_id;
42499 + A_UINT16 filter_id;
42500 +} POSTPACK WMI_DEL_WOW_PATTERN_CMD;
42501 +
42502 +typedef PREPACK struct {
42503 + A_UINT8 macaddr[ATH_MAC_LEN];
42504 +} POSTPACK WMI_SET_MAC_ADDRESS_CMD;
42505 +
42506 +/*
42507 + * WMI_SET_AKMP_PARAMS_CMD
42508 + */
42509 +
42510 +#define WMI_AKMP_MULTI_PMKID_EN 0x000001
42511 +
42512 +typedef PREPACK struct {
42513 + A_UINT32 akmpInfo;
42514 +} POSTPACK WMI_SET_AKMP_PARAMS_CMD;
42515 +
42516 +typedef PREPACK struct {
42517 + A_UINT8 pmkid[WMI_PMKID_LEN];
42518 +} POSTPACK WMI_PMKID;
42519 +
42520 +/*
42521 + * WMI_SET_PMKID_LIST_CMD
42522 + */
42523 +#define WMI_MAX_PMKID_CACHE 8
42524 +
42525 +typedef PREPACK struct {
42526 + A_UINT32 numPMKID;
42527 + WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE];
42528 +} POSTPACK WMI_SET_PMKID_LIST_CMD;
42529 +
42530 +/*
42531 + * WMI_GET_PMKID_LIST_CMD Reply
42532 + * Following the Number of PMKIDs is the list of PMKIDs
42533 + */
42534 +typedef PREPACK struct {
42535 + A_UINT32 numPMKID;
42536 + WMI_PMKID pmkidList[1];
42537 +} POSTPACK WMI_PMKID_LIST_REPLY;
42538 +
42539 +/* index used for priority streams */
42540 +typedef enum {
42541 + WMI_NOT_MAPPED = -1,
42542 + WMI_CONTROL_PRI = 0,
42543 + WMI_BEST_EFFORT_PRI = 1,
42544 + WMI_LOW_PRI = 2,
42545 + WMI_HIGH_PRI = 3,
42546 + WMI_HIGHEST_PRI,
42547 + WMI_PRI_MAX_COUNT
42548 +} WMI_PRI_STREAM_ID;
42549 +
42550 +#ifndef ATH_TARGET
42551 +#include "athendpack.h"
42552 +#endif
42553 +
42554 +#ifdef __cplusplus
42555 +}
42556 +#endif
42557 +
42558 +#endif /* _WMI_H_ */
42559 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/include/wmix.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wmix.h
42560 --- linux-2.6.29-rc3.owrt/drivers/ar6000/include/wmix.h 1970-01-01 01:00:00.000000000 +0100
42561 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/include/wmix.h 2009-05-10 22:27:59.000000000 +0200
42562 @@ -0,0 +1,233 @@
42563 +/*
42564 + * Copyright (c) 2004-2005 Atheros Communications Inc.
42565 + * All rights reserved.
42566 + *
42567 + *
42568 + * $ATH_LICENSE_HOSTSDK0_C$
42569 + *
42570 + * This file contains extensions of the WMI protocol specified in the
42571 + * Wireless Module Interface (WMI). It includes definitions of all
42572 + * extended commands and events. Extensions include useful commands
42573 + * that are not directly related to wireless activities. They may
42574 + * be hardware-specific, and they might not be supported on all
42575 + * implementations.
42576 + *
42577 + * Extended WMIX commands are encapsulated in a WMI message with
42578 + * cmd=WMI_EXTENSION_CMD.
42579 + *
42580 + */
42581 +
42582 +#ifndef _WMIX_H_
42583 +#define _WMIX_H_
42584 +
42585 +#ifdef __cplusplus
42586 +extern "C" {
42587 +#endif
42588 +
42589 +#ifndef ATH_TARGET
42590 +#include "athstartpack.h"
42591 +#endif
42592 +
42593 +#include "dbglog.h"
42594 +
42595 +/*
42596 + * Extended WMI commands are those that are needed during wireless
42597 + * operation, but which are not really wireless commands. This allows,
42598 + * for instance, platform-specific commands. Extended WMI commands are
42599 + * embedded in a WMI command message with WMI_COMMAND_ID=WMI_EXTENSION_CMDID.
42600 + * Extended WMI events are similarly embedded in a WMI event message with
42601 + * WMI_EVENT_ID=WMI_EXTENSION_EVENTID.
42602 + */
42603 +typedef PREPACK struct {
42604 + A_UINT32 commandId;
42605 +} POSTPACK WMIX_CMD_HDR;
42606 +
42607 +typedef enum {
42608 + WMIX_DSETOPEN_REPLY_CMDID = 0x2001,
42609 + WMIX_DSETDATA_REPLY_CMDID,
42610 + WMIX_GPIO_OUTPUT_SET_CMDID,
42611 + WMIX_GPIO_INPUT_GET_CMDID,
42612 + WMIX_GPIO_REGISTER_SET_CMDID,
42613 + WMIX_GPIO_REGISTER_GET_CMDID,
42614 + WMIX_GPIO_INTR_ACK_CMDID,
42615 + WMIX_HB_CHALLENGE_RESP_CMDID,
42616 + WMIX_DBGLOG_CFG_MODULE_CMDID,
42617 +} WMIX_COMMAND_ID;
42618 +
42619 +typedef enum {
42620 + WMIX_DSETOPENREQ_EVENTID = 0x3001,
42621 + WMIX_DSETCLOSE_EVENTID,
42622 + WMIX_DSETDATAREQ_EVENTID,
42623 + WMIX_GPIO_INTR_EVENTID,
42624 + WMIX_GPIO_DATA_EVENTID,
42625 + WMIX_GPIO_ACK_EVENTID,
42626 + WMIX_HB_CHALLENGE_RESP_EVENTID,
42627 + WMIX_DBGLOG_EVENTID,
42628 +} WMIX_EVENT_ID;
42629 +
42630 +/*
42631 + * =============DataSet support=================
42632 + */
42633 +
42634 +/*
42635 + * WMIX_DSETOPENREQ_EVENTID
42636 + * DataSet Open Request Event
42637 + */
42638 +typedef PREPACK struct {
42639 + A_UINT32 dset_id;
42640 + A_UINT32 targ_dset_handle; /* echo'ed, not used by Host, */
42641 + A_UINT32 targ_reply_fn; /* echo'ed, not used by Host, */
42642 + A_UINT32 targ_reply_arg; /* echo'ed, not used by Host, */
42643 +} POSTPACK WMIX_DSETOPENREQ_EVENT;
42644 +
42645 +/*
42646 + * WMIX_DSETCLOSE_EVENTID
42647 + * DataSet Close Event
42648 + */
42649 +typedef PREPACK struct {
42650 + A_UINT32 access_cookie;
42651 +} POSTPACK WMIX_DSETCLOSE_EVENT;
42652 +
42653 +/*
42654 + * WMIX_DSETDATAREQ_EVENTID
42655 + * DataSet Data Request Event
42656 + */
42657 +typedef PREPACK struct {
42658 + A_UINT32 access_cookie;
42659 + A_UINT32 offset;
42660 + A_UINT32 length;
42661 + A_UINT32 targ_buf; /* echo'ed, not used by Host, */
42662 + A_UINT32 targ_reply_fn; /* echo'ed, not used by Host, */
42663 + A_UINT32 targ_reply_arg; /* echo'ed, not used by Host, */
42664 +} POSTPACK WMIX_DSETDATAREQ_EVENT;
42665 +
42666 +typedef PREPACK struct {
42667 + A_UINT32 status;
42668 + A_UINT32 targ_dset_handle;
42669 + A_UINT32 targ_reply_fn;
42670 + A_UINT32 targ_reply_arg;
42671 + A_UINT32 access_cookie;
42672 + A_UINT32 size;
42673 + A_UINT32 version;
42674 +} POSTPACK WMIX_DSETOPEN_REPLY_CMD;
42675 +
42676 +typedef PREPACK struct {
42677 + A_UINT32 status;
42678 + A_UINT32 targ_buf;
42679 + A_UINT32 targ_reply_fn;
42680 + A_UINT32 targ_reply_arg;
42681 + A_UINT32 length;
42682 + A_UINT8 buf[1];
42683 +} POSTPACK WMIX_DSETDATA_REPLY_CMD;
42684 +
42685 +
42686 +/*
42687 + * =============GPIO support=================
42688 + * All masks are 18-bit masks with bit N operating on GPIO pin N.
42689 + */
42690 +
42691 +#include "gpio.h"
42692 +
42693 +/*
42694 + * Set GPIO pin output state.
42695 + * In order for output to be driven, a pin must be enabled for output.
42696 + * This can be done during initialization through the GPIO Configuration
42697 + * DataSet, or during operation with the enable_mask.
42698 + *
42699 + * If a request is made to simultaneously set/clear or set/disable or
42700 + * clear/disable or disable/enable, results are undefined.
42701 + */
42702 +typedef PREPACK struct {
42703 + A_UINT32 set_mask; /* pins to set */
42704 + A_UINT32 clear_mask; /* pins to clear */
42705 + A_UINT32 enable_mask; /* pins to enable for output */
42706 + A_UINT32 disable_mask; /* pins to disable/tristate */
42707 +} POSTPACK WMIX_GPIO_OUTPUT_SET_CMD;
42708 +
42709 +/*
42710 + * Set a GPIO register. For debug/exceptional cases.
42711 + * Values for gpioreg_id are GPIO_REGISTER_IDs, defined in a
42712 + * platform-dependent header.
42713 + */
42714 +typedef PREPACK struct {
42715 + A_UINT32 gpioreg_id; /* GPIO register ID */
42716 + A_UINT32 value; /* value to write */
42717 +} POSTPACK WMIX_GPIO_REGISTER_SET_CMD;
42718 +
42719 +/* Get a GPIO register. For debug/exceptional cases. */
42720 +typedef PREPACK struct {
42721 + A_UINT32 gpioreg_id; /* GPIO register to read */
42722 +} POSTPACK WMIX_GPIO_REGISTER_GET_CMD;
42723 +
42724 +/*
42725 + * Host acknowledges and re-arms GPIO interrupts. A single
42726 + * message should be used to acknowledge all interrupts that
42727 + * were delivered in an earlier WMIX_GPIO_INTR_EVENT message.
42728 + */
42729 +typedef PREPACK struct {
42730 + A_UINT32 ack_mask; /* interrupts to acknowledge */
42731 +} POSTPACK WMIX_GPIO_INTR_ACK_CMD;
42732 +
42733 +/*
42734 + * Target informs Host of GPIO interrupts that have ocurred since the
42735 + * last WMIX_GIPO_INTR_ACK_CMD was received. Additional information --
42736 + * the current GPIO input values is provided -- in order to support
42737 + * use of a GPIO interrupt as a Data Valid signal for other GPIO pins.
42738 + */
42739 +typedef PREPACK struct {
42740 + A_UINT32 intr_mask; /* pending GPIO interrupts */
42741 + A_UINT32 input_values; /* recent GPIO input values */
42742 +} POSTPACK WMIX_GPIO_INTR_EVENT;
42743 +
42744 +/*
42745 + * Target responds to Host's earlier WMIX_GPIO_INPUT_GET_CMDID request
42746 + * using a GPIO_DATA_EVENT with
42747 + * value set to the mask of GPIO pin inputs and
42748 + * reg_id set to GPIO_ID_NONE
42749 + *
42750 + *
42751 + * Target responds to Hosts's earlier WMIX_GPIO_REGISTER_GET_CMDID request
42752 + * using a GPIO_DATA_EVENT with
42753 + * value set to the value of the requested register and
42754 + * reg_id identifying the register (reflects the original request)
42755 + * NB: reg_id supports the future possibility of unsolicited
42756 + * WMIX_GPIO_DATA_EVENTs (for polling GPIO input), and it may
42757 + * simplify Host GPIO support.
42758 + */
42759 +typedef PREPACK struct {
42760 + A_UINT32 value;
42761 + A_UINT32 reg_id;
42762 +} POSTPACK WMIX_GPIO_DATA_EVENT;
42763 +
42764 +/*
42765 + * =============Error Detection support=================
42766 + */
42767 +
42768 +/*
42769 + * WMIX_HB_CHALLENGE_RESP_CMDID
42770 + * Heartbeat Challenge Response command
42771 + */
42772 +typedef PREPACK struct {
42773 + A_UINT32 cookie;
42774 + A_UINT32 source;
42775 +} POSTPACK WMIX_HB_CHALLENGE_RESP_CMD;
42776 +
42777 +/*
42778 + * WMIX_HB_CHALLENGE_RESP_EVENTID
42779 + * Heartbeat Challenge Response Event
42780 + */
42781 +#define WMIX_HB_CHALLENGE_RESP_EVENT WMIX_HB_CHALLENGE_RESP_CMD
42782 +
42783 +typedef PREPACK struct {
42784 + struct dbglog_config_s config;
42785 +} POSTPACK WMIX_DBGLOG_CFG_MODULE_CMD;
42786 +
42787 +#ifndef ATH_TARGET
42788 +#include "athendpack.h"
42789 +#endif
42790 +
42791 +#ifdef __cplusplus
42792 +}
42793 +#endif
42794 +
42795 +#endif /* _WMIX_H_ */
42796 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/Kconfig linux-2.6.29-rc3.owrt.om/drivers/ar6000/Kconfig
42797 --- linux-2.6.29-rc3.owrt/drivers/ar6000/Kconfig 1970-01-01 01:00:00.000000000 +0100
42798 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/Kconfig 2009-05-10 22:27:59.000000000 +0200
42799 @@ -0,0 +1,31 @@
42800 +config AR6000_WLAN
42801 + tristate "AR6000 wireless networking over SDIO"
42802 + depends on MMC
42803 + select WIRELESS_EXT
42804 + default m
42805 + help
42806 + good luck.
42807 +
42808 +config AR6000_WLAN_DEBUG
42809 + bool "Enable retrieval of firmware debugging information"
42810 + depends on AR6000_WLAN
42811 + default n
42812 + help
42813 + The AR6k firmware maintains a log of debugging events that
42814 + gets flushed to the host on various occasions. Retrieval of
42815 + this data is very slow, taking several seconds.
42816 +
42817 + If in doubt, say N.
42818 +
42819 +config AR6000_WLAN_RESET
42820 + bool "Soft-reset when shutting down"
42821 + depends on AR6000_WLAN
42822 + default n
42823 + help
42824 + The AR6k module can be explicitly reset when shutting down
42825 + the device. This adds a delay of about two seconds to suspend,
42826 + module removal, and so on. Since the WLAN SDIO function is
42827 + generally disabled soon thereafter anyway, this reset seems
42828 + superfluous.
42829 +
42830 + If in doubt, say N.
42831 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/Makefile linux-2.6.29-rc3.owrt.om/drivers/ar6000/Makefile
42832 --- linux-2.6.29-rc3.owrt/drivers/ar6000/Makefile 1970-01-01 01:00:00.000000000 +0100
42833 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/Makefile 2009-05-10 22:27:59.000000000 +0200
42834 @@ -0,0 +1,38 @@
42835 +REV ?= 2
42836 +
42837 +PWD := $(shell pwd)
42838 +
42839 +EXTRA_CFLAGS += -I$(src)/include
42840 +
42841 +EXTRA_CFLAGS += -DLINUX -D__KERNEL__ -DHTC_RAW_INTERFACE\
42842 + -DTCMD -DUSER_KEYS \
42843 + -DNO_SYNC_FLUSH #\
42844 + -DMULTIPLE_FRAMES_PER_INTERRUPT -DAR6000REV$(REV) \
42845 + -DBLOCK_TX_PATH_FLAG \
42846 + -DSDIO \
42847 +
42848 +EXTRA_CFLAGS += -DKERNEL_2_6
42849 +
42850 +obj-$(CONFIG_AR6000_WLAN) += ar6000.o
42851 +
42852 +ar6000-objs += htc/ar6k.o \
42853 + htc/ar6k_events.o \
42854 + htc/htc_send.o \
42855 + htc/htc_recv.o \
42856 + htc/htc_services.o \
42857 + htc/htc.o \
42858 + hif/hif2.o \
42859 + bmi/bmi.o \
42860 + ar6000/ar6000_drv.o \
42861 + ar6000/ar6000_raw_if.o \
42862 + ar6000/netbuf.o \
42863 + ar6000/wireless_ext.o \
42864 + ar6000/ioctl.o \
42865 + miscdrv/common_drv.o \
42866 + miscdrv/credit_dist.o \
42867 + wmi/wmi.o \
42868 + wlan/wlan_node.o \
42869 + wlan/wlan_recv_beacon.o \
42870 + wlan/wlan_utils.o
42871 +
42872 +
42873 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/miscdrv/common_drv.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/miscdrv/common_drv.c
42874 --- linux-2.6.29-rc3.owrt/drivers/ar6000/miscdrv/common_drv.c 1970-01-01 01:00:00.000000000 +0100
42875 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/miscdrv/common_drv.c 2009-05-10 22:27:59.000000000 +0200
42876 @@ -0,0 +1,467 @@
42877 +
42878 +/*
42879 + *
42880 + * Copyright (c) 2004-2007 Atheros Communications Inc.
42881 + * All rights reserved.
42882 + *
42883 + *
42884 + * This program is free software; you can redistribute it and/or modify
42885 + * it under the terms of the GNU General Public License version 2 as
42886 + * published by the Free Software Foundation;
42887 + *
42888 + * Software distributed under the License is distributed on an "AS
42889 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
42890 + * implied. See the License for the specific language governing
42891 + * rights and limitations under the License.
42892 + *
42893 + *
42894 + *
42895 + */
42896 +
42897 +#include "a_config.h"
42898 +#include "athdefs.h"
42899 +#include "a_types.h"
42900 +#include "AR6Khwreg.h"
42901 +#include "targaddrs.h"
42902 +#include "a_osapi.h"
42903 +#include "hif.h"
42904 +#include "htc_api.h"
42905 +#include "bmi.h"
42906 +#include "bmi_msg.h"
42907 +#include "common_drv.h"
42908 +#include "a_debug.h"
42909 +#include "targaddrs.h"
42910 +
42911 +#define HOST_INTEREST_ITEM_ADDRESS(target, item) \
42912 +(((TargetType) == TARGET_TYPE_AR6001) ? \
42913 + AR6001_HOST_INTEREST_ITEM_ADDRESS(item) : \
42914 + AR6002_HOST_INTEREST_ITEM_ADDRESS(item))
42915 +
42916 +
42917 +/* Compile the 4BYTE version of the window register setup routine,
42918 + * This mitigates host interconnect issues with non-4byte aligned bus requests, some
42919 + * interconnects use bus adapters that impose strict limitations.
42920 + * Since diag window access is not intended for performance critical operations, the 4byte mode should
42921 + * be satisfactory even though it generates 4X the bus activity. */
42922 +
42923 +#ifdef USE_4BYTE_REGISTER_ACCESS
42924 +
42925 + /* set the window address register (using 4-byte register access ). */
42926 +A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
42927 +{
42928 + A_STATUS status;
42929 + A_UINT8 addrValue[4];
42930 + int i;
42931 +
42932 + /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
42933 + * last to initiate the access cycle */
42934 +
42935 + for (i = 1; i <= 3; i++) {
42936 + /* fill the buffer with the address byte value we want to hit 4 times*/
42937 + addrValue[0] = ((A_UINT8 *)&Address)[i];
42938 + addrValue[1] = addrValue[0];
42939 + addrValue[2] = addrValue[0];
42940 + addrValue[3] = addrValue[0];
42941 +
42942 + /* hit each byte of the register address with a 4-byte write operation to the same address,
42943 + * this is a harmless operation */
42944 + status = HIFReadWrite(hifDevice,
42945 + RegisterAddr+i,
42946 + addrValue,
42947 + 4,
42948 + HIF_WR_SYNC_BYTE_FIX,
42949 + NULL);
42950 + if (status != A_OK) {
42951 + break;
42952 + }
42953 + }
42954 +
42955 + if (status != A_OK) {
42956 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
42957 + RegisterAddr, Address));
42958 + return status;
42959 + }
42960 +
42961 + /* write the address register again, this time write the whole 4-byte value.
42962 + * The effect here is that the LSB write causes the cycle to start, the extra
42963 + * 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */
42964 + status = HIFReadWrite(hifDevice,
42965 + RegisterAddr,
42966 + (A_UCHAR *)(&Address),
42967 + 4,
42968 + HIF_WR_SYNC_BYTE_INC,
42969 + NULL);
42970 +
42971 + if (status != A_OK) {
42972 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
42973 + RegisterAddr, Address));
42974 + return status;
42975 + }
42976 +
42977 + return A_OK;
42978 +
42979 +
42980 +
42981 +}
42982 +
42983 +
42984 +#else
42985 +
42986 + /* set the window address register */
42987 +A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
42988 +{
42989 + A_STATUS status;
42990 +
42991 + /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
42992 + * last to initiate the access cycle */
42993 + status = HIFReadWrite(hifDevice,
42994 + RegisterAddr+1, /* write upper 3 bytes */
42995 + ((A_UCHAR *)(&Address))+1,
42996 + sizeof(A_UINT32)-1,
42997 + HIF_WR_SYNC_BYTE_INC,
42998 + NULL);
42999 +
43000 + if (status != A_OK) {
43001 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
43002 + RegisterAddr, Address));
43003 + return status;
43004 + }
43005 +
43006 + /* write the LSB of the register, this initiates the operation */
43007 + status = HIFReadWrite(hifDevice,
43008 + RegisterAddr,
43009 + (A_UCHAR *)(&Address),
43010 + sizeof(A_UINT8),
43011 + HIF_WR_SYNC_BYTE_INC,
43012 + NULL);
43013 +
43014 + if (status != A_OK) {
43015 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
43016 + RegisterAddr, Address));
43017 + return status;
43018 + }
43019 +
43020 + return A_OK;
43021 +}
43022 +
43023 +#endif
43024 +
43025 +/*
43026 + * Read from the AR6000 through its diagnostic window.
43027 + * No cooperation from the Target is required for this.
43028 + */
43029 +A_STATUS
43030 +ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
43031 +{
43032 + A_STATUS status;
43033 +
43034 + /* set window register to start read cycle */
43035 + status = ar6000_SetAddressWindowRegister(hifDevice,
43036 + WINDOW_READ_ADDR_ADDRESS,
43037 + *address);
43038 +
43039 + if (status != A_OK) {
43040 + return status;
43041 + }
43042 +
43043 + /* read the data */
43044 + status = HIFReadWrite(hifDevice,
43045 + WINDOW_DATA_ADDRESS,
43046 + (A_UCHAR *)data,
43047 + sizeof(A_UINT32),
43048 + HIF_RD_SYNC_BYTE_INC,
43049 + NULL);
43050 + if (status != A_OK) {
43051 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
43052 + return status;
43053 + }
43054 +
43055 + return status;
43056 +}
43057 +
43058 +
43059 +/*
43060 + * Write to the AR6000 through its diagnostic window.
43061 + * No cooperation from the Target is required for this.
43062 + */
43063 +A_STATUS
43064 +ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
43065 +{
43066 + A_STATUS status;
43067 +
43068 + /* set write data */
43069 + status = HIFReadWrite(hifDevice,
43070 + WINDOW_DATA_ADDRESS,
43071 + (A_UCHAR *)data,
43072 + sizeof(A_UINT32),
43073 + HIF_WR_SYNC_BYTE_INC,
43074 + NULL);
43075 + if (status != A_OK) {
43076 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data));
43077 + return status;
43078 + }
43079 +
43080 + /* set window register, which starts the write cycle */
43081 + return ar6000_SetAddressWindowRegister(hifDevice,
43082 + WINDOW_WRITE_ADDR_ADDRESS,
43083 + *address);
43084 +}
43085 +
43086 +A_STATUS
43087 +ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
43088 + A_UCHAR *data, A_UINT32 length)
43089 +{
43090 + A_UINT32 count;
43091 + A_STATUS status = A_OK;
43092 +
43093 + for (count = 0; count < length; count += 4, address += 4) {
43094 + if ((status = ar6000_ReadRegDiag(hifDevice, &address,
43095 + (A_UINT32 *)&data[count])) != A_OK)
43096 + {
43097 + break;
43098 + }
43099 + }
43100 +
43101 + return status;
43102 +}
43103 +
43104 +A_STATUS
43105 +ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
43106 + A_UCHAR *data, A_UINT32 length)
43107 +{
43108 + A_UINT32 count;
43109 + A_STATUS status = A_OK;
43110 +
43111 + for (count = 0; count < length; count += 4, address += 4) {
43112 + if ((status = ar6000_WriteRegDiag(hifDevice, &address,
43113 + (A_UINT32 *)&data[count])) != A_OK)
43114 + {
43115 + break;
43116 + }
43117 + }
43118 +
43119 + return status;
43120 +}
43121 +
43122 +A_STATUS
43123 +ar6000_reset_device_skipflash(HIF_DEVICE *hifDevice)
43124 +{
43125 + int i;
43126 + struct forceROM_s {
43127 + A_UINT32 addr;
43128 + A_UINT32 data;
43129 + };
43130 + struct forceROM_s *ForceROM;
43131 + int szForceROM;
43132 + A_UINT32 instruction;
43133 +
43134 + static struct forceROM_s ForceROM_REV2[] = {
43135 + /* NB: This works for old REV2 ROM (old). */
43136 + {0x00001ff0, 0x175b0027}, /* jump instruction at 0xa0001ff0 */
43137 + {0x00001ff4, 0x00000000}, /* nop instruction at 0xa0001ff4 */
43138 +
43139 + {MC_REMAP_TARGET_ADDRESS, 0x00001ff0}, /* remap to 0xa0001ff0 */
43140 + {MC_REMAP_COMPARE_ADDRESS, 0x01000040},/* ...from 0xbfc00040 */
43141 + {MC_REMAP_SIZE_ADDRESS, 0x00000000}, /* ...1 cache line */
43142 + {MC_REMAP_VALID_ADDRESS, 0x00000001}, /* ...remap is valid */
43143 +
43144 + {LOCAL_COUNT_ADDRESS+0x10, 0}, /* clear BMI credit counter */
43145 +
43146 + {RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
43147 + };
43148 +
43149 + static struct forceROM_s ForceROM_NEW[] = {
43150 + /* NB: This works for AR6000 ROM REV3 and beyond. */
43151 + {LOCAL_SCRATCH_ADDRESS, AR6K_OPTION_IGNORE_FLASH},
43152 + {LOCAL_COUNT_ADDRESS+0x10, 0}, /* clear BMI credit counter */
43153 + {RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
43154 + };
43155 +
43156 + /*
43157 + * Examine a semi-arbitrary instruction that's different
43158 + * in REV2 and other revisions.
43159 + * NB: If a Host port does not require simultaneous support
43160 + * for multiple revisions of Target ROM, this code can be elided.
43161 + */
43162 + (void)ar6000_ReadDataDiag(hifDevice, 0x01000040,
43163 + (A_UCHAR *)&instruction, 4);
43164 +
43165 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("instruction=0x%x\n", instruction));
43166 +
43167 + if (instruction == 0x3c1aa200) {
43168 + /* It's an old ROM */
43169 + ForceROM = ForceROM_REV2;
43170 + szForceROM = sizeof(ForceROM_REV2)/sizeof(*ForceROM);
43171 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Using OLD method\n"));
43172 + } else {
43173 + ForceROM = ForceROM_NEW;
43174 + szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM);
43175 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Using NEW method\n"));
43176 + }
43177 +
43178 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Force Target to execute from ROM....\n"));
43179 + for (i = 0; i < szForceROM; i++)
43180 + {
43181 + if (ar6000_WriteRegDiag(hifDevice,
43182 + &ForceROM[i].addr,
43183 + &ForceROM[i].data) != A_OK)
43184 + {
43185 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot force Target to execute ROM!\n"));
43186 + return A_ERROR;
43187 + }
43188 + }
43189 +
43190 + msleep(50); /* delay to allow dragon to come to BMI phase */
43191 + return A_OK;
43192 +}
43193 +
43194 +/* reset device */
43195 +A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
43196 +{
43197 +
43198 +#if !defined(DWSIM)
43199 + A_STATUS status = A_OK;
43200 + A_UINT32 address;
43201 + A_UINT32 data;
43202 +
43203 + do {
43204 +
43205 + // address = RESET_CONTROL_ADDRESS;
43206 + data = RESET_CONTROL_COLD_RST_MASK;
43207 +
43208 + /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
43209 + if (TargetType == TARGET_TYPE_AR6001) {
43210 + address = 0x0C000000;
43211 + } else {
43212 + if (TargetType == TARGET_TYPE_AR6002) {
43213 + address = 0x00004000;
43214 + } else {
43215 + A_ASSERT(0);
43216 + }
43217 + }
43218 +
43219 + status = ar6000_WriteRegDiag(hifDevice, &address, &data);
43220 +
43221 + if (A_FAILED(status)) {
43222 + break;
43223 + }
43224 +
43225 + /*
43226 + * Read back the RESET CAUSE register to ensure that the cold reset
43227 + * went through.
43228 + */
43229 + msleep(2000); /* 2 second delay to allow things to settle down */
43230 +
43231 +
43232 + // address = RESET_CAUSE_ADDRESS;
43233 + /* Hardcode the address of RESET_CAUSE_ADDRESS based on the target type */
43234 + if (TargetType == TARGET_TYPE_AR6001) {
43235 + address = 0x0C0000CC;
43236 + } else {
43237 + if (TargetType == TARGET_TYPE_AR6002) {
43238 + address = 0x000040C0;
43239 + } else {
43240 + A_ASSERT(0);
43241 + }
43242 + }
43243 +
43244 + data = 0;
43245 + status = ar6000_ReadRegDiag(hifDevice, &address, &data);
43246 +
43247 + if (A_FAILED(status)) {
43248 + break;
43249 + }
43250 +
43251 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data));
43252 + data &= RESET_CAUSE_LAST_MASK;
43253 + if (data != 2) {
43254 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"));
43255 + }
43256 +
43257 + } while (FALSE);
43258 +
43259 + if (A_FAILED(status)) {
43260 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
43261 + }
43262 +#endif
43263 + return A_OK;
43264 +}
43265 +
43266 +#define REG_DUMP_COUNT_AR6001 38 /* WORDs, derived from AR6001_regdump.h */
43267 +#define REG_DUMP_COUNT_AR6002 32 /* WORDs, derived from AR6002_regdump.h */
43268 +
43269 +
43270 +#if REG_DUMP_COUNT_AR6001 <= REG_DUMP_COUNT_AR6002
43271 +#define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6002
43272 +#else
43273 +#define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6001
43274 +#endif
43275 +
43276 +void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
43277 +{
43278 + A_UINT32 address;
43279 + A_UINT32 regDumpArea = 0;
43280 + A_STATUS status;
43281 + A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
43282 + A_UINT32 regDumpCount = 0;
43283 + A_UINT32 i;
43284 +
43285 + do {
43286 +
43287 + /* the reg dump pointer is copied to the host interest area */
43288 + address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state);
43289 +
43290 + if (TargetType == TARGET_TYPE_AR6001) {
43291 + /* for AR6001, this is a fixed location because the ptr is actually stuck in cache,
43292 + * this may be fixed in later firmware versions */
43293 + address = 0x18a0;
43294 + regDumpCount = REG_DUMP_COUNT_AR6001;
43295 +
43296 + } else if (TargetType == TARGET_TYPE_AR6002) {
43297 +
43298 + regDumpCount = REG_DUMP_COUNT_AR6002;
43299 +
43300 + } else {
43301 + A_ASSERT(0);
43302 + }
43303 +
43304 + /* read RAM location through diagnostic window */
43305 + status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);
43306 +
43307 + if (A_FAILED(status)) {
43308 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
43309 + break;
43310 + }
43311 +
43312 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea));
43313 +
43314 + if (regDumpArea == 0) {
43315 + /* no reg dump */
43316 + break;
43317 + }
43318 +
43319 + if (TargetType == TARGET_TYPE_AR6001) {
43320 + regDumpArea &= 0x0FFFFFFF; /* convert to physical address in target memory */
43321 + }
43322 +
43323 + /* fetch register dump data */
43324 + status = ar6000_ReadDataDiag(hifDevice,
43325 + regDumpArea,
43326 + (A_UCHAR *)&regDumpValues[0],
43327 + regDumpCount * (sizeof(A_UINT32)));
43328 +
43329 + if (A_FAILED(status)) {
43330 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
43331 + break;
43332 + }
43333 +
43334 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n"));
43335 +
43336 + for (i = 0; i < regDumpCount; i++) {
43337 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[i]));
43338 + }
43339 +
43340 + } while (FALSE);
43341 +
43342 +}
43343 +
43344 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/miscdrv/credit_dist.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/miscdrv/credit_dist.c
43345 --- linux-2.6.29-rc3.owrt/drivers/ar6000/miscdrv/credit_dist.c 1970-01-01 01:00:00.000000000 +0100
43346 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/miscdrv/credit_dist.c 2009-05-10 22:27:59.000000000 +0200
43347 @@ -0,0 +1,346 @@
43348 +
43349 +/*
43350 + *
43351 + * Copyright (c) 2004-2007 Atheros Communications Inc.
43352 + * All rights reserved.
43353 + *
43354 + *
43355 + * This program is free software; you can redistribute it and/or modify
43356 + * it under the terms of the GNU General Public License version 2 as
43357 + * published by the Free Software Foundation;
43358 + *
43359 + * Software distributed under the License is distributed on an "AS
43360 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
43361 + * implied. See the License for the specific language governing
43362 + * rights and limitations under the License.
43363 + *
43364 + *
43365 + *
43366 + */
43367 +
43368 +#include "a_config.h"
43369 +#include "athdefs.h"
43370 +#include "a_types.h"
43371 +#include "a_osapi.h"
43372 +#include "a_debug.h"
43373 +#include "htc_api.h"
43374 +#include "common_drv.h"
43375 +
43376 +/********* CREDIT DISTRIBUTION FUNCTIONS ******************************************/
43377 +
43378 +#define NO_VO_SERVICE 1 /* currently WMI only uses 3 data streams, so we leave VO service inactive */
43379 +
43380 +#ifdef NO_VO_SERVICE
43381 +#define DATA_SVCS_USED 3
43382 +#else
43383 +#define DATA_SVCS_USED 4
43384 +#endif
43385 +
43386 +static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
43387 + HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
43388 +
43389 +static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
43390 + HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
43391 +
43392 +/* reduce an ep's credits back to a set limit */
43393 +static INLINE void ReduceCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
43394 + HTC_ENDPOINT_CREDIT_DIST *pEpDist,
43395 + int Limit)
43396 +{
43397 + int credits;
43398 +
43399 + /* set the new limit */
43400 + pEpDist->TxCreditsAssigned = Limit;
43401 +
43402 + if (pEpDist->TxCredits <= Limit) {
43403 + return;
43404 + }
43405 +
43406 + /* figure out how much to take away */
43407 + credits = pEpDist->TxCredits - Limit;
43408 + /* take them away */
43409 + pEpDist->TxCredits -= credits;
43410 + pCredInfo->CurrentFreeCredits += credits;
43411 +}
43412 +
43413 +/* give an endpoint some credits from the free credit pool */
43414 +#define GiveCredits(pCredInfo,pEpDist,credits) \
43415 +{ \
43416 + (pEpDist)->TxCredits += (credits); \
43417 + (pEpDist)->TxCreditsAssigned += (credits); \
43418 + (pCredInfo)->CurrentFreeCredits -= (credits); \
43419 +}
43420 +
43421 +
43422 +/* default credit init callback.
43423 + * This function is called in the context of HTCStart() to setup initial (application-specific)
43424 + * credit distributions */
43425 +static void ar6000_credit_init(void *Context,
43426 + HTC_ENDPOINT_CREDIT_DIST *pEPList,
43427 + int TotalCredits)
43428 +{
43429 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
43430 + int count;
43431 + COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
43432 +
43433 + pCredInfo->CurrentFreeCredits = TotalCredits;
43434 + pCredInfo->TotalAvailableCredits = TotalCredits;
43435 +
43436 + pCurEpDist = pEPList;
43437 +
43438 + /* run through the list and initialize */
43439 + while (pCurEpDist != NULL) {
43440 +
43441 + /* set minimums for each endpoint */
43442 + pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg;
43443 +
43444 + if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) {
43445 + /* give control service some credits */
43446 + GiveCredits(pCredInfo,pCurEpDist,pCurEpDist->TxCreditsMin);
43447 + /* control service is always marked active, it never goes inactive EVER */
43448 + SET_EP_ACTIVE(pCurEpDist);
43449 + } else if (pCurEpDist->ServiceID == WMI_DATA_BK_SVC) {
43450 + /* this is the lowest priority data endpoint, save this off for easy access */
43451 + pCredInfo->pLowestPriEpDist = pCurEpDist;
43452 + }
43453 +
43454 + /* Streams have to be created (explicit | implicit)for all kinds
43455 + * of traffic. BE endpoints are also inactive in the beginning.
43456 + * When BE traffic starts it creates implicit streams that
43457 + * redistributes credits.
43458 + */
43459 +
43460 + /* note, all other endpoints have minimums set but are initially given NO credits.
43461 + * Credits will be distributed as traffic activity demands */
43462 + pCurEpDist = pCurEpDist->pNext;
43463 + }
43464 +
43465 + if (pCredInfo->CurrentFreeCredits <= 0) {
43466 + AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit distributions \n", TotalCredits));
43467 + A_ASSERT(FALSE);
43468 + return;
43469 + }
43470 +
43471 + /* reset list */
43472 + pCurEpDist = pEPList;
43473 + /* now run through the list and set max operating credit limits for everyone */
43474 + while (pCurEpDist != NULL) {
43475 + if (pCurEpDist->ServiceID == WMI_CONTROL_SVC) {
43476 + /* control service max is just 1 max message */
43477 + pCurEpDist->TxCreditsNorm = pCurEpDist->TxCreditsPerMaxMsg;
43478 + } else {
43479 + /* for the remaining data endpoints, we assume that each TxCreditsPerMaxMsg are
43480 + * the same.
43481 + * We use a simple calculation here, we take the remaining credits and
43482 + * determine how many max messages this can cover and then set each endpoint's
43483 + * normal value equal to half this amount.
43484 + * */
43485 + count = (pCredInfo->CurrentFreeCredits/pCurEpDist->TxCreditsPerMaxMsg) * pCurEpDist->TxCreditsPerMaxMsg;
43486 + count = count >> 1;
43487 + count = max(count,pCurEpDist->TxCreditsPerMaxMsg);
43488 + /* set normal */
43489 + pCurEpDist->TxCreditsNorm = count;
43490 +
43491 + }
43492 + pCurEpDist = pCurEpDist->pNext;
43493 + }
43494 +
43495 +}
43496 +
43497 +
43498 +/* default credit distribution callback
43499 + * This callback is invoked whenever endpoints require credit distributions.
43500 + * A lock is held while this function is invoked, this function shall NOT block.
43501 + * The pEPDistList is a list of distribution structures in prioritized order as
43502 + * defined by the call to the HTCSetCreditDistribution() api.
43503 + *
43504 + */
43505 +static void ar6000_credit_distribute(void *Context,
43506 + HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
43507 + HTC_CREDIT_DIST_REASON Reason)
43508 +{
43509 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
43510 + COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
43511 +
43512 + switch (Reason) {
43513 + case HTC_CREDIT_DIST_SEND_COMPLETE :
43514 + pCurEpDist = pEPDistList;
43515 + /* we are given the start of the endpoint distribution list.
43516 + * There may be one or more endpoints to service.
43517 + * Run through the list and distribute credits */
43518 + while (pCurEpDist != NULL) {
43519 +
43520 + if (pCurEpDist->TxCreditsToDist > 0) {
43521 + /* return the credits back to the endpoint */
43522 + pCurEpDist->TxCredits += pCurEpDist->TxCreditsToDist;
43523 + /* always zero out when we are done */
43524 + pCurEpDist->TxCreditsToDist = 0;
43525 +
43526 + if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsAssigned) {
43527 + /* reduce to the assigned limit, previous credit reductions
43528 + * could have caused the limit to change */
43529 + ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsAssigned);
43530 + }
43531 +
43532 + if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsNorm) {
43533 + /* oversubscribed endpoints need to reduce back to normal */
43534 + ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsNorm);
43535 + }
43536 + }
43537 +
43538 + pCurEpDist = pCurEpDist->pNext;
43539 + }
43540 +
43541 + A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits);
43542 +
43543 + break;
43544 +
43545 + case HTC_CREDIT_DIST_ACTIVITY_CHANGE :
43546 + RedistributeCredits(pCredInfo,pEPDistList);
43547 + break;
43548 + case HTC_CREDIT_DIST_SEEK_CREDITS :
43549 + SeekCredits(pCredInfo,pEPDistList);
43550 + break;
43551 + case HTC_DUMP_CREDIT_STATE :
43552 + AR_DEBUG_PRINTF(ATH_LOG_INF, ("Credit Distribution, total : %d, free : %d\n",
43553 + pCredInfo->TotalAvailableCredits, pCredInfo->CurrentFreeCredits));
43554 + break;
43555 + default:
43556 + break;
43557 +
43558 + }
43559 +
43560 +}
43561 +
43562 +/* redistribute credits based on activity change */
43563 +static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
43564 + HTC_ENDPOINT_CREDIT_DIST *pEPDistList)
43565 +{
43566 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist = pEPDistList;
43567 +
43568 + /* walk through the list and remove credits from inactive endpoints */
43569 + while (pCurEpDist != NULL) {
43570 +
43571 + if (pCurEpDist->ServiceID != WMI_CONTROL_SVC) {
43572 + if (!IS_EP_ACTIVE(pCurEpDist)) {
43573 + /* EP is inactive, reduce credits back to zero */
43574 + ReduceCredits(pCredInfo, pCurEpDist, 0);
43575 + }
43576 + }
43577 +
43578 + /* NOTE in the active case, we do not need to do anything further,
43579 + * when an EP goes active and needs credits, HTC will call into
43580 + * our distribution function using a reason code of HTC_CREDIT_DIST_SEEK_CREDITS */
43581 +
43582 + pCurEpDist = pCurEpDist->pNext;
43583 + }
43584 +
43585 + A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits);
43586 +
43587 +}
43588 +
43589 +/* HTC has an endpoint that needs credits, pEPDist is the endpoint in question */
43590 +static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
43591 + HTC_ENDPOINT_CREDIT_DIST *pEPDist)
43592 +{
43593 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
43594 + int credits = 0;
43595 + int need;
43596 +
43597 + do {
43598 +
43599 + if (pEPDist->ServiceID == WMI_CONTROL_SVC) {
43600 + /* we never oversubscribe on the control service, this is not
43601 + * a high performance path and the target never holds onto control
43602 + * credits for too long */
43603 + break;
43604 + }
43605 +
43606 + /* for all other services, we follow a simple algorithm of
43607 + * 1. checking the free pool for credits
43608 + * 2. checking lower priority endpoints for credits to take */
43609 +
43610 + if (pCredInfo->CurrentFreeCredits >= 2 * pEPDist->TxCreditsSeek) {
43611 + /* try to give more credits than it needs */
43612 + credits = 2 * pEPDist->TxCreditsSeek;
43613 + } else {
43614 + /* give what we can */
43615 + credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
43616 + }
43617 +
43618 + if (credits >= pEPDist->TxCreditsSeek) {
43619 + /* we found some to fullfill the seek request */
43620 + break;
43621 + }
43622 +
43623 + /* we don't have enough in the free pool, try taking away from lower priority services
43624 + *
43625 + * The rule for taking away credits:
43626 + * 1. Only take from lower priority endpoints
43627 + * 2. Only take what is allocated above the minimum (never starve an endpoint completely)
43628 + * 3. Only take what you need.
43629 + *
43630 + * */
43631 +
43632 + /* starting at the lowest priority */
43633 + pCurEpDist = pCredInfo->pLowestPriEpDist;
43634 +
43635 + /* work backwards until we hit the endpoint again */
43636 + while (pCurEpDist != pEPDist) {
43637 + /* calculate how many we need so far */
43638 + need = pEPDist->TxCreditsSeek - pCredInfo->CurrentFreeCredits;
43639 +
43640 + if ((pCurEpDist->TxCreditsAssigned - need) > pCurEpDist->TxCreditsMin) {
43641 + /* the current one has been allocated more than it's minimum and it
43642 + * has enough credits assigned above it's minimum to fullfill our need
43643 + * try to take away just enough to fullfill our need */
43644 + ReduceCredits(pCredInfo,
43645 + pCurEpDist,
43646 + pCurEpDist->TxCreditsAssigned - need);
43647 +
43648 + if (pCredInfo->CurrentFreeCredits >= pEPDist->TxCreditsSeek) {
43649 + /* we have enough */
43650 + break;
43651 + }
43652 + }
43653 +
43654 + pCurEpDist = pCurEpDist->pPrev;
43655 + }
43656 +
43657 + /* return what we can get */
43658 + credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
43659 +
43660 + } while (FALSE);
43661 +
43662 + /* did we find some credits? */
43663 + if (credits) {
43664 + /* give what we can */
43665 + GiveCredits(pCredInfo, pEPDist, credits);
43666 + }
43667 +
43668 +}
43669 +
43670 +/* initialize and setup credit distribution */
43671 +A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo)
43672 +{
43673 + HTC_SERVICE_ID servicepriority[5];
43674 +
43675 + A_MEMZERO(pCredInfo,sizeof(COMMON_CREDIT_STATE_INFO));
43676 +
43677 + servicepriority[0] = WMI_CONTROL_SVC; /* highest */
43678 + servicepriority[1] = WMI_DATA_VO_SVC;
43679 + servicepriority[2] = WMI_DATA_VI_SVC;
43680 + servicepriority[3] = WMI_DATA_BE_SVC;
43681 + servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */
43682 +
43683 + /* set callbacks and priority list */
43684 + HTCSetCreditDistribution(HTCHandle,
43685 + pCredInfo,
43686 + ar6000_credit_distribute,
43687 + ar6000_credit_init,
43688 + servicepriority,
43689 + 5);
43690 +
43691 + return A_OK;
43692 +}
43693 +
43694 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/wlan/wlan_node.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/wlan/wlan_node.c
43695 --- linux-2.6.29-rc3.owrt/drivers/ar6000/wlan/wlan_node.c 1970-01-01 01:00:00.000000000 +0100
43696 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/wlan/wlan_node.c 2009-05-10 22:27:59.000000000 +0200
43697 @@ -0,0 +1,371 @@
43698 +/*-
43699 + * Copyright (c) 2001 Atsushi Onoe
43700 + * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
43701 + * Copyright (c) 2004-2005 Atheros Communications
43702 + * All rights reserved.
43703 + *
43704 + * Redistribution and use in source and binary forms, with or without
43705 + * modification, are permitted provided that the following conditions
43706 + * are met:
43707 + * 1. Redistributions of source code must retain the above copyright
43708 + * notice, this list of conditions and the following disclaimer.
43709 + * 2. Redistributions in binary form must reproduce the above copyright
43710 + * notice, this list of conditions and the following disclaimer in the
43711 + * documentation and/or other materials provided with the distribution.
43712 + * 3. The name of the author may not be used to endorse or promote products
43713 + * derived from this software without specific prior written permission.
43714 + *
43715 + * Alternatively, this software may be distributed under the terms of the
43716 + * GNU General Public License ("GPL") version 2 as published by the Free
43717 + * Software Foundation.
43718 + *
43719 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
43720 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43721 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
43722 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
43723 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
43724 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
43725 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
43726 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
43727 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
43728 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
43729 + *
43730 + * $Id: //depot/sw/releases/olca2.0-GPL/host/wlan/src/wlan_node.c#1 $
43731 + */
43732 +/*
43733 + * IEEE 802.11 node handling support.
43734 + */
43735 +#include <a_config.h>
43736 +#include <athdefs.h>
43737 +#include <a_types.h>
43738 +#include <a_osapi.h>
43739 +#include <a_debug.h>
43740 +#include <ieee80211.h>
43741 +#include <wlan_api.h>
43742 +#include <ieee80211_node.h>
43743 +#include <htc_api.h>
43744 +#include <wmi.h>
43745 +#include <wmi_api.h>
43746 +
43747 +static void wlan_node_timeout(A_ATH_TIMER arg);
43748 +static bss_t * _ieee80211_find_node(struct ieee80211_node_table *nt,
43749 + const A_UINT8 *macaddr);
43750 +
43751 +bss_t *
43752 +wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size)
43753 +{
43754 + bss_t *ni;
43755 +
43756 + ni = A_MALLOC_NOWAIT(sizeof(bss_t));
43757 +
43758 + if (ni != NULL) {
43759 + ni->ni_buf = A_MALLOC_NOWAIT(wh_size);
43760 + if (ni->ni_buf == NULL) {
43761 + A_FREE(ni);
43762 + ni = NULL;
43763 + return ni;
43764 + }
43765 + } else {
43766 + return ni;
43767 + }
43768 +
43769 + /* Make sure our lists are clean */
43770 + ni->ni_list_next = NULL;
43771 + ni->ni_list_prev = NULL;
43772 + ni->ni_hash_next = NULL;
43773 + ni->ni_hash_prev = NULL;
43774 +
43775 + //
43776 + // ni_scangen never initialized before and during suspend/resume of winmobile, customer (LG/SEMCO) identified
43777 + // that some junk has been stored in this, due to this scan list didn't properly updated
43778 + //
43779 + ni->ni_scangen = 0;
43780 +
43781 + return ni;
43782 +}
43783 +
43784 +void
43785 +wlan_node_free(bss_t *ni)
43786 +{
43787 + if (ni->ni_buf != NULL) {
43788 + A_FREE(ni->ni_buf);
43789 + }
43790 + A_FREE(ni);
43791 +}
43792 +
43793 +void
43794 +wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
43795 + const A_UINT8 *macaddr)
43796 +{
43797 + int hash;
43798 +
43799 + A_MEMCPY(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN);
43800 + hash = IEEE80211_NODE_HASH(macaddr);
43801 + ieee80211_node_initref(ni); /* mark referenced */
43802 +
43803 + ni->ni_tstamp = A_GET_MS(WLAN_NODE_INACT_TIMEOUT_MSEC);
43804 + IEEE80211_NODE_LOCK_BH(nt);
43805 +
43806 + /* Insert at the end of the node list */
43807 + ni->ni_list_next = NULL;
43808 + ni->ni_list_prev = nt->nt_node_last;
43809 + if(nt->nt_node_last != NULL)
43810 + {
43811 + nt->nt_node_last->ni_list_next = ni;
43812 + }
43813 + nt->nt_node_last = ni;
43814 + if(nt->nt_node_first == NULL)
43815 + {
43816 + nt->nt_node_first = ni;
43817 + }
43818 +
43819 + /* Insert into the hash list i.e. the bucket */
43820 + if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL)
43821 + {
43822 + nt->nt_hash[hash]->ni_hash_prev = ni;
43823 + }
43824 + ni->ni_hash_prev = NULL;
43825 + nt->nt_hash[hash] = ni;
43826 +
43827 + if (!nt->isTimerArmed) {
43828 + A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0);
43829 + nt->isTimerArmed = TRUE;
43830 + }
43831 +
43832 + IEEE80211_NODE_UNLOCK_BH(nt);
43833 +}
43834 +
43835 +static bss_t *
43836 +_ieee80211_find_node(struct ieee80211_node_table *nt,
43837 + const A_UINT8 *macaddr)
43838 +{
43839 + bss_t *ni;
43840 + int hash;
43841 +
43842 + IEEE80211_NODE_LOCK_ASSERT(nt);
43843 +
43844 + hash = IEEE80211_NODE_HASH(macaddr);
43845 + for(ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) {
43846 + if (IEEE80211_ADDR_EQ(ni->ni_macaddr, macaddr)) {
43847 + ieee80211_node_incref(ni); /* mark referenced */
43848 + return ni;
43849 + }
43850 + }
43851 + return NULL;
43852 +}
43853 +
43854 +bss_t *
43855 +wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr)
43856 +{
43857 + bss_t *ni;
43858 +
43859 + IEEE80211_NODE_LOCK(nt);
43860 + ni = _ieee80211_find_node(nt, macaddr);
43861 + IEEE80211_NODE_UNLOCK(nt);
43862 + return ni;
43863 +}
43864 +
43865 +/*
43866 + * Reclaim a node. If this is the last reference count then
43867 + * do the normal free work. Otherwise remove it from the node
43868 + * table and mark it gone by clearing the back-reference.
43869 + */
43870 +void
43871 +wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni)
43872 +{
43873 + IEEE80211_NODE_LOCK(nt);
43874 +
43875 + if(ni->ni_list_prev == NULL)
43876 + {
43877 + /* First in list so fix the list head */
43878 + nt->nt_node_first = ni->ni_list_next;
43879 + }
43880 + else
43881 + {
43882 + ni->ni_list_prev->ni_list_next = ni->ni_list_next;
43883 + }
43884 +
43885 + if(ni->ni_list_next == NULL)
43886 + {
43887 + /* Last in list so fix list tail */
43888 + nt->nt_node_last = ni->ni_list_prev;
43889 + }
43890 + else
43891 + {
43892 + ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
43893 + }
43894 +
43895 + if(ni->ni_hash_prev == NULL)
43896 + {
43897 + /* First in list so fix the list head */
43898 + int hash;
43899 + hash = IEEE80211_NODE_HASH(ni->ni_macaddr);
43900 + nt->nt_hash[hash] = ni->ni_hash_next;
43901 + }
43902 + else
43903 + {
43904 + ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
43905 + }
43906 +
43907 + if(ni->ni_hash_next != NULL)
43908 + {
43909 + ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
43910 + }
43911 + wlan_node_free(ni);
43912 +
43913 + IEEE80211_NODE_UNLOCK(nt);
43914 +}
43915 +
43916 +static void
43917 +wlan_node_dec_free(bss_t *ni)
43918 +{
43919 + if (ieee80211_node_dectestref(ni)) {
43920 + wlan_node_free(ni);
43921 + }
43922 +}
43923 +
43924 +void
43925 +wlan_free_allnodes(struct ieee80211_node_table *nt)
43926 +{
43927 + bss_t *ni;
43928 +
43929 + while ((ni = nt->nt_node_first) != NULL) {
43930 + wlan_node_reclaim(nt, ni);
43931 + }
43932 +}
43933 +
43934 +void
43935 +wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
43936 + void *arg)
43937 +{
43938 + bss_t *ni;
43939 + A_UINT32 gen;
43940 +
43941 + gen = ++nt->nt_scangen;
43942 +
43943 + IEEE80211_NODE_LOCK(nt);
43944 + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
43945 + if (ni->ni_scangen != gen) {
43946 + ni->ni_scangen = gen;
43947 + (void) ieee80211_node_incref(ni);
43948 + (*f)(arg, ni);
43949 + wlan_node_dec_free(ni);
43950 + }
43951 + }
43952 + IEEE80211_NODE_UNLOCK(nt);
43953 +}
43954 +
43955 +/*
43956 + * Node table support.
43957 + */
43958 +void
43959 +wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt)
43960 +{
43961 + int i;
43962 +
43963 + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN, ("node table = 0x%x\n", (A_UINT32)nt));
43964 + IEEE80211_NODE_LOCK_INIT(nt);
43965 +
43966 + nt->nt_node_first = nt->nt_node_last = NULL;
43967 + for(i = 0; i < IEEE80211_NODE_HASHSIZE; i++)
43968 + {
43969 + nt->nt_hash[i] = NULL;
43970 + }
43971 + A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt);
43972 + nt->isTimerArmed = FALSE;
43973 + nt->nt_wmip = wmip;
43974 +}
43975 +
43976 +static void
43977 +wlan_node_timeout(A_ATH_TIMER arg)
43978 +{
43979 + struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg;
43980 + bss_t *bss, *nextBss;
43981 + A_UINT8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = FALSE;
43982 +
43983 + wmi_get_current_bssid(nt->nt_wmip, myBssid);
43984 +
43985 + bss = nt->nt_node_first;
43986 + while (bss != NULL)
43987 + {
43988 + nextBss = bss->ni_list_next;
43989 + if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
43990 + {
43991 +
43992 + if (bss->ni_tstamp <= A_GET_MS(0))
43993 + {
43994 + /*
43995 + * free up all but the current bss - if set
43996 + */
43997 + wlan_node_reclaim(nt, bss);
43998 + }
43999 + else
44000 + {
44001 + /*
44002 + * Re-arm timer, only when we have a bss other than
44003 + * current bss AND it is not aged-out.
44004 + */
44005 + reArmTimer = TRUE;
44006 + }
44007 + }
44008 + bss = nextBss;
44009 + }
44010 +
44011 + if(reArmTimer)
44012 + A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0);
44013 +
44014 + nt->isTimerArmed = reArmTimer;
44015 +}
44016 +
44017 +void
44018 +wlan_node_table_cleanup(struct ieee80211_node_table *nt)
44019 +{
44020 + A_UNTIMEOUT(&nt->nt_inact_timer);
44021 + A_DELETE_TIMER(&nt->nt_inact_timer);
44022 + wlan_free_allnodes(nt);
44023 + IEEE80211_NODE_LOCK_DESTROY(nt);
44024 +}
44025 +
44026 +bss_t *
44027 +wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
44028 + A_UINT32 ssidLength, A_BOOL bIsWPA2)
44029 +{
44030 + bss_t *ni = NULL;
44031 + A_UCHAR *pIESsid = NULL;
44032 +
44033 + IEEE80211_NODE_LOCK (nt);
44034 +
44035 + for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
44036 + pIESsid = ni->ni_cie.ie_ssid;
44037 + if (pIESsid[1] <= 32) {
44038 +
44039 + // Step 1 : Check SSID
44040 + if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {
44041 +
44042 + // Step 2 : if SSID matches, check WPA or WPA2
44043 + if (TRUE == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) {
44044 + ieee80211_node_incref (ni); /* mark referenced */
44045 + IEEE80211_NODE_UNLOCK (nt);
44046 + return ni;
44047 + }
44048 + if (FALSE == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) {
44049 + ieee80211_node_incref(ni); /* mark referenced */
44050 + IEEE80211_NODE_UNLOCK (nt);
44051 + return ni;
44052 + }
44053 + }
44054 + }
44055 + }
44056 +
44057 + IEEE80211_NODE_UNLOCK (nt);
44058 +
44059 + return NULL;
44060 +}
44061 +
44062 +void
44063 +wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni)
44064 +{
44065 + IEEE80211_NODE_LOCK (nt);
44066 + wlan_node_dec_free (ni);
44067 + IEEE80211_NODE_UNLOCK (nt);
44068 +}
44069 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/wlan/wlan_recv_beacon.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/wlan/wlan_recv_beacon.c
44070 --- linux-2.6.29-rc3.owrt/drivers/ar6000/wlan/wlan_recv_beacon.c 1970-01-01 01:00:00.000000000 +0100
44071 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/wlan/wlan_recv_beacon.c 2009-05-10 22:27:59.000000000 +0200
44072 @@ -0,0 +1,192 @@
44073 +/*-
44074 + * Copyright (c) 2001 Atsushi Onoe
44075 + * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
44076 + * All rights reserved.
44077 + *
44078 + * Redistribution and use in source and binary forms, with or without
44079 + * modification, are permitted provided that the following conditions
44080 + * are met:
44081 + * 1. Redistributions of source code must retain the above copyright
44082 + * notice, this list of conditions and the following disclaimer.
44083 + * 2. Redistributions in binary form must reproduce the above copyright
44084 + * notice, this list of conditions and the following disclaimer in the
44085 + * documentation and/or other materials provided with the distribution.
44086 + * 3. The name of the author may not be used to endorse or promote products
44087 + * derived from this software without specific prior written permission.
44088 + *
44089 + * Alternatively, this software may be distributed under the terms of the
44090 + * GNU General Public License ("GPL") version 2 as published by the Free
44091 + * Software Foundation.
44092 + *
44093 + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
44094 + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
44095 + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
44096 + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
44097 + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
44098 + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
44099 + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
44100 + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44101 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
44102 + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
44103 + */
44104 +/*
44105 + * IEEE 802.11 input handling.
44106 + */
44107 +
44108 +#include "a_config.h"
44109 +#include "athdefs.h"
44110 +#include "a_types.h"
44111 +#include "a_osapi.h"
44112 +#include <wmi.h>
44113 +#include <ieee80211.h>
44114 +#include <wlan_api.h>
44115 +
44116 +#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \
44117 + if ((_len) < (_minlen)) { \
44118 + return A_EINVAL; \
44119 + } \
44120 +} while (0)
44121 +
44122 +#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \
44123 + if ((__elem) == NULL) { \
44124 + return A_EINVAL; \
44125 + } \
44126 + if ((__elem)[1] > (__maxlen)) { \
44127 + return A_EINVAL; \
44128 + } \
44129 +} while (0)
44130 +
44131 +
44132 +/* unaligned little endian access */
44133 +#define LE_READ_2(p) \
44134 + ((A_UINT16) \
44135 + ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8)))
44136 +
44137 +#define LE_READ_4(p) \
44138 + ((A_UINT32) \
44139 + ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8) | \
44140 + (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24)))
44141 +
44142 +
44143 +static int __inline
44144 +iswpaoui(const A_UINT8 *frm)
44145 +{
44146 + return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
44147 +}
44148 +
44149 +static int __inline
44150 +iswmmoui(const A_UINT8 *frm)
44151 +{
44152 + return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
44153 +}
44154 +
44155 +static int __inline
44156 +iswmmparam(const A_UINT8 *frm)
44157 +{
44158 + return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
44159 +}
44160 +
44161 +static int __inline
44162 +iswmminfo(const A_UINT8 *frm)
44163 +{
44164 + return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE;
44165 +}
44166 +
44167 +static int __inline
44168 +isatherosoui(const A_UINT8 *frm)
44169 +{
44170 + return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
44171 +}
44172 +
44173 +static int __inline
44174 +iswscoui(const A_UINT8 *frm)
44175 +{
44176 + return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI);
44177 +}
44178 +
44179 +A_STATUS
44180 +wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie)
44181 +{
44182 + A_UINT8 *frm, *efrm;
44183 +
44184 + frm = buf;
44185 + efrm = (A_UINT8 *) (frm + framelen);
44186 +
44187 + /*
44188 + * beacon/probe response frame format
44189 + * [8] time stamp
44190 + * [2] beacon interval
44191 + * [2] capability information
44192 + * [tlv] ssid
44193 + * [tlv] supported rates
44194 + * [tlv] country information
44195 + * [tlv] parameter set (FH/DS)
44196 + * [tlv] erp information
44197 + * [tlv] extended supported rates
44198 + * [tlv] WMM
44199 + * [tlv] WPA or RSN
44200 + * [tlv] Atheros Advanced Capabilities
44201 + */
44202 + IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
44203 + A_MEMZERO(cie, sizeof(*cie));
44204 +
44205 + cie->ie_tstamp = frm; frm += 8;
44206 + cie->ie_beaconInt = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2;
44207 + cie->ie_capInfo = A_LE2CPU16(*(A_UINT16 *)frm); frm += 2;
44208 + cie->ie_chan = 0;
44209 +
44210 + while (frm < efrm) {
44211 + switch (*frm) {
44212 + case IEEE80211_ELEMID_SSID:
44213 + cie->ie_ssid = frm;
44214 + break;
44215 + case IEEE80211_ELEMID_RATES:
44216 + cie->ie_rates = frm;
44217 + break;
44218 + case IEEE80211_ELEMID_COUNTRY:
44219 + cie->ie_country = frm;
44220 + break;
44221 + case IEEE80211_ELEMID_FHPARMS:
44222 + break;
44223 + case IEEE80211_ELEMID_DSPARMS:
44224 + cie->ie_chan = frm[2];
44225 + break;
44226 + case IEEE80211_ELEMID_TIM:
44227 + cie->ie_tim = frm;
44228 + break;
44229 + case IEEE80211_ELEMID_IBSSPARMS:
44230 + break;
44231 + case IEEE80211_ELEMID_XRATES:
44232 + cie->ie_xrates = frm;
44233 + break;
44234 + case IEEE80211_ELEMID_ERP:
44235 + if (frm[1] != 1) {
44236 + //A_PRINTF("Discarding ERP Element - Bad Len\n");
44237 + return A_EINVAL;
44238 + }
44239 + cie->ie_erp = frm[2];
44240 + break;
44241 + case IEEE80211_ELEMID_RSN:
44242 + cie->ie_rsn = frm;
44243 + break;
44244 + case IEEE80211_ELEMID_VENDOR:
44245 + if (iswpaoui(frm)) {
44246 + cie->ie_wpa = frm;
44247 + } else if (iswmmoui(frm)) {
44248 + cie->ie_wmm = frm;
44249 + } else if (isatherosoui(frm)) {
44250 + cie->ie_ath = frm;
44251 + } else if(iswscoui(frm)) {
44252 + cie->ie_wsc = frm;
44253 + }
44254 + break;
44255 + default:
44256 + break;
44257 + }
44258 + frm += frm[1] + 2;
44259 + }
44260 + IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE);
44261 + IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN);
44262 +
44263 + return A_OK;
44264 +}
44265 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/wlan/wlan_utils.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/wlan/wlan_utils.c
44266 --- linux-2.6.29-rc3.owrt/drivers/ar6000/wlan/wlan_utils.c 1970-01-01 01:00:00.000000000 +0100
44267 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/wlan/wlan_utils.c 2009-05-10 22:27:59.000000000 +0200
44268 @@ -0,0 +1,59 @@
44269 +/*
44270 + * Copyright (c) 2004-2005 Atheros Communications Inc.
44271 + * All rights reserved.
44272 + *
44273 + * This module implements frequently used wlan utilies
44274 + *
44275 + * $Id: //depot/sw/releases/olca2.0-GPL/host/wlan/src/wlan_utils.c#1 $
44276 + *
44277 + *
44278 + * This program is free software; you can redistribute it and/or modify
44279 + * it under the terms of the GNU General Public License version 2 as
44280 + * published by the Free Software Foundation;
44281 + *
44282 + * Software distributed under the License is distributed on an "AS
44283 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
44284 + * implied. See the License for the specific language governing
44285 + * rights and limitations under the License.
44286 + *
44287 + *
44288 + *
44289 + */
44290 +
44291 +#include <a_config.h>
44292 +#include <athdefs.h>
44293 +#include <a_types.h>
44294 +#include <a_osapi.h>
44295 +
44296 +/*
44297 + * converts ieee channel number to frequency
44298 + */
44299 +A_UINT16
44300 +wlan_ieee2freq(int chan)
44301 +{
44302 + if (chan == 14) {
44303 + return 2484;
44304 + }
44305 + if (chan < 14) { /* 0-13 */
44306 + return (2407 + (chan*5));
44307 + }
44308 + if (chan < 27) { /* 15-26 */
44309 + return (2512 + ((chan-15)*20));
44310 + }
44311 + return (5000 + (chan*5));
44312 +}
44313 +
44314 +/*
44315 + * Converts MHz frequency to IEEE channel number.
44316 + */
44317 +A_UINT32
44318 +wlan_freq2ieee(A_UINT16 freq)
44319 +{
44320 + if (freq == 2484)
44321 + return 14;
44322 + if (freq < 2484)
44323 + return (freq - 2407) / 5;
44324 + if (freq < 5000)
44325 + return 15 + ((freq - 2512) / 20);
44326 + return (freq - 5000) / 5;
44327 +}
44328 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/wmi/wmi.c linux-2.6.29-rc3.owrt.om/drivers/ar6000/wmi/wmi.c
44329 --- linux-2.6.29-rc3.owrt/drivers/ar6000/wmi/wmi.c 1970-01-01 01:00:00.000000000 +0100
44330 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/wmi/wmi.c 2009-05-10 22:27:59.000000000 +0200
44331 @@ -0,0 +1,3954 @@
44332 +/*
44333 + * Copyright (c) 2004-2007 Atheros Communications Inc.
44334 + * All rights reserved.
44335 + *
44336 + * This module implements the hardware independent layer of the
44337 + * Wireless Module Interface (WMI) protocol.
44338 + *
44339 + * $Id: //depot/sw/releases/olca2.0-GPL/host/wmi/wmi.c#3 $
44340 + *
44341 + *
44342 + * This program is free software; you can redistribute it and/or modify
44343 + * it under the terms of the GNU General Public License version 2 as
44344 + * published by the Free Software Foundation;
44345 + *
44346 + * Software distributed under the License is distributed on an "AS
44347 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
44348 + * implied. See the License for the specific language governing
44349 + * rights and limitations under the License.
44350 + *
44351 + *
44352 + *
44353 + */
44354 +
44355 +#include <a_config.h>
44356 +#include <athdefs.h>
44357 +#include <a_types.h>
44358 +#include <a_osapi.h>
44359 +#include "htc.h"
44360 +#include "htc_api.h"
44361 +#include "wmi.h"
44362 +#include <ieee80211.h>
44363 +#include <ieee80211_node.h>
44364 +#include <wlan_api.h>
44365 +#include <wmi_api.h>
44366 +#include "dset_api.h"
44367 +#include "gpio_api.h"
44368 +#include "wmi_host.h"
44369 +#include "a_drv.h"
44370 +#include "a_drv_api.h"
44371 +#include "a_debug.h"
44372 +#include "dbglog_api.h"
44373 +
44374 +static A_STATUS wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44375 +
44376 +static A_STATUS wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44377 + int len);
44378 +static A_STATUS wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44379 + int len);
44380 +static A_STATUS wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44381 + int len);
44382 +static A_STATUS wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44383 + int len);
44384 +static A_STATUS wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44385 + int len);
44386 +static A_STATUS wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44387 + int len);
44388 +static A_STATUS wmi_sync_point(struct wmi_t *wmip);
44389 +
44390 +static A_STATUS wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
44391 + int len);
44392 +static A_STATUS wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
44393 + int len);
44394 +static A_STATUS wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
44395 + int len);
44396 +static A_STATUS wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44397 + int len);
44398 +static A_STATUS wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44399 +static A_STATUS wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44400 + int len);
44401 +
44402 +static A_STATUS wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap,
44403 + int len);
44404 +#ifdef CONFIG_HOST_DSET_SUPPORT
44405 +static A_STATUS wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44406 +static A_STATUS wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap,
44407 + int len);
44408 +#endif /* CONFIG_HOST_DSET_SUPPORT */
44409 +
44410 +
44411 +static A_STATUS wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap,
44412 + int len);
44413 +static A_STATUS wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44414 +static A_STATUS wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44415 +static A_STATUS wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44416 +static A_STATUS wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44417 +static A_STATUS wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44418 +static A_STATUS wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44419 +static A_STATUS wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44420 + int len);
44421 +static A_STATUS wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44422 + int len);
44423 +static A_STATUS wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44424 + int len);
44425 +static A_STATUS
44426 +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len);
44427 +
44428 +#ifdef CONFIG_HOST_GPIO_SUPPORT
44429 +static A_STATUS wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44430 +static A_STATUS wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44431 +static A_STATUS wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44432 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
44433 +
44434 +#ifdef CONFIG_HOST_TCMD_SUPPORT
44435 +static A_STATUS
44436 +wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44437 +#endif
44438 +
44439 +static A_STATUS
44440 +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44441 +
44442 +static A_STATUS
44443 +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44444 +
44445 +static A_STATUS
44446 +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44447 +
44448 +static A_BOOL
44449 +wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex);
44450 +
44451 +static A_STATUS
44452 +wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44453 +
44454 +static A_STATUS
44455 +wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44456 +
44457 +static A_STATUS wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44458 +
44459 +int wps_enable;
44460 +static const A_INT32 wmi_rateTable[] = {
44461 + 1000,
44462 + 2000,
44463 + 5500,
44464 + 11000,
44465 + 6000,
44466 + 9000,
44467 + 12000,
44468 + 18000,
44469 + 24000,
44470 + 36000,
44471 + 48000,
44472 + 54000,
44473 + 0};
44474 +
44475 +#define MODE_A_SUPPORT_RATE_START 4
44476 +#define MODE_A_SUPPORT_RATE_STOP 11
44477 +
44478 +#define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START
44479 +#define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP
44480 +
44481 +#define MODE_B_SUPPORT_RATE_START 0
44482 +#define MODE_B_SUPPORT_RATE_STOP 3
44483 +
44484 +#define MODE_G_SUPPORT_RATE_START 0
44485 +#define MODE_G_SUPPORT_RATE_STOP 11
44486 +
44487 +#define MAX_NUMBER_OF_SUPPORT_RATES (MODE_G_SUPPORT_RATE_STOP + 1)
44488 +
44489 +/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
44490 +const A_UINT8 up_to_ac[]= {
44491 + WMM_AC_BE,
44492 + WMM_AC_BK,
44493 + WMM_AC_BK,
44494 + WMM_AC_BE,
44495 + WMM_AC_VI,
44496 + WMM_AC_VI,
44497 + WMM_AC_VO,
44498 + WMM_AC_VO,
44499 + };
44500 +
44501 +void *
44502 +wmi_init(void *devt)
44503 +{
44504 + struct wmi_t *wmip;
44505 +
44506 + wmip = A_MALLOC(sizeof(struct wmi_t));
44507 + if (wmip == NULL) {
44508 + return (NULL);
44509 + }
44510 + A_MEMZERO(wmip, sizeof(*wmip));
44511 + A_MUTEX_INIT(&wmip->wmi_lock);
44512 + wmip->wmi_devt = devt;
44513 + wlan_node_table_init(wmip, &wmip->wmi_scan_table);
44514 + wmi_qos_state_init(wmip);
44515 + wmip->wmi_powerMode = REC_POWER;
44516 + wmip->wmi_phyMode = WMI_11G_MODE;
44517 +
44518 + return (wmip);
44519 +}
44520 +
44521 +void
44522 +wmi_qos_state_init(struct wmi_t *wmip)
44523 +{
44524 + A_UINT8 i;
44525 +
44526 + if (wmip == NULL) {
44527 + return;
44528 + }
44529 + LOCK_WMI(wmip);
44530 +
44531 + /* Initialize QoS States */
44532 + wmip->wmi_numQoSStream = 0;
44533 +
44534 + wmip->wmi_fatPipeExists = 0;
44535 +
44536 + for (i=0; i < WMM_NUM_AC; i++) {
44537 + wmip->wmi_streamExistsForAC[i]=0;
44538 + }
44539 +
44540 + /* Initialize the static Wmi stream Pri to WMM AC mappings Arrays */
44541 + WMI_INIT_WMISTREAM_AC_MAP(wmip);
44542 +
44543 + UNLOCK_WMI(wmip);
44544 +
44545 + A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1);
44546 +}
44547 +
44548 +void
44549 +wmi_shutdown(struct wmi_t *wmip)
44550 +{
44551 + if (wmip != NULL) {
44552 + wlan_node_table_cleanup(&wmip->wmi_scan_table);
44553 + if (A_IS_MUTEX_VALID(&wmip->wmi_lock)) {
44554 + A_MUTEX_DELETE(&wmip->wmi_lock);
44555 + }
44556 + A_FREE(wmip);
44557 + }
44558 +}
44559 +
44560 +/*
44561 + * performs DIX to 802.3 encapsulation for transmit packets.
44562 + * uses passed in buffer. Returns buffer or NULL if failed.
44563 + * Assumes the entire DIX header is contigous and that there is
44564 + * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
44565 + */
44566 +A_STATUS
44567 +wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
44568 +{
44569 + A_UINT8 *datap;
44570 + A_UINT16 typeorlen;
44571 + ATH_MAC_HDR macHdr;
44572 + ATH_LLC_SNAP_HDR *llcHdr;
44573 +
44574 + A_ASSERT(osbuf != NULL);
44575 +
44576 + if (A_NETBUF_HEADROOM(osbuf) <
44577 + (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
44578 + {
44579 + return A_NO_MEMORY;
44580 + }
44581 +
44582 + datap = A_NETBUF_DATA(osbuf);
44583 +
44584 + typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
44585 +
44586 + if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
44587 + /*
44588 + * packet is already in 802.3 format - return success
44589 + */
44590 + A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
44591 + return (A_OK);
44592 + }
44593 +
44594 + /*
44595 + * Save mac fields and length to be inserted later
44596 + */
44597 + A_MEMCPY(macHdr.dstMac, datap, ATH_MAC_LEN);
44598 + A_MEMCPY(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
44599 + macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
44600 + sizeof(ATH_LLC_SNAP_HDR));
44601 +
44602 + /*
44603 + * Make room for LLC+SNAP headers
44604 + */
44605 + if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
44606 + return A_NO_MEMORY;
44607 + }
44608 +
44609 + datap = A_NETBUF_DATA(osbuf);
44610 +
44611 + A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
44612 +
44613 + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
44614 + llcHdr->dsap = 0xAA;
44615 + llcHdr->ssap = 0xAA;
44616 + llcHdr->cntl = 0x03;
44617 + llcHdr->orgCode[0] = 0x0;
44618 + llcHdr->orgCode[1] = 0x0;
44619 + llcHdr->orgCode[2] = 0x0;
44620 + llcHdr->etherType = typeorlen;
44621 +
44622 + return (A_OK);
44623 +}
44624 +
44625 +/*
44626 + * Adds a WMI data header
44627 + * Assumes there is enough room in the buffer to add header.
44628 + */
44629 +A_STATUS
44630 +wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType)
44631 +{
44632 + WMI_DATA_HDR *dtHdr;
44633 +
44634 + A_ASSERT(osbuf != NULL);
44635 +
44636 + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
44637 + return A_NO_MEMORY;
44638 + }
44639 +
44640 + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
44641 + dtHdr->info = msgType;
44642 + dtHdr->rssi = 0;
44643 +
44644 + return (A_OK);
44645 +}
44646 +
44647 +A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT8 dir, A_UINT8 up)
44648 +{
44649 + A_UINT8 *datap;
44650 + A_UINT8 trafficClass = WMM_AC_BE, userPriority = up;
44651 + ATH_LLC_SNAP_HDR *llcHdr;
44652 + A_UINT16 ipType = IP_ETHERTYPE;
44653 + WMI_DATA_HDR *dtHdr;
44654 + WMI_CREATE_PSTREAM_CMD cmd;
44655 + A_BOOL streamExists = FALSE;
44656 +
44657 + A_ASSERT(osbuf != NULL);
44658 +
44659 + datap = A_NETBUF_DATA(osbuf);
44660 +
44661 + if (up == UNDEFINED_PRI) {
44662 + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) +
44663 + sizeof(ATH_MAC_HDR));
44664 +
44665 + if (llcHdr->etherType == A_CPU2BE16(ipType)) {
44666 + /* Extract the endpoint info from the TOS field in the IP header */
44667 + userPriority = A_WMI_IPTOS_TO_USERPRIORITY(((A_UINT8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR));
44668 + }
44669 + }
44670 +
44671 + if (userPriority < MAX_NUM_PRI) {
44672 + trafficClass = convert_userPriority_to_trafficClass(userPriority);
44673 + }
44674 +
44675 + dtHdr = (WMI_DATA_HDR *)datap;
44676 + if(dir==UPLINK_TRAFFIC)
44677 + dtHdr->info |= (userPriority & WMI_DATA_HDR_UP_MASK) << WMI_DATA_HDR_UP_SHIFT; /* lower 3-bits are 802.1d priority */
44678 +
44679 + LOCK_WMI(wmip);
44680 + streamExists = wmip->wmi_fatPipeExists;
44681 + UNLOCK_WMI(wmip);
44682 +
44683 + if (!(streamExists & (1 << trafficClass))) {
44684 +
44685 + A_MEMZERO(&cmd, sizeof(cmd));
44686 + cmd.trafficClass = trafficClass;
44687 + cmd.userPriority = userPriority;
44688 + cmd.inactivityInt = WMI_IMPLICIT_PSTREAM_INACTIVITY_INT;
44689 + /* Implicit streams are created with TSID 0xFF */
44690 + cmd.tsid = WMI_IMPLICIT_PSTREAM;
44691 + wmi_create_pstream_cmd(wmip, &cmd);
44692 + }
44693 +
44694 + return trafficClass;
44695 +}
44696 +
44697 +WMI_PRI_STREAM_ID
44698 +wmi_get_stream_id(struct wmi_t *wmip, A_UINT8 trafficClass)
44699 +{
44700 + return WMI_ACCESSCATEGORY_WMISTREAM(wmip, trafficClass);
44701 +}
44702 +
44703 +/*
44704 + * performs 802.3 to DIX encapsulation for received packets.
44705 + * Assumes the entire 802.3 header is contigous.
44706 + */
44707 +A_STATUS
44708 +wmi_dot3_2_dix(struct wmi_t *wmip, void *osbuf)
44709 +{
44710 + A_UINT8 *datap;
44711 + ATH_MAC_HDR macHdr;
44712 + ATH_LLC_SNAP_HDR *llcHdr;
44713 +
44714 + A_ASSERT(osbuf != NULL);
44715 + datap = A_NETBUF_DATA(osbuf);
44716 +
44717 + A_MEMCPY(&macHdr, datap, sizeof(ATH_MAC_HDR));
44718 + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
44719 + macHdr.typeOrLen = llcHdr->etherType;
44720 +
44721 + if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
44722 + return A_NO_MEMORY;
44723 + }
44724 +
44725 + datap = A_NETBUF_DATA(osbuf);
44726 +
44727 + A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
44728 +
44729 + return (A_OK);
44730 +}
44731 +
44732 +/*
44733 + * Removes a WMI data header
44734 + */
44735 +A_STATUS
44736 +wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
44737 +{
44738 + A_ASSERT(osbuf != NULL);
44739 +
44740 + return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR)));
44741 +}
44742 +
44743 +void
44744 +wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
44745 +{
44746 + wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);
44747 +}
44748 +
44749 +/*
44750 + * WMI Extended Event received from Target.
44751 + */
44752 +A_STATUS
44753 +wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
44754 +{
44755 + WMIX_CMD_HDR *cmd;
44756 + A_UINT16 id;
44757 + A_UINT8 *datap;
44758 + A_UINT32 len;
44759 + A_STATUS status = A_OK;
44760 +
44761 + if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) {
44762 + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
44763 + wmip->wmi_stats.cmd_len_err++;
44764 + A_NETBUF_FREE(osbuf);
44765 + return A_ERROR;
44766 + }
44767 +
44768 + cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
44769 + id = cmd->commandId;
44770 +
44771 + if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {
44772 + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
44773 + wmip->wmi_stats.cmd_len_err++;
44774 + A_NETBUF_FREE(osbuf);
44775 + return A_ERROR;
44776 + }
44777 +
44778 + datap = A_NETBUF_DATA(osbuf);
44779 + len = A_NETBUF_LEN(osbuf);
44780 +
44781 + switch (id) {
44782 + case (WMIX_DSETOPENREQ_EVENTID):
44783 + status = wmi_dset_open_req_rx(wmip, datap, len);
44784 + break;
44785 +#ifdef CONFIG_HOST_DSET_SUPPORT
44786 + case (WMIX_DSETCLOSE_EVENTID):
44787 + status = wmi_dset_close_rx(wmip, datap, len);
44788 + break;
44789 + case (WMIX_DSETDATAREQ_EVENTID):
44790 + status = wmi_dset_data_req_rx(wmip, datap, len);
44791 + break;
44792 +#endif /* CONFIG_HOST_DSET_SUPPORT */
44793 +#ifdef CONFIG_HOST_GPIO_SUPPORT
44794 + case (WMIX_GPIO_INTR_EVENTID):
44795 + wmi_gpio_intr_rx(wmip, datap, len);
44796 + break;
44797 + case (WMIX_GPIO_DATA_EVENTID):
44798 + wmi_gpio_data_rx(wmip, datap, len);
44799 + break;
44800 + case (WMIX_GPIO_ACK_EVENTID):
44801 + wmi_gpio_ack_rx(wmip, datap, len);
44802 + break;
44803 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
44804 + case (WMIX_HB_CHALLENGE_RESP_EVENTID):
44805 + wmi_hbChallengeResp_rx(wmip, datap, len);
44806 + break;
44807 + case (WMIX_DBGLOG_EVENTID):
44808 + wmi_dbglog_event_rx(wmip, datap, len);
44809 + break;
44810 + default:
44811 + A_DPRINTF(DBG_WMI|DBG_ERROR,
44812 + (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
44813 + wmip->wmi_stats.cmd_id_err++;
44814 + status = A_ERROR;
44815 + break;
44816 + }
44817 +
44818 + return status;
44819 +}
44820 +
44821 +/*
44822 + * Control Path
44823 + */
44824 +A_UINT32 cmdRecvNum;
44825 +
44826 +A_STATUS
44827 +wmi_control_rx(struct wmi_t *wmip, void *osbuf)
44828 +{
44829 + WMI_CMD_HDR *cmd;
44830 + A_UINT16 id;
44831 + A_UINT8 *datap;
44832 + A_UINT32 len, i, loggingReq;
44833 + A_STATUS status = A_OK;
44834 +
44835 + A_ASSERT(osbuf != NULL);
44836 + if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) {
44837 + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
44838 + wmip->wmi_stats.cmd_len_err++;
44839 + A_NETBUF_FREE(osbuf);
44840 + return A_ERROR;
44841 + }
44842 +
44843 + cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
44844 + id = cmd->commandId;
44845 +
44846 + if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
44847 + A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
44848 + wmip->wmi_stats.cmd_len_err++;
44849 + A_NETBUF_FREE(osbuf);
44850 + return A_ERROR;
44851 + }
44852 +
44853 + datap = A_NETBUF_DATA(osbuf);
44854 + len = A_NETBUF_LEN(osbuf);
44855 +
44856 + ar6000_get_driver_cfg(wmip->wmi_devt,
44857 + AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS,
44858 + &loggingReq);
44859 +
44860 + if(loggingReq) {
44861 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI %d \n",id));
44862 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("WMI recv, MsgNo %d : ", cmdRecvNum));
44863 + for(i = 0; i < len; i++)
44864 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("%x ", datap[i]));
44865 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("\n"));
44866 + }
44867 +
44868 + LOCK_WMI(wmip);
44869 + cmdRecvNum++;
44870 + UNLOCK_WMI(wmip);
44871 +
44872 + switch (id) {
44873 + case (WMI_GET_BITRATE_CMDID):
44874 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_BITRATE_CMDID\n", DBGARG));
44875 + status = wmi_bitrate_reply_rx(wmip, datap, len);
44876 + break;
44877 + case (WMI_GET_CHANNEL_LIST_CMDID):
44878 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_CHANNEL_LIST_CMDID\n", DBGARG));
44879 + status = wmi_channelList_reply_rx(wmip, datap, len);
44880 + break;
44881 + case (WMI_GET_TX_PWR_CMDID):
44882 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_TX_PWR_CMDID\n", DBGARG));
44883 + status = wmi_txPwr_reply_rx(wmip, datap, len);
44884 + break;
44885 + case (WMI_READY_EVENTID):
44886 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_READY_EVENTID\n", DBGARG));
44887 + status = wmi_ready_event_rx(wmip, datap, len);
44888 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44889 + A_WMI_DBGLOG_INIT_DONE(wmip->wmi_devt);
44890 + break;
44891 + case (WMI_CONNECT_EVENTID):
44892 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CONNECT_EVENTID\n", DBGARG));
44893 + status = wmi_connect_event_rx(wmip, datap, len);
44894 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44895 + break;
44896 + case (WMI_DISCONNECT_EVENTID):
44897 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_DISCONNECT_EVENTID\n", DBGARG));
44898 + status = wmi_disconnect_event_rx(wmip, datap, len);
44899 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44900 + break;
44901 + case (WMI_TKIP_MICERR_EVENTID):
44902 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TKIP_MICERR_EVENTID\n", DBGARG));
44903 + status = wmi_tkip_micerr_event_rx(wmip, datap, len);
44904 + break;
44905 + case (WMI_BSSINFO_EVENTID):
44906 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_BSSINFO_EVENTID\n", DBGARG));
44907 + status = wmi_bssInfo_event_rx(wmip, datap, len);
44908 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44909 + break;
44910 + case (WMI_REGDOMAIN_EVENTID):
44911 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REGDOMAIN_EVENTID\n", DBGARG));
44912 + status = wmi_regDomain_event_rx(wmip, datap, len);
44913 + break;
44914 + case (WMI_PSTREAM_TIMEOUT_EVENTID):
44915 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_PSTREAM_TIMEOUT_EVENTID\n", DBGARG));
44916 + status = wmi_pstream_timeout_event_rx(wmip, datap, len);
44917 + /* pstreams are fatpipe abstractions that get implicitly created.
44918 + * User apps only deal with thinstreams. creation of a thinstream
44919 + * by the user or data traffic flow in an AC triggers implicit
44920 + * pstream creation. Do we need to send this event to App..?
44921 + * no harm in sending it.
44922 + */
44923 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44924 + break;
44925 + case (WMI_NEIGHBOR_REPORT_EVENTID):
44926 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_NEIGHBOR_REPORT_EVENTID\n", DBGARG));
44927 + status = wmi_neighborReport_event_rx(wmip, datap, len);
44928 + break;
44929 + case (WMI_SCAN_COMPLETE_EVENTID):
44930 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SCAN_COMPLETE_EVENTID\n", DBGARG));
44931 + status = wmi_scanComplete_rx(wmip, datap, len);
44932 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44933 + break;
44934 + case (WMI_CMDERROR_EVENTID):
44935 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG));
44936 + status = wmi_errorEvent_rx(wmip, datap, len);
44937 + break;
44938 + case (WMI_REPORT_STATISTICS_EVENTID):
44939 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_STATISTICS_EVENTID\n", DBGARG));
44940 + status = wmi_statsEvent_rx(wmip, datap, len);
44941 + break;
44942 + case (WMI_RSSI_THRESHOLD_EVENTID):
44943 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_RSSI_THRESHOLD_EVENTID\n", DBGARG));
44944 + status = wmi_rssiThresholdEvent_rx(wmip, datap, len);
44945 + break;
44946 + case (WMI_ERROR_REPORT_EVENTID):
44947 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_ERROR_REPORT_EVENTID\n", DBGARG));
44948 + status = wmi_reportErrorEvent_rx(wmip, datap, len);
44949 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44950 + break;
44951 + case (WMI_OPT_RX_FRAME_EVENTID):
44952 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_OPT_RX_FRAME_EVENTID\n", DBGARG));
44953 + status = wmi_opt_frame_event_rx(wmip, datap, len);
44954 + break;
44955 + case (WMI_REPORT_ROAM_TBL_EVENTID):
44956 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_TBL_EVENTID\n", DBGARG));
44957 + status = wmi_roam_tbl_event_rx(wmip, datap, len);
44958 + break;
44959 + case (WMI_EXTENSION_EVENTID):
44960 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG));
44961 + status = wmi_control_rx_xtnd(wmip, osbuf);
44962 + break;
44963 + case (WMI_CAC_EVENTID):
44964 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CAC_EVENTID\n", DBGARG));
44965 + status = wmi_cac_event_rx(wmip, datap, len);
44966 + break;
44967 + case (WMI_REPORT_ROAM_DATA_EVENTID):
44968 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_REPORT_ROAM_DATA_EVENTID\n", DBGARG));
44969 + status = wmi_roam_data_event_rx(wmip, datap, len);
44970 + break;
44971 +#ifdef CONFIG_HOST_TCMD_SUPPORT
44972 + case (WMI_TEST_EVENTID):
44973 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TEST_EVENTID\n", DBGARG));
44974 + status = wmi_tcmd_test_report_rx(wmip, datap, len);
44975 + break;
44976 +#endif
44977 + case (WMI_GET_FIXRATES_CMDID):
44978 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_FIXRATES_CMDID\n", DBGARG));
44979 + status = wmi_ratemask_reply_rx(wmip, datap, len);
44980 + break;
44981 + case (WMI_TX_RETRY_ERR_EVENTID):
44982 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_TX_RETRY_ERR_EVENTID\n", DBGARG));
44983 + status = wmi_txRetryErrEvent_rx(wmip, datap, len);
44984 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44985 + break;
44986 + case (WMI_SNR_THRESHOLD_EVENTID):
44987 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_SNR_THRESHOLD_EVENTID\n", DBGARG));
44988 + status = wmi_snrThresholdEvent_rx(wmip, datap, len);
44989 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44990 + break;
44991 + case (WMI_LQ_THRESHOLD_EVENTID):
44992 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_LQ_THRESHOLD_EVENTID\n", DBGARG));
44993 + status = wmi_lqThresholdEvent_rx(wmip, datap, len);
44994 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
44995 + break;
44996 + case (WMI_APLIST_EVENTID):
44997 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n"));
44998 + status = wmi_aplistEvent_rx(wmip, datap, len);
44999 + break;
45000 + case (WMI_GET_KEEPALIVE_CMDID):
45001 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_KEEPALIVE_CMDID\n", DBGARG));
45002 + status = wmi_keepalive_reply_rx(wmip, datap, len);
45003 + break;
45004 + case (WMI_GET_WOW_LIST_EVENTID):
45005 + status = wmi_get_wow_list_event_rx(wmip, datap, len);
45006 + break;
45007 + case (WMI_GET_PMKID_LIST_EVENTID):
45008 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_GET_PMKID_LIST Event\n", DBGARG));
45009 + status = wmi_get_pmkid_list_event_rx(wmip, datap, len);
45010 + break;
45011 + default:
45012 + A_DPRINTF(DBG_WMI|DBG_ERROR,
45013 + (DBGFMT "Unknown id 0x%x\n", DBGARG, id));
45014 + wmip->wmi_stats.cmd_id_err++;
45015 + status = A_ERROR;
45016 + break;
45017 + }
45018 +
45019 + A_NETBUF_FREE(osbuf);
45020 +
45021 + return status;
45022 +}
45023 +
45024 +static A_STATUS
45025 +wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45026 +{
45027 + WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
45028 +
45029 + if (len < sizeof(WMI_READY_EVENT)) {
45030 + return A_EINVAL;
45031 + }
45032 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45033 + wmip->wmi_ready = TRUE;
45034 + A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability);
45035 +
45036 + return A_OK;
45037 +}
45038 +
45039 +static A_STATUS
45040 +wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45041 +{
45042 + WMI_CONNECT_EVENT *ev;
45043 +
45044 + if (len < sizeof(WMI_CONNECT_EVENT)) {
45045 + return A_EINVAL;
45046 + }
45047 + ev = (WMI_CONNECT_EVENT *)datap;
45048 + A_DPRINTF(DBG_WMI,
45049 + (DBGFMT "freq %d bssid %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
45050 + DBGARG, ev->channel,
45051 + ev->bssid[0], ev->bssid[1], ev->bssid[2],
45052 + ev->bssid[3], ev->bssid[4], ev->bssid[5]));
45053 +
45054 + A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
45055 +
45056 + A_WMI_CONNECT_EVENT(wmip->wmi_devt, ev->channel, ev->bssid,
45057 + ev->listenInterval, ev->beaconInterval,
45058 + ev->networkType, ev->beaconIeLen,
45059 + ev->assocReqLen, ev->assocRespLen,
45060 + ev->assocInfo);
45061 +
45062 + return A_OK;
45063 +}
45064 +
45065 +static A_STATUS
45066 +wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45067 +{
45068 + WMI_REG_DOMAIN_EVENT *ev;
45069 +
45070 + if (len < sizeof(*ev)) {
45071 + return A_EINVAL;
45072 + }
45073 + ev = (WMI_REG_DOMAIN_EVENT *)datap;
45074 +
45075 + A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
45076 +
45077 + return A_OK;
45078 +}
45079 +
45080 +static A_STATUS
45081 +wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45082 +{
45083 + WMI_NEIGHBOR_REPORT_EVENT *ev;
45084 + int numAps;
45085 +
45086 + if (len < sizeof(*ev)) {
45087 + return A_EINVAL;
45088 + }
45089 + ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
45090 + numAps = ev->numberOfAps;
45091 +
45092 + if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
45093 + return A_EINVAL;
45094 + }
45095 +
45096 + A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
45097 +
45098 + return A_OK;
45099 +}
45100 +
45101 +static A_STATUS
45102 +wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45103 +{
45104 + WMI_DISCONNECT_EVENT *ev;
45105 +
45106 + if (len < sizeof(WMI_DISCONNECT_EVENT)) {
45107 + return A_EINVAL;
45108 + }
45109 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45110 +
45111 + ev = (WMI_DISCONNECT_EVENT *)datap;
45112 +
45113 + A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
45114 +
45115 + A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
45116 + ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
45117 +
45118 + return A_OK;
45119 +}
45120 +
45121 +static A_STATUS
45122 +wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45123 +{
45124 + WMI_TKIP_MICERR_EVENT *ev;
45125 +
45126 + if (len < sizeof(*ev)) {
45127 + return A_EINVAL;
45128 + }
45129 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45130 +
45131 + ev = (WMI_TKIP_MICERR_EVENT *)datap;
45132 + A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
45133 +
45134 + return A_OK;
45135 +}
45136 +
45137 +static A_STATUS
45138 +wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45139 +{
45140 + bss_t *bss;
45141 + WMI_BSS_INFO_HDR *bih;
45142 + A_UINT8 *buf;
45143 + A_UINT32 nodeCachingAllowed;
45144 +
45145 + if (len <= sizeof(WMI_BSS_INFO_HDR)) {
45146 + return A_EINVAL;
45147 + }
45148 +
45149 + A_WMI_BSSINFO_EVENT_RX(wmip->wmi_devt, datap, len);
45150 + /* What is driver config for wlan node caching? */
45151 + if(ar6000_get_driver_cfg(wmip->wmi_devt,
45152 + AR6000_DRIVER_CFG_GET_WLANNODECACHING,
45153 + &nodeCachingAllowed) != A_OK) {
45154 + return A_EINVAL;
45155 + }
45156 +
45157 + if(!nodeCachingAllowed) {
45158 + return A_OK;
45159 + }
45160 +
45161 +
45162 + bih = (WMI_BSS_INFO_HDR *)datap;
45163 + buf = datap + sizeof(WMI_BSS_INFO_HDR);
45164 + len -= sizeof(WMI_BSS_INFO_HDR);
45165 +
45166 + A_DPRINTF(DBG_WMI2, (DBGFMT "bssInfo event - ch %u, rssi %02x, "
45167 + "bssid \"%02x:%02x:%02x:%02x:%02x:%02x\"\n", DBGARG,
45168 + bih->channel, (unsigned char) bih->rssi, bih->bssid[0],
45169 + bih->bssid[1], bih->bssid[2], bih->bssid[3], bih->bssid[4],
45170 + bih->bssid[5]));
45171 +
45172 + if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
45173 + printk("%s() A_OK 2\n", __FUNCTION__);
45174 + return A_OK;
45175 + }
45176 +
45177 + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
45178 + if (bss != NULL) {
45179 + /*
45180 + * Free up the node. Not the most efficient process given
45181 + * we are about to allocate a new node but it is simple and should be
45182 + * adequate.
45183 + */
45184 + wlan_node_reclaim(&wmip->wmi_scan_table, bss);
45185 + }
45186 +
45187 + bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
45188 + if (bss == NULL) {
45189 + return A_NO_MEMORY;
45190 + }
45191 +
45192 + bss->ni_snr = bih->snr;
45193 + bss->ni_rssi = bih->rssi;
45194 + A_ASSERT(bss->ni_buf != NULL);
45195 + A_MEMCPY(bss->ni_buf, buf, len);
45196 +
45197 + if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != A_OK) {
45198 + wlan_node_free(bss);
45199 + return A_EINVAL;
45200 + }
45201 +
45202 + /*
45203 + * Update the frequency in ie_chan, overwriting of channel number
45204 + * which is done in wlan_parse_beacon
45205 + */
45206 + bss->ni_cie.ie_chan = bih->channel;
45207 + wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
45208 +
45209 + return A_OK;
45210 +}
45211 +
45212 +static A_STATUS
45213 +wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45214 +{
45215 + bss_t *bss;
45216 + WMI_OPT_RX_INFO_HDR *bih;
45217 + A_UINT8 *buf;
45218 +
45219 + if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
45220 + return A_EINVAL;
45221 + }
45222 +
45223 + bih = (WMI_OPT_RX_INFO_HDR *)datap;
45224 + buf = datap + sizeof(WMI_OPT_RX_INFO_HDR);
45225 + len -= sizeof(WMI_OPT_RX_INFO_HDR);
45226 +
45227 + A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG,
45228 + bih->bssid[4], bih->bssid[5]));
45229 +
45230 + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
45231 + if (bss != NULL) {
45232 + /*
45233 + * Free up the node. Not the most efficient process given
45234 + * we are about to allocate a new node but it is simple and should be
45235 + * adequate.
45236 + */
45237 + wlan_node_reclaim(&wmip->wmi_scan_table, bss);
45238 + }
45239 +
45240 + bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
45241 + if (bss == NULL) {
45242 + return A_NO_MEMORY;
45243 + }
45244 +
45245 + bss->ni_snr = bih->snr;
45246 + bss->ni_cie.ie_chan = bih->channel;
45247 + A_ASSERT(bss->ni_buf != NULL);
45248 + A_MEMCPY(bss->ni_buf, buf, len);
45249 + wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
45250 +
45251 + return A_OK;
45252 +}
45253 +
45254 + /* This event indicates inactivity timeout of a fatpipe(pstream)
45255 + * at the target
45256 + */
45257 +static A_STATUS
45258 +wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45259 +{
45260 + WMI_PSTREAM_TIMEOUT_EVENT *ev;
45261 +
45262 + if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) {
45263 + return A_EINVAL;
45264 + }
45265 +
45266 + A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG));
45267 +
45268 + ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap;
45269 +
45270 + /* When the pstream (fat pipe == AC) timesout, it means there were no
45271 + * thinStreams within this pstream & it got implicitly created due to
45272 + * data flow on this AC. We start the inactivity timer only for
45273 + * implicitly created pstream. Just reset the host state.
45274 + */
45275 + /* Set the activeTsids for this AC to 0 */
45276 + LOCK_WMI(wmip);
45277 + wmip->wmi_streamExistsForAC[ev->trafficClass]=0;
45278 + wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass);
45279 + UNLOCK_WMI(wmip);
45280 +
45281 + /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
45282 + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
45283 +
45284 + return A_OK;
45285 +}
45286 +
45287 +static A_STATUS
45288 +wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45289 +{
45290 + WMI_BIT_RATE_CMD *reply;
45291 + A_INT32 rate;
45292 +
45293 + if (len < sizeof(WMI_BIT_RATE_CMD)) {
45294 + return A_EINVAL;
45295 + }
45296 + reply = (WMI_BIT_RATE_CMD *)datap;
45297 + A_DPRINTF(DBG_WMI,
45298 + (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
45299 +
45300 + if (reply->rateIndex == RATE_AUTO) {
45301 + rate = RATE_AUTO;
45302 + } else {
45303 + rate = wmi_rateTable[(A_UINT32) reply->rateIndex];
45304 + }
45305 +
45306 + A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
45307 +
45308 + return A_OK;
45309 +}
45310 +
45311 +static A_STATUS
45312 +wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45313 +{
45314 + WMI_FIX_RATES_CMD *reply;
45315 +
45316 + if (len < sizeof(WMI_BIT_RATE_CMD)) {
45317 + return A_EINVAL;
45318 + }
45319 + reply = (WMI_FIX_RATES_CMD *)datap;
45320 + A_DPRINTF(DBG_WMI,
45321 + (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask));
45322 +
45323 + A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
45324 +
45325 + return A_OK;
45326 +}
45327 +
45328 +static A_STATUS
45329 +wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45330 +{
45331 + WMI_CHANNEL_LIST_REPLY *reply;
45332 +
45333 + if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) {
45334 + return A_EINVAL;
45335 + }
45336 + reply = (WMI_CHANNEL_LIST_REPLY *)datap;
45337 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45338 +
45339 + A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
45340 + reply->channelList);
45341 +
45342 + return A_OK;
45343 +}
45344 +
45345 +static A_STATUS
45346 +wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45347 +{
45348 + WMI_TX_PWR_REPLY *reply;
45349 +
45350 + if (len < sizeof(*reply)) {
45351 + return A_EINVAL;
45352 + }
45353 + reply = (WMI_TX_PWR_REPLY *)datap;
45354 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45355 +
45356 + A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
45357 +
45358 + return A_OK;
45359 +}
45360 +static A_STATUS
45361 +wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45362 +{
45363 + WMI_GET_KEEPALIVE_CMD *reply;
45364 +
45365 + if (len < sizeof(*reply)) {
45366 + return A_EINVAL;
45367 + }
45368 + reply = (WMI_GET_KEEPALIVE_CMD *)datap;
45369 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45370 +
45371 + A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
45372 +
45373 + return A_OK;
45374 +}
45375 +
45376 +
45377 +static A_STATUS
45378 +wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45379 +{
45380 + WMIX_DSETOPENREQ_EVENT *dsetopenreq;
45381 +
45382 + if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) {
45383 + return A_EINVAL;
45384 + }
45385 + dsetopenreq = (WMIX_DSETOPENREQ_EVENT *)datap;
45386 + A_DPRINTF(DBG_WMI,
45387 + (DBGFMT "Enter - dset_id=0x%x\n", DBGARG, dsetopenreq->dset_id));
45388 + A_WMI_DSET_OPEN_REQ(wmip->wmi_devt,
45389 + dsetopenreq->dset_id,
45390 + dsetopenreq->targ_dset_handle,
45391 + dsetopenreq->targ_reply_fn,
45392 + dsetopenreq->targ_reply_arg);
45393 +
45394 + return A_OK;
45395 +}
45396 +
45397 +#ifdef CONFIG_HOST_DSET_SUPPORT
45398 +static A_STATUS
45399 +wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45400 +{
45401 + WMIX_DSETCLOSE_EVENT *dsetclose;
45402 +
45403 + if (len < sizeof(WMIX_DSETCLOSE_EVENT)) {
45404 + return A_EINVAL;
45405 + }
45406 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45407 +
45408 + dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
45409 + A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
45410 +
45411 + return A_OK;
45412 +}
45413 +
45414 +static A_STATUS
45415 +wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45416 +{
45417 + WMIX_DSETDATAREQ_EVENT *dsetdatareq;
45418 +
45419 + if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) {
45420 + return A_EINVAL;
45421 + }
45422 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45423 +
45424 + dsetdatareq = (WMIX_DSETDATAREQ_EVENT *)datap;
45425 + A_WMI_DSET_DATA_REQ(wmip->wmi_devt,
45426 + dsetdatareq->access_cookie,
45427 + dsetdatareq->offset,
45428 + dsetdatareq->length,
45429 + dsetdatareq->targ_buf,
45430 + dsetdatareq->targ_reply_fn,
45431 + dsetdatareq->targ_reply_arg);
45432 +
45433 + return A_OK;
45434 +}
45435 +#endif /* CONFIG_HOST_DSET_SUPPORT */
45436 +
45437 +static A_STATUS
45438 +wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45439 +{
45440 + WMI_SCAN_COMPLETE_EVENT *ev;
45441 +
45442 + ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
45443 + A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, ev->status);
45444 +
45445 + return A_OK;
45446 +}
45447 +
45448 +/*
45449 + * Target is reporting a programming error. This is for
45450 + * developer aid only. Target only checks a few common violations
45451 + * and it is responsibility of host to do all error checking.
45452 + * Behavior of target after wmi error event is undefined.
45453 + * A reset is recommended.
45454 + */
45455 +static A_STATUS
45456 +wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45457 +{
45458 + WMI_CMD_ERROR_EVENT *ev;
45459 +
45460 + ev = (WMI_CMD_ERROR_EVENT *)datap;
45461 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Programming Error: cmd=%d ", ev->commandId));
45462 + switch (ev->errorCode) {
45463 + case (INVALID_PARAM):
45464 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal Parameter\n"));
45465 + break;
45466 + case (ILLEGAL_STATE):
45467 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n"));
45468 + break;
45469 + case (INTERNAL_ERROR):
45470 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n"));
45471 + break;
45472 + }
45473 +
45474 + return A_OK;
45475 +}
45476 +
45477 +
45478 +static A_STATUS
45479 +wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45480 +{
45481 + WMI_TARGET_STATS *reply;
45482 +
45483 + if (len < sizeof(*reply)) {
45484 + return A_EINVAL;
45485 + }
45486 + reply = (WMI_TARGET_STATS *)datap;
45487 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45488 +
45489 + A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, reply);
45490 +
45491 + return A_OK;
45492 +}
45493 +
45494 +static A_STATUS
45495 +wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45496 +{
45497 + WMI_RSSI_THRESHOLD_EVENT *reply;
45498 +
45499 + if (len < sizeof(*reply)) {
45500 + return A_EINVAL;
45501 + }
45502 + reply = (WMI_RSSI_THRESHOLD_EVENT *)datap;
45503 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45504 +
45505 + A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, reply->range, reply->rssi);
45506 +
45507 + return A_OK;
45508 +}
45509 +
45510 +
45511 +static A_STATUS
45512 +wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45513 +{
45514 + WMI_TARGET_ERROR_REPORT_EVENT *reply;
45515 +
45516 + if (len < sizeof(*reply)) {
45517 + return A_EINVAL;
45518 + }
45519 + reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap;
45520 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45521 +
45522 + A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, reply->errorVal);
45523 +
45524 + return A_OK;
45525 +}
45526 +
45527 +static A_STATUS
45528 +wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45529 +{
45530 + WMI_CAC_EVENT *reply;
45531 +
45532 + if (len < sizeof(*reply)) {
45533 + return A_EINVAL;
45534 + }
45535 + reply = (WMI_CAC_EVENT *)datap;
45536 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45537 +
45538 + A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac,
45539 + reply->cac_indication, reply->statusCode,
45540 + reply->tspecSuggestion);
45541 +
45542 + return A_OK;
45543 +}
45544 +
45545 +static A_STATUS
45546 +wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45547 +{
45548 + WMIX_HB_CHALLENGE_RESP_EVENT *reply;
45549 +
45550 + if (len < sizeof(*reply)) {
45551 + return A_EINVAL;
45552 + }
45553 + reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap;
45554 + A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG));
45555 +
45556 + A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
45557 +
45558 + return A_OK;
45559 +}
45560 +
45561 +static A_STATUS
45562 +wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45563 +{
45564 + WMI_TARGET_ROAM_TBL *reply;
45565 +
45566 + if (len < sizeof(*reply)) {
45567 + return A_EINVAL;
45568 + }
45569 + reply = (WMI_TARGET_ROAM_TBL *)datap;
45570 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45571 +
45572 + A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
45573 +
45574 + return A_OK;
45575 +}
45576 +
45577 +static A_STATUS
45578 +wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45579 +{
45580 + WMI_TARGET_ROAM_DATA *reply;
45581 +
45582 + if (len < sizeof(*reply)) {
45583 + return A_EINVAL;
45584 + }
45585 + reply = (WMI_TARGET_ROAM_DATA *)datap;
45586 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45587 +
45588 + A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
45589 +
45590 + return A_OK;
45591 +}
45592 +
45593 +static A_STATUS
45594 +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45595 +{
45596 + WMI_TX_RETRY_ERR_EVENT *reply;
45597 +
45598 + if (len < sizeof(*reply)) {
45599 + return A_EINVAL;
45600 + }
45601 + reply = (WMI_TX_RETRY_ERR_EVENT *)datap;
45602 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45603 +
45604 + A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
45605 +
45606 + return A_OK;
45607 +}
45608 +
45609 +static A_STATUS
45610 +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45611 +{
45612 + WMI_SNR_THRESHOLD_EVENT *reply;
45613 +
45614 + if (len < sizeof(*reply)) {
45615 + return A_EINVAL;
45616 + }
45617 + reply = (WMI_SNR_THRESHOLD_EVENT *)datap;
45618 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45619 +
45620 + A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->snr);
45621 +
45622 + return A_OK;
45623 +}
45624 +
45625 +static A_STATUS
45626 +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45627 +{
45628 + WMI_LQ_THRESHOLD_EVENT *reply;
45629 +
45630 + if (len < sizeof(*reply)) {
45631 + return A_EINVAL;
45632 + }
45633 + reply = (WMI_LQ_THRESHOLD_EVENT *)datap;
45634 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45635 +
45636 + A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->lq);
45637 +
45638 + return A_OK;
45639 +}
45640 +
45641 +static A_STATUS
45642 +wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45643 +{
45644 + A_UINT16 ap_info_entry_size;
45645 + WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
45646 + WMI_AP_INFO_V1 *ap_info_v1;
45647 + A_UINT8 i;
45648 +
45649 + if (len < sizeof(WMI_APLIST_EVENT)) {
45650 + return A_EINVAL;
45651 + }
45652 +
45653 + if (ev->apListVer == APLIST_VER1) {
45654 + ap_info_entry_size = sizeof(WMI_AP_INFO_V1);
45655 + ap_info_v1 = (WMI_AP_INFO_V1 *)ev->apList;
45656 + } else {
45657 + return A_EINVAL;
45658 + }
45659 +
45660 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Number of APs in APLIST Event is %d\n", ev->numAP));
45661 + if (len < (int)(sizeof(WMI_APLIST_EVENT) +
45662 + (ev->numAP - 1) * ap_info_entry_size))
45663 + {
45664 + return A_EINVAL;
45665 + }
45666 +
45667 + /*
45668 + * AP List Ver1 Contents
45669 + */
45670 + for (i = 0; i < ev->numAP; i++) {
45671 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("AP#%d BSSID %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x "\
45672 + "Channel %d\n", i,
45673 + ap_info_v1->bssid[0], ap_info_v1->bssid[1],
45674 + ap_info_v1->bssid[2], ap_info_v1->bssid[3],
45675 + ap_info_v1->bssid[4], ap_info_v1->bssid[5],
45676 + ap_info_v1->channel));
45677 + ap_info_v1++;
45678 + }
45679 + return A_OK;
45680 +}
45681 +
45682 +static A_STATUS
45683 +wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45684 +{
45685 + A_UINT32 dropped;
45686 +
45687 + dropped = *((A_UINT32 *)datap);
45688 + datap += sizeof(dropped);
45689 + len -= sizeof(dropped);
45690 + A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, datap, len);
45691 + return A_OK;
45692 +}
45693 +
45694 +#ifdef CONFIG_HOST_GPIO_SUPPORT
45695 +static A_STATUS
45696 +wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45697 +{
45698 + WMIX_GPIO_INTR_EVENT *gpio_intr = (WMIX_GPIO_INTR_EVENT *)datap;
45699 +
45700 + A_DPRINTF(DBG_WMI,
45701 + (DBGFMT "Enter - intrmask=0x%x input=0x%x.\n", DBGARG,
45702 + gpio_intr->intr_mask, gpio_intr->input_values));
45703 +
45704 + A_WMI_GPIO_INTR_RX(gpio_intr->intr_mask, gpio_intr->input_values);
45705 +
45706 + return A_OK;
45707 +}
45708 +
45709 +static A_STATUS
45710 +wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45711 +{
45712 + WMIX_GPIO_DATA_EVENT *gpio_data = (WMIX_GPIO_DATA_EVENT *)datap;
45713 +
45714 + A_DPRINTF(DBG_WMI,
45715 + (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG,
45716 + gpio_data->reg_id, gpio_data->value));
45717 +
45718 + A_WMI_GPIO_DATA_RX(gpio_data->reg_id, gpio_data->value);
45719 +
45720 + return A_OK;
45721 +}
45722 +
45723 +static A_STATUS
45724 +wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45725 +{
45726 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45727 +
45728 + A_WMI_GPIO_ACK_RX();
45729 +
45730 + return A_OK;
45731 +}
45732 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
45733 +
45734 +/*
45735 + * Called to send a wmi command. Command specific data is already built
45736 + * on osbuf and current osbuf->data points to it.
45737 + */
45738 +A_STATUS
45739 +wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
45740 + WMI_SYNC_FLAG syncflag)
45741 +{
45742 +#define IS_LONG_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID) || (cmdId == WMI_ADD_WOW_PATTERN_CMDID))
45743 + WMI_CMD_HDR *cHdr;
45744 + WMI_PRI_STREAM_ID streamID = WMI_CONTROL_PRI;
45745 +
45746 + A_ASSERT(osbuf != NULL);
45747 +
45748 + if (syncflag >= END_WMIFLAG) {
45749 + return A_EINVAL;
45750 + }
45751 +
45752 + if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
45753 + /*
45754 + * We want to make sure all data currently queued is transmitted before
45755 + * the cmd execution. Establish a new sync point.
45756 + */
45757 + wmi_sync_point(wmip);
45758 + }
45759 +
45760 + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
45761 + return A_NO_MEMORY;
45762 + }
45763 +
45764 + cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
45765 + cHdr->commandId = cmdId;
45766 +
45767 + /*
45768 + * Send cmd, some via control pipe, others via data pipe
45769 + */
45770 + if (IS_LONG_CMD(cmdId)) {
45771 + wmi_data_hdr_add(wmip, osbuf, CNTL_MSGTYPE);
45772 + // TODO ... these can now go through the control endpoint via HTC 2.0
45773 + streamID = WMI_BEST_EFFORT_PRI;
45774 + }
45775 + A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID);
45776 +
45777 + if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
45778 + /*
45779 + * We want to make sure all new data queued waits for the command to
45780 + * execute. Establish a new sync point.
45781 + */
45782 + wmi_sync_point(wmip);
45783 + }
45784 + return (A_OK);
45785 +#undef IS_LONG_CMD
45786 +}
45787 +
45788 +A_STATUS
45789 +wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
45790 + WMI_SYNC_FLAG syncflag)
45791 +{
45792 + WMIX_CMD_HDR *cHdr;
45793 +
45794 + if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {
45795 + return A_NO_MEMORY;
45796 + }
45797 +
45798 + cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
45799 + cHdr->commandId = cmdId;
45800 +
45801 + return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
45802 +}
45803 +
45804 +A_STATUS
45805 +wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
45806 + DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
45807 + CRYPTO_TYPE pairwiseCrypto, A_UINT8 pairwiseCryptoLen,
45808 + CRYPTO_TYPE groupCrypto,A_UINT8 groupCryptoLen,
45809 + int ssidLength, A_UCHAR *ssid,
45810 + A_UINT8 *bssid, A_UINT16 channel, A_UINT32 ctrl_flags)
45811 +{
45812 + void *osbuf;
45813 + WMI_CONNECT_CMD *cc;
45814 +
45815 + if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) {
45816 + return A_EINVAL;
45817 + }
45818 + if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) {
45819 + return A_EINVAL;
45820 + }
45821 +
45822 + osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD));
45823 + if (osbuf == NULL) {
45824 + return A_NO_MEMORY;
45825 + }
45826 +
45827 + A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD));
45828 +
45829 + cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
45830 + A_MEMZERO(cc, sizeof(*cc));
45831 +
45832 + A_MEMCPY(cc->ssid, ssid, ssidLength);
45833 + cc->ssidLength = ssidLength;
45834 + cc->networkType = netType;
45835 + cc->dot11AuthMode = dot11AuthMode;
45836 + cc->authMode = authMode;
45837 + cc->pairwiseCryptoType = pairwiseCrypto;
45838 + cc->pairwiseCryptoLen = pairwiseCryptoLen;
45839 + cc->groupCryptoType = groupCrypto;
45840 + cc->groupCryptoLen = groupCryptoLen;
45841 + cc->channel = channel;
45842 + cc->ctrl_flags = ctrl_flags;
45843 +
45844 + if (bssid != NULL) {
45845 + A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
45846 + }
45847 + if (wmi_set_keepalive_cmd(wmip, wmip->wmi_keepaliveInterval) != A_OK) {
45848 + return(A_ERROR);
45849 + }
45850 +
45851 + return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
45852 +}
45853 +
45854 +A_STATUS
45855 +wmi_reconnect_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT16 channel)
45856 +{
45857 + void *osbuf;
45858 + WMI_RECONNECT_CMD *cc;
45859 +
45860 + osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD));
45861 + if (osbuf == NULL) {
45862 + return A_NO_MEMORY;
45863 + }
45864 +
45865 + A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD));
45866 +
45867 + cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf));
45868 + A_MEMZERO(cc, sizeof(*cc));
45869 +
45870 + cc->channel = channel;
45871 +
45872 + if (bssid != NULL) {
45873 + A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
45874 + }
45875 +
45876 + return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
45877 +}
45878 +
45879 +A_STATUS
45880 +wmi_disconnect_cmd(struct wmi_t *wmip)
45881 +{
45882 + void *osbuf;
45883 + A_STATUS status;
45884 +
45885 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
45886 + if (osbuf == NULL) {
45887 + return A_NO_MEMORY;
45888 + }
45889 +
45890 + /* Bug fix for 24817(elevator bug) - the disconnect command does not
45891 + need to do a SYNC before.*/
45892 + status = (wmi_cmd_send(wmip, osbuf, WMI_DISCONNECT_CMDID,
45893 + NO_SYNC_WMIFLAG));
45894 +
45895 + return status;
45896 +}
45897 +
45898 +A_STATUS
45899 +wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
45900 + A_BOOL forceFgScan, A_BOOL isLegacy,
45901 + A_UINT32 homeDwellTime, A_UINT32 forceScanInterval)
45902 +{
45903 + void *osbuf;
45904 + WMI_START_SCAN_CMD *sc;
45905 +
45906 + if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) {
45907 + return A_EINVAL;
45908 + }
45909 +
45910 + osbuf = A_NETBUF_ALLOC(sizeof(*sc));
45911 + if (osbuf == NULL) {
45912 + return A_NO_MEMORY;
45913 + }
45914 +
45915 + A_NETBUF_PUT(osbuf, sizeof(*sc));
45916 +
45917 + sc = (WMI_START_SCAN_CMD *)(A_NETBUF_DATA(osbuf));
45918 + sc->scanType = scanType;
45919 + sc->forceFgScan = forceFgScan;
45920 + sc->isLegacy = isLegacy;
45921 + sc->homeDwellTime = homeDwellTime;
45922 + sc->forceScanInterval = forceScanInterval;
45923 +
45924 + return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
45925 +}
45926 +
45927 +A_STATUS
45928 +wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec,
45929 + A_UINT16 fg_end_sec, A_UINT16 bg_sec,
45930 + A_UINT16 minact_chdw_msec, A_UINT16 maxact_chdw_msec,
45931 + A_UINT16 pas_chdw_msec,
45932 + A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags,
45933 + A_UINT32 max_dfsch_act_time)
45934 +{
45935 + void *osbuf;
45936 + WMI_SCAN_PARAMS_CMD *sc;
45937 +
45938 + osbuf = A_NETBUF_ALLOC(sizeof(*sc));
45939 + if (osbuf == NULL) {
45940 + return A_NO_MEMORY;
45941 + }
45942 +
45943 + A_NETBUF_PUT(osbuf, sizeof(*sc));
45944 +
45945 + sc = (WMI_SCAN_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
45946 + A_MEMZERO(sc, sizeof(*sc));
45947 + sc->fg_start_period = fg_start_sec;
45948 + sc->fg_end_period = fg_end_sec;
45949 + sc->bg_period = bg_sec;
45950 + sc->minact_chdwell_time = minact_chdw_msec;
45951 + sc->maxact_chdwell_time = maxact_chdw_msec;
45952 + sc->pas_chdwell_time = pas_chdw_msec;
45953 + sc->shortScanRatio = shScanRatio;
45954 + sc->scanCtrlFlags = scanCtrlFlags;
45955 + sc->max_dfsch_act_time = max_dfsch_act_time;
45956 +
45957 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID,
45958 + NO_SYNC_WMIFLAG));
45959 +}
45960 +
45961 +A_STATUS
45962 +wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask)
45963 +{
45964 + void *osbuf;
45965 + WMI_BSS_FILTER_CMD *cmd;
45966 +
45967 + if (filter >= LAST_BSS_FILTER) {
45968 + return A_EINVAL;
45969 + }
45970 +
45971 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
45972 + if (osbuf == NULL) {
45973 + return A_NO_MEMORY;
45974 + }
45975 +
45976 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
45977 +
45978 + cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
45979 + A_MEMZERO(cmd, sizeof(*cmd));
45980 + cmd->bssFilter = filter;
45981 + cmd->ieMask = ieMask;
45982 +
45983 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID,
45984 + NO_SYNC_WMIFLAG));
45985 +}
45986 +
45987 +A_STATUS
45988 +wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
45989 + A_UINT8 ssidLength, A_UCHAR *ssid)
45990 +{
45991 + void *osbuf;
45992 + WMI_PROBED_SSID_CMD *cmd;
45993 +
45994 + if (index > MAX_PROBED_SSID_INDEX) {
45995 + return A_EINVAL;
45996 + }
45997 + if (ssidLength > sizeof(cmd->ssid)) {
45998 + return A_EINVAL;
45999 + }
46000 + if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) {
46001 + return A_EINVAL;
46002 + }
46003 + if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) {
46004 + return A_EINVAL;
46005 + }
46006 +
46007 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46008 + if (osbuf == NULL) {
46009 + return A_NO_MEMORY;
46010 + }
46011 +
46012 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46013 +
46014 + cmd = (WMI_PROBED_SSID_CMD *)(A_NETBUF_DATA(osbuf));
46015 + A_MEMZERO(cmd, sizeof(*cmd));
46016 + cmd->entryIndex = index;
46017 + cmd->flag = flag;
46018 + cmd->ssidLength = ssidLength;
46019 + A_MEMCPY(cmd->ssid, ssid, ssidLength);
46020 +
46021 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
46022 + NO_SYNC_WMIFLAG));
46023 +}
46024 +
46025 +A_STATUS
46026 +wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons)
46027 +{
46028 + void *osbuf;
46029 + WMI_LISTEN_INT_CMD *cmd;
46030 +
46031 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46032 + if (osbuf == NULL) {
46033 + return A_NO_MEMORY;
46034 + }
46035 +
46036 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46037 +
46038 + cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf));
46039 + A_MEMZERO(cmd, sizeof(*cmd));
46040 + cmd->listenInterval = listenInterval;
46041 + cmd->numBeacons = listenBeacons;
46042 +
46043 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID,
46044 + NO_SYNC_WMIFLAG));
46045 +}
46046 +
46047 +A_STATUS
46048 +wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmissTime, A_UINT16 bmissBeacons)
46049 +{
46050 + void *osbuf;
46051 + WMI_BMISS_TIME_CMD *cmd;
46052 +
46053 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46054 + if (osbuf == NULL) {
46055 + return A_NO_MEMORY;
46056 + }
46057 +
46058 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46059 +
46060 + cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf));
46061 + A_MEMZERO(cmd, sizeof(*cmd));
46062 + cmd->bmissTime = bmissTime;
46063 + cmd->numBeacons = bmissBeacons;
46064 +
46065 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID,
46066 + NO_SYNC_WMIFLAG));
46067 +}
46068 +
46069 +A_STATUS
46070 +wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
46071 + A_UINT8 ieLen, A_UINT8 *ieInfo)
46072 +{
46073 + void *osbuf;
46074 + WMI_SET_ASSOC_INFO_CMD *cmd;
46075 + A_UINT16 cmdLen;
46076 +
46077 + cmdLen = sizeof(*cmd) + ieLen - 1;
46078 + osbuf = A_NETBUF_ALLOC(cmdLen);
46079 + if (osbuf == NULL) {
46080 + return A_NO_MEMORY;
46081 + }
46082 +
46083 + A_NETBUF_PUT(osbuf, cmdLen);
46084 +
46085 + cmd = (WMI_SET_ASSOC_INFO_CMD *)(A_NETBUF_DATA(osbuf));
46086 + A_MEMZERO(cmd, cmdLen);
46087 + cmd->ieType = ieType;
46088 + cmd->bufferSize = ieLen;
46089 + A_MEMCPY(cmd->assocInfo, ieInfo, ieLen);
46090 +
46091 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
46092 + NO_SYNC_WMIFLAG));
46093 +}
46094 +
46095 +A_STATUS
46096 +wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode)
46097 +{
46098 + void *osbuf;
46099 + WMI_POWER_MODE_CMD *cmd;
46100 +
46101 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46102 + if (osbuf == NULL) {
46103 + return A_NO_MEMORY;
46104 + }
46105 +
46106 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46107 +
46108 + cmd = (WMI_POWER_MODE_CMD *)(A_NETBUF_DATA(osbuf));
46109 + A_MEMZERO(cmd, sizeof(*cmd));
46110 + cmd->powerMode = powerMode;
46111 + wmip->wmi_powerMode = powerMode;
46112 +
46113 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID,
46114 + NO_SYNC_WMIFLAG));
46115 +}
46116 +
46117 +A_STATUS
46118 +wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
46119 + A_UINT16 atim_windows, A_UINT16 timeout_value)
46120 +{
46121 + void *osbuf;
46122 + WMI_IBSS_PM_CAPS_CMD *cmd;
46123 +
46124 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46125 + if (osbuf == NULL) {
46126 + return A_NO_MEMORY;
46127 + }
46128 +
46129 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46130 +
46131 + cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf));
46132 + A_MEMZERO(cmd, sizeof(*cmd));
46133 + cmd->power_saving = pmEnable;
46134 + cmd->ttl = ttl;
46135 + cmd->atim_windows = atim_windows;
46136 + cmd->timeout_value = timeout_value;
46137 +
46138 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID,
46139 + NO_SYNC_WMIFLAG));
46140 +}
46141 +
46142 +A_STATUS
46143 +wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
46144 + A_UINT16 psPollNum, A_UINT16 dtimPolicy)
46145 +{
46146 + void *osbuf;
46147 + WMI_POWER_PARAMS_CMD *pm;
46148 +
46149 + osbuf = A_NETBUF_ALLOC(sizeof(*pm));
46150 + if (osbuf == NULL) {
46151 + return A_NO_MEMORY;
46152 + }
46153 +
46154 + A_NETBUF_PUT(osbuf, sizeof(*pm));
46155 +
46156 + pm = (WMI_POWER_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
46157 + A_MEMZERO(pm, sizeof(*pm));
46158 + pm->idle_period = idlePeriod;
46159 + pm->pspoll_number = psPollNum;
46160 + pm->dtim_policy = dtimPolicy;
46161 +
46162 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID,
46163 + NO_SYNC_WMIFLAG));
46164 +}
46165 +
46166 +A_STATUS
46167 +wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout)
46168 +{
46169 + void *osbuf;
46170 + WMI_DISC_TIMEOUT_CMD *cmd;
46171 +
46172 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46173 + if (osbuf == NULL) {
46174 + return A_NO_MEMORY;
46175 + }
46176 +
46177 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46178 +
46179 + cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf));
46180 + A_MEMZERO(cmd, sizeof(*cmd));
46181 + cmd->disconnectTimeout = timeout;
46182 +
46183 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID,
46184 + NO_SYNC_WMIFLAG));
46185 +}
46186 +
46187 +A_STATUS
46188 +wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex, CRYPTO_TYPE keyType,
46189 + A_UINT8 keyUsage, A_UINT8 keyLength, A_UINT8 *keyRSC,
46190 + A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl,
46191 + WMI_SYNC_FLAG sync_flag)
46192 +{
46193 + void *osbuf;
46194 + WMI_ADD_CIPHER_KEY_CMD *cmd;
46195 +
46196 + if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) ||
46197 + (keyMaterial == NULL))
46198 + {
46199 + return A_EINVAL;
46200 + }
46201 +
46202 + if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) {
46203 + return A_EINVAL;
46204 + }
46205 +
46206 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46207 + if (osbuf == NULL) {
46208 + return A_NO_MEMORY;
46209 + }
46210 +
46211 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46212 +
46213 + cmd = (WMI_ADD_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
46214 + A_MEMZERO(cmd, sizeof(*cmd));
46215 + cmd->keyIndex = keyIndex;
46216 + cmd->keyType = keyType;
46217 + cmd->keyUsage = keyUsage;
46218 + cmd->keyLength = keyLength;
46219 + A_MEMCPY(cmd->key, keyMaterial, keyLength);
46220 + if (NULL != keyRSC) {
46221 + A_MEMCPY(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
46222 + }
46223 + cmd->key_op_ctrl = key_op_ctrl;
46224 +
46225 + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
46226 +}
46227 +
46228 +A_STATUS
46229 +wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk)
46230 +{
46231 + void *osbuf;
46232 + WMI_ADD_KRK_CMD *cmd;
46233 +
46234 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46235 +
46236 + if (osbuf == NULL) {
46237 + return A_NO_MEMORY;
46238 + }
46239 +
46240 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46241 +
46242 + cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf));
46243 + A_MEMZERO(cmd, sizeof(*cmd));
46244 + A_MEMCPY(cmd->krk, krk, WMI_KRK_LEN);
46245 +
46246 + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
46247 +}
46248 +
46249 +A_STATUS
46250 +wmi_delete_krk_cmd(struct wmi_t *wmip)
46251 +{
46252 + void *osbuf;
46253 +
46254 + osbuf = A_NETBUF_ALLOC(0);
46255 +
46256 + if (osbuf == NULL) {
46257 + return A_NO_MEMORY;
46258 + }
46259 +
46260 + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_KRK_CMDID, NO_SYNC_WMIFLAG));
46261 +}
46262 +
46263 +A_STATUS
46264 +wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex)
46265 +{
46266 + void *osbuf;
46267 + WMI_DELETE_CIPHER_KEY_CMD *cmd;
46268 +
46269 + if (keyIndex > WMI_MAX_KEY_INDEX) {
46270 + return A_EINVAL;
46271 + }
46272 +
46273 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46274 + if (osbuf == NULL) {
46275 + return A_NO_MEMORY;
46276 + }
46277 +
46278 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46279 +
46280 + cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
46281 + A_MEMZERO(cmd, sizeof(*cmd));
46282 + cmd->keyIndex = keyIndex;
46283 +
46284 + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID,
46285 + NO_SYNC_WMIFLAG));
46286 +}
46287 +
46288 +A_STATUS
46289 +wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
46290 + A_BOOL set)
46291 +{
46292 + void *osbuf;
46293 + WMI_SET_PMKID_CMD *cmd;
46294 +
46295 + if (bssid == NULL) {
46296 + return A_EINVAL;
46297 + }
46298 +
46299 + if ((set == TRUE) && (pmkId == NULL)) {
46300 + return A_EINVAL;
46301 + }
46302 +
46303 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46304 + if (osbuf == NULL) {
46305 + return A_NO_MEMORY;
46306 + }
46307 +
46308 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46309 +
46310 + cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf));
46311 + A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
46312 + if (set == TRUE) {
46313 + A_MEMCPY(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
46314 + cmd->enable = PMKID_ENABLE;
46315 + } else {
46316 + A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
46317 + cmd->enable = PMKID_DISABLE;
46318 + }
46319 +
46320 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
46321 +}
46322 +
46323 +A_STATUS
46324 +wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en)
46325 +{
46326 + void *osbuf;
46327 + WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
46328 +
46329 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46330 + if (osbuf == NULL) {
46331 + return A_NO_MEMORY;
46332 + }
46333 +
46334 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46335 +
46336 + cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf));
46337 + cmd->cm_en = (en == TRUE)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
46338 +
46339 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
46340 + NO_SYNC_WMIFLAG));
46341 +}
46342 +
46343 +A_STATUS
46344 +wmi_set_akmp_params_cmd(struct wmi_t *wmip,
46345 + WMI_SET_AKMP_PARAMS_CMD *akmpParams)
46346 +{
46347 + void *osbuf;
46348 + WMI_SET_AKMP_PARAMS_CMD *cmd;
46349 +
46350 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46351 + if (osbuf == NULL) {
46352 + return A_NO_MEMORY;
46353 + }
46354 +
46355 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46356 + cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
46357 + cmd->akmpInfo = akmpParams->akmpInfo;
46358 +
46359 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID,
46360 + NO_SYNC_WMIFLAG));
46361 +}
46362 +
46363 +A_STATUS
46364 +wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
46365 + WMI_SET_PMKID_LIST_CMD *pmkInfo)
46366 +{
46367 + void *osbuf;
46368 + WMI_SET_PMKID_LIST_CMD *cmd;
46369 + A_UINT16 cmdLen;
46370 + A_UINT8 i;
46371 +
46372 + cmdLen = sizeof(pmkInfo->numPMKID) +
46373 + pmkInfo->numPMKID * sizeof(WMI_PMKID);
46374 +
46375 + osbuf = A_NETBUF_ALLOC(cmdLen);
46376 +
46377 + if (osbuf == NULL) {
46378 + return A_NO_MEMORY;
46379 + }
46380 +
46381 + A_NETBUF_PUT(osbuf, cmdLen);
46382 + cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf));
46383 + cmd->numPMKID = pmkInfo->numPMKID;
46384 +
46385 + for (i = 0; i < cmd->numPMKID; i++) {
46386 + A_MEMCPY(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
46387 + WMI_PMKID_LEN);
46388 + }
46389 +
46390 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID,
46391 + NO_SYNC_WMIFLAG));
46392 +}
46393 +
46394 +A_STATUS
46395 +wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
46396 +{
46397 + void *osbuf;
46398 +
46399 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
46400 + if (osbuf == NULL) {
46401 + return A_NO_MEMORY;
46402 + }
46403 +
46404 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_PMKID_LIST_CMDID,
46405 + NO_SYNC_WMIFLAG));
46406 +}
46407 +
46408 +A_STATUS
46409 +wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, WMI_PRI_STREAM_ID streamID)
46410 +{
46411 + WMI_DATA_HDR *dtHdr;
46412 +
46413 + A_ASSERT(streamID != WMI_CONTROL_PRI);
46414 + A_ASSERT(osbuf != NULL);
46415 +
46416 + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
46417 + return A_NO_MEMORY;
46418 + }
46419 +
46420 + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
46421 + dtHdr->info =
46422 + (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT;
46423 +
46424 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - streamID %d\n", DBGARG, streamID));
46425 +
46426 + return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID));
46427 +}
46428 +
46429 +typedef struct _WMI_DATA_SYNC_BUFS {
46430 + A_UINT8 trafficClass;
46431 + void *osbuf;
46432 +}WMI_DATA_SYNC_BUFS;
46433 +
46434 +static A_STATUS
46435 +wmi_sync_point(struct wmi_t *wmip)
46436 +{
46437 + void *cmd_osbuf;
46438 + WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
46439 + A_UINT8 i,numPriStreams=0;
46440 + A_STATUS status;
46441 +
46442 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
46443 +
46444 + memset(dataSyncBufs,0,sizeof(dataSyncBufs));
46445 +
46446 + /* lock out while we walk through the priority list and assemble our local array */
46447 + LOCK_WMI(wmip);
46448 +
46449 + for (i=0; i < WMM_NUM_AC ; i++) {
46450 + if (wmip->wmi_fatPipeExists & (1 << i)) {
46451 + numPriStreams++;
46452 + dataSyncBufs[numPriStreams-1].trafficClass = i;
46453 + }
46454 + }
46455 +
46456 + UNLOCK_WMI(wmip);
46457 +
46458 + /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */
46459 +
46460 + do {
46461 + /*
46462 + * We allocate all network buffers needed so we will be able to
46463 + * send all required frames.
46464 + */
46465 + cmd_osbuf = A_NETBUF_ALLOC(0); /* no payload */
46466 + if (cmd_osbuf == NULL) {
46467 + status = A_NO_MEMORY;
46468 + break;
46469 + }
46470 +
46471 + for (i=0; i < numPriStreams ; i++) {
46472 + dataSyncBufs[i].osbuf = A_NETBUF_ALLOC(0);
46473 + if (dataSyncBufs[i].osbuf == NULL) {
46474 + status = A_NO_MEMORY;
46475 + break;
46476 + }
46477 + } //end for
46478 +
46479 + /*
46480 + * Send sync cmd followed by sync data messages on all endpoints being
46481 + * used
46482 + */
46483 + status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
46484 + NO_SYNC_WMIFLAG);
46485 +
46486 + if (A_FAILED(status)) {
46487 + break;
46488 + }
46489 + /* cmd buffer sent, we no longer own it */
46490 + cmd_osbuf = NULL;
46491 +
46492 + for(i=0; i < numPriStreams; i++) {
46493 + A_ASSERT(dataSyncBufs[i].osbuf != NULL);
46494 +
46495 + status = wmi_dataSync_send(wmip, dataSyncBufs[i].osbuf,
46496 + WMI_ACCESSCATEGORY_WMISTREAM(wmip,dataSyncBufs[i].trafficClass));
46497 +
46498 + if (A_FAILED(status)) {
46499 + break;
46500 + }
46501 + /* we don't own this buffer anymore, NULL it out of the array so it
46502 + * won't get cleaned up */
46503 + dataSyncBufs[i].osbuf = NULL;
46504 + } //end for
46505 +
46506 + } while(FALSE);
46507 +
46508 + /* free up any resources left over (possibly due to an error) */
46509 +
46510 + if (cmd_osbuf != NULL) {
46511 + A_NETBUF_FREE(cmd_osbuf);
46512 + }
46513 +
46514 + for (i = 0; i < numPriStreams; i++) {
46515 + if (dataSyncBufs[i].osbuf != NULL) {
46516 + A_NETBUF_FREE(dataSyncBufs[i].osbuf);
46517 + }
46518 + }
46519 +
46520 + return (status);
46521 +}
46522 +
46523 +A_STATUS
46524 +wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
46525 +{
46526 + void *osbuf;
46527 + WMI_CREATE_PSTREAM_CMD *cmd;
46528 + A_UINT16 activeTsids=0;
46529 + A_UINT8 fatPipeExistsForAC=0;
46530 +
46531 + /* Validate all the parameters. */
46532 + if( !((params->userPriority < 8) &&
46533 + (params->userPriority <= 0x7) &&
46534 + (convert_userPriority_to_trafficClass(params->userPriority) == params->trafficClass) &&
46535 + (params->trafficDirection == UPLINK_TRAFFIC ||
46536 + params->trafficDirection == DNLINK_TRAFFIC ||
46537 + params->trafficDirection == BIDIR_TRAFFIC) &&
46538 + (params->trafficType == TRAFFIC_TYPE_APERIODIC ||
46539 + params->trafficType == TRAFFIC_TYPE_PERIODIC ) &&
46540 + (params->voicePSCapability == DISABLE_FOR_THIS_AC ||
46541 + params->voicePSCapability == ENABLE_FOR_THIS_AC ||
46542 + params->voicePSCapability == ENABLE_FOR_ALL_AC) &&
46543 + (params->tsid == WMI_IMPLICIT_PSTREAM || params->tsid <= WMI_MAX_THINSTREAM)) )
46544 + {
46545 + return A_EINVAL;
46546 + }
46547 +
46548 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46549 + if (osbuf == NULL) {
46550 + return A_NO_MEMORY;
46551 + }
46552 +
46553 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46554 +
46555 + A_DPRINTF(DBG_WMI,
46556 + (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG,
46557 + params->trafficClass, params->tsid));
46558 +
46559 + cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
46560 + A_MEMZERO(cmd, sizeof(*cmd));
46561 + A_MEMCPY(cmd, params, sizeof(*cmd));
46562 +
46563 + /* this is an implicitly created Fat pipe */
46564 + if (params->tsid == WMI_IMPLICIT_PSTREAM) {
46565 + LOCK_WMI(wmip);
46566 + fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
46567 + wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
46568 + UNLOCK_WMI(wmip);
46569 + } else {
46570 + /* this is an explicitly created thin stream within a fat pipe */
46571 + LOCK_WMI(wmip);
46572 + fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
46573 + activeTsids = wmip->wmi_streamExistsForAC[params->trafficClass];
46574 + wmip->wmi_streamExistsForAC[params->trafficClass] |= (1<<params->tsid);
46575 + /* if a thinstream becomes active, the fat pipe automatically
46576 + * becomes active
46577 + */
46578 + wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
46579 + UNLOCK_WMI(wmip);
46580 + }
46581 +
46582 + /* Indicate activty change to driver layer only if this is the
46583 + * first TSID to get created in this AC explicitly or an implicit
46584 + * fat pipe is getting created.
46585 + */
46586 + if (!fatPipeExistsForAC) {
46587 + A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass);
46588 + }
46589 +
46590 + /* mike: should be SYNC_BEFORE_WMIFLAG */
46591 + return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID,
46592 + NO_SYNC_WMIFLAG));
46593 +}
46594 +
46595 +A_STATUS
46596 +wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 tsid)
46597 +{
46598 + void *osbuf;
46599 + WMI_DELETE_PSTREAM_CMD *cmd;
46600 + A_STATUS status;
46601 + A_UINT16 activeTsids=0;
46602 +
46603 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46604 + if (osbuf == NULL) {
46605 + return A_NO_MEMORY;
46606 + }
46607 +
46608 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46609 +
46610 + cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
46611 + A_MEMZERO(cmd, sizeof(*cmd));
46612 +
46613 + cmd->trafficClass = trafficClass;
46614 + cmd->tsid = tsid;
46615 +
46616 + LOCK_WMI(wmip);
46617 + activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
46618 + UNLOCK_WMI(wmip);
46619 +
46620 + /* Check if the tsid was created & exists */
46621 + if (!(activeTsids & (1<<tsid))) {
46622 +
46623 + A_DPRINTF(DBG_WMI,
46624 + (DBGFMT "TSID %d does'nt exist for trafficClass: %d\n", DBGARG, tsid, trafficClass));
46625 + /* TODO: return a more appropriate err code */
46626 + return A_ERROR;
46627 + }
46628 +
46629 + A_DPRINTF(DBG_WMI,
46630 + (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid));
46631 +
46632 + status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID,
46633 + SYNC_BEFORE_WMIFLAG));
46634 +
46635 + LOCK_WMI(wmip);
46636 + wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid);
46637 + activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
46638 + UNLOCK_WMI(wmip);
46639 +
46640 +
46641 + /* Indicate stream inactivity to driver layer only if all tsids
46642 + * within this AC are deleted.
46643 + */
46644 + if(!activeTsids) {
46645 + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass);
46646 + wmip->wmi_fatPipeExists &= ~(1<<trafficClass);
46647 + }
46648 +
46649 + return status;
46650 +}
46651 +
46652 +/*
46653 + * used to set the bit rate. rate is in Kbps. If rate == -1
46654 + * then auto selection is used.
46655 + */
46656 +A_STATUS
46657 +wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 rate)
46658 +{
46659 + void *osbuf;
46660 + WMI_BIT_RATE_CMD *cmd;
46661 + A_INT8 index;
46662 +
46663 + if (rate != -1) {
46664 + index = wmi_validate_bitrate(wmip, rate);
46665 + if(index == A_EINVAL){
46666 + return A_EINVAL;
46667 + }
46668 + } else {
46669 + index = -1;
46670 + }
46671 +
46672 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46673 + if (osbuf == NULL) {
46674 + return A_NO_MEMORY;
46675 + }
46676 +
46677 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46678 +
46679 + cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf));
46680 + A_MEMZERO(cmd, sizeof(*cmd));
46681 +
46682 + cmd->rateIndex = index;
46683 +
46684 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
46685 +}
46686 +
46687 +A_STATUS
46688 +wmi_get_bitrate_cmd(struct wmi_t *wmip)
46689 +{
46690 + void *osbuf;
46691 +
46692 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
46693 + if (osbuf == NULL) {
46694 + return A_NO_MEMORY;
46695 + }
46696 +
46697 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
46698 +}
46699 +
46700 +/*
46701 + * Returns TRUE iff the given rate index is legal in the current PHY mode.
46702 + */
46703 +A_BOOL
46704 +wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex)
46705 +{
46706 + WMI_PHY_MODE phyMode = wmip->wmi_phyMode;
46707 + A_BOOL isValid = TRUE;
46708 + switch(phyMode) {
46709 + case WMI_11A_MODE:
46710 + if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
46711 + isValid = FALSE;
46712 + }
46713 + break;
46714 +
46715 + case WMI_11B_MODE:
46716 + if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
46717 + isValid = FALSE;
46718 + }
46719 + break;
46720 +
46721 + case WMI_11GONLY_MODE:
46722 + if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
46723 + isValid = FALSE;
46724 + }
46725 + break;
46726 +
46727 + case WMI_11G_MODE:
46728 + case WMI_11AG_MODE:
46729 + if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
46730 + isValid = FALSE;
46731 + }
46732 + break;
46733 +
46734 + default:
46735 + A_ASSERT(FALSE);
46736 + break;
46737 + }
46738 +
46739 + return isValid;
46740 +}
46741 +
46742 +A_INT8
46743 +wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate)
46744 +{
46745 + A_INT8 i;
46746 + if (rate != -1)
46747 + {
46748 + for (i=0;;i++)
46749 + {
46750 + if (wmi_rateTable[(A_UINT32) i] == 0) {
46751 + return A_EINVAL;
46752 + }
46753 + if (wmi_rateTable[(A_UINT32) i] == rate) {
46754 + break;
46755 + }
46756 + }
46757 + }
46758 + else{
46759 + i = -1;
46760 + }
46761 +
46762 + if(wmi_is_bitrate_index_valid(wmip, i) != TRUE) {
46763 + return A_EINVAL;
46764 + }
46765 +
46766 + return i;
46767 +}
46768 +
46769 +A_STATUS
46770 +wmi_set_fixrates_cmd(struct wmi_t *wmip, A_INT16 fixRatesMask)
46771 +{
46772 + void *osbuf;
46773 + WMI_FIX_RATES_CMD *cmd;
46774 + A_UINT32 rateIndex;
46775 +
46776 + /* Make sure all rates in the mask are valid in the current PHY mode */
46777 + for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
46778 + if((1 << rateIndex) & (A_UINT32)fixRatesMask) {
46779 + if(wmi_is_bitrate_index_valid(wmip, rateIndex) != TRUE) {
46780 + A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
46781 + return A_EINVAL;
46782 + }
46783 + }
46784 + }
46785 +
46786 +
46787 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46788 + if (osbuf == NULL) {
46789 + return A_NO_MEMORY;
46790 + }
46791 +
46792 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46793 +
46794 + cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf));
46795 + A_MEMZERO(cmd, sizeof(*cmd));
46796 +
46797 + cmd->fixRateMask = fixRatesMask;
46798 +
46799 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
46800 +}
46801 +
46802 +A_STATUS
46803 +wmi_get_ratemask_cmd(struct wmi_t *wmip)
46804 +{
46805 + void *osbuf;
46806 +
46807 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
46808 + if (osbuf == NULL) {
46809 + return A_NO_MEMORY;
46810 + }
46811 +
46812 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
46813 +}
46814 +
46815 +A_STATUS
46816 +wmi_get_channelList_cmd(struct wmi_t *wmip)
46817 +{
46818 + void *osbuf;
46819 +
46820 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
46821 + if (osbuf == NULL) {
46822 + return A_NO_MEMORY;
46823 + }
46824 +
46825 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_CHANNEL_LIST_CMDID,
46826 + NO_SYNC_WMIFLAG));
46827 +}
46828 +
46829 +/*
46830 + * used to generate a wmi sey channel Parameters cmd.
46831 + * mode should always be specified and corresponds to the phy mode of the
46832 + * wlan.
46833 + * numChan should alway sbe specified. If zero indicates that all available
46834 + * channels should be used.
46835 + * channelList is an array of channel frequencies (in Mhz) which the radio
46836 + * should limit its operation to. It should be NULL if numChan == 0. Size of
46837 + * array should correspond to numChan entries.
46838 + */
46839 +A_STATUS
46840 +wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
46841 + WMI_PHY_MODE mode, A_INT8 numChan,
46842 + A_UINT16 *channelList)
46843 +{
46844 + void *osbuf;
46845 + WMI_CHANNEL_PARAMS_CMD *cmd;
46846 + A_INT8 size;
46847 +
46848 + size = sizeof (*cmd);
46849 +
46850 + if (numChan) {
46851 + if (numChan > WMI_MAX_CHANNELS) {
46852 + return A_EINVAL;
46853 + }
46854 + size += sizeof(A_UINT16) * (numChan - 1);
46855 + }
46856 +
46857 + osbuf = A_NETBUF_ALLOC(size);
46858 + if (osbuf == NULL) {
46859 + return A_NO_MEMORY;
46860 + }
46861 +
46862 + A_NETBUF_PUT(osbuf, size);
46863 +
46864 + cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
46865 + A_MEMZERO(cmd, size);
46866 +
46867 + wmip->wmi_phyMode = mode;
46868 + cmd->scanParam = scanParam;
46869 + cmd->phyMode = mode;
46870 + cmd->numChannels = numChan;
46871 + A_MEMCPY(cmd->channelList, channelList, numChan * sizeof(A_UINT16));
46872 +
46873 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
46874 + NO_SYNC_WMIFLAG));
46875 +}
46876 +
46877 +A_STATUS
46878 +wmi_set_rssi_threshold_params(struct wmi_t *wmip,
46879 + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
46880 +{
46881 + void *osbuf;
46882 + A_INT8 size;
46883 + WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
46884 + /* These values are in ascending order */
46885 + if( rssiCmd->thresholdAbove6_Val <= rssiCmd->thresholdAbove5_Val ||
46886 + rssiCmd->thresholdAbove5_Val <= rssiCmd->thresholdAbove4_Val ||
46887 + rssiCmd->thresholdAbove4_Val <= rssiCmd->thresholdAbove3_Val ||
46888 + rssiCmd->thresholdAbove3_Val <= rssiCmd->thresholdAbove2_Val ||
46889 + rssiCmd->thresholdAbove2_Val <= rssiCmd->thresholdAbove1_Val ||
46890 + rssiCmd->thresholdBelow6_Val <= rssiCmd->thresholdBelow5_Val ||
46891 + rssiCmd->thresholdBelow5_Val <= rssiCmd->thresholdBelow4_Val ||
46892 + rssiCmd->thresholdBelow4_Val <= rssiCmd->thresholdBelow3_Val ||
46893 + rssiCmd->thresholdBelow3_Val <= rssiCmd->thresholdBelow2_Val ||
46894 + rssiCmd->thresholdBelow2_Val <= rssiCmd->thresholdBelow1_Val) {
46895 +
46896 + return A_EINVAL;
46897 + }
46898 +
46899 + size = sizeof (*cmd);
46900 +
46901 + osbuf = A_NETBUF_ALLOC(size);
46902 + if (osbuf == NULL) {
46903 + return A_NO_MEMORY;
46904 + }
46905 +
46906 + A_NETBUF_PUT(osbuf, size);
46907 +
46908 + cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
46909 + A_MEMZERO(cmd, size);
46910 + A_MEMCPY(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
46911 +
46912 + return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
46913 + NO_SYNC_WMIFLAG));
46914 +}
46915 +
46916 +A_STATUS
46917 +wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
46918 + WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
46919 +{
46920 + void *osbuf;
46921 + A_INT8 size;
46922 + WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
46923 +
46924 + if( hostModeCmd->awake == hostModeCmd->asleep) {
46925 + return A_EINVAL;
46926 + }
46927 +
46928 + size = sizeof (*cmd);
46929 +
46930 + osbuf = A_NETBUF_ALLOC(size);
46931 + if (osbuf == NULL) {
46932 + return A_NO_MEMORY;
46933 + }
46934 +
46935 + A_NETBUF_PUT(osbuf, size);
46936 +
46937 + cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
46938 + A_MEMZERO(cmd, size);
46939 + A_MEMCPY(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
46940 +
46941 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID,
46942 + NO_SYNC_WMIFLAG));
46943 +}
46944 +
46945 +A_STATUS
46946 +wmi_set_wow_mode_cmd(struct wmi_t *wmip,
46947 + WMI_SET_WOW_MODE_CMD *wowModeCmd)
46948 +{
46949 + void *osbuf;
46950 + A_INT8 size;
46951 + WMI_SET_WOW_MODE_CMD *cmd;
46952 +
46953 + size = sizeof (*cmd);
46954 +
46955 + osbuf = A_NETBUF_ALLOC(size);
46956 + if (osbuf == NULL) {
46957 + return A_NO_MEMORY;
46958 + }
46959 +
46960 + A_NETBUF_PUT(osbuf, size);
46961 +
46962 + cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
46963 + A_MEMZERO(cmd, size);
46964 + A_MEMCPY(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
46965 +
46966 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
46967 + NO_SYNC_WMIFLAG));
46968 +
46969 +}
46970 +
46971 +A_STATUS
46972 +wmi_get_wow_list_cmd(struct wmi_t *wmip,
46973 + WMI_GET_WOW_LIST_CMD *wowListCmd)
46974 +{
46975 + void *osbuf;
46976 + A_INT8 size;
46977 + WMI_GET_WOW_LIST_CMD *cmd;
46978 +
46979 + size = sizeof (*cmd);
46980 +
46981 + osbuf = A_NETBUF_ALLOC(size);
46982 + if (osbuf == NULL) {
46983 + return A_NO_MEMORY;
46984 + }
46985 +
46986 + A_NETBUF_PUT(osbuf, size);
46987 +
46988 + cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
46989 + A_MEMZERO(cmd, size);
46990 + A_MEMCPY(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
46991 +
46992 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
46993 + NO_SYNC_WMIFLAG));
46994 +
46995 +}
46996 +
46997 +static A_STATUS
46998 +wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
46999 +{
47000 + WMI_GET_WOW_LIST_REPLY *reply;
47001 +
47002 + if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) {
47003 + return A_EINVAL;
47004 + }
47005 + reply = (WMI_GET_WOW_LIST_REPLY *)datap;
47006 +
47007 + A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
47008 + reply);
47009 +
47010 + return A_OK;
47011 +}
47012 +
47013 +A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
47014 + WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
47015 + A_UINT8* pattern, A_UINT8* mask,
47016 + A_UINT8 pattern_size)
47017 +{
47018 + void *osbuf;
47019 + A_INT8 size;
47020 + WMI_ADD_WOW_PATTERN_CMD *cmd;
47021 + A_UINT8 *filter_mask = NULL;
47022 +
47023 + size = sizeof (*cmd);
47024 +
47025 + size += ((2 * addWowCmd->filter_size)* sizeof(A_UINT8));
47026 + osbuf = A_NETBUF_ALLOC(size);
47027 + if (osbuf == NULL) {
47028 + return A_NO_MEMORY;
47029 + }
47030 +
47031 + A_NETBUF_PUT(osbuf, size);
47032 +
47033 + cmd = (WMI_ADD_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
47034 + cmd->filter_list_id = addWowCmd->filter_list_id;
47035 + cmd->filter_offset = addWowCmd->filter_offset;
47036 + cmd->filter_size = addWowCmd->filter_size;
47037 +
47038 + A_MEMCPY(cmd->filter, pattern, addWowCmd->filter_size);
47039 +
47040 + filter_mask = (A_UINT8*)(cmd->filter + cmd->filter_size);
47041 + A_MEMCPY(filter_mask, mask, addWowCmd->filter_size);
47042 +
47043 +
47044 + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
47045 + NO_SYNC_WMIFLAG));
47046 +}
47047 +
47048 +A_STATUS
47049 +wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
47050 + WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
47051 +{
47052 + void *osbuf;
47053 + A_INT8 size;
47054 + WMI_DEL_WOW_PATTERN_CMD *cmd;
47055 +
47056 + size = sizeof (*cmd);
47057 +
47058 + osbuf = A_NETBUF_ALLOC(size);
47059 + if (osbuf == NULL) {
47060 + return A_NO_MEMORY;
47061 + }
47062 +
47063 + A_NETBUF_PUT(osbuf, size);
47064 +
47065 + cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
47066 + A_MEMZERO(cmd, size);
47067 + A_MEMCPY(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
47068 +
47069 + return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
47070 + NO_SYNC_WMIFLAG));
47071 +
47072 +}
47073 +
47074 +A_STATUS
47075 +wmi_set_snr_threshold_params(struct wmi_t *wmip,
47076 + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
47077 +{
47078 + void *osbuf;
47079 + A_INT8 size;
47080 + WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
47081 + /* These values are in ascending order */
47082 + if( snrCmd->thresholdAbove4_Val <= snrCmd->thresholdAbove3_Val ||
47083 + snrCmd->thresholdAbove3_Val <= snrCmd->thresholdAbove2_Val ||
47084 + snrCmd->thresholdAbove2_Val <= snrCmd->thresholdAbove1_Val ||
47085 + snrCmd->thresholdBelow4_Val <= snrCmd->thresholdBelow3_Val ||
47086 + snrCmd->thresholdBelow3_Val <= snrCmd->thresholdBelow2_Val ||
47087 + snrCmd->thresholdBelow2_Val <= snrCmd->thresholdBelow1_Val) {
47088 +
47089 + return A_EINVAL;
47090 + }
47091 +
47092 + size = sizeof (*cmd);
47093 +
47094 + osbuf = A_NETBUF_ALLOC(size);
47095 + if (osbuf == NULL) {
47096 + return A_NO_MEMORY;
47097 + }
47098 +
47099 + A_NETBUF_PUT(osbuf, size);
47100 +
47101 + cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
47102 + A_MEMZERO(cmd, size);
47103 + A_MEMCPY(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
47104 +
47105 + return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
47106 + NO_SYNC_WMIFLAG));
47107 +}
47108 +
47109 +A_STATUS
47110 +wmi_clr_rssi_snr(struct wmi_t *wmip)
47111 +{
47112 + void *osbuf;
47113 +
47114 + osbuf = A_NETBUF_ALLOC(sizeof(int));
47115 + if (osbuf == NULL) {
47116 + return A_NO_MEMORY;
47117 + }
47118 +
47119 + return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID,
47120 + NO_SYNC_WMIFLAG));
47121 +}
47122 +
47123 +A_STATUS
47124 +wmi_set_lq_threshold_params(struct wmi_t *wmip,
47125 + WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
47126 +{
47127 + void *osbuf;
47128 + A_INT8 size;
47129 + WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
47130 + /* These values are in ascending order */
47131 + if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
47132 + lqCmd->thresholdAbove3_Val <= lqCmd->thresholdAbove2_Val ||
47133 + lqCmd->thresholdAbove2_Val <= lqCmd->thresholdAbove1_Val ||
47134 + lqCmd->thresholdBelow4_Val <= lqCmd->thresholdBelow3_Val ||
47135 + lqCmd->thresholdBelow3_Val <= lqCmd->thresholdBelow2_Val ||
47136 + lqCmd->thresholdBelow2_Val <= lqCmd->thresholdBelow1_Val ) {
47137 +
47138 + return A_EINVAL;
47139 + }
47140 +
47141 + size = sizeof (*cmd);
47142 +
47143 + osbuf = A_NETBUF_ALLOC(size);
47144 + if (osbuf == NULL) {
47145 + return A_NO_MEMORY;
47146 + }
47147 +
47148 + A_NETBUF_PUT(osbuf, size);
47149 +
47150 + cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
47151 + A_MEMZERO(cmd, size);
47152 + A_MEMCPY(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
47153 +
47154 + return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
47155 + NO_SYNC_WMIFLAG));
47156 +}
47157 +
47158 +A_STATUS
47159 +wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 mask)
47160 +{
47161 + void *osbuf;
47162 + A_INT8 size;
47163 + WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
47164 +
47165 + size = sizeof (*cmd);
47166 +
47167 + osbuf = A_NETBUF_ALLOC(size);
47168 + if (osbuf == NULL) {
47169 + return A_NO_MEMORY;
47170 + }
47171 +
47172 + A_NETBUF_PUT(osbuf, size);
47173 +
47174 + cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf));
47175 + A_MEMZERO(cmd, size);
47176 +
47177 + cmd->bitmask = mask;
47178 +
47179 + return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
47180 + NO_SYNC_WMIFLAG));
47181 +}
47182 +
47183 +A_STATUS
47184 +wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie, A_UINT32 source)
47185 +{
47186 + void *osbuf;
47187 + WMIX_HB_CHALLENGE_RESP_CMD *cmd;
47188 +
47189 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47190 + if (osbuf == NULL) {
47191 + return A_NO_MEMORY;
47192 + }
47193 +
47194 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47195 +
47196 + cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf));
47197 + cmd->cookie = cookie;
47198 + cmd->source = source;
47199 +
47200 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID,
47201 + NO_SYNC_WMIFLAG));
47202 +}
47203 +
47204 +A_STATUS
47205 +wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
47206 + A_UINT16 tsr, A_BOOL rep, A_UINT16 size,
47207 + A_UINT32 valid)
47208 +{
47209 + void *osbuf;
47210 + WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
47211 +
47212 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47213 + if (osbuf == NULL) {
47214 + return A_NO_MEMORY;
47215 + }
47216 +
47217 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47218 +
47219 + cmd = (WMIX_DBGLOG_CFG_MODULE_CMD *)(A_NETBUF_DATA(osbuf));
47220 + cmd->config.cfgmmask = mmask;
47221 + cmd->config.cfgtsr = tsr;
47222 + cmd->config.cfgrep = rep;
47223 + cmd->config.cfgsize = size;
47224 + cmd->config.cfgvalid = valid;
47225 +
47226 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID,
47227 + NO_SYNC_WMIFLAG));
47228 +}
47229 +
47230 +A_STATUS
47231 +wmi_get_stats_cmd(struct wmi_t *wmip)
47232 +{
47233 + void *osbuf;
47234 +
47235 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
47236 + if (osbuf == NULL) {
47237 + return A_NO_MEMORY;
47238 + }
47239 +
47240 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_STATISTICS_CMDID,
47241 + NO_SYNC_WMIFLAG));
47242 +}
47243 +
47244 +A_STATUS
47245 +wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid)
47246 +{
47247 + void *osbuf;
47248 + WMI_ADD_BAD_AP_CMD *cmd;
47249 +
47250 + if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) {
47251 + return A_EINVAL;
47252 + }
47253 +
47254 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47255 + if (osbuf == NULL) {
47256 + return A_NO_MEMORY;
47257 + }
47258 +
47259 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47260 +
47261 + cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
47262 + cmd->badApIndex = apIndex;
47263 + A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
47264 +
47265 + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, NO_SYNC_WMIFLAG));
47266 +}
47267 +
47268 +A_STATUS
47269 +wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex)
47270 +{
47271 + void *osbuf;
47272 + WMI_DELETE_BAD_AP_CMD *cmd;
47273 +
47274 + if (apIndex > WMI_MAX_BAD_AP_INDEX) {
47275 + return A_EINVAL;
47276 + }
47277 +
47278 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47279 + if (osbuf == NULL) {
47280 + return A_NO_MEMORY;
47281 + }
47282 +
47283 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47284 +
47285 + cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
47286 + cmd->badApIndex = apIndex;
47287 +
47288 + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID,
47289 + NO_SYNC_WMIFLAG));
47290 +}
47291 +
47292 +A_STATUS
47293 +wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM)
47294 +{
47295 + void *osbuf;
47296 + WMI_SET_TX_PWR_CMD *cmd;
47297 +
47298 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47299 + if (osbuf == NULL) {
47300 + return A_NO_MEMORY;
47301 + }
47302 +
47303 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47304 +
47305 + cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf));
47306 + cmd->dbM = dbM;
47307 +
47308 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
47309 +}
47310 +
47311 +A_STATUS
47312 +wmi_get_txPwr_cmd(struct wmi_t *wmip)
47313 +{
47314 + void *osbuf;
47315 +
47316 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
47317 + if (osbuf == NULL) {
47318 + return A_NO_MEMORY;
47319 + }
47320 +
47321 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
47322 +}
47323 +
47324 +A_STATUS
47325 +wmi_switch_radio(struct wmi_t *wmip, A_UINT8 on)
47326 +{
47327 + WMI_SCAN_PARAMS_CMD scParams = {0, 0, 0, 0, 0,
47328 + WMI_SHORTSCANRATIO_DEFAULT,
47329 + DEFAULT_SCAN_CTRL_FLAGS,
47330 + 0};
47331 +
47332 + if (on) {
47333 + /* Enable foreground scanning */
47334 + if (wmi_scanparams_cmd(wmip, scParams.fg_start_period,
47335 + scParams.fg_end_period,
47336 + scParams.bg_period,
47337 + scParams.minact_chdwell_time,
47338 + scParams.maxact_chdwell_time,
47339 + scParams.pas_chdwell_time,
47340 + scParams.shortScanRatio,
47341 + scParams.scanCtrlFlags,
47342 + scParams.max_dfsch_act_time) != A_OK) {
47343 + return -EIO;
47344 + }
47345 + } else {
47346 + wmi_disconnect_cmd(wmip);
47347 + if (wmi_scanparams_cmd(wmip, 0xFFFF, 0, 0, 0,
47348 + 0, 0, 0, 0xFF, 0) != A_OK) {
47349 + return -EIO;
47350 + }
47351 + }
47352 +
47353 + return A_OK;
47354 +}
47355 +
47356 +
47357 +A_UINT16
47358 +wmi_get_mapped_qos_queue(struct wmi_t *wmip, A_UINT8 trafficClass)
47359 +{
47360 + A_UINT16 activeTsids=0;
47361 +
47362 + LOCK_WMI(wmip);
47363 + activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
47364 + UNLOCK_WMI(wmip);
47365 +
47366 + return activeTsids;
47367 +}
47368 +
47369 +A_STATUS
47370 +wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
47371 +{
47372 + void *osbuf;
47373 +
47374 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
47375 + if (osbuf == NULL) {
47376 + return A_NO_MEMORY;
47377 + }
47378 +
47379 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_TBL_CMDID,
47380 + NO_SYNC_WMIFLAG));
47381 +}
47382 +
47383 +A_STATUS
47384 +wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType)
47385 +{
47386 + void *osbuf;
47387 + A_UINT32 size = sizeof(A_UINT8);
47388 + WMI_TARGET_ROAM_DATA *cmd;
47389 +
47390 + osbuf = A_NETBUF_ALLOC(size); /* no payload */
47391 + if (osbuf == NULL) {
47392 + return A_NO_MEMORY;
47393 + }
47394 +
47395 + A_NETBUF_PUT(osbuf, size);
47396 +
47397 + cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf));
47398 + cmd->roamDataType = roamDataType;
47399 +
47400 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID,
47401 + NO_SYNC_WMIFLAG));
47402 +}
47403 +
47404 +A_STATUS
47405 +wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
47406 + A_UINT8 size)
47407 +{
47408 + void *osbuf;
47409 + WMI_SET_ROAM_CTRL_CMD *cmd;
47410 +
47411 + osbuf = A_NETBUF_ALLOC(size);
47412 + if (osbuf == NULL) {
47413 + return A_NO_MEMORY;
47414 + }
47415 +
47416 + A_NETBUF_PUT(osbuf, size);
47417 +
47418 + cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
47419 + A_MEMZERO(cmd, size);
47420 +
47421 + A_MEMCPY(cmd, p, size);
47422 +
47423 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
47424 + NO_SYNC_WMIFLAG));
47425 +}
47426 +
47427 +A_STATUS
47428 +wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
47429 + WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
47430 + A_UINT8 size)
47431 +{
47432 + void *osbuf;
47433 + WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
47434 +
47435 + /* These timers can't be zero */
47436 + if(!pCmd->psPollTimeout || !pCmd->triggerTimeout ||
47437 + !(pCmd->apsdTimPolicy == IGNORE_TIM_ALL_QUEUES_APSD ||
47438 + pCmd->apsdTimPolicy == PROCESS_TIM_ALL_QUEUES_APSD) ||
47439 + !(pCmd->simulatedAPSDTimPolicy == IGNORE_TIM_SIMULATED_APSD ||
47440 + pCmd->simulatedAPSDTimPolicy == PROCESS_TIM_SIMULATED_APSD))
47441 + return A_EINVAL;
47442 +
47443 + osbuf = A_NETBUF_ALLOC(size);
47444 + if (osbuf == NULL) {
47445 + return A_NO_MEMORY;
47446 + }
47447 +
47448 + A_NETBUF_PUT(osbuf, size);
47449 +
47450 + cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
47451 + A_MEMZERO(cmd, size);
47452 +
47453 + A_MEMCPY(cmd, pCmd, size);
47454 +
47455 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
47456 + NO_SYNC_WMIFLAG));
47457 +}
47458 +
47459 +#ifdef CONFIG_HOST_GPIO_SUPPORT
47460 +/* Send a command to Target to change GPIO output pins. */
47461 +A_STATUS
47462 +wmi_gpio_output_set(struct wmi_t *wmip,
47463 + A_UINT32 set_mask,
47464 + A_UINT32 clear_mask,
47465 + A_UINT32 enable_mask,
47466 + A_UINT32 disable_mask)
47467 +{
47468 + void *osbuf;
47469 + WMIX_GPIO_OUTPUT_SET_CMD *output_set;
47470 + int size;
47471 +
47472 + size = sizeof(*output_set);
47473 +
47474 + A_DPRINTF(DBG_WMI,
47475 + (DBGFMT "Enter - set=0x%x clear=0x%x enb=0x%x dis=0x%x\n", DBGARG,
47476 + set_mask, clear_mask, enable_mask, disable_mask));
47477 +
47478 + osbuf = A_NETBUF_ALLOC(size);
47479 + if (osbuf == NULL) {
47480 + return A_NO_MEMORY;
47481 + }
47482 + A_NETBUF_PUT(osbuf, size);
47483 + output_set = (WMIX_GPIO_OUTPUT_SET_CMD *)(A_NETBUF_DATA(osbuf));
47484 +
47485 + output_set->set_mask = set_mask;
47486 + output_set->clear_mask = clear_mask;
47487 + output_set->enable_mask = enable_mask;
47488 + output_set->disable_mask = disable_mask;
47489 +
47490 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_OUTPUT_SET_CMDID,
47491 + NO_SYNC_WMIFLAG));
47492 +}
47493 +
47494 +/* Send a command to the Target requesting state of the GPIO input pins */
47495 +A_STATUS
47496 +wmi_gpio_input_get(struct wmi_t *wmip)
47497 +{
47498 + void *osbuf;
47499 +
47500 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
47501 +
47502 + osbuf = A_NETBUF_ALLOC(0);
47503 + if (osbuf == NULL) {
47504 + return A_NO_MEMORY;
47505 + }
47506 +
47507 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INPUT_GET_CMDID,
47508 + NO_SYNC_WMIFLAG));
47509 +}
47510 +
47511 +/* Send a command to the Target that changes the value of a GPIO register. */
47512 +A_STATUS
47513 +wmi_gpio_register_set(struct wmi_t *wmip,
47514 + A_UINT32 gpioreg_id,
47515 + A_UINT32 value)
47516 +{
47517 + void *osbuf;
47518 + WMIX_GPIO_REGISTER_SET_CMD *register_set;
47519 + int size;
47520 +
47521 + size = sizeof(*register_set);
47522 +
47523 + A_DPRINTF(DBG_WMI,
47524 + (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, gpioreg_id, value));
47525 +
47526 + osbuf = A_NETBUF_ALLOC(size);
47527 + if (osbuf == NULL) {
47528 + return A_NO_MEMORY;
47529 + }
47530 + A_NETBUF_PUT(osbuf, size);
47531 + register_set = (WMIX_GPIO_REGISTER_SET_CMD *)(A_NETBUF_DATA(osbuf));
47532 +
47533 + register_set->gpioreg_id = gpioreg_id;
47534 + register_set->value = value;
47535 +
47536 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_SET_CMDID,
47537 + NO_SYNC_WMIFLAG));
47538 +}
47539 +
47540 +/* Send a command to the Target to fetch the value of a GPIO register. */
47541 +A_STATUS
47542 +wmi_gpio_register_get(struct wmi_t *wmip,
47543 + A_UINT32 gpioreg_id)
47544 +{
47545 + void *osbuf;
47546 + WMIX_GPIO_REGISTER_GET_CMD *register_get;
47547 + int size;
47548 +
47549 + size = sizeof(*register_get);
47550 +
47551 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - reg=%d\n", DBGARG, gpioreg_id));
47552 +
47553 + osbuf = A_NETBUF_ALLOC(size);
47554 + if (osbuf == NULL) {
47555 + return A_NO_MEMORY;
47556 + }
47557 + A_NETBUF_PUT(osbuf, size);
47558 + register_get = (WMIX_GPIO_REGISTER_GET_CMD *)(A_NETBUF_DATA(osbuf));
47559 +
47560 + register_get->gpioreg_id = gpioreg_id;
47561 +
47562 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_GET_CMDID,
47563 + NO_SYNC_WMIFLAG));
47564 +}
47565 +
47566 +/* Send a command to the Target acknowledging some GPIO interrupts. */
47567 +A_STATUS
47568 +wmi_gpio_intr_ack(struct wmi_t *wmip,
47569 + A_UINT32 ack_mask)
47570 +{
47571 + void *osbuf;
47572 + WMIX_GPIO_INTR_ACK_CMD *intr_ack;
47573 + int size;
47574 +
47575 + size = sizeof(*intr_ack);
47576 +
47577 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter ack_mask=0x%x\n", DBGARG, ack_mask));
47578 +
47579 + osbuf = A_NETBUF_ALLOC(size);
47580 + if (osbuf == NULL) {
47581 + return A_NO_MEMORY;
47582 + }
47583 + A_NETBUF_PUT(osbuf, size);
47584 + intr_ack = (WMIX_GPIO_INTR_ACK_CMD *)(A_NETBUF_DATA(osbuf));
47585 +
47586 + intr_ack->ack_mask = ack_mask;
47587 +
47588 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INTR_ACK_CMDID,
47589 + NO_SYNC_WMIFLAG));
47590 +}
47591 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
47592 +
47593 +A_STATUS
47594 +wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT16 txop, A_UINT8 eCWmin,
47595 + A_UINT8 eCWmax, A_UINT8 aifsn)
47596 +{
47597 + void *osbuf;
47598 + WMI_SET_ACCESS_PARAMS_CMD *cmd;
47599 +
47600 + if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) ||
47601 + (aifsn > WMI_MAX_AIFSN_ACPARAM))
47602 + {
47603 + return A_EINVAL;
47604 + }
47605 +
47606 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47607 + if (osbuf == NULL) {
47608 + return A_NO_MEMORY;
47609 + }
47610 +
47611 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47612 +
47613 + cmd = (WMI_SET_ACCESS_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
47614 + cmd->txop = txop;
47615 + cmd->eCWmin = eCWmin;
47616 + cmd->eCWmax = eCWmax;
47617 + cmd->aifsn = aifsn;
47618 +
47619 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID,
47620 + NO_SYNC_WMIFLAG));
47621 +}
47622 +
47623 +A_STATUS
47624 +wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
47625 + A_UINT8 trafficClass, A_UINT8 maxRetries,
47626 + A_UINT8 enableNotify)
47627 +{
47628 + void *osbuf;
47629 + WMI_SET_RETRY_LIMITS_CMD *cmd;
47630 +
47631 + if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) &&
47632 + (frameType != DATA_FRAMETYPE))
47633 + {
47634 + return A_EINVAL;
47635 + }
47636 +
47637 + if (maxRetries > WMI_MAX_RETRIES) {
47638 + return A_EINVAL;
47639 + }
47640 +
47641 + if (frameType != DATA_FRAMETYPE) {
47642 + trafficClass = 0;
47643 + }
47644 +
47645 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47646 + if (osbuf == NULL) {
47647 + return A_NO_MEMORY;
47648 + }
47649 +
47650 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47651 +
47652 + cmd = (WMI_SET_RETRY_LIMITS_CMD *)(A_NETBUF_DATA(osbuf));
47653 + cmd->frameType = frameType;
47654 + cmd->trafficClass = trafficClass;
47655 + cmd->maxRetries = maxRetries;
47656 + cmd->enableNotify = enableNotify;
47657 +
47658 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID,
47659 + NO_SYNC_WMIFLAG));
47660 +}
47661 +
47662 +void
47663 +wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid)
47664 +{
47665 + if (bssid != NULL) {
47666 + A_MEMCPY(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
47667 + }
47668 +}
47669 +
47670 +A_STATUS
47671 +wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode)
47672 +{
47673 + void *osbuf;
47674 + WMI_SET_OPT_MODE_CMD *cmd;
47675 +
47676 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47677 + if (osbuf == NULL) {
47678 + return A_NO_MEMORY;
47679 + }
47680 +
47681 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47682 +
47683 + cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf));
47684 + A_MEMZERO(cmd, sizeof(*cmd));
47685 + cmd->optMode = optMode;
47686 +
47687 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID,
47688 + SYNC_BOTH_WMIFLAG));
47689 +}
47690 +
47691 +A_STATUS
47692 +wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
47693 + A_UINT8 frmType,
47694 + A_UINT8 *dstMacAddr,
47695 + A_UINT8 *bssid,
47696 + A_UINT16 optIEDataLen,
47697 + A_UINT8 *optIEData)
47698 +{
47699 + void *osbuf;
47700 + WMI_OPT_TX_FRAME_CMD *cmd;
47701 + osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd));
47702 + if (osbuf == NULL) {
47703 + return A_NO_MEMORY;
47704 + }
47705 +
47706 + A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd)));
47707 +
47708 + cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf));
47709 + A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1));
47710 +
47711 + cmd->frmType = frmType;
47712 + cmd->optIEDataLen = optIEDataLen;
47713 + //cmd->optIEData = (A_UINT8 *)((int)cmd + sizeof(*cmd));
47714 + A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
47715 + A_MEMCPY(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
47716 + A_MEMCPY(&cmd->optIEData[0], optIEData, optIEDataLen);
47717 +
47718 + return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
47719 + NO_SYNC_WMIFLAG));
47720 +}
47721 +
47722 +A_STATUS
47723 +wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl)
47724 +{
47725 + void *osbuf;
47726 + WMI_BEACON_INT_CMD *cmd;
47727 +
47728 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47729 + if (osbuf == NULL) {
47730 + return A_NO_MEMORY;
47731 + }
47732 +
47733 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47734 +
47735 + cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf));
47736 + A_MEMZERO(cmd, sizeof(*cmd));
47737 + cmd->beaconInterval = intvl;
47738 +
47739 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID,
47740 + NO_SYNC_WMIFLAG));
47741 +}
47742 +
47743 +
47744 +A_STATUS
47745 +wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize)
47746 +{
47747 + void *osbuf;
47748 + WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
47749 +
47750 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47751 + if (osbuf == NULL) {
47752 + return A_NO_MEMORY;
47753 + }
47754 +
47755 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47756 +
47757 + cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf));
47758 + A_MEMZERO(cmd, sizeof(*cmd));
47759 + cmd->voicePktSize = voicePktSize;
47760 +
47761 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID,
47762 + NO_SYNC_WMIFLAG));
47763 +}
47764 +
47765 +
47766 +A_STATUS
47767 +wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSPLen)
47768 +{
47769 + void *osbuf;
47770 + WMI_SET_MAX_SP_LEN_CMD *cmd;
47771 +
47772 + /* maxSPLen is a two-bit value. If user trys to set anything
47773 + * other than this, then its invalid
47774 + */
47775 + if(maxSPLen & ~0x03)
47776 + return A_EINVAL;
47777 +
47778 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47779 + if (osbuf == NULL) {
47780 + return A_NO_MEMORY;
47781 + }
47782 +
47783 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47784 +
47785 + cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf));
47786 + A_MEMZERO(cmd, sizeof(*cmd));
47787 + cmd->maxSPLen = maxSPLen;
47788 +
47789 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID,
47790 + NO_SYNC_WMIFLAG));
47791 +}
47792 +
47793 +A_UINT8
47794 +convert_userPriority_to_trafficClass(A_UINT8 userPriority)
47795 +{
47796 + return (up_to_ac[userPriority & 0x7]);
47797 +}
47798 +
47799 +A_UINT8
47800 +wmi_get_power_mode_cmd(struct wmi_t *wmip)
47801 +{
47802 + return wmip->wmi_powerMode;
47803 +}
47804 +
47805 +A_STATUS
47806 +wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance)
47807 +{
47808 + return A_OK;
47809 +}
47810 +
47811 +#ifdef CONFIG_HOST_TCMD_SUPPORT
47812 +static A_STATUS
47813 +wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
47814 +{
47815 +
47816 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
47817 +
47818 + A_WMI_TCMD_RX_REPORT_EVENT(wmip->wmi_devt, datap, len);
47819 +
47820 + return A_OK;
47821 +}
47822 +
47823 +#endif /* CONFIG_HOST_TCMD_SUPPORT*/
47824 +
47825 +A_STATUS
47826 +wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
47827 +{
47828 + void *osbuf;
47829 + WMI_SET_AUTH_MODE_CMD *cmd;
47830 +
47831 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47832 + if (osbuf == NULL) {
47833 + return A_NO_MEMORY;
47834 + }
47835 +
47836 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47837 +
47838 + cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf));
47839 + A_MEMZERO(cmd, sizeof(*cmd));
47840 + cmd->mode = mode;
47841 +
47842 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID,
47843 + NO_SYNC_WMIFLAG));
47844 +}
47845 +
47846 +A_STATUS
47847 +wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
47848 +{
47849 + void *osbuf;
47850 + WMI_SET_REASSOC_MODE_CMD *cmd;
47851 +
47852 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47853 + if (osbuf == NULL) {
47854 + return A_NO_MEMORY;
47855 + }
47856 +
47857 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47858 +
47859 + cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf));
47860 + A_MEMZERO(cmd, sizeof(*cmd));
47861 + cmd->mode = mode;
47862 +
47863 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID,
47864 + NO_SYNC_WMIFLAG));
47865 +}
47866 +
47867 +A_STATUS
47868 +wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status)
47869 +{
47870 + void *osbuf;
47871 + WMI_SET_LPREAMBLE_CMD *cmd;
47872 +
47873 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47874 + if (osbuf == NULL) {
47875 + return A_NO_MEMORY;
47876 + }
47877 +
47878 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47879 +
47880 + cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf));
47881 + A_MEMZERO(cmd, sizeof(*cmd));
47882 + cmd->status = status;
47883 +
47884 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID,
47885 + NO_SYNC_WMIFLAG));
47886 +}
47887 +
47888 +A_STATUS
47889 +wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold)
47890 +{
47891 + void *osbuf;
47892 + WMI_SET_RTS_CMD *cmd;
47893 +
47894 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47895 + if (osbuf == NULL) {
47896 + return A_NO_MEMORY;
47897 + }
47898 +
47899 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47900 +
47901 + cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf));
47902 + A_MEMZERO(cmd, sizeof(*cmd));
47903 + cmd->threshold = threshold;
47904 +
47905 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID,
47906 + NO_SYNC_WMIFLAG));
47907 +}
47908 +
47909 +A_STATUS
47910 +wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
47911 +{
47912 + void *osbuf;
47913 + WMI_SET_WMM_CMD *cmd;
47914 +
47915 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47916 + if (osbuf == NULL) {
47917 + return A_NO_MEMORY;
47918 + }
47919 +
47920 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47921 +
47922 + cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf));
47923 + A_MEMZERO(cmd, sizeof(*cmd));
47924 + cmd->status = status;
47925 +
47926 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID,
47927 + NO_SYNC_WMIFLAG));
47928 +
47929 +}
47930 +
47931 +A_STATUS
47932 +wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
47933 +{
47934 + void *osbuf;
47935 + WMI_SET_WMM_TXOP_CMD *cmd;
47936 +
47937 + if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) )
47938 + return A_EINVAL;
47939 +
47940 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47941 + if (osbuf == NULL) {
47942 + return A_NO_MEMORY;
47943 + }
47944 +
47945 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47946 +
47947 + cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf));
47948 + A_MEMZERO(cmd, sizeof(*cmd));
47949 + cmd->txopEnable = cfg;
47950 +
47951 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID,
47952 + NO_SYNC_WMIFLAG));
47953 +
47954 +}
47955 +
47956 +#ifdef CONFIG_HOST_TCMD_SUPPORT
47957 +/* WMI layer doesn't need to know the data type of the test cmd.
47958 + This would be beneficial for customers like Qualcomm, who might
47959 + have different test command requirements from differnt manufacturers
47960 + */
47961 +A_STATUS
47962 +wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32 len)
47963 +{
47964 + void *osbuf;
47965 + char *data;
47966 +
47967 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
47968 +
47969 + osbuf= A_NETBUF_ALLOC(len);
47970 + if(osbuf == NULL)
47971 + {
47972 + return A_NO_MEMORY;
47973 + }
47974 + A_NETBUF_PUT(osbuf, len);
47975 + data = A_NETBUF_DATA(osbuf);
47976 + A_MEMCPY(data, buf, len);
47977 +
47978 + return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
47979 + NO_SYNC_WMIFLAG));
47980 +}
47981 +
47982 +#endif
47983 +
47984 +A_STATUS
47985 +wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status)
47986 +{
47987 + void *osbuf;
47988 + WMI_SET_BT_STATUS_CMD *cmd;
47989 +
47990 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47991 + if (osbuf == NULL) {
47992 + return A_NO_MEMORY;
47993 + }
47994 +
47995 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47996 +
47997 + cmd = (WMI_SET_BT_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
47998 + A_MEMZERO(cmd, sizeof(*cmd));
47999 + cmd->streamType = streamType;
48000 + cmd->status = status;
48001 +
48002 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID,
48003 + NO_SYNC_WMIFLAG));
48004 +}
48005 +
48006 +A_STATUS
48007 +wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
48008 +{
48009 + void *osbuf;
48010 + WMI_SET_BT_PARAMS_CMD* alloc_cmd;
48011 +
48012 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
48013 + if (osbuf == NULL) {
48014 + return A_NO_MEMORY;
48015 + }
48016 +
48017 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
48018 +
48019 + alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
48020 + A_MEMZERO(alloc_cmd, sizeof(*cmd));
48021 + A_MEMCPY(alloc_cmd, cmd, sizeof(*cmd));
48022 +
48023 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
48024 + NO_SYNC_WMIFLAG));
48025 +}
48026 +
48027 +A_STATUS
48028 +wmi_get_keepalive_configured(struct wmi_t *wmip)
48029 +{
48030 + void *osbuf;
48031 + WMI_GET_KEEPALIVE_CMD *cmd;
48032 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
48033 + if (osbuf == NULL) {
48034 + return A_NO_MEMORY;
48035 + }
48036 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
48037 + cmd = (WMI_GET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
48038 + A_MEMZERO(cmd, sizeof(*cmd));
48039 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_KEEPALIVE_CMDID,
48040 + NO_SYNC_WMIFLAG));
48041 +}
48042 +
48043 +A_UINT8
48044 +wmi_get_keepalive_cmd(struct wmi_t *wmip)
48045 +{
48046 + return wmip->wmi_keepaliveInterval;
48047 +}
48048 +
48049 +A_STATUS
48050 +wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval)
48051 +{
48052 + void *osbuf;
48053 + WMI_SET_KEEPALIVE_CMD *cmd;
48054 +
48055 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
48056 + if (osbuf == NULL) {
48057 + return A_NO_MEMORY;
48058 + }
48059 +
48060 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
48061 +
48062 + cmd = (WMI_SET_KEEPALIVE_CMD *)(A_NETBUF_DATA(osbuf));
48063 + A_MEMZERO(cmd, sizeof(*cmd));
48064 + cmd->keepaliveInterval = keepaliveInterval;
48065 + wmip->wmi_keepaliveInterval = keepaliveInterval;
48066 +
48067 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID,
48068 + NO_SYNC_WMIFLAG));
48069 +}
48070 +
48071 +A_STATUS
48072 +wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType, A_UINT8 ieLen,
48073 + A_UINT8 *ieInfo)
48074 +{
48075 + void *osbuf;
48076 + WMI_SET_APPIE_CMD *cmd;
48077 + A_UINT16 cmdLen;
48078 +
48079 + if (ieLen > WMI_MAX_IE_LEN) {
48080 + return A_ERROR;
48081 + }
48082 + cmdLen = sizeof(*cmd) + ieLen - 1;
48083 + osbuf = A_NETBUF_ALLOC(cmdLen);
48084 + if (osbuf == NULL) {
48085 + return A_NO_MEMORY;
48086 + }
48087 +
48088 + A_NETBUF_PUT(osbuf, cmdLen);
48089 +
48090 + cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf));
48091 + A_MEMZERO(cmd, cmdLen);
48092 +
48093 + cmd->mgmtFrmType = mgmtFrmType;
48094 + cmd->ieLen = ieLen;
48095 + A_MEMCPY(cmd->ieInfo, ieInfo, ieLen);
48096 +
48097 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
48098 +}
48099 +
48100 +A_STATUS
48101 +wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen)
48102 +{
48103 + void *osbuf;
48104 + A_UINT8 *data;
48105 +
48106 + osbuf = A_NETBUF_ALLOC(dataLen);
48107 + if (osbuf == NULL) {
48108 + return A_NO_MEMORY;
48109 + }
48110 +
48111 + A_NETBUF_PUT(osbuf, dataLen);
48112 +
48113 + data = A_NETBUF_DATA(osbuf);
48114 +
48115 + A_MEMCPY(data, cmd, dataLen);
48116 +
48117 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
48118 +}
48119 +
48120 +A_INT32
48121 +wmi_get_rate(A_INT8 rateindex)
48122 +{
48123 + if (rateindex == RATE_AUTO) {
48124 + return 0;
48125 + } else {
48126 + return(wmi_rateTable[(A_UINT32) rateindex]);
48127 + }
48128 +}
48129 +
48130 +void
48131 +wmi_node_return (struct wmi_t *wmip, bss_t *bss)
48132 +{
48133 + if (NULL != bss)
48134 + {
48135 + wlan_node_return (&wmip->wmi_scan_table, bss);
48136 + }
48137 +}
48138 +
48139 +bss_t *
48140 +wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
48141 + A_UINT32 ssidLength, A_BOOL bIsWPA2)
48142 +{
48143 + bss_t *node = NULL;
48144 + node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
48145 + ssidLength, bIsWPA2);
48146 + return node;
48147 +}
48148 +
48149 +void
48150 +wmi_free_allnodes(struct wmi_t *wmip)
48151 +{
48152 + wlan_free_allnodes(&wmip->wmi_scan_table);
48153 +}
48154 +
48155 +bss_t *
48156 +wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr)
48157 +{
48158 + bss_t *ni=NULL;
48159 + ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
48160 + return ni;
48161 +}
48162 +
48163 +A_STATUS
48164 +wmi_dset_open_reply(struct wmi_t *wmip,
48165 + A_UINT32 status,
48166 + A_UINT32 access_cookie,
48167 + A_UINT32 dset_size,
48168 + A_UINT32 dset_version,
48169 + A_UINT32 targ_handle,
48170 + A_UINT32 targ_reply_fn,
48171 + A_UINT32 targ_reply_arg)
48172 +{
48173 + void *osbuf;
48174 + WMIX_DSETOPEN_REPLY_CMD *open_reply;
48175 +
48176 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%x\n", DBGARG, (int)wmip));
48177 +
48178 + osbuf = A_NETBUF_ALLOC(sizeof(*open_reply));
48179 + if (osbuf == NULL) {
48180 + return A_NO_MEMORY;
48181 + }
48182 +
48183 + A_NETBUF_PUT(osbuf, sizeof(*open_reply));
48184 + open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
48185 +
48186 + open_reply->status = status;
48187 + open_reply->targ_dset_handle = targ_handle;
48188 + open_reply->targ_reply_fn = targ_reply_fn;
48189 + open_reply->targ_reply_arg = targ_reply_arg;
48190 + open_reply->access_cookie = access_cookie;
48191 + open_reply->size = dset_size;
48192 + open_reply->version = dset_version;
48193 +
48194 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID,
48195 + NO_SYNC_WMIFLAG));
48196 +}
48197 +
48198 +static A_STATUS
48199 +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
48200 +{
48201 + WMI_PMKID_LIST_REPLY *reply;
48202 + A_UINT32 expected_len;
48203 +
48204 + if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
48205 + return A_EINVAL;
48206 + }
48207 + reply = (WMI_PMKID_LIST_REPLY *)datap;
48208 + expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN;
48209 +
48210 + if (len < expected_len) {
48211 + return A_EINVAL;
48212 + }
48213 +
48214 + A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
48215 + reply->pmkidList);
48216 +
48217 + return A_OK;
48218 +}
48219 +
48220 +#ifdef CONFIG_HOST_DSET_SUPPORT
48221 +A_STATUS
48222 +wmi_dset_data_reply(struct wmi_t *wmip,
48223 + A_UINT32 status,
48224 + A_UINT8 *user_buf,
48225 + A_UINT32 length,
48226 + A_UINT32 targ_buf,
48227 + A_UINT32 targ_reply_fn,
48228 + A_UINT32 targ_reply_arg)
48229 +{
48230 + void *osbuf;
48231 + WMIX_DSETDATA_REPLY_CMD *data_reply;
48232 + int size;
48233 +
48234 + size = sizeof(*data_reply) + length;
48235 +
48236 + A_DPRINTF(DBG_WMI,
48237 + (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status));
48238 +
48239 + osbuf = A_NETBUF_ALLOC(size);
48240 + if (osbuf == NULL) {
48241 + return A_NO_MEMORY;
48242 + }
48243 + A_NETBUF_PUT(osbuf, size);
48244 + data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
48245 +
48246 + data_reply->status = status;
48247 + data_reply->targ_buf = targ_buf;
48248 + data_reply->targ_reply_fn = targ_reply_fn;
48249 + data_reply->targ_reply_arg = targ_reply_arg;
48250 + data_reply->length = length;
48251 +
48252 + if (status == A_OK) {
48253 + if (a_copy_from_user(data_reply->buf, user_buf, length)) {
48254 + return A_ERROR;
48255 + }
48256 + }
48257 +
48258 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID,
48259 + NO_SYNC_WMIFLAG));
48260 +}
48261 +#endif /* CONFIG_HOST_DSET_SUPPORT */
48262 +
48263 +A_STATUS
48264 +wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status)
48265 +{
48266 + void *osbuf;
48267 + char *cmd;
48268 +
48269 + wps_enable = status;
48270 +
48271 + osbuf = a_netbuf_alloc(sizeof(1));
48272 + if (osbuf == NULL) {
48273 + return A_NO_MEMORY;
48274 + }
48275 +
48276 + a_netbuf_put(osbuf, sizeof(1));
48277 +
48278 + cmd = (char *)(a_netbuf_to_data(osbuf));
48279 +
48280 + A_MEMZERO(cmd, sizeof(*cmd));
48281 + cmd[0] = (status?1:0);
48282 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WSC_STATUS_CMDID,
48283 + NO_SYNC_WMIFLAG));
48284 +}
48285 +
48286 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/wmi/wmi_doc.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/wmi/wmi_doc.h
48287 --- linux-2.6.29-rc3.owrt/drivers/ar6000/wmi/wmi_doc.h 1970-01-01 01:00:00.000000000 +0100
48288 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/wmi/wmi_doc.h 2009-05-10 22:27:59.000000000 +0200
48289 @@ -0,0 +1,4421 @@
48290 +/*
48291 + *
48292 + * Copyright (c) 2004-2007 Atheros Communications Inc.
48293 + * All rights reserved.
48294 + *
48295 + *
48296 + * This program is free software; you can redistribute it and/or modify
48297 + * it under the terms of the GNU General Public License version 2 as
48298 + * published by the Free Software Foundation;
48299 + *
48300 + * Software distributed under the License is distributed on an "AS
48301 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
48302 + * implied. See the License for the specific language governing
48303 + * rights and limitations under the License.
48304 + *
48305 + *
48306 + *
48307 + */
48308 +
48309 +
48310 +#if 0
48311 +Wireless Module Interface (WMI) Documentaion
48312 +
48313 + This section describes the format and the usage model for WMI control and
48314 + data messages between the host and the AR6000-based targets. The header
48315 + file include/wmi.h contains all command and event manifest constants as
48316 + well as structure typedefs for each set of command and reply parameters.
48317 +
48318 +Data Frames
48319 +
48320 + The data payload transmitted and received by the target follows RFC-1042
48321 + encapsulation and thus starts with an 802.2-style LLC-SNAP header. The
48322 + WLAN module completes 802.11 encapsulation of the payload, including the
48323 + MAC header, FCS, and WLAN security related fields. At the interface to the
48324 + message transport (HTC), a data frame is encapsulated in a WMI message.
48325 +
48326 +WMI Message Structure
48327 +
48328 + The WMI protocol leverages an 802.3-style Ethernet header in communicating
48329 + the source and destination information between the host and the AR6000
48330 + modules using a 14-byte 802.3 header ahead of the 802.2-style payload. In
48331 + addition, the WMI protocol adds a header to all data messages:
48332 +
48333 + {
48334 + INT8 rssi
48335 + The RSSI of the received packet and its units are shown in db above the
48336 + noise floor, and the noise floor is shown in dbm.
48337 + UINT8 info
48338 + Contains information on message type and user priority. Message type
48339 + differentiates between a data packet and a synchronization message.
48340 + } WMI_DATA_HDR
48341 +
48342 + User priority contains the 802.1d user priority info from host to target. Host
48343 + software translates the host Ethernet format to 802.3 format prior to Tx and
48344 + 802.3 format to host format in the Rx direction. The host does not transmit the
48345 + FCS that follows the data. MsgType differentiates between a regular data
48346 + packet (msgType=0) and a synchronization message (msgType=1).
48347 +
48348 +Data Endpoints
48349 +
48350 + The AR6000 chipset provides several data endpoints to support quality of
48351 + service (QoS) and maintains separate queues and separate DMA engines for
48352 + each data endpoint. A data endpoint can be bi-directional.
48353 +
48354 + Best effort (BE) class traffic uses the default data endpoint (2). The host can
48355 + establish up to two additional data endpoints for other traffic classes. Once
48356 + such a data endpoint is established, it sends and receives corresponding QoS
48357 + traffic in a manner similar to the default data endpoint.
48358 +
48359 + If QoS is desired over the interconnect, host software must classify each data
48360 + packet and place it on the appropriate data endpoint. The information
48361 + required to classify data is generally available in-band as an 802.1p/q style
48362 + tag or as the ToS field in the IP header. The information may also be available
48363 + out-of-band depending on the host DDI.
48364 +
48365 +Connection States
48366 +
48367 + Table B-1 describes the AR6000 WLAN connection states:
48368 +
48369 + Table B-1. AR6000 Connection States
48370 +
48371 +Connection State
48372 + Description
48373 +
48374 + DISCONNECTED
48375 + In this state, the AR6000 device is not connected to a wireless
48376 + network. The device is in this state after reset when it sends the
48377 + WIRELESS MODULE \93READY\94 EVENT, after it processes a
48378 + DISCONNECT command, and when it loses its link with the
48379 + access point (AP) that it was connected to. The device signals a
48380 + transition to the DISCONNECTED state with a \93DISCONNECT\94
48381 + event.
48382 +
48383 +CONNECTED
48384 + In this state, the AR6000 device is connected to wireless networks.
48385 + The device enters this state after successfully processing a
48386 + CONNECT, which establishes a connection with a wireless
48387 + network. The device signals a transition to the CONNECTED state
48388 + with a \93CONNECT\94 event.
48389 +
48390 +
48391 +Message Types
48392 +
48393 + WMI uses commands, replies, and events for the control and configuration of
48394 + the AR6000 device. The control protocol is asynchronous. Table B-2 describes
48395 + AR6000 message types:
48396 +
48397 +Table B-2. AR6000 Message Types
48398 +
48399 +Message Type
48400 + Description
48401 +
48402 +Commands
48403 + Control messages that flow from the host to the device
48404 +
48405 +Replies/Events
48406 + Control messages that flow from the device to the host.
48407 +
48408 + The device issues a reply to some WMI commands, but not to others.
48409 + The payload in a reply is command-specific, and some commands do
48410 + not trigger a reply message at all. Events are control messages issued
48411 + by the device to signal the occurrence of an asynchronous event.
48412 +
48413 +
48414 +WMI Message Format
48415 +
48416 + All WMI control commands, replies and events use the header format:
48417 +
48418 + WMI_CMD_HDR Header Format
48419 + {
48420 + UINT16 id
48421 + This 16-bit constant identifies which WMI command the host is issuing,
48422 + which command the target is replying to, or which event has occurred.
48423 + WMI_CMD_HDR
48424 + }
48425 +
48426 +
48427 + A variable-size command-, reply-, or event-specific payload follows the
48428 + header. Over the interconnect, all fields in control messages (including
48429 + WMI_CMD_HDR and the command specific payload) use 32-bit little Endian
48430 + byte ordering and fields are packed. The AR6000 device always executes
48431 + commands in order, and the host may send multiple commands without
48432 + waiting for previous commands to complete. A majority of commands are
48433 + processed to completion once received. Other commands trigger a longer
48434 + duration activity whose completion is signaled to the host through an event.
48435 +
48436 +Command Restrictions
48437 +
48438 + Some commands may only be issued when the AR6000 device is in a certain
48439 + state. The host is required to wait for an event signaling a state transition
48440 + before such a command can be issued. For example, if a command requires
48441 + the device to be in the CONNECTED state, then the host is required to wait
48442 + for a \93CONNECT\94 event before it issues that command.
48443 +
48444 + The device ignores any commands inappropriate for its current state. If the
48445 + command triggers a reply, the device generates an error reply. Otherwise, the
48446 + device silently ignores the inappropriate command.
48447 +
48448 +Command and Data Synchronization
48449 +
48450 + WMI provides a mechanism for a host to advise the device of necessary
48451 + synchronization between commands and data. The device implements
48452 + synchronization; no implicit synchronization exists between endpoints.
48453 +
48454 + The host controls synchronization using the \93SYNCHRONIZE\94 command
48455 + over the control channel and synchronization messages over data channels.
48456 + The device stops each data channel upon receiving a synchronization message
48457 + on that channel, processing all data packets received prior to that message.
48458 + After the device receives synchronization messages for each data endpoint
48459 + and the \93SYNCHRONIZE\94 command, it resumes all channels.
48460 +
48461 + When the host must guarantee a command executes before processing new
48462 + data packets, it first issues the command, then issues the \93SYNCHRONIZE\94
48463 + command and sends synchronization messages on data channels. When the
48464 + host must guarantee the device has processed all old data packets before a
48465 + processing a new command, it issues a \93SYNCHRONIZE\94 command and
48466 + synchronization messages on all data channels, then issues the desired
48467 + command.
48468 +
48469 +
48470 +
48471 +WMI Commands
48472 +
48473 + ADD_BAD_AP
48474 + Cause the AR6000 device to avoid a particular AP
48475 + ADD_CIPHER_KEY
48476 + Add or replace any of the four AR6000 encryption keys
48477 + ADD_WOW_PATTERN
48478 + Used to add a pattern to the WoW pattern list
48479 + CLR_RSSI_SNR
48480 + Clear the current calculated RSSI and SNR value
48481 + CONNECT_CMD
48482 + Request that the AR6000 device establish a wireless connection
48483 + with the specified SSID
48484 + CREATE_PSTREAM
48485 + Create prioritized data endpoint between the host and device
48486 + DELETE_BAD_AP
48487 + Clear an entry in the bad AP table
48488 + DELETE_CIPHER_KEY
48489 + Delete a previously added cipher key
48490 + DELETE_PSTREAM
48491 + Delete a prioritized data endpoint
48492 + DELETE_WOW_PATTERN
48493 + Remove a pre-specified pattern from the WoW pattern list
48494 + EXTENSION
48495 + WMI message interface command
48496 + GET_BIT_RATE
48497 + Retrieve rate most recently used by the AR6000
48498 + GET_CHANNEL_LIST
48499 + Retrieve list of channels used by the AR6000
48500 + GET_FIXRATES
48501 + Retrieves the rate-mask set via the SET_FIXRATES command.
48502 + GET_PMKID_LIST_CMD
48503 + Retrieve the firmware list of PMKIDs
48504 + GET_ROAM_DATA
48505 + Internal use for data collection; available in special build only
48506 + GET_ROAM_TBL
48507 + Retrieve the roaming table maintained on the target
48508 + GET_TARGET_STATS
48509 + Request that the target send the statistics it maintains
48510 + GET_TX_PWR
48511 + Retrieve the current AR6000 device Tx power levels
48512 + GET_WOW_LIST
48513 + Retrieve the current list of WoW patterns
48514 + LQ_THRESHOLD_PARAMS
48515 + Set the link quality thresholds
48516 + OPT_TX_FRAME
48517 + Send a special frame (special feature)
48518 + RECONNECT
48519 + Request a reconnection to a BSS
48520 + RSSI_THRESHOLD_PARAMS
48521 + Configure how the AR6000 device monitors and reports signal
48522 + strength (RSSI) of the connected BSS
48523 + SCAN_PARAMS
48524 + Determine dwell time and changes scanned channels
48525 + SET_ACCESS_PARAMS
48526 + Set access parameters for the wireless network
48527 + SET_ADHOC_BSSID
48528 + Set the BSSID for an ad hoc network
48529 + SET_AKMP_PARAMS
48530 + Set multiPMKID mode
48531 + SET_APPIE
48532 + Add application-specified IE to a management frame
48533 + SET_ASSOC_INFO
48534 + Specify the IEs the device should add to association or
48535 + reassociation requests
48536 + SET_AUTH_MODE
48537 + Set 802.11 authentication mode of reconnection
48538 + SET_BEACON_INT
48539 + Set the beacon interval for an ad hoc network
48540 + SET_BIT_RATE
48541 + Set the AR6000 to a specific fixed bit rate
48542 + SET_BMISS_TIME
48543 + Set the beacon miss time
48544 + SET_BSS_FILTER
48545 + Inform the AR6000 of network types about which it wants to
48546 + receive information using a \93BSSINFO\94 event
48547 + SET_BT_PARAMS
48548 + Set the status of a Bluetooth stream (SCO or A2DP) or set
48549 + Bluetooth coexistence register parameters
48550 + SET_BT_STATUS
48551 + Set the status of a Bluetooth stream (SCO or A2DP)
48552 + SET_CHANNEL_PARAMETERS
48553 + Configure WLAN channel parameters
48554 + SET_DISC_TIMEOUT
48555 + Set the amount of time the AR6000 spends attempting to
48556 + reestablish a connection
48557 + SET_FIXRATES
48558 + Set the device to a specific fixed PHY rate (supported subset)
48559 + SET_HALPARAM
48560 + Internal AR6000 command to set certain hardware parameters
48561 + SET_HOST_SLEEP_MODE
48562 + Set the host mode to asleep or awake
48563 + SET_IBSS_PM_CAPS
48564 + Support a non-standard power management scheme for an
48565 + ad hoc network
48566 + SET_LISTEN_INT
48567 + Request a listen interval
48568 + SET_LPREAMBLE
48569 + Override the short preamble capability of the AR6000 device
48570 + SET_MAX_SP_LEN
48571 + Set the maximum service period
48572 + SET_OPT_MODE
48573 + Set the special mode on/off (special feature)
48574 + SET_PMKID
48575 + Set the pairwise master key ID (PMKID)
48576 + SET_PMKID_LIST_CMD
48577 + Configure the firmware list of PMKIDs
48578 + SET_POWER_MODE
48579 + Set guidelines on trade-off between power utilization
48580 + SET_POWER_PARAMS
48581 + Configure power parameters
48582 + SET_POWERSAVE_PARAMS
48583 + Set the two AR6000 power save timers
48584 + SET_PROBED_SSID
48585 + Provide list of SSIDs the device should seek
48586 + SET_REASSOC_MODE
48587 + Specify whether the disassociated frame should be sent upon
48588 + reassociation
48589 + SET_RETRY_LIMITS
48590 + Limit how many times the device tries to send a frame
48591 + SET_ROAM_CTRL
48592 + Control roaming behavior
48593 + SET_RTS
48594 + Determine when RTS should be sent
48595 + SET_SCAN_PARAMS
48596 + Set the AR6000 scan parameters
48597 + SET_TKIP_COUNTERMEASURES
48598 + Enable/disable reports of TKIP MIC errors
48599 + SET_TX_PWR
48600 + Specify the AR6000 device Tx power levels
48601 + SET_VOICE_PKT_SIZE
48602 + Set voice packet size
48603 + SET_WMM
48604 + Override the AR6000 WMM capability
48605 + SET_WMM_TXOP
48606 + Configure TxOP bursting when sending traffic to a WMM-
48607 + capable AP
48608 + SET_WOW_MODE
48609 + Enable/disable WoW mode
48610 + SET_WSC_STATUS
48611 + Enable/disable profile check in cserv when the WPS protocol
48612 + is in progress
48613 + SNR_THRESHOLD_PARAMS
48614 + Configure how the device monitors and reports SNR of BSS
48615 + START_SCAN
48616 + Start a long or short channel scan
48617 + SYNCHRONIZE
48618 + Force a synchronization point between command and data
48619 + paths
48620 + TARGET_REPORT_ERROR_BITMASK
48621 + Control \93ERROR_REPORT\94 events from the AR6000
48622 +
48623 +
48624 +
48625 +
48626 +Name
48627 + ADD_BAD_AP
48628 +
48629 +Synopsis
48630 + The host uses this command to cause the AR6000 to avoid a particular AP. The
48631 + AR6000 maintain a table with up to two APs to avoid. An ADD_BAD_AP command
48632 + adds or replaces the specified entry in this bad AP table.
48633 +
48634 + If the AR6000 are currently connected to the AP specified in this command, they
48635 + disassociate.
48636 +
48637 +Command
48638 + wmiconfig eth1 --badap <bssid> <badApIndex>
48639 +
48640 +Command Parameters
48641 + UINT8 badApIndex Index [0...1] that identifies which entry in the
48642 + bad AP table to use
48643 +
48644 +
48645 + UINT8 bssid[6] MAC address of the AP to avoid
48646 +
48647 +Command Values
48648 + badApIndex = 0, 1 Entry in the bad AP table to use
48649 +
48650 +Reset Value
48651 + The bad AP table is cleared
48652 +
48653 +Restrictions
48654 + None
48655 +
48656 +See Also
48657 + \93DELETE_BAD_AP\94 on page B-13
48658 +
48659 +=====================================================================
48660 +Name
48661 + ADD_CIPHER_KEY
48662 +
48663 +Synopsis
48664 + The host uses this command to add/replace any of four encryption keys on the
48665 + AR6000. The ADD_CIPHER_KEY command is issued after the CONNECT event
48666 + has been received by the host for all dot11Auth modes except for SHARED_AUTH.
48667 + When the dot11AuthMode is SHARED_AUTH, then the ADD_CIPHER_KEY
48668 + command should be issued before the \93CONNECT\94 command.
48669 +
48670 +Command
48671 + wmiconfig eth1 --cipherkey <keyIndex> <keyType> <keyUsage>
48672 + <keyLength> <keyopctrl> <keyRSC> <key>
48673 +
48674 +Command Parameters
48675 + UINT8 keyIndex Index (0...3) of the key to add/replace;
48676 + uniquely identifies the key
48677 + UINT8 keyType CRYPTO_TYPE
48678 + UINT8 keyUsage Specifies usage parameters of the key when
48679 + keyType = WEP_CRYPT
48680 + UINT8 keyLength Length of the key in bytes
48681 + UINT8 keyOpCtrl bit[0] = Initialize TSC (default),
48682 + bit[1] = Initialize RSC
48683 + UINT8 keyRSC[8] Key replay sequence counter (RSC) initial
48684 + value the device should use
48685 + UINT8 key[32] Key material used for this connection
48686 + Command Values
48687 + {
48688 + NONE_CRYPT = 1
48689 + WEP_CRYPT = 2
48690 + TKIP_CRYPT = 3
48691 + AES_CRYPT = 4
48692 + KEY_OP_INIT_TSC 0x01
48693 + KEY_OP_INIT_RSC 0x02
48694 + KEY_OP_INIT_VAL 0x03
48695 + Default is to Initialize the TSC
48696 + KEY_OP_VALID_MASK 0x04
48697 + Two operations defined
48698 + } CRYPTO_TYPE
48699 +
48700 + {
48701 + PAIRWISE_USAGE = 0 Set if the key is used for unicast traffic only
48702 + GROUP_USAGE = 1 Set if the key is used to receive multicast
48703 + traffic (also set for static WEP keys)
48704 + TX_USAGE = 2 Set for the GROUP key used to transmit frames
48705 + All others are reserved
48706 + } KEY_USAGE
48707 +
48708 +Reset Value
48709 + The four available keys are disabled.
48710 +
48711 +Restrictions
48712 + The cipher should correspond to the encryption mode specified in the \93CONNECT\94
48713 + command.
48714 +
48715 +See Also
48716 + \93DELETE_CIPHER_KEY\94
48717 +
48718 +=====================================================================
48719 +
48720 +
48721 +Name
48722 + ADD_WOW_PATTERN
48723 +
48724 +Synopsis
48725 + The host uses this command to add a pattern to the WoW pattern list; used for
48726 + pattern-matching for host wakeups by the WoW module. If the host mode is asleep
48727 + and WoW is enabled, all packets are matched against the existing WoW patterns. If a
48728 + packet matches any of the patterns specified, the target will wake up the host. All
48729 + non-matching packets are discarded by the target without being sent up to the host.
48730 +
48731 +Command
48732 + wmiconfig \96addwowpattern <list-id> <filter-size> <filter-offset>
48733 + <pattern> <mask>
48734 +
48735 +Command Parameters
48736 + A_UINT8 filter_list_id ID of the list that is to include the new pattern
48737 + A_UINT8 filter_size Size of the new pattern
48738 + A_UINT8 filter_offset Offset at which the pattern matching for this
48739 + new pattern should begin at
48740 + A_UINT8 filter[1] Byte stream that contains both the pattern and
48741 + the mask of the new WoW wake-up pattern
48742 +
48743 +Reply Parameters
48744 + None
48745 +
48746 +Reset Value
48747 + None defined (default host mode is awake)
48748 +
48749 +Restrictions
48750 + None
48751 +
48752 +See Also
48753 + \93DELETE_WOW_PATTERN\94
48754 +
48755 +=====================================================================
48756 +
48757 +
48758 +Name
48759 + CLR_RSSI_SNR
48760 +
48761 +Synopsis
48762 + Clears the current calculated RSSI and SNR value. RSSI and SNR are reported by
48763 + running-average value. This command will clear the history and have a fresh start
48764 + for the running-average mechanism.
48765 +
48766 +Command
48767 + wmiconfig eth1 --cleanRssiSnr
48768 +
48769 +Command Parameters
48770 + None
48771 +
48772 +Reply Parameters
48773 + None
48774 +
48775 +Reset Value
48776 + None defined
48777 +
48778 +Restrictions
48779 + None
48780 +
48781 +=====================================================================
48782 +
48783 +Name
48784 + CONNECT_CMD
48785 +
48786 +Synopsis
48787 + New connect control information (connectCtrl) is added, with 32 possible modifiers.
48788 +
48789 + CONNECT_SEND_REASSOC
48790 + Valid only for a host-controlled connection to a
48791 + particular AP. If this bit is set, a reassociation frame is
48792 + sent. If this bit is clear, an association request frame is
48793 + sent to the AP.
48794 +
48795 + CONNECT_IGNORE_WPAx_GROUP_CIPHER
48796 + No group key is issued in the CONNECT command,
48797 + so use the group key advertised by the AP. In a target-
48798 + initiated roaming situation this allows a STA to roam
48799 + between APs that support different multicast ciphers.
48800 +
48801 + CONNECT_PROFILE_MATCH_DONE
48802 + In a host-controlled connection case, it is possible that
48803 + during connect, firmware may not have the
48804 + information for a profile match (e.g, when the AP
48805 + supports hidden SSIDs and the device may not
48806 + transmit probe requests during connect). By setting
48807 + this bit in the connection control information, the
48808 + firmware waits for a beacon from the AP with the
48809 + BSSID supplied in the CONNECT command. No
48810 + additional profile checks are done.
48811 +
48812 + CONNECT_IGNORE_AAC_BEACON
48813 + Ignore the Admission Capacity information in the
48814 + beacon of the AP
48815 +
48816 + CONNECT_ASSOC_POLICY_USER
48817 + When set, the CONNECT_SEND_REASSOC setting
48818 + determines if an Assoc or Reassoc is sent to an AP
48819 +
48820 +Command
48821 + wmiconfig --setconnectctrl <ctrl flags bitmask>
48822 +
48823 +Command Parameters
48824 + typedef struct{
48825 + A_UINT8 networktype;
48826 + A_UINT8 dot11authmode;
48827 + A_UINT8 authmode;
48828 + A_UINT8 pairwiseCryptoType; /*CRYPTO_TYPE*/
48829 + A_UINT8 pairwiseCryptoLen;
48830 + A_UINT8 groupCryptoType; /*CRYPTO_TYPE*/
48831 + A_UINT8 groupCryptoLen;
48832 + A_UINT8 ssidLength;
48833 + A_UCHAR ssid[WMI_MAX_SSID_LEN];
48834 + A_UINT16 channel;
48835 + A_UINT8 bssid[AUTH_MAC_LEN];
48836 + A_UINT8 ctrl_flags; /*WMI_CONNECT_CTRL_FLAGS_BITS*/
48837 + } WMI_CONNECT_CMD;
48838 +
48839 + ctrl flags bitmask
48840 + = 0x0001 CONNECT_ASSOC_POLICY_USER
48841 + Assoc frames are sent using the policy specified by
48842 + the flag
48843 + = 0x0002 CONNECT_SEND_REASSOC
48844 + Send Reassoc frame while connecting, otherwise send
48845 + assoc frames
48846 + = 0x0004 CONNECT_IGNORE_WPAx_GROUP_CIPHER
48847 + Ignore WPAx group cipher for WPA/WPA2
48848 + = 0x0008 CONNECT_PROFILE_MATCH_DONE
48849 + Ignore any profile check
48850 + = 0x0010 CONNECT_IGNORE_AAC_BEACON
48851 + Ignore the admission control information in the
48852 + beacon
48853 + ... CONNECT_CMD, continued
48854 + Command Values
48855 + typedef enum {
48856 + INFRA_NETWORK = 0x01,
48857 + ADHOC_NETWORK = 0x02,
48858 + ADHOC_CREATOR = 0x04,
48859 + } NETWORK_TYPE;
48860 +
48861 + typedef enum {
48862 + OPEN_AUTH = 0x01,
48863 + SHARED_AUTH = 0x02,
48864 + LEAP_AUTH = 0x04,
48865 + } DOT11_AUTH_MODE;
48866 + typedef enum {
48867 + NONE_AUTH = 0x01,
48868 + WPA_AUTH = 0x02,
48869 + WPA_PSK_AUTH = 0x03,
48870 + WPA2_AUTH = 0x04,
48871 + WPA2_PSK_AUTH = 0x05,
48872 + WPA_AUTH_CCKM = 0x06,
48873 + WPA2_AUTH_CCKM = 0x07,
48874 + } AUTH_MODE;
48875 + typedef enum {
48876 + NONE_CRYPT = 0x01,
48877 + WEP_CRYPT = 0x02,
48878 + TKIP_CRYPT = 0x03,
48879 + AES_CRYPT = 0x04,
48880 + } CRYPTO_TYPE;
48881 + typedef enum {
48882 + CONNECT_ASSOC_POLICY_USER = 0x0001,
48883 + CONNECT_SEND_REASSOC = 0x0002,
48884 + CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004,
48885 + CONNECT_PROFILE_MATCH_DONE = 0x0008,
48886 + CONNECT_IGNORE_AAC_BEACON = 0x0010,
48887 + } WMI_CONNECT_CTRL_FLAGS_BITS;
48888 +
48889 + pairwiseCryptoLen and groupCryptoLen are valid when the respective
48890 + CryptoTypesis WEP_CRYPT, otherwise this value should be 0. This is the length in
48891 + bytes.
48892 +
48893 +Reset Value
48894 + None defined
48895 +
48896 +Restrictions
48897 + None
48898 +
48899 +=====================================================================
48900 +
48901 +
48902 +Name
48903 + CREATE_PSTREAM
48904 +
48905 +Synopsis
48906 + The host uses this command to create a new prioritized data endpoint between the
48907 + host and the AR6000 device that carries a prioritized stream of data. If the AP that the
48908 + device connects to requires TSPEC stream establishment, the device requests the
48909 + corresponding TSPEC with the AP. The maximum and minimum service interval
48910 + ranges from 0 \96 0x7FFFFFFF (ms), where 0 = disabled. The device does not send a
48911 + reply event for this command, as it is always assumed the command has succeeded.
48912 + An AP admission control response comes to the host via a WMI_CAC_INDICATION
48913 + event, once the response for the ADDTS frame comes.
48914 +
48915 + Examples of cases where reassociation is generated (when WMM) and cases where
48916 + ADDTS is generated (when WMM and enabling ACM) are when:
48917 + Changing UAPSD flags in WMM mode, reassociation is generated
48918 + Changing the interval of sending auto QoS Null frame in WMM mode;
48919 + reassociation is not generated
48920 + Issuing a command with same previous parameters in WMM mode and enabling
48921 + ACM, an ADDTS request is generated
48922 + Changing the interval of a QoS null frame sending in WMM mode and enabling
48923 + ACM, an ADDTS request is generated
48924 + Issuing the command in disconnected state, reassociation or ADDTS is not
48925 + generated but the parameters are available after (re)association
48926 +
48927 +Command
48928 + --createqos <user priority> <direction> <traffic class>
48929 +<trafficType> <voice PS capability> <min service interval> <max
48930 +service interval> <inactivity interval> <suspension interval>
48931 +<service start time> <tsid> <nominal MSDU> <max MSDU> <min data
48932 +rate> <mean data rate> <peak data rate> <max burst size> <delay
48933 +bound> <min phy rate> <sba> <medium time> where:
48934 +
48935 + <user priority>
48936 + 802.1D user priority range (0\967)
48937 + <direction>
48938 + = 0 Tx (uplink) traffic
48939 + = 1 Rx (downlink) traffic
48940 + = 2 Bi-directional traffic
48941 + <traffic class>
48942 + = 1 BK
48943 + = 2 VI
48944 + = 3 VO
48945 + <trafficType>
48946 + = 0 Aperiodic
48947 + = 1 Periodic
48948 + <voice PS capability>
48949 + Specifies whether the voice power save mechanism
48950 + (APSD if AP supports it or legacy/simulated APSD
48951 + [using PS-Poll]) should be used
48952 + = 0 Disable voice power save for traffic class
48953 + = 1 Enable APSD voice power save for traffic class
48954 + = 2 Enable voice power save for all traffic classes
48955 + <min service interval>
48956 + (In ms)
48957 + <max service interval>
48958 + Inactivity interval (in ms) (0 = Infinite)
48959 + <suspension interval>
48960 + (In ms)
48961 + <service start time>
48962 + Service start time
48963 + <tsid>
48964 + TSID range (0\9615)
48965 + <nominal MSDU>
48966 + Nominal MAC SDU size
48967 + <max MSDU>
48968 + Maximum MAC SDU size
48969 + <min data rate>
48970 + Minimum data rate (in bps)
48971 + <mean data rate>
48972 + Mean data rate (in bps)
48973 + <peak data rate>
48974 + Peak data rate (in bps)
48975 + <max burst size>
48976 + Maximum burst size (in bps)
48977 + <delay bound>
48978 + Delay bound
48979 + <min phy rate>
48980 + Minimum PHY rate (in bps)
48981 + <sba>
48982 + Surplus bandwidth allowance
48983 + <medium time>
48984 + Medium time in TU of 32-ms periods per sec
48985 + ... CREATE_PSTREAM (continued)
48986 +
48987 +Command Parameters
48988 + UINT8 trafficClass TRAFFIC_CLASS value
48989 + UINT8 traffic
48990 + Direction
48991 + DIR_TYPE value
48992 + UINT8 rxQueueNum
48993 + AR6000 device mailbox index (2 or 3)
48994 + corresponding to the endpoint the host
48995 + wishes to use to receive packets for the
48996 + prioritized stream
48997 + UINT8 trafficType TRAFFIC_TYPE value
48998 + UINT8 voicePS
48999 +Capability
49000 + VOICEPS_CAP_TYPE value
49001 + UINT8 tsid Traffic stream ID
49002 + UINT8 userPriority 802.1D user priority
49003 + UINT16 nominalMSDU Nominal MSDU in octets
49004 + UINT16 maxMSDU Maximum MSDU in octets
49005 + UINT32 minServiceInt Minimum service interval: the min.
49006 + period of traffic specified (in ms)
49007 + UINT32 maxServiceInt Maximum service interval: the max.
49008 + period of traffic specified (in ms)
49009 + UINT32 inactivityInt Indicates how many ms an established
49010 + stream is inactive before the prioritized
49011 + data endpoint is taken down and the
49012 + corresponding T-SPEC deleted
49013 + UINT32 suspensionInt Suspension interval (in ms)
49014 + UINT32 service StartTime Service start time
49015 + UINT32 minDataRate Minimum data rate (in bps)
49016 + UINT32 meanDataRate Mean data rate (in bps)
49017 + UINT32 peakDataRate Peak data rate (in bps)
49018 + UINT32 maxBurstSize
49019 + UINT32 delayBound
49020 + UINT32 minPhyRate Minimum PHY rate for TSPEC (in bps)
49021 + UINT32 sba Surplus bandwidth allowance
49022 + UINT32 mediumTime Medium TSPEC time (in units of 32 ms)
49023 +Command Values
49024 + {
49025 + WMM_AC_BE = 0 Best Effort
49026 + WMM_AC_BK = 1 Background
49027 + WMM_AC_VI = 2 Video
49028 + WMM_AC_VO = 3 Voice
49029 + All other values reserved
49030 + } TRAFFIC_CLASS
49031 + {
49032 + UPLINK_TRAFFIC = 0 From the AR6000 device to the AP
49033 + DOWNLINK_TRAFFIC = 1 From the AP to the AR6000 device
49034 + BIDIR_TRAFFIC = 2 Bi-directional traffic
49035 + All other values reserved
49036 + } DIR_TYPE
49037 + {
49038 + DISABLE_FOR_THIS_AC = 0
49039 + ENABLE_FOR_THIS_AC = 1
49040 + ENABLE_FOR_ALL_AC = 2
49041 + All other values reserved
49042 + } VOICEPS_CAP_TYPE
49043 +
49044 + ... CREATE_PSTREAM (continued)
49045 +
49046 +
49047 + VI BE BK Supported, Y/N?
49048 + 0 0 0 0 Y
49049 + 0 0 0 1 Y
49050 + 0 0 1 0 N
49051 + 0 0 1 1 N
49052 + 0 1 0 0 Y
49053 + 0 1 0 1 Y
49054 + 0 1 1 0 N
49055 + 0 1 1 1 N
49056 + 1 0 0 0 Y
49057 + 1 0 0 1 Y
49058 + 1 0 1 0 N
49059 + 1 1 0 0 N
49060 + 1 1 0 1 Y
49061 + 1 1 0 0 N
49062 + 1 1 1 0 N
49063 + 1 1 1 1 Y
49064 +
49065 +Reset Value
49066 + No pstream is present after reset; each of the BE, BK, VI,VO pstreams must be created
49067 + (either implicitly by data flow or explicitly by user)
49068 +
49069 +Restrictions
49070 + This command can only be issued when the device is in the CONNECTED state. If
49071 + the device receives the command while in DISCONNECTED state, it replies with a
49072 + failure indication. At most four prioritized data endpoints can be created, one for
49073 + each AC.
49074 +
49075 +See Also
49076 + \93DELETE_PSTREAM\94
49077 +=====================================================================
49078 +
49079 +Name
49080 + DELETE_BAD_AP
49081 +
49082 +Synopsis
49083 + The host uses this command to clear a particular entry in the bad AP table
49084 +
49085 +Command
49086 + wmiconfig eth1 --rmAP [--num=<index>] // used to clear a badAP
49087 + entry. num is index from 0-3
49088 +
49089 +Command Parameters
49090 + UINT8 badApIndex Index [0...n] that identifies the entry in the bad
49091 + AP table to delete
49092 +
49093 +Command Values
49094 + badApIndex = 0, 1, 2, 3
49095 + Entry in the bad AP table
49096 +
49097 +Reset Value
49098 + None defined
49099 +
49100 +Restrictions
49101 + None
49102 +
49103 +See Also
49104 + \93ADD_BAD_AP\94
49105 +
49106 +=====================================================================
49107 +
49108 +
49109 +Name
49110 + DELETE_CIPHER_KEY
49111 +
49112 +Synopsis
49113 + The host uses this command to delete a key that was previously added with the
49114 + \93ADD_CIPHER_KEY\94 command.
49115 +
49116 +Command
49117 + TBD
49118 +
49119 +Command Parameters
49120 + UINT8 keyIndex Index (0...3) of the key to be deleted
49121 +
49122 +Command Values
49123 + keyIndex = 0, 1,2, 3 Key to delete
49124 +
49125 +Reset Value
49126 + None
49127 +
49128 +Restrictions
49129 + The host should not delete a key that is currently in use by the AR6000.
49130 +
49131 +See Also
49132 + \93ADD_CIPHER_KEY\94
49133 +
49134 +=====================================================================
49135 +
49136 +Name
49137 + DELETE_PSTREAM
49138 +
49139 +Synopsis
49140 + The host uses this command to delete a prioritized data endpoint created by a
49141 + previous \93CREATE_PSTREAM\94 command
49142 +
49143 +Command
49144 + --deleteqos <trafficClass> <tsid>, where:
49145 +
49146 + <traffic class>
49147 + = 0 BE
49148 + = 1 BK
49149 + = 2 VI
49150 + = 3 VO
49151 + <tsid>
49152 + The TSpec ID; use the -qosqueue option
49153 + to get the active TSpec IDs for each traffic class
49154 +
49155 +Command Parameters
49156 + A_UINT8 trafficClass Indicate the traffic class of the stream
49157 + being deleted
49158 +
49159 +Command Values
49160 + {
49161 + WMM_AC_BE = 0 Best effort
49162 + WMM_AC_BK = 1 Background
49163 + WMM_AC_VI = 2 Video
49164 + WMM_AC_VO = 3 Voice
49165 + } TRAFFIC CLASS
49166 +
49167 + 0-15 for TSID
49168 +
49169 +Reply Values
49170 + N/A
49171 +
49172 +Restrictions
49173 + This command should only be issued after a \93CREATE_PSTREAM\94 command has
49174 + successfully created a prioritized stream
49175 +
49176 +See Also
49177 + \93CREATE_PSTREAM\94
49178 +
49179 +=====================================================================
49180 +
49181 +
49182 +Name
49183 + DELETE_WOW_PATTERN
49184 +
49185 +Synopsis
49186 + The host uses this command to remove a pre-specified pattern from the
49187 + WoW pattern list.
49188 +
49189 +Command
49190 + wmiconfig \96delwowpattern <list-id> <pattern-id>
49191 +
49192 +Command Parameters
49193 + A_UINT8 filter_list_id ID of the list that contains the WoW filter
49194 + pattern to delete
49195 + A_UINT8 filter_id ID of the WoW filter pattern to delete
49196 +
49197 +Reply Parameters
49198 + None
49199 +
49200 +
49201 +
49202 +Reset Value
49203 + None defined
49204 +
49205 +Restrictions
49206 + None
49207 +
49208 +See Also
49209 + \93ADD_WOW_PATTERN\94
49210 +
49211 +=====================================================================
49212 +
49213 +
49214 +Name
49215 + EXTENSION
49216 +
49217 +Synopsis
49218 + The WMI message interface is used mostly for wireless control messages to a wireless
49219 + module applicable to wireless module management regardless of the target platform
49220 + implementation. However, some commands only peripherally related to wireless
49221 + management are desired during operation. These wireless extension commands may
49222 + be platform-specific or implementation-dependent.
49223 +
49224 +Command
49225 + N/A
49226 +
49227 +Command Parameters
49228 + Command-specific
49229 +
49230 +Command Values
49231 + Command-specific
49232 +
49233 +Reply Parameters
49234 + Command-specific
49235 +
49236 +Reset Values
49237 + None defined
49238 +
49239 +Restrictions
49240 + None defined
49241 +
49242 +=====================================================================
49243 +
49244 +
49245 +Name
49246 + GET_BIT_RATE
49247 +
49248 +Synopsis
49249 + Used by the host to obtain the rate most recently used by the AR6000 device
49250 +
49251 +Command
49252 + wmiconfig eth1 --getfixrates
49253 +
49254 +Command Parameters
49255 + None
49256 +
49257 +
49258 +
49259 +Reply Parameters
49260 + INT8
49261 + rateIndex
49262 + See the \93SET_BIT_RATE\94 command
49263 +
49264 +Reset Values
49265 + None
49266 +
49267 +Restrictions
49268 + This command should only be used during development/debug; it is not intended
49269 +for use in production. It is only valid when the device is in the CONNECTED state
49270 +
49271 +See Also
49272 + \93SET_BIT_RATE\94
49273 +
49274 +=====================================================================
49275 +
49276 +
49277 +Name
49278 + GET_CHANNEL_LIST
49279 +
49280 +Synopsis
49281 + Used by the host uses to retrieve the list of channels that can be used by the device
49282 + while in the current wireless mode and in the current regulatory domain.
49283 +
49284 +Command
49285 + TBD
49286 +
49287 +Command Parameters
49288 + None
49289 +
49290 +Reply Parameters
49291 + UINT8 reserved Reserved
49292 + UINT8 numberOfChannels Number of channels the reply contains
49293 + UINT16 channelList[numberOfChannels] Array of channel frequencies (in MHz)
49294 +
49295 +Reset Values
49296 + None defined
49297 +
49298 +Restrictions
49299 + The maximum number of channels that can be reported are 32
49300 +
49301 +=====================================================================
49302 +
49303 +
49304 +Name
49305 + GET_FIXRATES
49306 +
49307 +Synopsis
49308 + Clears the current calculated RSSI and SNR value. RSSI and SNR are reported by
49309 + running-average value. This command will clear the history and have a fresh start for
49310 + the running-average mechanism.
49311 +
49312 +Synopsis
49313 + This returns rate-mask set via WMI_SET_FIXRATES to retrieve the current fixed rate
49314 + that the AR6001 or AR6001 is using. See \93SET_FIXRATES\94.
49315 +
49316 +Command
49317 + wmiconfig eth1 --getfixrates
49318 +
49319 +Command Parameters
49320 + A_UINT16 fixRateMask; Note: if this command is used prior to
49321 + using WMI_SET_FIXRATES, AR6000
49322 + returns 0xffff as fixRateMask, indicating
49323 + all the rates are enabled
49324 +
49325 +Reply Parameters
49326 + None
49327 +
49328 +Reset Value
49329 + None defined
49330 +
49331 +Restrictions
49332 + None
49333 +
49334 +See Also
49335 + \93SET_FIXRATES\94
49336 +
49337 +=====================================================================
49338 +
49339 +
49340 +
49341 +Name
49342 + GET_PMKID_LIST_CMD
49343 +
49344 +Synopsis
49345 + Retrieves the list of PMKIDs on the firmware. The
49346 + WMI_GET_PMKID_LIST_EVENT is generated by the firmware.
49347 +
49348 +Command
49349 + TBD
49350 +
49351 +Command Parameters
49352 +
49353 +Reset Values
49354 + None
49355 +
49356 +Restrictions
49357 + None
49358 +
49359 +See Also
49360 + SET_PMKID_LIST_CMD GET_PMKID_LIST_EVENT
49361 +
49362 +=====================================================================
49363 +
49364 +
49365 +Name
49366 + GET_ROAM_TBL
49367 +
49368 +Synopsis
49369 + Retrieve the roaming table maintained on the target. The response is reported
49370 + asynchronously through the ROAM_TBL_EVENT.
49371 +
49372 +Command
49373 + wmiconfig --getroamtable <roamctrl> <info>
49374 +
49375 +Command Parameters
49376 + A_UINT8 roamCtrlType;
49377 + A_UINT16 roamMode
49378 + A_UINT16 numEntries
49379 + WMI_BSS_ROAM_INFO bssRoamInfo[1]
49380 +
49381 +Reply Value
49382 + Reported asynchronously through the ROAM_TBL_EVENT
49383 +
49384 +Reset Value
49385 + None defined
49386 +
49387 +Restrictions
49388 + None
49389 +
49390 +See Also
49391 + SET_KEEPALIVE
49392 +
49393 +=====================================================================
49394 +
49395 +
49396 +Name
49397 + GET_TARGET_STATS
49398 +
49399 +Synopsis
49400 + The host uses this command to request that the target send the statistics that it
49401 + maintains. The statistics obtained from the target are accrued in the host every time
49402 + the GET_TARGET_STATS command is issued. The --clearStats option is added to
49403 + clear the target statistics maintained in the host.
49404 +
49405 +Command
49406 + wmiconfig --getTargetStats --clearStats
49407 +
49408 +Command Parameters
49409 + TARGET_STATS targetStats
49410 + WMI_TARGET_STATS
49411 + UINT8 clearStats
49412 +
49413 +
49414 +Reply Value
49415 + RSSI return value (0\96100)
49416 +
49417 +Reset Values
49418 + All statistics are cleared (zeroed)
49419 +
49420 +Restrictions
49421 + The --getTargetStats option must be used; the --clearStats option is also available also
49422 +
49423 +
49424 +=====================================================================
49425 +
49426 +Name
49427 + GET_TX_PWR
49428 +
49429 +Synopsis
49430 + The host uses this command to retrieve the current Tx power level
49431 +
49432 +Command
49433 + wmiconfig -i eth1 --getpower
49434 +
49435 +Command Parameters
49436 + None
49437 +
49438 +Reply Parameters
49439 + UINT16 dbM The current Tx power level specified in dbM
49440 +
49441 +Reset Values
49442 + The maximum permitted by the regulatory domain
49443 +
49444 +Restrictions
49445 + None
49446 +
49447 +See Also
49448 + \93SET_TX_PWR\94
49449 +
49450 +=====================================================================
49451 +
49452 +
49453 +Name
49454 + GET_WOW_LIST
49455 +
49456 +Synopsis
49457 + The host uses this command to retrieve the current list of WoW patterns.
49458 +
49459 +Command
49460 + wmiconfig \96getwowlist <list-id>
49461 +
49462 +Command Parameters
49463 + A_UINT8 filter_list_id ID of the list of WoW patterns to retrieve
49464 +
49465 +Reply Value(s)
49466 + A_UINT16 num_filters Number of WoW patterns contained in the list
49467 + A_UINT8 wow_mode Current mode of WoW (enabled or disabled)
49468 + A_UINT8 host_mode Current host mode (asleep or awake)
49469 + WOW_FILTER wow_filters[1]
49470 + Contents of the WoW filter pattern list
49471 + (contains mask, pattern, offset and size
49472 + information for each of the patterns)
49473 +
49474 +Reset Value
49475 + None defined
49476 +
49477 +Restrictions
49478 + None
49479 +
49480 +See Also
49481 + \93SET_WSC_STATUS\94
49482 +
49483 +=====================================================================
49484 +
49485 +
49486 +Name
49487 + LQ_THRESHOLD_PARAMS
49488 +
49489 +Synopsis
49490 + Sets Link Quality thresholds, the sampling will happen at every unicast data frame
49491 + Tx if a certain threshold is met, and the corresponding event will be sent to the host.
49492 +
49493 +Command
49494 + --lqThreshold <enable> <upper_threshold_1> ...
49495 + <upper_threshold_4> <lower_threshold_1> ... <lower_threshold_4>
49496 +
49497 +Command Parameters
49498 + <enable> = 0 Disable link quality sampling
49499 + = 1 Enable link quality sampling
49500 + <upper_threshold_x> Above thresholds (value in [0,100]), in
49501 + ascending order
49502 + <lower_threshold_x> Below thresholds (value in [0,100]), in
49503 + ascending order
49504 +
49505 +Command Values
49506 + See command parameters
49507 +
49508 +Reset Value
49509 + None defined
49510 +
49511 +Restrictions
49512 + None
49513 +
49514 +=====================================================================
49515 +
49516 +
49517 +Name
49518 + OPT_TX_FRAME
49519 +
49520 +Synopsis
49521 + Special feature, sends a special frame.
49522 +
49523 +Command
49524 + wmiconfig --sendframe <frmType> <dstaddr> <bssid> <optIEDatalen>
49525 + <optIEData>
49526 +
49527 +Command Parameters
49528 + {
49529 + A_UINT16 optIEDataLen;
49530 + A_UINT8 frmType;
49531 + A_UINT8 dstAddr[ATH_MAC_LEN];
49532 + A_UINT8 bssid[ATH_MAC_LEN];
49533 + A_UINT8 optIEData[1];
49534 + } WMI_OPT_TX_FRAME_CMD;
49535 +
49536 +Command Values
49537 + <frmtype> = 1 Probe request frame
49538 + = 2 Probe response frame
49539 + = 3 CPPP start
49540 + = 4 CPPP stop
49541 +
49542 +Reset Value
49543 + None defined
49544 +
49545 +Restrictions
49546 + Send a special frame only when special mode is on.
49547 +
49548 +=====================================================================
49549 +
49550 +
49551 +Name
49552 + RECONNECT
49553 +
49554 +Synopsis
49555 + This command requests a reconnection to a BSS to which the AR6000 device was
49556 + formerly connected
49557 +
49558 +Command
49559 + TBD
49560 +
49561 +Command Parameters
49562 + UINT16 channel Provides a hint as to which channel was
49563 + used for a previous connection
49564 + UINT8 bssid[6] If set, indicates which BSSID to connect to
49565 +
49566 +Command Values
49567 + None
49568 +
49569 +Reset Values
49570 + None
49571 +
49572 +Restrictions
49573 + None
49574 +
49575 +See Also
49576 + \93CONNECT_CMD\94
49577 +
49578 +=====================================================================
49579 +
49580 +
49581 +Name
49582 + RSSI_THRESHOLD_PARAMS
49583 +
49584 +Synopsis
49585 + Configures how the AR6000 device monitors and reports signal strength (RSSI) of the
49586 + connected BSS, which is used as a link quality metric. The four RSSI threshold sets (in
49587 + dbM) of the host specification divide the signal strength range into six segments.
49588 + When signal strength increases or decreases across one of the boundaries, an
49589 + RSSI_THRESHOLD event is signaled to the host. The host may then choose to take
49590 + action (such as influencing roaming).
49591 +
49592 +Command
49593 + wmiconfig eth1 --rssiThreshold <weight> <pollTime>
49594 + <above_threshold_val_1> ... <above_threshold_tag_6>
49595 + <above_threshold_val_6>
49596 + <below_threshold_tag_1> <below_threshold_val_1> ...
49597 + <below_threshold_tag_6> <below_threshold_val_6>
49598 +
49599 +Command Parameters
49600 + UINT8 weight Range in [1, 16] used to calculate average RSSI
49601 + UINT32 pollTime RSSI (signal strength) sampling frequency in
49602 + seconds (if pollTime = 0, single strength
49603 + sampling is disabled)
49604 + USER_RSS__THOLD tholds[12] Thresholds (6 x 2)
49605 +
49606 +Command Values
49607 + None defined
49608 +
49609 +Reset Values
49610 + pollTime is 0, and sampling is disabled
49611 +
49612 +Restrictions
49613 + Can only be issued if the AR6000 device is connected
49614 +
49615 +
49616 +=====================================================================
49617 +
49618 +Name
49619 + SCAN_PARAMS
49620 +
49621 +Synopsis
49622 + The minact parameter determines the minimum active channel dwell time, within
49623 + which if the STA receives any beacon, it remains on that channel until the maxact
49624 + channel dwell time. If the STA does not receive a beacon within the minact dwell
49625 + time, it switches to scan the next channel.
49626 +
49627 +Command
49628 + wmiconfig -scan -minact=<ms> --maxact=<ms>
49629 +
49630 +Command Parameters
49631 + UINT16 maxact Channel dwell time (in ms), default = 0
49632 + UINT16 minact Channel dwell time (in ms), default = 105
49633 +
49634 +Command Values
49635 + See channel parameters
49636 +
49637 +Reset Values
49638 + None defined
49639 +
49640 +Restrictions
49641 + The minact value should be greater than 0; maxact should be between 5\9665535 ms
49642 + and greater than minact
49643 +
49644 +=====================================================================
49645 +
49646 +
49647 +Name
49648 + SET_ACCESS_PARAMS
49649 +
49650 +Synopsis
49651 + Allows the host to set access parameters for the wireless network. A thorough
49652 + understanding of IEEE 802.11 is required to properly manipulate these parameters.
49653 +
49654 +Command
49655 + wmiconfig eth1 --acparams --txop <limit> --cwmin <0-15>
49656 + --cwmax <0-15> --aifsn<0-15>
49657 +
49658 +Command Parameters
49659 + UINT16 txop The maximum time (expressed in units of
49660 + 32 ms) the device can spend transmitting
49661 + after acquiring the right to transmit
49662 + UINT8 eCWmin Minimum contention window
49663 + UINT8 eCWmax Maximum contention window
49664 + UINT8 aifsn The arbitration inter-frame space number
49665 +
49666 +Command Values
49667 + None
49668 +
49669 +Reset Values
49670 + Reasonable defaults that vary, between endpoints (prioritized streams)
49671 +
49672 +Restrictions
49673 + None
49674 +
49675 +=====================================================================
49676 +
49677 +
49678 +Name
49679 + SET_ADHOC_BSSID
49680 +
49681 +Synopsis
49682 + Allows the host to set the BSSID for an ad hoc network. If a network with this BSSID
49683 + is not found, the target creates an ad hoc network with this BSSID after the connect
49684 + WMI command is triggered (e.g., by the SIOCSIWESSID IOCTL).
49685 +
49686 +Command
49687 + wmiconfig eth1 --adhocbssid <bssid>
49688 +
49689 +Command Parameters
49690 + A_UINT8 bssid[ATH_MAC_LEN] BSSID is specified in xx:xx:xx:xx:xx:xx format
49691 +
49692 +Command Values
49693 + None
49694 +
49695 +Reset Values
49696 + None
49697 +
49698 +Restrictions
49699 + None
49700 +
49701 +=====================================================================
49702 +
49703 +
49704 +Name
49705 + SET_AKMP_PARAMS
49706 +
49707 +Synopsis
49708 + Enables or disables multi PMKID mode.
49709 +
49710 +Command
49711 + wmiconfig eth1 --setakmp --multipmkid=<on/off>
49712 +
49713 +Command Parameters
49714 + typedef struct {
49715 + A_UINT32 akmpInfo;
49716 + } WMI_SET_AKMP_PARAMS_CMD;
49717 +
49718 +Command Values
49719 + akmpInfo;
49720 + bit[0] = 0
49721 + MultiPMKID mode is disabled and PMKIDs that
49722 + were set using the WMI_SET_PMKID_CMD are
49723 + used in the [Re]AssocRequest frame.
49724 + bit[0] = 1
49725 + MultiPMKID mode is enabled and PMKIDs issued
49726 + by the WMI_SET_PMKID_LIST_CMD are used in
49727 + the next [Re]AssocRequest sent to the AP.
49728 +
49729 +Reset Values
49730 + MultiPMKID mode is disabled
49731 +
49732 +Restrictions
49733 + None
49734 +
49735 +=====================================================================
49736 +
49737 +
49738 +Name
49739 + SET_APPIE
49740 +
49741 +Synopsis
49742 + Add an application-specified IE to a management frame. The maximum length is
49743 + 76 bytes. Including the length and the element ID, this translates to 78 bytes.
49744 +
49745 +Command
49746 + wmiconfig --setappie <frame> <IE>, where:
49747 +
49748 + frame
49749 + One of beacon, probe, respon, assoc
49750 +
49751 + IE
49752 + A hex string beginning with DD (if = 0, no
49753 + IE is sent in the management frame)
49754 +
49755 +Command Parameters
49756 + mgmtFrmType;
49757 + A WMI_MGMT_FRAME_TYPE
49758 +
49759 + ieLen;
49760 + Length of the IE to add to the GMT frame
49761 +
49762 +Command Values
49763 + None
49764 +
49765 +Reset Value
49766 + None defined
49767 +
49768 +Restrictions
49769 + Supported only for the probe request and association request management frame
49770 +types. Also, only one IE can be added per management frame type.
49771 +
49772 +=====================================================================
49773 +
49774 +
49775 +Name
49776 + SET_ASSOC_INFO
49777 +
49778 +Synopsis
49779 + The host uses this command to specify any information elements (IEs) it wishes the
49780 + AR6000 device to add to all future association and reassociation requests. IEs must be
49781 + correct and are used as is by the device. IEs specified through this command are
49782 + cleared with a DISCONNECT.
49783 +
49784 +Command
49785 + wmiconfig eth1 --setAssocIe <IE>
49786 +
49787 +Command Parameters
49788 + UINT8 ieType Used directly in 802.11 frames
49789 + UINT8 bufferSize Size of assocInfo (in bytes) ranging from
49790 + 0\96240. If = 0, previously set IEs are cleared.
49791 + UINT8 assocInfo[bufferSize] Used directly in 802.11 frames
49792 +
49793 +Command Values
49794 + None
49795 +
49796 +Reset Values
49797 + IEs are cleared
49798 +
49799 +Restrictions
49800 + This command can only be issued in the DISCONNECTED state
49801 +
49802 +=====================================================================
49803 +
49804 +
49805 +Name
49806 + SET_AUTHMODE
49807 +
49808 +Synopsis
49809 + Sets the 802.11 authentication mode of reconnection
49810 +
49811 +Command
49812 + wmiconfig eth1 --setauthmode <mode>
49813 +
49814 +Command Parameters
49815 + UINT8 mode
49816 +
49817 +Command Values
49818 + mode = 0x00 Proceed with authentication during reconnect
49819 + = 0x01 Do not proceed with authentication during reconnect
49820 +
49821 +Reset Values
49822 + Authentication
49823 +
49824 +Restrictions
49825 + None
49826 +
49827 +=====================================================================
49828 +
49829 +
49830 +Name
49831 + SET_BEACON_INT
49832 +
49833 +Synopsis
49834 + Sets the beacon interval for an ad hoc network. Beacon interval selection may have an
49835 + impact on power savings. To some degree, a longer interval reduces power
49836 + consumption but also decreases throughput. A thorough understanding of IEEE
49837 + 802.11 ad hoc networks is required to use this command effectively.
49838 +
49839 +Command
49840 + wmiconfig eth1 --ibssconintv
49841 +
49842 +Command Parameters
49843 + UINT16 beaconInterval Specifies the beacon interval in TU units (1024 ms)
49844 +
49845 +Command Values
49846 + None
49847 +
49848 +Reset Values
49849 + The default beacon interval is 100 TUs (102.4 ms)
49850 +
49851 +Restrictions
49852 + This command can only be issued before the AR6000 device starts an ad hoc network
49853 +
49854 +See Also
49855 + \93SET_IBSS_PM_CAPS\94
49856 +
49857 +=====================================================================
49858 +
49859 +
49860 +Name
49861 + SET_BIT_RATE
49862 +
49863 +Synopsis
49864 + The host uses this command to set the AR6000 device to a specific fixed rate.
49865 +
49866 +Command
49867 + wmiconfig eth1 --setfixrates <rate_0> ... <rate_n>
49868 +
49869 +Command Parameters
49870 + INT8 rateIndex
49871 + A WMI_BIT_RATE value
49872 + {
49873 + RATE_AUTO = -1
49874 + RATE_1Mb = 0
49875 + RATE_2Mb = 1
49876 + RATE_5_5M = 2
49877 + RATE_11Mb = 3
49878 + RATE_6Mb = 4
49879 + RATE_9Mb = 5
49880 + RATE_12Mb = 6
49881 + RATE_18Mb = 7
49882 + RATE_24Mb = 8
49883 + RATE_36Mb = 9
49884 + RATE_48Mb = 10
49885 + RATE_54Mb = 11
49886 + } WMI_BIT_RATE
49887 +
49888 +
49889 +Command Values
49890 + See command parameters
49891 +
49892 +Reset Values
49893 + The dynamic rate is determined by the AR6000 device
49894 +
49895 +Restrictions
49896 + This command is intended for use only during development/debug; it is not
49897 +intended for use in production
49898 +
49899 +See Also
49900 + \93GET_BIT_RATE\94
49901 +
49902 +=====================================================================
49903 +
49904 +
49905 +Name
49906 + SET_BMISS_TIME
49907 +
49908 +Synopsis
49909 + This command sets the beacon miss (BMISS) time, which the AR6000 hardware use
49910 + to recognize missed beacons. When an excessive number (15) of consecutive beacons
49911 + are missed, the AR6000 consider switching to a different BSS. The time can be
49912 + specified in number of beacons or in TUs.
49913 +
49914 +Command(s)
49915 + wmiconfig eth1 --setbmissbeacons=<val>
49916 + wmiconfig eth1 --setbmisstime=<val>
49917 +
49918 +Command Parameters
49919 + UINT16 bmissTime Specifies the beacon miss time
49920 + [1000...5000] in TUs (1024 ms)
49921 + UINT16 bmissbeacons Specifies the number of beacons [5...50]
49922 +
49923 +Command Values
49924 + None
49925 +
49926 +Reset Values
49927 + bmissTime is 1500 TUs (1536 ms)
49928 +
49929 +Restrictions
49930 + None
49931 +
49932 +=====================================================================
49933 +
49934 +
49935 +Name
49936 + SET_BSS_FILTER
49937 +
49938 +Synopsis
49939 + The host uses this to inform the AR6000 device of the types of networks about which
49940 + it wants to receive information from the \93BSSINFO\94 event. As the device performs
49941 + either foreground or background scans, it applies the filter and sends \93BSSINFO\94
49942 + events only for the networks that pass the filter. If any of the bssFilter or the ieMask
49943 + filter matches, a BSS Info is sent to the host. The ieMask currently is used as a match
49944 + for the IEs in the beacons, probe reponses and channel switch action management
49945 + frame. See also \93Scan and Roam\94 on page C-1.
49946 +
49947 + The BSS filter command has been enhanced to support IE based filtering. The IEs can
49948 + be specified as a bitmask through this command using this enum.
49949 +
49950 +Command
49951 + wmiconfig eth1 \96filter = <filter> --ieMask 0x<mask>
49952 +
49953 +Command Parameters
49954 + UINT8 BssFilter
49955 +
49956 + Command Values
49957 + typedef struct {
49958 + A_UINT8 bssFilter; See WMI_BSS_FILTER
49959 + A_UINT32 ieMask;
49960 + } __ATTRIB_PACK WMI_BSS_FILTER_CMD;
49961 +
49962 + The ieMask can take this combination of values:
49963 +
49964 + enum {
49965 + BSS_ELEMID_CHANSWITCH = 0x01
49966 + BSS_ELEMID_ATHEROS = 0x02,
49967 + }
49968 +
49969 +Reply Value
49970 + None
49971 +
49972 +Reset Value
49973 + BssFilter = NONE_BSS_FILTER (0)
49974 +
49975 +Restrictions
49976 + None
49977 +
49978 +See Also
49979 + \93CONNECT_CMD\94
49980 +
49981 +=====================================================================
49982 +
49983 +
49984 +Name
49985 + SET_BT_PARAMS
49986 +
49987 +Synopsis
49988 + This command is used to set the status of a Bluetooth stream or set Bluetooth
49989 + coexistence register parameters. The stream may be an SCO or an A2DP stream and
49990 + its status can be started/stopped/suspended/resumed.
49991 +
49992 +Command
49993 + wmiconfig \96setBTparams <paramType> <params>
49994 +
49995 +Command Parameters
49996 + struct {
49997 + union {
49998 + BT_PARAMS_SCO scoParams;
49999 + BT_PARAMS_A2DP a2dpParams;
50000 + BT_PARAMS_MISC miscParams;
50001 + BT_COEX_REGS regs;
50002 + } info;
50003 + A_UINT8 paramType;
50004 + struct {
50005 + A_UINT8 noSCOPkts; Number of SCO packets between consecutive PS-POLLs
50006 + A_UINT8 pspollTimeout;
50007 + A_UINT8 stompbt;
50008 + } BT_PARAMS_SCO;
50009 + struct {
50010 + A2DP BT stream parameters
50011 + A_UINT32 period;
50012 + A_UINT32 dutycycle;
50013 + A_UINT8 stompbt;
50014 + } BT_PARAMS_A2DP;
50015 + struct {
50016 + union {
50017 + WLAN_PROTECT_POLICY_TYPE protectParams;
50018 + A_UINT16 wlanCtrlFlags;
50019 + }info;
50020 + A_UINT8 paramType;
50021 + } BT_PARAMS_MISC;
50022 + struct {
50023 + BT coexistence registers values
50024 + A_UINT32 mode; Coexistence mode
50025 + A_UINT32 scoWghts; WLAN and BT weights
50026 + A_UINT32 a2dpWghts;
50027 + A_UINT32 genWghts;
50028 + A_UINT32 mode2; Coexistence mode2
50029 + A_UINT8 setVal;
50030 + } BT_COEX_REGS;
50031 +
50032 +Command Values
50033 + None defined
50034 +
50035 +Reset Value
50036 + None
50037 +
50038 +Restrictions
50039 + None
50040 +
50041 +=====================================================================
50042 +
50043 +
50044 +Name
50045 + SET_BT_STATUS
50046 +
50047 +Synopsis
50048 + Sets the status of a Bluetooth stream. The stream may be a SCO or an A2DP stream
50049 + and its status can be started/stopped/suspended/resumed.
50050 +
50051 +Command
50052 + wmiconfig \96setBTstatus <streamType> <status>
50053 +
50054 +Command Parameters
50055 + {
50056 + A_UINT8 streamType; Stream type
50057 + A_UINT8 status; Stream status
50058 + }WMI_SET_BT_STATUS_CMD;
50059 +
50060 +Command Values
50061 + {
50062 + BT_STREAM_UNDEF = 0
50063 + BT_STREAM_SCO
50064 + SCO stream
50065 + BT_STREAM_A2DP
50066 + A2DP stream
50067 + BT_STREAM_MAX
50068 + } BT_STREAM_TYPE;
50069 +
50070 + {
50071 + BT_STATUS_UNDEF = 0
50072 + BT_STATUS_START
50073 + BT_STATUS_STOP
50074 + BT_STATUS_RESUME
50075 + BT_STATUS_SUSPEND
50076 + BT_STATUS_MAX
50077 + } BT_STREAM_STATUS;
50078 +
50079 +Reset Value
50080 + None defined
50081 +
50082 +Restrictions
50083 + None
50084 +
50085 +=====================================================================
50086 +
50087 +
50088 +Name
50089 + SET_CHANNEL_PARAMETERS
50090 +
50091 +Synopsis
50092 + Configures various WLAN parameters related to channels, sets the wireless mode,
50093 + and can restrict the AR6000 device to a subset of available channels. The list of
50094 + available channels varies depending on the wireless mode and the regulatory
50095 + domain. The device never operates on a channel outside of its regulatory domain. The
50096 + device starts to scan the list of channels right after this command.
50097 +
50098 +Command
50099 + wmiconfig eth1 --wmode <mode> <list>
50100 +
50101 +Command Parameters
50102 + UINT8 phyMode See Values below.
50103 + UINT8 numberOfChannels
50104 + Number of channels in the channel array that
50105 + follows. If = 0, then the device uses all of the
50106 + channels permitted by the regulatory domain
50107 + and by the specified phyMode.
50108 + UINT16 channel[numberOfChannels]
50109 + Array listing the subset of channels (expressed
50110 + as frequencies in MHz) the host wants the
50111 + device to use. Any channel not permitted by
50112 + the specified phyMode or by the specified
50113 + regulatory domain is ignored by the device.
50114 +
50115 +Command Values
50116 + phyMode = {
50117 + Wireless mode
50118 + 11a = 0x01
50119 + 11g = 0x02
50120 + 11ag = 0x03
50121 + 11b = 0x04
50122 + 11g only = 0x05
50123 + }
50124 +
50125 +Reset Values
50126 + phyMode
50127 + 11ag
50128 + 802.11a/g modules
50129 + 11g
50130 + 802.11g module
50131 + channels
50132 + Defaults to all channels permitted by the
50133 + current regulatory domain.
50134 +
50135 +Restrictions
50136 + This command, if issued, should be issued soon after reset and prior to the first
50137 + connection. This command should only be issued in the DISCONNECTED state.
50138 +
50139 +=====================================================================
50140 +
50141 +
50142 +Name
50143 + SET_DISC_TIMEOUT
50144 +
50145 +Synopsis
50146 + The host uses this command to configure the amount of time that the AR6000 should
50147 + spend when it attempts to reestablish a connection after losing link with its current
50148 + BSS. If this time limit is exceeded, the AR6000 send a \93DISCONNECT\94 event. After
50149 + sending the \93DISCONNECT\94 event the AR6000 continues to attempt to reestablish a
50150 + connection, but they do so at the interval corresponding to a foreground scan as
50151 + established by the \93SET_SCAN_PARAMS\94 command.
50152 +
50153 + A timeout value of 0 indicates that the AR6000 will disable all autonomous roaming,
50154 + so that the AR6000 will not perform any scans after sending a \93DISCONNECT\94
50155 + event to the host. The state is maintained until a shutdown or host sets different
50156 + timeout value from 0.
50157 +
50158 +Command
50159 + wmiconfig eth1 --disc=<timeout in seconds>
50160 +
50161 +Command Parameters
50162 + UINT8 disconnectTimeout
50163 + Specifies the time limit (in seconds) after
50164 + which a failure to reestablish a connection
50165 + results in a \93DISCONNECT\94 event
50166 +
50167 +Command Values
50168 + None
50169 +
50170 +Reset Values
50171 + disconnectTimeout is 10 seconds
50172 +
50173 +Restrictions
50174 + This command can only be issued while in a DISCONNECTED state
50175 +
50176 +=====================================================================
50177 +
50178 +
50179 +Name
50180 + SET_FIXRATES
50181 +
50182 +Synopsis
50183 + By default, the AR6000 device uses all PHY rates based on mode of operation. If the
50184 + host application requires the device to use subset of supported rates, it can set those
50185 + rates with this command. In 802.11g mode, the AR6000 device takes the entire
50186 + 802.11g basic rate set and the rates specified with this command and uses it as the
50187 + supported rate set.
50188 +
50189 + This rate set is advertised in the probe request and the assoc/re-assoc request as
50190 + supported rates. Upon successful association, the device modifies the rate set pool
50191 + using the: intersection of AP-supported rates with the union of the 802.11g basic rate
50192 + set and rates set using this command. The device picks transmission rates from this
50193 + pool based on a rate control algorithm.
50194 +
50195 +Command
50196 + TBD
50197 +
50198 +Command Parameters
50199 + A_UINT16 fixRateMask;
50200 + The individual bit is an index for rate table,
50201 + and setting the that index to 1 would set that
50202 + corresponding rate. E.g., fixRateMask = 9
50203 + (1001) sets 1 Mbps and 11 Mbps.
50204 +
50205 +Command Values
50206 + None
50207 +
50208 +Reset Value
50209 + None defined
50210 +
50211 +Restrictions
50212 + None
50213 +
50214 +See Also
50215 + \93GET_FIXRATES\94
50216 +
50217 +=====================================================================
50218 +
50219 +
50220 +Name
50221 + SET_WHAL_PARAM
50222 +
50223 +Synopsis
50224 + An internal AR6000 command that is used to set certain hardware parameters. The
50225 + description of this command is in $WORKAREA/include/halapi.h.
50226 +
50227 +Command
50228 + TBD
50229 +
50230 +Command Parameters
50231 + ATH_HAL_SETCABTO_CMDID
50232 + Sets the timeout waiting for the multicast
50233 + traffic after a DTIM beacon (in TUs).
50234 +
50235 +Command Values
50236 + None
50237 +
50238 +Reset Value
50239 + Default = 10 TUs
50240 +
50241 +Restrictions
50242 + This command should be executed before issuing a connect command.
50243 +
50244 +=====================================================================
50245 +
50246 +
50247 +Name
50248 + SET_HOST_SLEEP_MODE
50249 +
50250 +Synopsis
50251 + The host uses this command to set the host mode to asleep or awake. All packets are
50252 + delivered to the host when the host mode is awake. When host mode is asleep, only if
50253 + WoW is enabled and the incoming packet matches one of the specified WoW
50254 + patterns, will the packet be delivered to the host. The host will also be woken up by
50255 + the target for pattern-matching packets and important events.
50256 +
50257 +Command
50258 + wmiconfig \96sethostmode=<asleep/awake>
50259 +
50260 +Command Parameters
50261 + A_BOOL awake Set the host mode to awake
50262 + A_BOOL asleep Set the host mode to asleep
50263 +
50264 +Command Values
50265 + 1 = awake, 0 = asleep
50266 +
50267 +Reset Value
50268 + None defined (default host mode is awake)
50269 +
50270 +Restrictions
50271 + None
50272 +
50273 +
50274 +=====================================================================
50275 +
50276 +Name
50277 + SET_IBSS_PM_CAPS
50278 +
50279 +Synopsis
50280 + Used to support a non-standard power management scheme for an ad hoc wireless
50281 + network consisting of up to eight stations (STAs) that support this form of power
50282 + saving (e.g., Atheros-based STAs). A thorough understanding of IEEE 802.11 ad hoc
50283 + networks is required to use this command effectively.
50284 +
50285 +Command
50286 + wmiconfig eth1 --ibsspmcaps --ps=<enable/disable>
50287 + --aw=<ATIM Windows in ms>
50288 + --ttl=<Time to live in number of beacon periods>
50289 + --to=<timeout in ms>
50290 +
50291 +Command Parameters
50292 + UINT8 power_saving
50293 + = 0
50294 + The non-standard power saving scheme is
50295 + disabled and maximum throughput (with no
50296 + power saving) is obtained.
50297 +
50298 + = 1
50299 + Ad hoc power saving scheme is enabled (but
50300 + throughput may be decreased)
50301 +
50302 + UINT16 atim_windows
50303 + Specifies the length (in ms) of the ad hoc traffic
50304 + indication message (ATIM) windows used in an ad
50305 + hoc network. All Atheros-based STAs that join the
50306 + network use this duration ATIM window.
50307 +
50308 + The duration is communicated between wireless
50309 + STAs through an IE in beacons and probe responses.
50310 +
50311 + The host sets atim_windows to control trade-offs
50312 + between power use and throughput. The value
50313 + chosen should be based on the beacon interval (see
50314 + the \93SET_BEACON_INT\94 command) on the
50315 + expected number of STAs in the IBSS, and on the
50316 + amount of traffic and traffic patterns between STAs.
50317 +
50318 + UINT16 timeout_value
50319 + Specifies the timeout (in ms). The value is the same
50320 + for all ad hoc connections, but tracks separately for
50321 + each.
50322 +
50323 + Applicable only for a beacon period and used to
50324 + derive actual timeout values on the Tx and Rx sides.
50325 + On the Tx side, the value defines a window during
50326 + which the STA accepts the frame(s) from the host for a
50327 + particular connection. Until closed, the window
50328 + restarts with every frame received from the host. On
50329 + the Rx side, indicates the time until which the STA
50330 + continues accepting frames from a particular
50331 + connection. The value resets with every frame
50332 + received. The value can be used to determine the
50333 + trade off between throughput and power.
50334 + Default = 10 ms
50335 +
50336 + UINT8 ttl
50337 + Specifies the value in number of beacon periods. The
50338 + value is used to set a limit on the time until which a
50339 + frame is kept alive in the AR6001 before being
50340 + discarded. Default = 5
50341 +
50342 +Command Values
50343 + None
50344 +
50345 +Reset Values
50346 + By default, power_saving is enabled with atim_window = 20 ms
50347 +
50348 +Restrictions
50349 + Can only be issued before the AR6000 starts an ad hoc network
50350 +
50351 +See Also
50352 + \93SET_BEACON_INT\94
50353 +
50354 +=====================================================================
50355 +
50356 +
50357 +
50358 +Name
50359 + SET_LISTEN_INT
50360 +
50361 +Synopsis
50362 + The host uses this command to request a listen interval, which determines how often
50363 + the AR6000 device should wake up and listen for traffic. The listen interval can be set
50364 + by the TUs or by the number of beacons. The device may not be able to comply with
50365 + the request (e.g., if the beacon interval is greater than the requested listen interval, the
50366 + device sets the listen interval to the beacon interval). The actual listen interval used
50367 + by the device is available in the \93CONNECT\94 event.
50368 +
50369 +Command
50370 + wmiconfig eth1 --listen=<#of TUs, can range from 15 to 3000>
50371 +
50372 + --listenbeacons=<#of beacons, can range from 1 to 50>
50373 +
50374 +Command Parameters
50375 + UINT16 listenInterval
50376 + Specifies the listen interval in Kms
50377 + (1024 ms), ranging from 100 to 1000
50378 +
50379 + UINT16 listenbeacons
50380 + Specifies the listen interval in beacons,
50381 + ranging from 1 to 50
50382 +
50383 +Command Values
50384 + None
50385 +
50386 +Reset Values
50387 + The device sets the listen interval equal to the beacon interval of the AP it associates
50388 + to.
50389 +
50390 +Restrictions
50391 + None
50392 +
50393 +=====================================================================
50394 +
50395 +
50396 +Name
50397 + SET_LPREAMBLE
50398 +
50399 +Synopsis
50400 + Overrides the short preamble capability of the AR6000 device
50401 +
50402 +Command
50403 + TBD
50404 +
50405 +Command Parameters
50406 + WMI_LPREAMBLE_DISABLED
50407 + The device is short-preamble capable
50408 +
50409 + WMI_LPREAMBLE_ENABLED
50410 + The device supports only the long-
50411 + preamble mode
50412 +
50413 +Command Values
50414 + None
50415 +
50416 +Reset Value
50417 + None defined
50418 +
50419 +Restrictions
50420 + None
50421 +
50422 +
50423 +=====================================================================
50424 +
50425 +Name
50426 + SET_MAX_SP_LEN
50427 +
50428 +Synopsis
50429 + Set the maximum service period; indicates the number of packets the AR6001 can
50430 + receive from the AP when triggered
50431 +
50432 +Command
50433 + wmiconfig eth1 --setMaxSPLength <maxSPLen>
50434 +
50435 +Command Parameters
50436 + UINT8 maxSPLen
50437 + An APSD_SP_LEN_TYPE value
50438 +
50439 +Command Values
50440 + {
50441 + DELIVER_ALL_PKT = 0x0
50442 + DELIVER_2_PKT = 0x1
50443 + DELIVER_4_PKT = 0x2
50444 + DELIVER_6_PKT = 0x3
50445 + }APSD_SP_LEN_TYPE
50446 +
50447 +
50448 +Reset Values
50449 + maxSPLen is DELIVER_ALL_PKT
50450 +
50451 +Restrictions
50452 + None
50453 +
50454 +=====================================================================
50455 +
50456 +
50457 +Name
50458 + SET_OPT_MODE
50459 +
50460 +Synopsis
50461 + Special feature, sets the special mode on/off
50462 +
50463 +Command
50464 + wmiconfig eth1 --mode <mode>
50465 + Set the optional mode, where mode is special or off
50466 +
50467 +Command Parameters
50468 + enum {
50469 + SPECIAL_OFF
50470 + SPECIAL_ON
50471 + } OPT_MODE_TYPE;
50472 +
50473 +Command Values
50474 +
50475 +Reset Value
50476 + Mode = Off
50477 +
50478 +Restrictions
50479 + None
50480 +
50481 +=====================================================================
50482 +
50483 +
50484 +Name
50485 + SET_PMKID
50486 +
50487 +Synopsis
50488 + The host uses this command to enable or disable a pairwise master key ID (PMKID)
50489 + in the AR6000 PMKID cache. The AR6000 clears its PMKID cache on receipt of a
50490 + DISCONNECT command from the host. Individual entries in the cache might be
50491 + deleted as the AR6000 detect new APs and decides to remove old ones.
50492 +
50493 +Command
50494 + wmiconfig eth1 --setbsspmkid --bssid=<aabbccddeeff>
50495 + --bsspmkid=<pmkid>
50496 +
50497 +Command Parameters
50498 + UINT8 bssid[6]
50499 + The MAC address of the AP that the
50500 + PMKID corresponds to (6 bytes in hex
50501 + format)
50502 +
50503 + UINT8 enable
50504 + Either PMKID_DISABLE (0) to disable
50505 + the PMKID or PMKID_ENABLE (1) to
50506 + enable it (16 bytes in hex format)
50507 +
50508 + UINT8 pmkid[16]
50509 + Meaningful only if enable is
50510 + PMKID_ENABLE, when it is the PMKID
50511 + that the AR6000 should use on the next
50512 + reassociation with the specified AP
50513 +
50514 +Command Values
50515 + enable
50516 + = 0 (disable), 1 (enable)
50517 + PKMID enabled/disabled
50518 +
50519 +Reset Values
50520 + None defined
50521 +
50522 +Restrictions
50523 + Only supported in infrastructure networks
50524 +
50525 +=====================================================================
50526 +
50527 +
50528 +Name
50529 + SET_PMKID_LIST_CMD
50530 +
50531 +Synopsis
50532 + Configures the list of PMKIDs on the firmware.
50533 +
50534 +Command
50535 + wmiconfig --setpmkidlist --numpmkid=<n> --pmkid=<pmkid_1>
50536 + ... --pmkid=<pmkid_n>
50537 +
50538 + Where n is the number of pmkids (maximum = 8) and pmkid_i is the ith pmkid (16
50539 + bytes in hex format)
50540 +
50541 +Command Parameters
50542 + {
50543 + A_UINT8 pmkid[WMI_PMKID_LEN];
50544 + } __ATTRIB_PACK WMI_PMKID;
50545 +
50546 + {
50547 + A_UINT32 numPMKID;
50548 + WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE];
50549 + } __ATTRIB_PACK WMI_SET_PMKID_LIST_CMD;
50550 +
50551 +Command Values
50552 + None
50553 +
50554 +Reset Values
50555 + None
50556 +
50557 +Restrictions
50558 + Supported only in infrastructure modes
50559 +
50560 +=====================================================================
50561 +
50562 +
50563 +Name
50564 + SET_POWER_MODE
50565 +
50566 +Synopsis
50567 + The host uses this command to provide the AR6000 device with guidelines on the
50568 + desired trade-off between power utilization and performance.
50569 +
50570 + In normal power mode, the device enters a sleep state if they have nothing to do,
50571 + which conserves power but may cost performance as it can take up to 2 ms to
50572 + resume operation after leaving sleep state.
50573 +
50574 + In maximum performance mode, the device never enters sleep state, thus no time
50575 + is spent waking up, resulting in higher power consumption and better
50576 + performance.
50577 +
50578 +Command
50579 + TBD
50580 +
50581 +Command Parameters
50582 + UINT8 powerMode
50583 + WMI_POWER_MODE value
50584 + {
50585 + REC_POWER = 1
50586 + (Recommended setting) Tries to conserve
50587 + power without sacrificing performance
50588 + MAX_PERF_POWER = 2
50589 + Setting that maximizes performance at
50590 + the expense of power
50591 +
50592 + All other values are reserved
50593 + } WMI_POWER_MODE
50594 +
50595 +Command Values
50596 + See command parameters
50597 +
50598 +Reset Values
50599 + powerMode is REC_POWER
50600 +
50601 +Restrictions
50602 + This command should only be issued in the DISCONNECTED state for the
50603 + infrastructure network.
50604 +
50605 + For a PM-disabled ad hoc network, the power mode should remain in
50606 + MAX_PERF_POWER.
50607 +
50608 + For a PM-enabled ad hoc network, the device can have REC_POWER or
50609 + MAX_PERF_POWER set, but either way it must follow the power save ad hoc
50610 + protocol. The host can change power modes in the CONNECTED state.
50611 +
50612 + Host changes to the PS setting when the STA is off the home channel take no effect
50613 + and cause a TARGET_PM_FAIL event.
50614 +
50615 +=====================================================================
50616 +
50617 +
50618 +Name
50619 + SET_POWER_PARAMS
50620 +
50621 +Synopsis
50622 + The host uses this command to configure power parameters
50623 +
50624 +Command
50625 + wmiconfig eth1 --pmparams --it=<ms> --np=<number of PS POLL>
50626 + --dp=<DTIM policy: ignore/normal/stick>
50627 +
50628 +Command Parameters
50629 + UINT16 idle_period
50630 + Length of time (in ms) the AR6000 device
50631 + remains awake after frame Rx/Tx before going
50632 + to SLEEP state
50633 +
50634 + UINT16 pspoll_number
50635 + The number of PowerSavePoll (PS-poll)
50636 + messages the device should send before
50637 + notifying the AP it is awake
50638 +
50639 + UINT16 dtim_policy
50640 + A WMI_POWER_PARAMS_CMD value
50641 +
50642 + {
50643 + IGNORE_DTIM =1
50644 + The device does not listen to any content after
50645 + beacon (CAB) traffic
50646 + NORMAL_DTIM = 2
50647 + DTIM period follows the listen interval (e.g., if
50648 + the listen interval is 4 and the DTIM period is 2,
50649 + the device wakes up every fourth beacon)
50650 + STICK_DTIM = 3
50651 + Device attempt to receive all CAB traffic (e.g., if
50652 + the DTIM period is 2 and the listen interval is 4,
50653 + the device wakes up every second beacon)
50654 + } WMI_POWER_PARAMS_CMD
50655 +
50656 +Command Parameters
50657 + See command parameters
50658 +
50659 +Reset Values
50660 + idle_period
50661 + 200 ms
50662 +
50663 + pspoll_number
50664 + = 1
50665 +
50666 + dtim_policy
50667 + = NORMAL_DTIM
50668 +
50669 +Restrictions
50670 + None
50671 +
50672 +=====================================================================
50673 +
50674 +
50675 +Name
50676 + SET_POWERSAVE_PARAMS
50677 +
50678 +Synopsis
50679 + Set the two AR6000 power save timers (PS-POLL timer and APSD trigger timer) and
50680 + the two ASPD TIM policies
50681 +
50682 +Command
50683 + wmiconfig eth1--psparams --psPollTimer=<psPollTimeout in ms>
50684 + --triggerTimer=<triggerTimeout in ms> --apsdTimPolicy=<ignore/
50685 + adhere> --simulatedAPSDTimPolicy=<ignore/adhere>
50686 +
50687 +Command Parameters
50688 + typedef struct {
50689 + A_UINT16 psPollTimeout;
50690 + Timeout (in ms) after sending PS-POLL; the
50691 + AR6000 device sleeps if it does not receive a
50692 + data packet from the AP
50693 +
50694 + A_UINT16 triggerTimeout;
50695 + Timeout (in ms) after sending a trigger; the
50696 + device sleeps if it does not receive any data
50697 + or null frame from the AP
50698 +
50699 + APSD_TIM_POLICY apsdTimPolicy;
50700 + TIM behavior with queue APSD enabled
50701 +
50702 + APSD_TIM_POLICY simulatedAPSD
50703 +
50704 + TimPolicy;
50705 + TIM behavior with simulated APSD
50706 + enabled
50707 +
50708 + typedef enum {
50709 + IGNORE_TIM_ALL_QUEUES_APSD = 0,
50710 + PROCESS_TIM_ALL_QUEUES_APSD = 1,
50711 + IGNORE_TIM_SIMULATED_APSD = 2,
50712 + POWERSAVE_TIMERS_POLICY = 3,
50713 + } APSD_TIM_POLICY;
50714 +
50715 +Command Values
50716 + None
50717 +
50718 +Reset Values
50719 + psPollTimeout is 50 ms; triggerTimeout is 10 ms;
50720 + apsdTimPolicy = IGNORE_TIM_ALL_QUEUES_APSD;
50721 + simulatedAPSDTimPolicy = POWERSAVE_TIMERS_POLICY
50722 +
50723 +Restrictions
50724 + When this command is used, all parameters must be set; this command does not
50725 + allow setting only one parameter.
50726 +
50727 +=====================================================================
50728 +
50729 +
50730 +Name
50731 + SET_PROBED_SSID
50732 +
50733 +Synopsis
50734 + The host uses this command to provide a list of up to MAX_PROBED_SSID_INDEX
50735 + (six) SSIDs that the AR6000 device should actively look for. It lists the active SSID
50736 + table. By default, the device actively looks for only the SSID specified in the
50737 + \93CONNECT_CMD\94 command, and only when the regulatory domain allows active
50738 + probing. With this command, specified SSIDs are probed for, even if they are hidden.
50739 +
50740 +Command
50741 + wmiconfig eth1 --ssid=<ssid> [--num=<index>]
50742 +
50743 +Command Parameters
50744 + {
50745 + A_UINT8 numSsids
50746 + A number from 0 to
50747 + MAX_PROBED_SSID_INDEX indicating
50748 + the active SSID table entry index for this
50749 + command (if the specified entry index
50750 + already has an SSID, the SSID specified in
50751 + this command replaces it)
50752 +
50753 + WMI_PROBED_SSID_INFO probedSSID[1]
50754 + } WMI_PROBED_SSID_CMD
50755 +
50756 + {
50757 + A_UINT8 flag
50758 + WMI_SSID_FLAG indicates the current
50759 + entry in the active SSID table
50760 + A_UINT8 ssidLength
50761 + Length of the specified SSID in bytes.
50762 + If = 0, the entry corresponding to the
50763 + index is erased
50764 + A_UINT8 ssid[32]
50765 + SSID string actively probed for when
50766 + permitted by the regulatory domain
50767 + } WMI_PROBED_SSID_INFO
50768 +
50769 +Command Values
50770 + WMI_SSID_FLAG
50771 + {
50772 + DISABLE_SSID_FLAG = 0
50773 + Disables entry
50774 + SPECIFIC_SSID_FLAG = 1
50775 + Probes specified SSID
50776 + ANY_SSID_FLAG = 2
50777 + Probes for any SSID
50778 + } WMI_SSID_FLAG
50779 +
50780 +Reset Value
50781 + The entries are unused.
50782 +
50783 +Restrictions
50784 + None
50785 +
50786 +=====================================================================
50787 +
50788 +
50789 +Name
50790 + SET_REASSOC_MODE
50791 +
50792 +Synopsis
50793 + Specify whether the disassociated frame should be sent or not upon reassociation.
50794 +
50795 +Command
50796 + wmiconfig eth1 --setreassocmode <mode>
50797 +
50798 +Command Parameters
50799 + UINT8 mode
50800 +
50801 +Command Values
50802 + mode
50803 + = 0x00
50804 + Send disassoc to a previously connected AP
50805 + upon reassociation
50806 + = 0x01
50807 + Do not send disassoc to previously connected
50808 + AP upon reassociation
50809 +
50810 +Reset Values
50811 + None defined
50812 +
50813 +Restrictions
50814 + None
50815 +
50816 +
50817 +=====================================================================
50818 +
50819 +Name
50820 + SET_RETRY_LIMITS
50821 +
50822 +Synopsis
50823 + Allows the host to influence the number of times that the AR6000 device should
50824 + attempt to send a frame before they give up.
50825 +
50826 +Command
50827 + wmiconfig --setretrylimits <frameType> <trafficClass> <maxRetries>
50828 + <enableNotify>
50829 +
50830 +Command Parameters
50831 + {
50832 + UINT8 frameType
50833 + A WMI_FRAMETYPE specifying
50834 + which type of frame is of interest.
50835 + UINT8 trafficClass
50836 + Specifies a traffic class (see
50837 + \93CREATE_PSTREAM\94). This
50838 + parameter is only significant when
50839 + frameType = DATA_FRAMETYPE.
50840 + UINT8 maxRetries
50841 + Maximum number of times the
50842 + device attempts to retry a frame Tx,
50843 + ranging from WMI_MIN_RETRIES
50844 + (2) to WMI_MAX_RETRIES (15). If
50845 + the special value 0 is used,
50846 + maxRetries is set to 15.
50847 + A_UINT8 enableNotify
50848 + Notify when enabled
50849 + } WMI_RETRY_LIMIT_INFO
50850 +
50851 + {
50852 + A_UINT8 numEntries
50853 + WMI_RETRY_LIMIT_INFO retryLimitInfo[1]
50854 + } WMI_SET_RETRY_LIMITS_CMD
50855 +
50856 +Command Values
50857 + {
50858 + MGMT_FRAMETYPE = 0 Management frame
50859 + CONTROL_FRAMETYPE = 1 Control frame
50860 + DATA_FRAMETYPE = 2 Data frame
50861 + } WMI_FRAMETYPE
50862 +
50863 +Reset Values
50864 + Retries are set to 15
50865 +
50866 +Restrictions
50867 + None
50868 +
50869 +=====================================================================
50870 +
50871 +
50872 +Name
50873 + SET_ROAM_CTRL
50874 +
50875 +Synopsis
50876 + Affects how the AR6000 device selects a BSS. The host uses this command to set and
50877 + enable low RSSI scan parameters. The time period of low RSSI background scan is
50878 + mentioned in scan period. Low RSSI scan is triggered when the current RSSI
50879 + threshold (75% of current RSSI) is equal to or less than scan threshold.
50880 +
50881 + Low RSSI roam is triggered when the current RSSI threshold falls below the roam
50882 + threshold and roams to a better AP by the end of the scan cycle. During Low RSSI
50883 + roam, if the STA finds a new AP with an RSSI greater than roam RSSI to floor, during
50884 + scan, it roams immediately to it instead of waiting for the end of the scan cycle. See
50885 + also \93Scan and Roam\94 on page C-1.
50886 +
50887 +Command
50888 + wmiconfig --roam <roamctrl> <info>, where info is <scan period>
50889 + <scan threshold> <roam threshold> <roam rssi floor>
50890 +
50891 +Command Parameters
50892 + A_UINT8 roamCtrlType;
50893 +
50894 +Command Values
50895 + WMI_FORCE_ROAM = 1
50896 + Roam to the specified BSSID
50897 +
50898 + WMI_SET_ROAM_MODE = 2
50899 + Default, progd bias, no roam
50900 +
50901 + WMI_SET_HOST_BIAS = 3
50902 + Set the host bias
50903 +
50904 + WMI_SET_LOWRSSI_SCAN_PARAMS = 4
50905 + Info parameters
50906 +
50907 + A_UINT8 bssid[ATH_MAC_LEN];
50908 + WMI_FORCE_ROAM
50909 +
50910 + A_UINT8 roamMode;
50911 + WMI_SET_ROAM_MODE
50912 +
50913 + A_UINT8 bssBiasInfo;
50914 + WMI_SET_HOST_BIAS
50915 +
50916 + A_UINT16 lowrssi_scan_period;
50917 + WMI_SET_LOWRSSI_SCAN_PARAMS
50918 +
50919 + A_INT16
50920 + lowrssi_scan_threshold;
50921 + WMI_SET_LOWRSSI_SCAN_PARAMS
50922 +
50923 + A_INT16 lowrssi_roam_threshold;
50924 + WMI_SET_LOWRSSI_SCAN_PARAMS
50925 +
50926 + A_UINT8 roam_rssi_floor;
50927 + WMI_SET_LOWRSSI_SCAN_PARAMS
50928 +
50929 +Reset Value
50930 + None defined (default lowrssi scan is disabled. Enabled only when scan period is set.)
50931 +
50932 +Restrictions
50933 + None
50934 +
50935 +=====================================================================
50936 +
50937 +
50938 +Name
50939 + SET_RTS
50940 +
50941 +Synopsis
50942 + Decides when RTS should be sent.
50943 +
50944 +Command
50945 + wmiconfig eth1 --setRTS <pkt length threshold>
50946 +
50947 +Command Parameters
50948 + A_UINT16
50949 + threshold;
50950 + Command parameter threshold in bytes. An RTS is
50951 + sent if the data length is more than this threshold.
50952 + The default is to NOT send RTS.
50953 +
50954 +Command Values
50955 + None
50956 +
50957 +Reset Value
50958 + Not to send RTS.
50959 +
50960 +Restrictions
50961 + None
50962 +
50963 +
50964 +=====================================================================
50965 +
50966 +Name
50967 + SET_SCAN_PARAMS
50968 +
50969 +Synopsis
50970 + The host uses this command to set the AR6000 scan parameters, including the duty
50971 + cycle for both foreground and background scanning. Foreground scanning takes
50972 + place when the AR6000 device is not connected, and discovers all available wireless
50973 + networks to find the best BSS to join. Background scanning takes place when the
50974 + device is already connected to a network and scans for potential roaming candidates
50975 + and maintains them in order of best to worst. A second priority of background
50976 + scanning is to find new wireless networks.
50977 +
50978 + The device initiates a scan when necessary. For example, a foreground scan is always
50979 + started on receipt of a \93CONNECT_CMD\94 command or when the device cannot find
50980 + a BSS to connect to. Foreground scanning is disabled by default until receipt of a
50981 + CONNECT command. Background scanning is enabled by default and occurs every
50982 + 60 seconds after the device is connected.
50983 +
50984 + The device implements a binary backoff interval for foreground scanning when it
50985 + enters the DISCONNECTED state after losing connectivity with an AP or when a
50986 + CONNECT command is received. The first interval is ForegroundScanStartPeriod,
50987 + which doubles after each scan until the interval reaches ForegroundScanEndPeriod.
50988 + If the host terminates a connection with DISCONNECT, the foreground scan period
50989 + is ForegroundScanEndPeriod. All scan intervals are measured from the time a full
50990 + scan ends to the time the next full scan starts. The host starts a scan by issuing a
50991 + \93START_SCAN\94 command. See also \93Scan and Roam\94 on page C-1.
50992 +
50993 +Command
50994 + wmiconfig eth1 --scan --fgstart=<sec> --fgend=<sec> --bg=<sec> --
50995 + act=<msec> --pas=<msec> --sr=<short scan ratio> --scanctrlflags
50996 + <connScan> <scanConnected> <activeScan> <reportBSSINFO>
50997 +
50998 +Command Parameters
50999 + UINT16 fgStartPeriod
51000 + First interval used by the device when it
51001 + disconnects from an AP or receives a
51002 + CONNECT command, specified in seconds (0\96
51003 + 65535). If = 0, the device uses the reset value.
51004 + If = 65535, the device disables foreground
51005 + scanning.
51006 +
51007 + UINT16 fgEndPeriod
51008 + The maximum interval the device waits between
51009 + foreground scans specified in seconds (from
51010 + ForegroundScanStartPeriod to 65535). If = 0, the
51011 + device uses the reset value.
51012 +
51013 + UINT16 bgScanPeriod
51014 + The period of background scan specified in
51015 + seconds (0\9665535). By default, it is set to the reset
51016 + value of 60 seconds. If 0 or 65535 is specified, the
51017 + device disables background scanning.
51018 +
51019 + UINT16 maxactChDwellTime
51020 + The period of time the device stays on a
51021 + particular channel while active scanning. It is
51022 + specified in ms (10\9665535). If the special value of
51023 + 0 is specified, the device uses the reset value.
51024 +
51025 + UINT16 PasChDwellTime
51026 + The period of time the device remains on a
51027 + particular channel while passive scanning. It is
51028 + specified in ms (10\9665535). If the special value of
51029 + 0 is specified, the device uses the reset value.
51030 +
51031 + UINT8 shortScanRatio
51032 + Number of short scans to perform for each
51033 + long scan.
51034 +
51035 + UINT8 scanCtrlFlasgs
51036 +
51037 + UINT16 minactChDwellTime
51038 + Specified in ms
51039 +
51040 + UINT32 maxDFSchActTime
51041 + The maximum time a DFS channel can stay
51042 + active before being marked passive, specified in
51043 + ms.
51044 +
51045 +Command Values
51046 + None
51047 +
51048 +Reset Values
51049 + ForegroundScanStart
51050 +Period
51051 + 1 sec
51052 +
51053 + ForegroundScanEndPeriod
51054 + 60 sec
51055 +
51056 + BackgroundScanPeriod
51057 + 60 sec
51058 +
51059 + ActiveChannelDwellTime
51060 + 105 ms
51061 +
51062 +=====================================================================
51063 +
51064 +
51065 +Name
51066 + SET_TKIP_COUNTERMEASURES
51067 +
51068 +Synopsis
51069 + The host issues this command to tell the target whether to enable or disable TKIP
51070 + countermeasures.
51071 +
51072 +Command
51073 + TBD
51074 +
51075 +Command Parameters
51076 + UINT8 WMI_TKIP_CM_ENABLE
51077 + Enables the countermeasures
51078 +
51079 +
51080 + UINT8 TKIP_CM_DISABLE
51081 + Disables the countermeasures
51082 +
51083 +Command Values
51084 + None
51085 +
51086 +Reset Values
51087 + By default, TKIP MIC reporting is disabled
51088 +
51089 +Restrictions
51090 + None
51091 +
51092 +=====================================================================
51093 +
51094 +
51095 +Name
51096 + SET_TX_PWR
51097 +
51098 +Synopsis
51099 + The host uses this command to specify the Tx power level of the AR6000. Cannot be
51100 + used to exceed the power limit permitted by the regulatory domain. The maximum
51101 + output power is limited in the chip to 31.5 dBm; the range is 0 \96 31.5 dbm.
51102 +
51103 +Command
51104 + wmiconfig --power <dbM>
51105 +
51106 +Command Parameters
51107 + UINT8 dbM
51108 + The desired Tx power specified in dbM.
51109 + If = 0, the device chooses the maximum
51110 + permitted by the regulatory domain.
51111 +
51112 +Command Values
51113 + None
51114 +
51115 +Reset Values
51116 + The maximum permitted by the regulatory domain
51117 +
51118 +Restrictions
51119 + None
51120 +
51121 +See Also
51122 + \93GET_TX_PWR\94
51123 +
51124 +
51125 +=====================================================================
51126 +
51127 +Name
51128 + SET_VOICE_PKT_SIZE
51129 +
51130 +Synopsis
51131 + If an AP does not support WMM, it has no way to differentiate voice from data.
51132 + Because the voice packet is typically small, packet in size less than voicePktSize are
51133 + assumed to be voice, otherwise it is treated as data.
51134 +
51135 +Command
51136 + wmiconfig eth1 --setVoicePktSize <size-in-bytes>
51137 +
51138 +Command Parameters
51139 + UINT16 voicePktSize
51140 + Packet size in octets
51141 +
51142 +Command Values
51143 + None
51144 +
51145 +Reset Values
51146 + voicePktSize default is 400 bytes
51147 +
51148 +Restrictions
51149 + No effect if WMM is unavailable
51150 +
51151 +
51152 +=====================================================================
51153 +
51154 +Name
51155 + SET_WMM
51156 +
51157 +Synopsis
51158 + Overrides the AR6000 device WMM capability
51159 +
51160 +Command
51161 + wmiconfig eth1 --setwmm <enable>
51162 +
51163 +Command Parameters
51164 + WMI_WMM_ENABLED
51165 + Enables WMM
51166 +
51167 + WMI_WMM_DISABLED
51168 + Disables WMM support
51169 +
51170 +Command Values
51171 + 0 = disabled
51172 + 1 = enabled
51173 +
51174 +Reset Value
51175 + WMM Disabled
51176 +
51177 +Restrictions
51178 + None
51179 +
51180 +
51181 +=====================================================================
51182 +
51183 +Name
51184 + SET_WMM_TXOP
51185 +
51186 +Synopsis
51187 + Configures TxOP Bursting when sending traffic to a WMM capable AP
51188 +
51189 +Command
51190 + wmiconfig eth1 --txopbursting <burstEnable>
51191 +
51192 + <burstEnable>
51193 + = 0
51194 + Disallow TxOp bursting
51195 +
51196 + = 1
51197 + Allow TxOp bursting
51198 +
51199 +Command Parameters
51200 + txopEnable
51201 + = WMI_TXOP_DISABLED
51202 + Disabled
51203 +
51204 + = WMI_TXOP_ENABLED
51205 + Enabled
51206 +
51207 +Command Values
51208 + txopEnable
51209 + = 0 Disabled
51210 +
51211 + = 1 Enabled
51212 +
51213 +Reset Value
51214 + Bursting is off by default
51215 +
51216 +Restrictions
51217 + None
51218 +
51219 +=====================================================================
51220 +
51221 +
51222 +Name
51223 + SET_WOW_MODE
51224 +
51225 +Synopsis
51226 + The host uses this command to enable or disable the WoW mode. When WoW mode
51227 + is enabled and the host is asleep, pattern matching takes place at the target level.
51228 + Only packets that match any of the pre-specified WoW filter patterns, will be passed
51229 + up to the host. The host will also be woken up by the target. Packets which do not
51230 + match any of the WoW patterns are discarded.
51231 +
51232 +Command
51233 + wmiconfig \96setwowmode <enable/disable>
51234 +
51235 +Command Parameters
51236 + A_BOOL enable_wow
51237 + Enable or disable WoW:
51238 +
51239 +Command Values
51240 + = 0
51241 + Disable WoW
51242 +
51243 + = 1
51244 + Enable WoW
51245 +
51246 +Reset Value
51247 + None defined (default WoW mode is disabled).
51248 +
51249 +Restrictions
51250 + None
51251 +
51252 +See Also
51253 + \93GET_WOW_LIST\94
51254 +
51255 +
51256 +=====================================================================
51257 +
51258 +Name
51259 + SET_WSC_STATUS
51260 +
51261 +Synopsis
51262 + The supplicant uses this command to inform the target about the status of the WSC
51263 + registration protocol. During the WSC registration protocol, a flag is set so the target
51264 + bypasses some of the checks in the CSERV module. At the end of the registration, this
51265 + flag is reset.
51266 +
51267 +Command
51268 + N/A
51269 +
51270 +Command Parameters
51271 + A_BOOL status
51272 + = 1 WSC registration in progress
51273 + = 0 WSC protocol not running
51274 +
51275 +Reply Parameters
51276 + None
51277 +
51278 +Reset Value
51279 + None defined (default = 0)
51280 +
51281 +Restrictions
51282 + None
51283 +
51284 +
51285 +=====================================================================
51286 +
51287 +Name
51288 + SNR_THRESHOLD_PARAMS
51289 +
51290 +Synopsis
51291 + Configures how the AR6000 device monitors and reports SNR of the connected BSS,
51292 + used as a link quality metric.
51293 +
51294 +Command
51295 + --snrThreshold <weight> <upper_threshold_1> ...
51296 + <upper_threshold_4> <lower_threshold_1> ... <lower_threshold_4>
51297 + <pollTimer>
51298 +
51299 +Command Parameters
51300 + <weight>
51301 + Share with rssiThreshold. Range in [1, 16], used
51302 + in the formula to calculate average RSSI
51303 +
51304 + <upper_threshold_x>
51305 + Above thresholds expressed in db, in ascending
51306 + order
51307 +
51308 + <lower_threshold_x>
51309 + Below thresholds expressed in db, in ascending
51310 + order
51311 +
51312 + <pollTimer>
51313 + The signal strength sampling frequency in
51314 + seconds. If polltime = 0, signal strength
51315 + sampling is disabled
51316 +
51317 +Command Values
51318 + None
51319 +
51320 +Reset Value
51321 + None defined
51322 +
51323 +Restrictions
51324 + None
51325 +
51326 +=====================================================================
51327 +
51328 +
51329 +Name
51330 + START_SCAN
51331 +
51332 +Synopsis
51333 + The host uses this command to start a long or short channel scan. All future scans are
51334 + relative to the time the AR6000 device processes this command. The device performs
51335 + a channel scan on receipt of this command, even if a scan was already in progress.
51336 + The host uses this command when it wishes to refresh its cached database of wireless
51337 + networks. The isLegacy field will be removed (0 for now) because it is achieved by
51338 + setting CONNECT_PROFILE_MATCH_DONE in the CONNECT command. See also
51339 + \93Scan and Roam\94
51340 +
51341 +Command
51342 + wmiconfig eth1 --startscan <scan type> <forcefgscan> 0
51343 + <homeDwellTime> <forceScanInterval>
51344 +
51345 +Command Parameters
51346 + UINT8 scanType
51347 + WMI_SCAN_TYPE
51348 +
51349 +Command Values
51350 + {
51351 + WMI_LONG_SCAN =0x0
51352 + Requests a full scan
51353 + WMI_SHORT_SCAN =0x1
51354 + Requests a short scan
51355 + } WMI_SCAN_TYPE
51356 +
51357 + A_BOOL forceFgScan
51358 + forceFgScan
51359 + = 0
51360 + Disable the foreground scan
51361 +
51362 + forceFgScan
51363 + = 1
51364 + Forces a foreground scan
51365 +
51366 + A_UINT32 homeDwellTime
51367 + Maximum duration in the home
51368 + channel (in ms)
51369 +
51370 + A_UINT32 forceScanInterval
51371 + Time interval between scans (in ms)
51372 +
51373 + A_UINT32 scanType
51374 + WMI_SCAN_TYPE
51375 +
51376 +Reset Value
51377 + Disable forcing foreground scan
51378 +
51379 +Restrictions
51380 + isLegacy field will no longer be supported (pass as 0 for now)
51381 +
51382 +
51383 +=====================================================================
51384 +
51385 +Name
51386 + SYNCHRONIZE
51387 +
51388 +Synopsis
51389 + The host uses this command to force a synchronization point between the command
51390 + and data paths
51391 +
51392 +Command
51393 + TBD
51394 +
51395 +Command Parameters
51396 + None
51397 +
51398 +
51399 +
51400 +Command Values
51401 + None
51402 +
51403 +
51404 +
51405 +Reset Values
51406 + None
51407 +
51408 +
51409 +
51410 +Restrictions
51411 + None
51412 +
51413 +
51414 +=====================================================================
51415 +
51416 +Name
51417 + TARGET_ERROR_REPORT_BITMASK
51418 +
51419 +Synopsis
51420 + Allows the host to control \93ERROR_REPORT\94 events from the AR6000 device.
51421 +
51422 + If error reporting is disabled for an error type, a count of errors of that type is
51423 + maintained by the device.
51424 +
51425 + If error reporting is enabled for an error type, an \93ERROR_REPORT\94 event is
51426 + sent when an error occurs and the error report bit is cleared.
51427 +
51428 + Error counts for each error type are available through the \93GET_TARGET_STATS\94
51429 + command.
51430 +
51431 +Command
51432 + wmiconfig eth1 --setErrorReportingBitmask
51433 +
51434 +Command Parameters
51435 + UINT32 bitmask
51436 + Represents the set of
51437 + WMI_TARGET_ERROR_VAL error types
51438 + enabled for reporting
51439 +
51440 +Command Values
51441 + {
51442 + WMI_TARGET_PM_ERR_FAIL = 0x00000001
51443 + Power save fails (only two cases):
51444 + Retry out of null function/QoS null
51445 + function to associated AP for PS
51446 + indication'
51447 + Host changes the PS setting when
51448 + STA is off home channel
51449 +
51450 + WMI_TARGET_KEY_NOT_FOUND = 0x00000002
51451 + No cipher key
51452 + WMI_TARGET_DECRYPTION_ERR = 0x00000004
51453 + Decryption error
51454 + WMI_TARGET_BMISS = 0x00000008
51455 + Beacon miss
51456 + WMI_PSDISABLE_NODE_JOIN = 0x00000010
51457 + A non-PS-enabled STA joined the
51458 + PS-enabled network
51459 + WMI_TARGET_COM_ERR = 0x00000020
51460 + Host/target communication error
51461 + WMI_TARGET_FATAL_ERR = 0x00000040
51462 + Fatal error
51463 + } WMI_TARGET_ERROR_VAL
51464 +
51465 +Reset Values
51466 + Bitmask is 0, and all error reporting is disabled
51467 +
51468 +Restrictions
51469 + None
51470 +
51471 +
51472 +=====================================================================
51473 +WMI Events
51474 +
51475 +Event
51476 + Description
51477 + Page
51478 +
51479 +
51480 +BSSINFO
51481 + Contains information describing BSSs collected during a scan
51482 +
51483 +CAC_EVENTID
51484 + Indicates signalling events in admission control
51485 +
51486 +CMDERROR
51487 + The AR6000 device encounters an error while attempting to process
51488 + a command
51489 +
51490 +CONNECT
51491 + The device has connected to a wireless network
51492 +
51493 +DISCONNECT
51494 + The device lost connectivity with a wireless network
51495 +
51496 +ERROR_REPORT
51497 + An error has occurred for which the host previously requested
51498 + notification with the command
51499 + \93TARGET_ERROR_REPORT_BITMASK\94
51500 +
51501 +EXTENSION
51502 + WMI extension event
51503 +
51504 +GET_PMKID_LIST_EVENT
51505 + Created in response to a \93GET_PMKID_LIST_CMD\94 command
51506 +
51507 +GET_WOW_LIST_EVENT
51508 + Response to the wmiconfig \93GET_WOW_LIST\94 command to
51509 + retrieve the configured WoW patterns
51510 +
51511 +NEIGHBOR_REPORT
51512 + Neighbor APs that match the current profile were detected
51513 +
51514 +OPT_RX_FRAME_EVENT
51515 + (Special feature) informs the host of the reception of a special frame
51516 +
51517 +PSTREAM_TIMEOUT
51518 + A prioritized stream has been idle for a specified interval
51519 +
51520 +READY
51521 + The AR6000 device is ready to accept commands
51522 +
51523 +REGDOMAIN
51524 + The regulatory domain has changed
51525 +
51526 +REPORT_ROAM_DATA_EVENT
51527 + Reports the roam time calculations made by the device
51528 + (generated with a special build)
51529 + \97
51530 +
51531 +REPORT_STATISTICS
51532 + Reply to a \93GET_TARGET_STATS\94 command
51533 +
51534 +ROAM_TBL_EVENT
51535 + Reports the roam table
51536 +
51537 +RSSI_THRESHOLD
51538 + Signal strength from the connected AP has crossed the threshold
51539 + defined in the \93RSSI_THRESHOLD_PARAMS\94 command
51540 +
51541 +SCAN_COMPLETE_EVENT
51542 + A scan has completed (added status SCAN_ABORTED in release 2.0)
51543 +
51544 +TEST_EVENT
51545 + Event generated by the TCMD
51546 +
51547 +TKIP_MICERROR
51548 + TKIP MIC errors were detected
51549 +
51550 +=====================================================================
51551 +
51552 +Name
51553 + BSSINFO
51554 +
51555 +Synopsis
51556 + Contains information describing one or more BSSs as collected during a scan.
51557 + Information includes the BSSID, SSID, RSSI, network type, channel, supported rates,
51558 + and IEs. BSSINFO events are sent only after the device receives a beacon or probe-
51559 + response frame that pass the filter specified in the \93SET_BSS_FILTER\94 command.
51560 + BSSINFO events consist of a small header followed by a copy of the beacon or probe
51561 + response frame. The 802.11 header is not present. For formats of beacon and probe-
51562 + response frames please consult the IEEE 802.11 specification.
51563 +
51564 + The beacons or probe responses containing the IE specified by the
51565 + WMI_BSS_FILTER_CMD are passed to the host through the
51566 + WMI_BSSINFO_EVENT. The event carries a 32-bit bitmask that indicates the IEs that
51567 + were detected in the management frame. The frame type field has been extended to
51568 + indicate action management frames. This would be helpful to route these frames
51569 + through the same event mechanism as used by the beacon processing function.
51570 +
51571 + If the bssFilter in the SET_BSS_FILTER matches, then the ieMask is not relevant
51572 + because the BSSINFO event is sent to the host. If the bssFilter doesnot match in the
51573 + beacons/probe respones, then the ieMask match dictates whether the BSSINFO
51574 + event is sent to the host. In the case of action management frames, the ieMask is the
51575 + filter that is applied.
51576 +
51577 +Event ID
51578 + 0x1004
51579 +
51580 +Event Parameters
51581 + typedef struct {
51582 + A_UINT16 channel;
51583 + Specifies the frequency (in MHz) where the
51584 + frame was received
51585 + A_UINT8 frameType;
51586 + A WMI_BI_FTYPE value
51587 + A_UINT8 snr;
51588 + A_INT16 rssi;
51589 + Indicates signal strength
51590 + A_UINT8 bssid[ATH_MAC_LEN];
51591 + A_UINT32 ieMask;
51592 + } _ATTRIB_PACK_WMI_BSS_INFO_HDR;
51593 +
51594 + Beacon or Probe Response Frame
51595 +
51596 +Event Values
51597 + {
51598 + BEACON_FTYPE = 0x1
51599 + Indicates a beacon frame
51600 + PROBERESP_FTYPE
51601 + Indicates a probe response frame
51602 + ACTION_MGMT_FTYPE
51603 + } WMI_BI_FTYPE
51604 +
51605 +=====================================================================
51606 +
51607 +Name
51608 + CAC_EVENTID
51609 +
51610 +Synopsis
51611 + Indicates signalling events in admission control. Events are generated when
51612 + admission is accepted, rejected, or deleted by either the host or the AP. If the AP does
51613 + not respond to an admission request within a timeout of 500 ms, an event is
51614 + generated to the host.
51615 +
51616 +Event ID
51617 + 0x1011
51618 +
51619 +Event Parameters
51620 + UINT8
51621 + ac
51622 + Access class pertaining to the
51623 +signalling
51624 +
51625 + UINT8 cac_indication
51626 + Type of indication; indications are
51627 + listed in WMI_CAC_INDICATION
51628 +
51629 + UINT8 statusCode
51630 + AP response status code for a
51631 + request
51632 +
51633 + UINT8 tspecSuggestion[63]
51634 + Suggested TSPEC from AP
51635 +
51636 +Event Values
51637 + {
51638 + CAC_INDICATION_ADMISSION = 0x00
51639 + CAC_INDICATION_ADMISSION_RESP = 0x01
51640 + CAC_INDICATION_DELETE = 0x02
51641 + CAC_INDICATION_NO_RESP = 0x03
51642 + } WMI_CAC_INDICATION
51643 +
51644 +
51645 +=====================================================================
51646 +
51647 +
51648 +Name
51649 + CMDERROR
51650 +
51651 +Synopsis
51652 + Indicates that the AR6000 device encountered an error while attempting to process a
51653 + command. This error is fatal and indicates that the device requires a reset.
51654 +
51655 +Event ID
51656 + 0x1005
51657 +
51658 +Event Parameters
51659 + UINT16 commandId
51660 + Corresponds to the command which generated
51661 + the error
51662 + UINT8 errorCode
51663 + A WMI_ERROR_CODE value
51664 +
51665 +Event Values
51666 + {
51667 + INVALID_PARAM = 1
51668 + Invalid parameter
51669 + ILLEGAL_STATE = 2
51670 + Illegal state
51671 + INTERNAL_ERROR = 3
51672 + Internal Error
51673 + All other values reserved
51674 + } WMI_ERROR_CODE
51675 +
51676 +
51677 +=====================================================================
51678 +
51679 +
51680 +Name
51681 + CONNECT
51682 +
51683 +Synopsis
51684 + Signals that the AR6000 connected to a wireless network. Connection occurs due to a
51685 + \93CONNECT\94 command or roaming to a new AP. For infrastructure networks, shows
51686 + that the AR6000 successfully performed 802.11 authentication and AP association.
51687 +
51688 +Event ID
51689 + 0x1002
51690 +
51691 +Event Parameters
51692 + UINT16 channel
51693 + Channel frequency (in MHz) of the network the
51694 + AR6000 are connected to
51695 +
51696 + UINT8 bssid[6]
51697 + MAC address of the AP the AR6000 are
51698 + connected to or the BSSID of the ad hoc
51699 + network
51700 +
51701 + UINT16 listenInterval
51702 + Listen interval (in Kms) that the AR6000 are
51703 + using
51704 +
51705 + UINT 8 beaconIeLen
51706 + Length (in bytes) of the beacon IEs
51707 +
51708 + UINT8 assocInfo
51709 + Pointer to an array containing beacon IEs,
51710 + followed first by association request IEs then by
51711 + association response IEs
51712 +
51713 + UINT8 assocReqLen
51714 + Length (in bytes) of the assocReqIEs array
51715 +
51716 + UINT8 assocRespLen
51717 + Length (in bytes) of the assocRespIEs array
51718 +
51719 +Event Values
51720 + None defined
51721 +
51722 +=====================================================================
51723 +
51724 +
51725 +Name
51726 + DISCONNECT
51727 +
51728 +Synopsis
51729 + Signals that the AR6000 device lost connectivity with the wireless network.
51730 + DISCONENCT is generated when the device fails to complete a \93CONNECT\94
51731 + command or as a result of a transition from a connected state to disconnected state.
51732 +
51733 + After sending the \93DISCONNECT\94 event the device continually tries to re-establish
51734 + a connection. A LOST_LINK occurs when STA cannot receive beacons within the
51735 + specified time for the SET_BMISS_TIME command.
51736 +
51737 +Event ID
51738 + 0x1003
51739 +
51740 +Event Parameters
51741 + UINT8 disconnect
51742 + Reason
51743 + A WMI_DISCONNECT_REASON value
51744 +
51745 + UINT8 bssid[6]
51746 + Indicates which BSS the device was connected to
51747 +
51748 + UINT8 assocRespLen
51749 + Length of the 802.11 association response frame
51750 + that triggered this event, or 0 if not applicable
51751 +
51752 + UINT8 assocInfo[assocRespLen]
51753 + Copy of the 802.11 association response frame
51754 +
51755 +Event Values
51756 + {
51757 + NO_NETWORK_AVAIL =0x01
51758 + Indicates that the device was unable to
51759 + establish or find the desired network
51760 + LOST_LINK =0x02
51761 + Indicates the devices is no longer receiving
51762 + beacons from the BSS it was previously
51763 + connected to
51764 +
51765 + DISCONNECT_CMD =0x03
51766 + Indicates a \93DISCONNECT\94 command was
51767 + processed
51768 + BSS_DISCONNECTED =0x04
51769 + Indicates the BSS explicitly disconnected the
51770 + device. Possible mechanisms include the AP
51771 + sending 802.11 management frames
51772 + (e.g., disassociate or deauthentication
51773 + messages).
51774 + AUTH_FAILED =0x05
51775 + Indicates that the device failed 802.11
51776 + authentication with the BSS
51777 + ASSOC_FAILED =0x06
51778 + Indicates that the device failed 802.11
51779 + association with the BSS
51780 + NO_RESOURCES_AVAIL =0x07
51781 + Indicates that a connection failed because the
51782 + AP had insufficient resources to complete the
51783 + connection
51784 + CSERV_DISCONNECT =0x08
51785 + Indicates that the device\92s connection services
51786 + module decided to disconnect from a BSS,
51787 + which can happen for a variety of reasons (e.g.,
51788 + the host marks the current connected AP as a
51789 + bad AP).
51790 + INVALID_PROFILE =0x0A
51791 + Indicates that an attempt was made to
51792 + reconnect to a BSS that no longer matches the
51793 + current profile
51794 + All other values are reserved
51795 + } WMI_DISCONNECT_REASON
51796 +
51797 +
51798 +=====================================================================
51799 +
51800 +
51801 +Name
51802 + ERROR_REPORT
51803 +
51804 +Synopsis
51805 + Signals that a type of error has occurred for which the host previously requested
51806 + notification through the \93TARGET_ERROR_REPORT_BITMASK\94 command.
51807 +
51808 +Event ID
51809 + 0x100D
51810 +
51811 +Event Parameters
51812 + UINT32 errorVal
51813 + WMI_TARGET_ERROR_VAL value. See
51814 + \93TARGET_ERROR_REPORT_BITMASK\94.
51815 +
51816 +Event Values
51817 + errorVal
51818 + = 0x00000001
51819 + Power save fails
51820 +
51821 + = 0x00000002
51822 + No cipher key
51823 +
51824 + = 0x00000004
51825 + Decryption error
51826 +
51827 + = 0x00000008
51828 + Beacon miss
51829 +
51830 + = 0x00000010
51831 + A non-power save disabled node has joined
51832 + the PS-enabled network
51833 +
51834 +
51835 +=====================================================================
51836 +
51837 +
51838 +Name
51839 + EXTENSION
51840 +
51841 +Synopsis
51842 + The WMI is used mostly for wireless control messages to a wireless module that
51843 + apply to wireless module management regardless of the target platform
51844 + implementation. However, some events peripherally related to wireless management
51845 + are desired during operation. These wireless extension events may be platform-
51846 + specific or implementation-dependent. See \93WMI Extension Commands\94
51847 +
51848 +
51849 +Event ID
51850 + 0x1010
51851 +
51852 +
51853 +=====================================================================
51854 +
51855 +
51856 +Name
51857 + GET_PMKID_LIST_EVENT
51858 +
51859 +Synopsis
51860 + Generated by firmware in response to a \93GET_PMKID_LIST_CMD\94 command.
51861 +
51862 +Event Parameters
51863 + typedef struct {
51864 + A_UINT32 numPMKID;
51865 + Contains the number of PMKIDs in the reply
51866 + WMI_PMKID pmkidList[1];
51867 + } __ATTRIB_PACK WMI_PMKID_LIST_REPLY;
51868 +
51869 +Event Values
51870 + None
51871 +
51872 +
51873 +=====================================================================
51874 +
51875 +
51876 +Name
51877 + GET_WOW_LIST_EVENT
51878 +
51879 +Synopsis
51880 + Response to the wmiconfig \96getwowlist command to retrieve the configured Wake on
51881 + Wireless patterns
51882 +
51883 +Event ID
51884 + 0x10018
51885 +
51886 +Event Parameters
51887 + {
51888 +
51889 + A_UINT8 num_filters
51890 + Total number of patterns in the list
51891 + A_UINT8 this_filter_num
51892 + The filter number
51893 + A_UINT8 wow_mode
51894 + Shows whether WoW is enabled or disabled
51895 + A_UINT8 host_mode
51896 + Shows whether the host is asleep or awake
51897 + WOW_FILTER wow_filters[1]
51898 + List of WoW filters (pattern and mask data bytes)
51899 + } WMI_GET_WOW_LIST_REPLY;
51900 +
51901 + {
51902 + Each wow_filter_list element shows:
51903 + A_UINT8 wow_valid_filter
51904 + Whether the filter is valid
51905 + A_UINT8 wow_filter_list_id
51906 + Filter List ID (23 = default)
51907 + A_UINT8 wow_filter_size
51908 + Size in bytes of the filter
51909 + A_UINT8 wow_filter_offset
51910 + Offset of the pattern to search in the data packet
51911 + A_UINT8 wow_filter_mask[MASK_SIZE]
51912 + The mask to be applied to the pattern
51913 + A_UINT8 wow_filter_pattern[WOW_PATTERN_SIZE]
51914 + The pattern that to match to wake up the host
51915 + } WOW_FILTER
51916 +
51917 +Event Values
51918 + None
51919 +
51920 +=====================================================================
51921 +
51922 +
51923 +
51924 +Name
51925 + NEIGHBOR_REPORT
51926 +
51927 +Synopsis
51928 + Indicates the existence of neighbor APs that match the current profile. The host uses
51929 + this event to populate the PMKID cache on the AR6000 and/or to perform
51930 + preauthentication. This event is only generated in infrastructure mode.
51931 +
51932 + A total of numberOfAps pairs of bssid/bssFlags exist, one pair for each AP.
51933 +
51934 +Event ID
51935 + 0x1008
51936 +
51937 +Event Parameters
51938 + UINT8 numberOfAps
51939 + The number of APs reported about in
51940 + this event
51941 + {
51942 + UINT8 bssid[6]
51943 + MAC address of a neighbor AP
51944 + UINT8 bssFlags
51945 + A WMI_BSS_FLAGS value
51946 + }[numberOfAps]
51947 +
51948 +
51949 +Event Values
51950 + {
51951 + WMI_DEFAULT_BSS_FLAGS = 0
51952 + Logical OR of 1 or more
51953 + WMI_BSS_FLAGS
51954 + WMI_PREAUTH_CAPABLE_BSS
51955 + = 1
51956 + Indicates that this AP is capable of
51957 + preauthentication
51958 + WMI_PMKID_VALID_BSS
51959 + = 2
51960 + Indicates that the AR6000 have a
51961 + valid pairwise master key for this AP
51962 + } WMI_BSS_FLAGS
51963 +
51964 +
51965 +=====================================================================
51966 +
51967 +
51968 +
51969 +Name
51970 + OPT_RX_FRAME_EVENT
51971 +
51972 +Synopsis
51973 + Special feature, informs host of the reception of a special frame.
51974 +
51975 +Event ID
51976 + 0x100E
51977 +
51978 +Event Parameters
51979 + {
51980 + A_UINT16 channel;
51981 + A_UINT8 frameType;
51982 + A_INT8 snr;
51983 + A_UINT8 srcAddr[ATH_MAC_LEN];
51984 + A_UINT8 bssid[ATH_MAC_LEN];
51985 + }WMI_OPT_RX_INFO_HDR
51986 +
51987 +Event Values
51988 + None
51989 +
51990 +=====================================================================
51991 +
51992 +
51993 +
51994 +Name
51995 + PSTREAM_TIMEOUT
51996 +
51997 +Synopsis
51998 + Indicates that a priority stream that got created as a result of priority-marked data
51999 + flow (priority marked in IP TOS) being idle for the default inactivity interval period
52000 + (specified in the \93CREATE_PSTREAM\94 command) used for priority streams created
52001 + implicitly by the driver. This event is not indicated for user-created priority streams.
52002 + User-created priority streams exist until the users delete them explicitly. They do not
52003 + timeout due to data inactivity.
52004 +
52005 +Event ID
52006 + 0x1007
52007 +
52008 +Event Parameters
52009 + A_UINT8
52010 + trafficClass
52011 + Indicated the traffic class of priority
52012 + stream that timed out
52013 +
52014 +Event Values
52015 + {
52016 + WMM_AC_BE = 0
52017 + Best effort
52018 + WMM_AC_BK = 1
52019 + Background
52020 + WMM_AC_VI = 2
52021 + Video
52022 + WMM_AC_VO = 3
52023 + Voice
52024 + } TRAFFIC CLASS
52025 +
52026 +
52027 +=====================================================================
52028 +
52029 +Name
52030 + READY
52031 +
52032 +Synopsis
52033 + Indicates that the AR6000 device is prepared to accept commands. It is sent once after
52034 + power on or reset. It also indicates the MAC address of the device.
52035 +
52036 +Event ID
52037 + 0x1001
52038 +
52039 +Event Parameters
52040 + UINT8 macAddr[6]
52041 + Device MAC address
52042 + UINT8 phyCapability
52043 + A WMI_PHY_CAPABILITY value. Indicates the
52044 + capabilities of the device wireless module\92s radio
52045 +
52046 +Event Values
52047 + {
52048 + WMI_11A_CAPABILITY = 1
52049 + WMI_11G_CAPABILITY = 2
52050 + WMI_11AG_CAPABILITY = 3
52051 + } WMI_PHY_CAPABILITY
52052 +
52053 +
52054 +=====================================================================
52055 +
52056 +Name
52057 + REGDOMAIN
52058 +
52059 +Synopsis
52060 + Indicates that the regulatory domain has changed. It initially occurs when the
52061 + AR6000 device reads the board data information. The regulatory domain can also
52062 + change when the device is a world-mode SKU. In this case, the regulatory domain is
52063 + based on the country advertised by APs per the IEEE 802.11d specification. A
52064 + potential side effect of a regulatory domain change is a change in the list of available
52065 + channels. Any channel restrictions that exist as a result of a previous
52066 + \93SET_CHANNEL_PARAMETERS\94 command are lifted.
52067 +
52068 +Event ID
52069 + 0x1006
52070 +
52071 +Event Parameters
52072 + UINT32 regDomain
52073 + The range of 0x0000 \96 0x00FF
52074 + corresponds to an ISO country code.
52075 +
52076 + Other regCodes are reserved for world
52077 + mode settings and specific regulatory
52078 + domains.
52079 +
52080 +Event Values
52081 + None
52082 +
52083 +
52084 +=====================================================================
52085 +
52086 +
52087 +
52088 +Name
52089 + REPORT_STATISTICS
52090 +
52091 +Synopsis
52092 + A reply to a \93GET_TARGET_STATS\94 command.
52093 +
52094 +Event ID
52095 + 0x100B
52096 +
52097 +Event Parameters
52098 + When the statistics are sent to the host, the AR6001 clear them so that a new set of
52099 + statistics are collected for the next report.
52100 +
52101 + UINT32 tx_packets
52102 + UINT32 tx_bytes
52103 + UINT32 tx_unicast_pkts
52104 + UINT32 tx_unicast_bytes
52105 + UINT32 tx_multicast_pkts
52106 + UINT32 tx_multicast_bytes
52107 + UINT32 tx_broadcast_pkts
52108 + UINT32 tx_broadcast_bytes
52109 + UINT32 tx_rts_success_cnt
52110 + UINT32 tx_packet_per_ac[4]
52111 + Tx packets per AC: [0] = BE, [1] = BK,
52112 + [2] = VI, [3] = VO
52113 + UINT32 tx_errors
52114 + Number of packets which failed Tx, due
52115 + to all failures
52116 + ... REPORT_STATISTICS, continued
52117 + UINT32 tx_failed_cnt
52118 + Number of data packets that failed Tx
52119 + UINT32 tx_retry_cnt
52120 + Number of Tx retries for all packets
52121 + UINT32 tx_rts_fail_cnt
52122 + Number of RTS Tx failed count
52123 + UINT32 rx_packets
52124 + UINT32 rx_bytes
52125 + UINT32 rx_unicast_pkts
52126 + UINT32 rx_unicast_bytes
52127 + UINT32 rx_multicast_pkts
52128 + UINT32 rx_multicast_bytes
52129 + UINT32 rx_broadcast_pkts
52130 + UINT32 rx_broadcast_bytes
52131 + UINT32 rx_fragment_pkt
52132 + Number of fragmented packets received
52133 + UINT32 rx_errors
52134 + Number of Rx errors due to all failures
52135 + UINT32 rx_crcerr
52136 + Number of Rx errors due to CRC errors
52137 + UINT32 rx_key_cache_miss
52138 + Number of Rx errors due to a key not
52139 + being plumbed
52140 + UINT32 rx_decrypt_err
52141 + Number of Rx errors due to decryption
52142 + failure
52143 + UINT32 rx_duplicate_frames
52144 + Number of duplicate frames received
52145 + UINT32 tkip_local_mic_failure
52146 + Number of TKIP MIC errors detected
52147 + UINT32 tkip_counter_measures_invoked
52148 + Number of times TKIP countermeasures
52149 + were invoked
52150 + UINT32 tkip_replays
52151 + Number of frames that replayed a TKIP
52152 + encrypted frame received earlier
52153 + UINT32 tkip_format_errors
52154 + Number of frames that did not conform
52155 + to the TKIP frame format
52156 + UINT32 ccmp_format_errors
52157 + Number of frames that did not conform
52158 + to the CCMP frame format
52159 + UINT32 ccmp_replays
52160 + Number of frames that replayed a CCMP
52161 + encrypted frame received earlier
52162 + UINT32 power_save_failure_cnt
52163 + Number of failures that occurred when
52164 + the AR6001 could not go to sleep
52165 + UINT32 cs_bmiss_cnt
52166 + Number of BMISS interrupts since
52167 + connection
52168 + UINT32 cs_lowRssi_cnt
52169 + Number of the times the RSSI went below
52170 + the low RSSI threshold
52171 + UINT16 cs_connect_cnt
52172 + Number of connection times
52173 + UINT16 cs_disconnect_cnt
52174 + Number of disconnection times
52175 + UINT8 cs_aveBeacon_rssi
52176 + The current averaged value of the RSSI
52177 + from the beacons of the connected BSS
52178 + UINT8 cs_lastRoam_msec
52179 + Time that the last roaming took, in ms.
52180 + This time is the difference between
52181 + roaming start and actual connection.
52182 +
52183 +Event Values
52184 + None defined
52185 +
52186 +
52187 +=====================================================================
52188 +
52189 +Name
52190 + ROAM_TBL_EVENT
52191 +
52192 +Synopsis
52193 + Reports the roam table, which contains the current roam mode and this information
52194 + for every BSS:
52195 +
52196 +Event ID
52197 + 0x100F
52198 +
52199 +Event Parameters
52200 + A_UINT8 bssid[ATH_MAC_LEN];
52201 + BSSID
52202 + A_UINT8 rssi
52203 + Averaged RSSI
52204 + A_UINT8 rssidt
52205 + Change in RSSI
52206 + A_UINT8 last_rssi
52207 + Last recorded RSSI
52208 + A_UINT8 roam_util
52209 + Utility value used in roaming decision
52210 + A_UINT8 util
52211 + Base utility with the BSS
52212 + A_UINT8 bias
52213 + Host configured for this BSS
52214 +
52215 +Event Values
52216 + roamMode
52217 + Current roam mode
52218 +
52219 + = 1
52220 + RSSI based roam
52221 +
52222 + = 2
52223 + Host bias-based roam
52224 +
52225 + = 3
52226 + Lock to the current BSS
52227 +
52228 + = 4
52229 + Autonomous roaming disabled
52230 +
52231 +
52232 +=====================================================================
52233 +
52234 +Name
52235 + RSSI_THRESHOLD
52236 +
52237 +Synopsis
52238 + Alerts the host that the signal strength from the connected AP has crossed a
52239 + interesting threshold as defined in a previous \93RSSI_THRESHOLD_PARAMS\94
52240 + command.
52241 +
52242 +Event ID
52243 + 0x100C
52244 +
52245 +Event Parameters
52246 + UINT8 range
52247 + A WMI_RSSI_THRESHOLD_VAL
52248 + value, which indicates the range of
52249 + the average signal strength
52250 +
52251 +Event Values
52252 + {
52253 + WMI_RSSI_LOWTHRESHOLD_BELOW_LOWERVAL = 1
52254 + WMI_RSSI_LOWTHRESHOLD_LOWERVAL = 2
52255 + WMI_RSSI_LOWTHRESHOLD_UPPERVAL = 3
52256 + WMI_RSSI_HIGHTHRESHOLD_LOWERVAL = 4
52257 + WMI_RSSI_HIGHTHRESHOLD_HIGHERVAL = 5
52258 + } WMI_RSSI_THRESHOLD_VAL
52259 +
52260 +
52261 +=====================================================================
52262 +
52263 +Name
52264 + SCAN_COMPLETE_EVENT
52265 +
52266 +Synopsis
52267 + Indicates the scan status. if the Scan was not completed, this event is generated with
52268 + the status A_ECANCELED.
52269 +
52270 +Event ID
52271 + 0x100A
52272 +
52273 +Event Parameters
52274 + A_UINT8 scanStatus
52275 +
52276 +Event Values
52277 + {
52278 + #define SCAN_ABORTED 16
52279 + #define SCAN_COMPLETED 0
52280 + A_UINT8 scanStatus
52281 + A_OK or A_ECANCELED
52282 + } WMI_SCAN_COMPLETE_EVENT;
52283 +
52284 +
52285 +=====================================================================
52286 +
52287 +Name
52288 + TEST_EVENT
52289 +
52290 +Synopsis
52291 + The TCMD application uses a single WMI event (WMI_TEST_EVENTID) to
52292 + communicate events from target to host. The events are parsed by the TCMD
52293 + application and WMI layer is oblivious of it.
52294 +
52295 +Event ID
52296 + 0x1016
52297 +
52298 +Event Parameters
52299 + WMI_TEST_EVENTID
52300 +
52301 +
52302 +Event Values
52303 + None
52304 +
52305 +
52306 +=====================================================================
52307 +
52308 +
52309 +
52310 +Name
52311 + TKIP_MICERR
52312 +
52313 +Synopsis
52314 + Indicates that TKIP MIC errors were detected.
52315 +
52316 +Event ID
52317 + 0x1009
52318 +
52319 +Event Parameters
52320 + UINT8 keyid
52321 + Indicates the TKIP key ID
52322 +
52323 + UINT8 ismcast
52324 + 0 = Unicast
52325 + 1 = Multicast
52326 +
52327 +Event Values
52328 + See event parameters
52329 +
52330 +=====================================================================
52331 +
52332 +WMI Extension Commands
52333 +
52334 +The WMI EXTENSION command is used to multiplex a collection of
52335 +commands that:
52336 +
52337 + Are not generic wireless commands
52338 + May be implementation-specific
52339 + May be target platform-specific
52340 + May be optional for a host implementation
52341 +
52342 + An extension command is sent to the AR6000 targets like any other WMI
52343 +command message and uses the WMI_EXTENSION. The first field of the
52344 +payload for this EXTENSION command is another commandId, sometimes
52345 +called the subcommandId, which indicates which extension command is
52346 +being used. A subcommandId-specific payload follows the subcommandId.
52347 +
52348 +All extensions (subcommandIds) are listed in the header file include/wmix.h.
52349 +See also \93WMI Extension Events\94 on page B-58.
52350 +
52351 +
52352 +WMI Extension Commands
52353 +
52354 +
52355 +GPIO_INPUT_GET
52356 + Read GPIO pins configured for input
52357 +
52358 +GPIO_INTR_ACK
52359 + Acknowledge and re-arm GPIO interrupts reported earlier
52360 +
52361 +GPIO_OUTPUT_SET
52362 + Manage output on GPIO pins configured for output
52363 +
52364 +GPIO_REGISTER_GET
52365 + Read an arbitrary GPIO register
52366 +
52367 +GPIO_REGISTER_SET
52368 + Dynamically change GPIO configuration
52369 +
52370 +SET_LQTHRESHOLD
52371 + Set link quality thresholds; the sampling happens at every unicast
52372 + data frame Tx, if certain thresholds are met, and corresponding
52373 + events are sent to the host
52374 +
52375 +
52376 +=====================================================================
52377 +
52378 +Name
52379 + GPIO_INPUT_GET
52380 +
52381 +Synopsis
52382 + Allows the host to read GPIO pins that are configured for input. The values read are
52383 + returned through a \93GPIO_DATA\94 extension event.
52384 +
52385 +NOTE: Support for GPIO is optional.
52386 +
52387 +Command
52388 + N/A
52389 +
52390 +Command Parameters
52391 + None
52392 +
52393 +
52394 +
52395 +Reply Parameters
52396 + None
52397 +
52398 +
52399 +Reset Value
52400 + None
52401 +
52402 +
52403 +
52404 +Restrictions
52405 + None
52406 +
52407 +=====================================================================
52408 +
52409 +
52410 +Name
52411 + GPIO_INTR_ACK
52412 +
52413 +Synopsis
52414 + The host uses this command to acknowledge and to re-arm GPIO interrupts reported
52415 + through an earlier \93GPIO_INTR\94 extension event. A single \93GPIO_INTR_ACK\94
52416 + command should be used to acknowledge all GPIO interrupts that the host knows to
52417 + be outstanding (if pending interrupts are not acknowledged through
52418 + \93GPIO_INTR_ACK\94, another \93GPIO_INTR\94 extension event is raised).
52419 +
52420 +NOTE: Support for GPIO is optional.
52421 +
52422 +Command
52423 + N/A
52424 +
52425 +Command Parameters
52426 + UINT32 ack_mask
52427 + A mask of interrupting GPIO pins (e.g., ack_mask
52428 + bit [3] acknowledges an interrupt from the pin GPIO3).
52429 +
52430 +Command Values
52431 + None
52432 +
52433 +Reset Value
52434 + None
52435 +
52436 +Restrictions
52437 + The host should acknowledge only interrupts about which it was notified.
52438 +
52439 +
52440 +=====================================================================
52441 +
52442 +Name
52443 + GPIO_OUTPUT_SET
52444 +
52445 +Synopsis
52446 + Manages output on GPIO pins configured for output.
52447 +
52448 + Conflicts between set_mask and clear_mask or enable_mask and disable_mask result
52449 + in undefined behavior.
52450 +
52451 +NOTE: Support for GPIO is optional.
52452 +
52453 +Command
52454 + N/A
52455 +
52456 +Command Parameters
52457 + UINT32 set_mask
52458 + Specifies which pins should drive a 1 out
52459 + UINT32 clear_mask
52460 + Specifies which pins should drive a 0 out
52461 + UINT32 enable_mask
52462 + Specifies which pins should be enabled for output
52463 + UINT32 disable_mask
52464 + Specifies which pins should be disabled for output
52465 +
52466 +Command Values
52467 + None
52468 +
52469 +
52470 +Reset Value
52471 + None
52472 +
52473 +
52474 +Restrictions
52475 + None
52476 +
52477 +
52478 +
52479 +=====================================================================
52480 +
52481 +
52482 +Name
52483 + GPIO_REGISTER_GET
52484 +
52485 +Synopsis
52486 + Allows the host to read an arbitrary GPIO register. It is intended for use during
52487 + bringup/debug. The target responds to this command with a \93GPIO_DATA\94 event.
52488 +
52489 +NOTE: Support for GPIO is optional.
52490 +
52491 +Command
52492 + N/A
52493 +
52494 +Command Parameters
52495 + UINT32
52496 + gpioreg_id
52497 + Specifies a GPIO register identifier, as defined
52498 +in include/AR6000/AR6000_gpio.h
52499 +
52500 +Reply Parameters
52501 + None
52502 +
52503 +Reset Value
52504 + N/A
52505 +
52506 +Restrictions
52507 + None
52508 +
52509 +
52510 +=====================================================================
52511 +
52512 +Name
52513 + GPIO_REGISTER_SET
52514 +
52515 +Synopsis
52516 + Allows the host to dynamically change GPIO configuration (usually handled
52517 + statically through the GPIO configuration DataSet).
52518 +
52519 +NOTE: Support for GPIO is optional.
52520 +
52521 +Command
52522 + N/A
52523 +
52524 +Command Parameters
52525 + UINT32 gpioreg_id
52526 + Specifies a GPIO register identifier, as defined in
52527 + include/AR6000/AR6000_gpio.h
52528 + UINT32 value
52529 + Specifies a value to write to the specified
52530 + GPIO register
52531 +
52532 +Command Values
52533 + None
52534 +
52535 +
52536 +Reset Value
52537 + Initial hardware configuration is as defined in the AR6001 or AR6002 ROCmTM
52538 + Single-Chip MAC/BB/Radio for 2.4/5 GHz Embedded WLAN Applications data sheet. This
52539 + configuration is modified by the GPIO Configuration DataSet, if one exists.
52540 +
52541 +Restrictions
52542 + None
52543 +
52544 +
52545 +=====================================================================
52546 +
52547 +
52548 +Name
52549 + SET_LQTHRESHOLD
52550 +
52551 +Synopsis
52552 + Set link quality thresholds, the sampling happens at every unicast data frame Tx, if
52553 + certain threshold is met, corresponding event will be sent to host.
52554 +
52555 +Command
52556 + wmiconfig eth1 --lqThreshold <enable> <upper_threshold_1>...
52557 + <upper_threshold_4> <lower_threshold_1>... <lower_threshold_4>
52558 +
52559 +Command Parameters
52560 + A_UINT8 enable;
52561 + A_UINT8 thresholdAbove1_Val;
52562 + A_UINT8 thresholdAbove2_Val;
52563 + A_UINT8 thresholdAbove3_Val;
52564 + A_UINT8 thresholdAbove4_Val;
52565 + A_UINT8 thresholdBelow1_Val;
52566 + A_UINT8 thresholdBelow2_Val;
52567 + A_UINT8 thresholdBelow3_Val;
52568 + A_UINT8 thresholdBelow4_Val;
52569 +
52570 +Command Values
52571 + enable
52572 + = 0
52573 + Disable link quality sampling
52574 +
52575 + = 1
52576 + Enable link quality sampling
52577 +
52578 +
52579 + thresholdAbove_Val
52580 + [1...4]
52581 + Above thresholds (value in [0,100]), in ascending
52582 + order threshold
52583 +
52584 + Below_Val [1...4] = below thresholds (value
52585 + in [0,100]), in ascending order
52586 +
52587 +Reset Values
52588 + None
52589 +
52590 +Restrictions
52591 + None
52592 +
52593 +=====================================================================
52594 +WMI Extension Events
52595 +
52596 +The WMI EXTENSION event is used for a collection of events that:
52597 +
52598 + Are not generic wireless events
52599 + May be implementation-specific
52600 + May be target platform-specific
52601 + May be optional for a host implementation
52602 +
52603 + An extension event is sent from the AR6000 device targets to the host just like
52604 +any other WMI event message, using the WMI_EXTENSION_EVENTID. The
52605 +first field of the payload for this \93EXTENSION\94 event is another commandId
52606 +(sometimes called the subcommandId) that indicates which \93EXTENSION\94
52607 +event is being used. A subcommandId-specific payload follows the
52608 +subcommandId.
52609 +
52610 +All extensions (subcommandIds) are listed in the header file include/wmix.h.
52611 +See also \93WMI Extension Commands\94 on page B-55.
52612 +
52613 +
52614 +WMI Extension Events
52615 +
52616 +
52617 +GPIO_ACK
52618 + Acknowledges a host set command has been processed by the device
52619 +
52620 +GPIO_DATA
52621 + Response to a host\92s request for data
52622 +
52623 +GPIO_INTR
52624 + Signals that GPIO interrupts are pending
52625 +
52626 +
52627 +=====================================================================
52628 +
52629 +Name
52630 + GPIO_ACK
52631 +
52632 +Synopsis
52633 + Acknowledges that a host set command (either \93GPIO_OUTPUT_SET\94 or
52634 + \93GPIO_REGISTER_SET\94) has been processed by the AR6000 device.
52635 +
52636 +NOTE: Support for GPIO is optional.
52637 +
52638 +Event ID
52639 + N/A
52640 +
52641 +Event Parameters
52642 + None
52643 +
52644 +
52645 +Event Values
52646 + None
52647 +
52648 +=====================================================================
52649 +
52650 +
52651 +Name
52652 + GPIO_DATA
52653 +
52654 +Synopsis
52655 + The AR6000 device uses this event to respond to the host\92s earlier request for data
52656 + (through either a \93GPIO_REGISTER_GET\94 or a \93GPIO_INPUT_GET\94 command).
52657 +
52658 +NOTE: Support for GPIO is optional.
52659 +
52660 +Event ID
52661 + N/A
52662 +
52663 +Event Parameters
52664 + UINT32 value
52665 + Holds the data of interest, which is either a register value
52666 + (in the case of \93GPIO_REGISTER_GET\94) or a mask of
52667 + pin inputs (in the case of \93GPIO_INPUT_GET\94).
52668 + UINT32 reg_id
52669 + Indicates which register was read (in the case of
52670 + \93GPIO_REGISTER_GET\94) or is GPIO_ID_NONE (in the
52671 + case of \93GPIO_INPUT_GET\94)
52672 +
52673 +Event Values
52674 + None
52675 +
52676 +
52677 +=====================================================================
52678 +
52679 +
52680 +
52681 +Name
52682 + GPIO_INTR
52683 +
52684 +Synopsis
52685 + The AR6000 device raises this event to signal that GPIO interrupts are pending.
52686 + These GPIOs may be interrupts that occurred after the last \93GPIO_INTR_ACK\94
52687 + command was issued, or may be GPIO interrupts that the host failed to acknowledge
52688 + in the last \93GPIO_INTR_ACK\94. The AR6000 will not raise another GPIO_INTR
52689 + event until this event is acknowledged through a \93GPIO_INTR_ACK\94 command.
52690 +
52691 +NOTE: Support for GPIO is optional.
52692 +
52693 +Event ID
52694 + N/A
52695 +
52696 +Event Parameters
52697 + UINT32 intr_mask
52698 + Indicates which GPIO interrupts are currently pending
52699 +
52700 + UINT32 input_values
52701 + A recent copy of the GPIO input values, taken at the
52702 + time the most recent GPIO interrupt was processed
52703 +
52704 +Event Values
52705 + None
52706 +
52707 +
52708 +
52709 +=====================================================================
52710 +#endif
52711 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/ar6000/wmi/wmi_host.h linux-2.6.29-rc3.owrt.om/drivers/ar6000/wmi/wmi_host.h
52712 --- linux-2.6.29-rc3.owrt/drivers/ar6000/wmi/wmi_host.h 1970-01-01 01:00:00.000000000 +0100
52713 +++ linux-2.6.29-rc3.owrt.om/drivers/ar6000/wmi/wmi_host.h 2009-05-10 22:27:59.000000000 +0200
52714 @@ -0,0 +1,71 @@
52715 +#ifndef _WMI_HOST_H_
52716 +#define _WMI_HOST_H_
52717 +/*
52718 + * Copyright (c) 2004-2006 Atheros Communications Inc.
52719 + * All rights reserved.
52720 + *
52721 + * This file contains local definitios for the wmi host module.
52722 + *
52723 + * $Id: //depot/sw/releases/olca2.0-GPL/host/wmi/wmi_host.h#1 $
52724 + *
52725 + *
52726 + * This program is free software; you can redistribute it and/or modify
52727 + * it under the terms of the GNU General Public License version 2 as
52728 + * published by the Free Software Foundation;
52729 + *
52730 + * Software distributed under the License is distributed on an "AS
52731 + * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
52732 + * implied. See the License for the specific language governing
52733 + * rights and limitations under the License.
52734 + *
52735 + *
52736 + *
52737 + */
52738 +
52739 +#ifdef __cplusplus
52740 +extern "C" {
52741 +#endif
52742 +
52743 +struct wmi_stats {
52744 + A_UINT32 cmd_len_err;
52745 + A_UINT32 cmd_id_err;
52746 +};
52747 +
52748 +struct wmi_t {
52749 + A_BOOL wmi_ready;
52750 + A_BOOL wmi_numQoSStream;
52751 + A_UINT8 wmi_wmiStream2AcMapping[WMI_PRI_MAX_COUNT];
52752 + WMI_PRI_STREAM_ID wmi_ac2WmiStreamMapping[WMM_NUM_AC];
52753 + A_UINT16 wmi_streamExistsForAC[WMM_NUM_AC];
52754 + A_UINT8 wmi_fatPipeExists;
52755 + void *wmi_devt;
52756 + struct wmi_stats wmi_stats;
52757 + struct ieee80211_node_table wmi_scan_table;
52758 + A_UINT8 wmi_bssid[ATH_MAC_LEN];
52759 + A_UINT8 wmi_powerMode;
52760 + A_UINT8 wmi_phyMode;
52761 + A_UINT8 wmi_keepaliveInterval;
52762 + A_MUTEX_T wmi_lock;
52763 +};
52764 +
52765 +#define WMI_INIT_WMISTREAM_AC_MAP(w) \
52766 +{ (w)->wmi_wmiStream2AcMapping[WMI_BEST_EFFORT_PRI] = WMM_AC_BE; \
52767 + (w)->wmi_wmiStream2AcMapping[WMI_LOW_PRI] = WMM_AC_BK; \
52768 + (w)->wmi_wmiStream2AcMapping[WMI_HIGH_PRI] = WMM_AC_VI; \
52769 + (w)->wmi_wmiStream2AcMapping[WMI_HIGHEST_PRI] = WMM_AC_VO; \
52770 + (w)->wmi_ac2WmiStreamMapping[WMM_AC_BE] = WMI_BEST_EFFORT_PRI; \
52771 + (w)->wmi_ac2WmiStreamMapping[WMM_AC_BK] = WMI_LOW_PRI; \
52772 + (w)->wmi_ac2WmiStreamMapping[WMM_AC_VI] = WMI_HIGH_PRI; \
52773 + (w)->wmi_ac2WmiStreamMapping[WMM_AC_VO] = WMI_HIGHEST_PRI; }
52774 +
52775 +#define WMI_WMISTREAM_ACCESSCATEGORY(w,s) (w)->wmi_wmiStream2AcMapping[s]
52776 +#define WMI_ACCESSCATEGORY_WMISTREAM(w,ac) (w)->wmi_ac2WmiStreamMapping[ac]
52777 +
52778 +#define LOCK_WMI(w) A_MUTEX_LOCK(&(w)->wmi_lock);
52779 +#define UNLOCK_WMI(w) A_MUTEX_UNLOCK(&(w)->wmi_lock);
52780 +
52781 +#ifdef __cplusplus
52782 +}
52783 +#endif
52784 +
52785 +#endif /* _WMI_HOST_H_ */
52786 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/base/bus.c linux-2.6.29-rc3.owrt.om/drivers/base/bus.c
52787 --- linux-2.6.29-rc3.owrt/drivers/base/bus.c 2009-05-10 22:04:49.000000000 +0200
52788 +++ linux-2.6.29-rc3.owrt.om/drivers/base/bus.c 2009-05-10 22:27:59.000000000 +0200
52789 @@ -141,6 +141,29 @@
52790 }
52791 EXPORT_SYMBOL_GPL(bus_remove_file);
52792
52793 +int bus_create_device_link(struct bus_type *bus, struct kobject *target,
52794 + const char *name)
52795 +{
52796 + int error;
52797 + if (bus_get(bus)) {
52798 + error = sysfs_create_link(&bus->p->devices_kset->kobj, target,
52799 + name);
52800 + bus_put(bus);
52801 + } else
52802 + error = -EINVAL;
52803 + return error;
52804 +}
52805 +EXPORT_SYMBOL_GPL(bus_create_device_link);
52806 +
52807 +void bus_remove_device_link(struct bus_type *bus, const char *name)
52808 +{
52809 + if (bus_get(bus)) {
52810 + sysfs_remove_link(&bus->p->devices_kset->kobj, name);
52811 + bus_put(bus);
52812 + }
52813 +}
52814 +EXPORT_SYMBOL_GPL(bus_remove_device_link);
52815 +
52816 static struct kobj_type bus_ktype = {
52817 .sysfs_ops = &bus_sysfs_ops,
52818 };
52819 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/base/core.c linux-2.6.29-rc3.owrt.om/drivers/base/core.c
52820 --- linux-2.6.29-rc3.owrt/drivers/base/core.c 2009-05-10 22:08:41.000000000 +0200
52821 +++ linux-2.6.29-rc3.owrt.om/drivers/base/core.c 2009-05-10 22:27:59.000000000 +0200
52822 @@ -55,6 +55,11 @@
52823 */
52824 const char *dev_driver_string(const struct device *dev)
52825 {
52826 + if (!dev) {
52827 + printk(KERN_ERR"Null dev to dev_driver_string\n");
52828 + dump_stack();
52829 + return "*NULL*";
52830 + }
52831 return dev->driver ? dev->driver->name :
52832 (dev->bus ? dev->bus->name :
52833 (dev->class ? dev->class->name : ""));
52834 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/base/power/main.c linux-2.6.29-rc3.owrt.om/drivers/base/power/main.c
52835 --- linux-2.6.29-rc3.owrt/drivers/base/power/main.c 2009-05-10 22:08:41.000000000 +0200
52836 +++ linux-2.6.29-rc3.owrt.om/drivers/base/power/main.c 2009-05-10 22:27:59.000000000 +0200
52837 @@ -69,9 +69,9 @@
52838 */
52839 void device_pm_add(struct device *dev)
52840 {
52841 - pr_debug("PM: Adding info for %s:%s\n",
52842 + /* pr_debug("PM: Adding info for %s:%s\n",
52843 dev->bus ? dev->bus->name : "No Bus",
52844 - kobject_name(&dev->kobj));
52845 + kobject_name(&dev->kobj)); */
52846 mutex_lock(&dpm_list_mtx);
52847 if (dev->parent) {
52848 if (dev->parent->power.status >= DPM_SUSPENDING)
52849 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/char/Kconfig linux-2.6.29-rc3.owrt.om/drivers/char/Kconfig
52850 --- linux-2.6.29-rc3.owrt/drivers/char/Kconfig 2009-05-10 22:08:42.000000000 +0200
52851 +++ linux-2.6.29-rc3.owrt.om/drivers/char/Kconfig 2009-05-10 22:27:59.000000000 +0200
52852 @@ -66,6 +66,18 @@
52853
52854 If unsure, say Y.
52855
52856 +config NR_TTY_DEVICES
52857 + int "Maximum tty device number"
52858 + depends on VT
52859 + default 63
52860 + ---help---
52861 + This is the highest numbered device created in /dev. You will actually have
52862 + NR_TTY_DEVICES+1 devices in /dev. The default is 63, which will result in
52863 + 64 /dev entries. The lowest number you can set is 11, anything below that,
52864 + and it will default to 11. 63 is also the upper limit so we don't overrun
52865 + the serial consoles.
52866 +
52867 +
52868 config HW_CONSOLE
52869 bool
52870 depends on VT && !S390 && !UML
52871 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/gpio/gpiolib.c linux-2.6.29-rc3.owrt.om/drivers/gpio/gpiolib.c
52872 --- linux-2.6.29-rc3.owrt/drivers/gpio/gpiolib.c 2009-05-10 22:08:42.000000000 +0200
52873 +++ linux-2.6.29-rc3.owrt.om/drivers/gpio/gpiolib.c 2009-05-10 22:27:59.000000000 +0200
52874 @@ -6,8 +6,7 @@
52875 #include <linux/err.h>
52876 #include <linux/debugfs.h>
52877 #include <linux/seq_file.h>
52878 -#include <linux/gpio.h>
52879 -
52880 +#include <mach/gpio.h>
52881
52882 /* Optional implementation infrastructure for GPIO interfaces.
52883 *
52884 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/busses/i2c-s3c2410.c linux-2.6.29-rc3.owrt.om/drivers/i2c/busses/i2c-s3c2410.c
52885 --- linux-2.6.29-rc3.owrt/drivers/i2c/busses/i2c-s3c2410.c 2009-05-10 22:04:49.000000000 +0200
52886 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/busses/i2c-s3c2410.c 2009-05-10 22:27:59.000000000 +0200
52887 @@ -34,9 +34,9 @@
52888 #include <linux/platform_device.h>
52889 #include <linux/clk.h>
52890 #include <linux/cpufreq.h>
52891 +#include <linux/io.h>
52892
52893 #include <asm/irq.h>
52894 -#include <asm/io.h>
52895
52896 #include <plat/regs-iic.h>
52897 #include <plat/iic.h>
52898 @@ -135,6 +135,14 @@
52899 unsigned long tmp;
52900
52901 tmp = readl(i2c->regs + S3C2410_IICCON);
52902 +
52903 +/* S3c2442 datasheet
52904 + *
52905 + * If the IICCON[5]=0, IICCON[4] does not operate correctly.
52906 + * So, It is recommended that you should set IICCON[5]=1,
52907 + * although you does not use the IIC interrupt.
52908 + */
52909 +
52910 writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
52911 }
52912
52913 @@ -480,6 +488,15 @@
52914 if (i2c->suspended)
52915 return -EIO;
52916
52917 + if (i2c->suspended) {
52918 + dev_err(i2c->dev,
52919 + "Hey I am still asleep (suspended: %d), retry later\n",
52920 + i2c->suspended);
52921 + dump_stack();
52922 + ret = -EAGAIN;
52923 + goto out;
52924 + }
52925 +
52926 ret = s3c24xx_i2c_set_master(i2c);
52927 if (ret != 0) {
52928 dev_err(i2c->dev, "cannot get bus (error %d)\n", ret);
52929 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/busses/Kconfig linux-2.6.29-rc3.owrt.om/drivers/i2c/busses/Kconfig
52930 --- linux-2.6.29-rc3.owrt/drivers/i2c/busses/Kconfig 2009-05-10 22:04:49.000000000 +0200
52931 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/busses/Kconfig 2009-05-10 22:27:59.000000000 +0200
52932 @@ -455,11 +455,12 @@
52933 I2C bus.
52934
52935 config I2C_S3C2410
52936 - tristate "S3C2410 I2C Driver"
52937 - depends on ARCH_S3C2410
52938 + tristate "Samsung SoC I2C Driver (S3C24XX and S3C64XX series)"
52939 + depends on ARCH_S3C2410 || ARCH_S3C64XX
52940 help
52941 Say Y here to include support for I2C controller in the
52942 - Samsung S3C2410 based System-on-Chip devices.
52943 + Samsung S3C based System-on-Chip devices such as the S3C2410,
52944 + S3C2440, S3C2442, S3C2443 and S3C6410.
52945
52946 config I2C_SH7760
52947 tristate "Renesas SH7760 I2C Controller"
52948 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/chips/Kconfig linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/Kconfig
52949 --- linux-2.6.29-rc3.owrt/drivers/i2c/chips/Kconfig 2009-05-10 22:04:49.000000000 +0200
52950 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/Kconfig 2009-05-10 22:27:59.000000000 +0200
52951 @@ -16,6 +16,53 @@
52952 This driver can also be built as a module. If so, the module
52953 will be called ds1682.
52954
52955 +config AT24
52956 + tristate "EEPROMs from most vendors"
52957 + depends on SYSFS && EXPERIMENTAL
52958 + help
52959 + Enable this driver to get read/write support to most I2C EEPROMs,
52960 + after you configure the driver to know about each EEPROM on
52961 + your target board. Use these generic chip names, instead of
52962 + vendor-specific ones like at24c64 or 24lc02:
52963 +
52964 + 24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
52965 + 24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
52966 +
52967 + Unless you like data loss puzzles, always be sure that any chip
52968 + you configure as a 24c32 (32 kbit) or larger is NOT really a
52969 + 24c16 (16 kbit) or smaller, and vice versa. Marking the chip
52970 + as read-only won't help recover from this. Also, if your chip
52971 + has any software write-protect mechanism you may want to review the
52972 + code to make sure this driver won't turn it on by accident.
52973 +
52974 + If you use this with an SMBus adapter instead of an I2C adapter,
52975 + full functionality is not available. Only smaller devices are
52976 + supported (24c16 and below, max 4 kByte).
52977 +
52978 + This driver can also be built as a module. If so, the module
52979 + will be called at24.
52980 +
52981 +config SENSORS_EEPROM
52982 + tristate "EEPROM reader"
52983 + depends on EXPERIMENTAL
52984 + help
52985 + If you say yes here you get read-only access to the EEPROM data
52986 + available on modern memory DIMMs and Sony Vaio laptops. Such
52987 + EEPROMs could theoretically be available on other devices as well.
52988 +
52989 + This driver can also be built as a module. If so, the module
52990 + will be called eeprom.
52991 +
52992 +config SENSORS_PCF50606
52993 + tristate "Philips/NXP PCF50606"
52994 + depends on I2C
52995 + help
52996 + If you say yes here you get support for Philips/NXP PCF50606
52997 + PMU (Power Management Unit) chips.
52998 +
52999 + This driver can also be built as a module. If so, the module
53000 + will be called pcf50606.
53001 +
53002 config SENSORS_PCF8574
53003 tristate "Philips PCF8574 and PCF8574A (DEPRECATED)"
53004 depends on EXPERIMENTAL && GPIO_PCF857X = "n"
53005 @@ -102,4 +149,14 @@
53006 This driver can also be built as a module. If so, the module
53007 will be called tsl2550.
53008
53009 +config PCA9632
53010 + tristate "Philips/NXP PCA9632 low power LED driver"
53011 + depends on I2C
53012 + help
53013 + If you say yes here you get support for the Philips/NXP PCA9632
53014 + LED driver.
53015 +
53016 + This driver can also be built as a module. If so, the module
53017 + will be called pca9632.
53018 +
53019 endmenu
53020 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/chips/Makefile linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/Makefile
53021 --- linux-2.6.29-rc3.owrt/drivers/i2c/chips/Makefile 2009-05-10 22:04:49.000000000 +0200
53022 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/Makefile 2009-05-10 22:27:59.000000000 +0200
53023 @@ -13,10 +13,12 @@
53024 obj-$(CONFIG_DS1682) += ds1682.o
53025 obj-$(CONFIG_SENSORS_MAX6875) += max6875.o
53026 obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o
53027 +obj-$(CONFIG_SENSORS_PCF50606) += pcf50606.o
53028 obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o
53029 obj-$(CONFIG_PCF8575) += pcf8575.o
53030 obj-$(CONFIG_SENSORS_PCF8591) += pcf8591.o
53031 obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
53032 +obj-$(CONFIG_PCA9632) += pca9632.o
53033
53034 ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
53035 EXTRA_CFLAGS += -DDEBUG
53036 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/chips/pca9632.c linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pca9632.c
53037 --- linux-2.6.29-rc3.owrt/drivers/i2c/chips/pca9632.c 1970-01-01 01:00:00.000000000 +0100
53038 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pca9632.c 2009-05-10 22:27:59.000000000 +0200
53039 @@ -0,0 +1,551 @@
53040 +/*
53041 + * Philips/NXP PCA9632 low power LED driver.
53042 + * Copyright (C) 2008 Matt Hsu <matt_hsu@openmoko.org>
53043 + *
53044 + * low_level implementation are based on pcf50606 driver
53045 + *
53046 + * This program is free software; you can redistribute it and/or modify
53047 + * it under the terms of the GNU General Public License as published by
53048 + * the Free Software Foundation; version 2 of the License.
53049 + *
53050 + * TODO:
53051 + * - attach ledclass??
53052 + * - add platform data
53053 + *
53054 + */
53055 +
53056 +#include <linux/module.h>
53057 +#include <linux/init.h>
53058 +#include <linux/i2c.h>
53059 +#include <linux/platform_device.h>
53060 +
53061 +#include "pca9632.h"
53062 +
53063 +/* Addresses to scan */
53064 +static unsigned short normal_i2c[] = { 0x62, I2C_CLIENT_END };
53065 +
53066 +/* Insmod parameters */
53067 +I2C_CLIENT_INSMOD_1(pca9632);
53068 +
53069 +enum pca9632_pwr_state {
53070 + PCA9632_NORMAL,
53071 + PCA9632_SLEEP,
53072 +};
53073 +
53074 +enum pca9632_led_output {
53075 + PCA9632_OFF,
53076 + PCA9632_ON,
53077 + PCA9632_CTRL_BY_PWM,
53078 + PCA9632_CTRL_BY_PWM_GRPPWM,
53079 +};
53080 +
53081 +static const char *led_output_name[] = {
53082 + [PCA9632_OFF] = "off",
53083 + [PCA9632_ON] = "fully-on",
53084 + [PCA9632_CTRL_BY_PWM] = "ctrl-by-pwm",
53085 + [PCA9632_CTRL_BY_PWM_GRPPWM] = "ctrl-by-pwm-grppwm",
53086 +};
53087 +
53088 +struct pca9632_data {
53089 + struct i2c_client client;
53090 + struct mutex lock;
53091 +};
53092 +
53093 +static struct i2c_driver pca9632_driver;
53094 +static struct platform_device *pca9632_pdev;
53095 +
53096 +static int pca9632_attach_adapter(struct i2c_adapter *adapter);
53097 +static int pca9632_detach_client(struct i2c_client *client);
53098 +
53099 +static int __reg_write(struct pca9632_data *pca, u_int8_t reg, u_int8_t val)
53100 +{
53101 + return i2c_smbus_write_byte_data(&pca->client, reg, val);
53102 +}
53103 +
53104 +static int reg_write(struct pca9632_data *pca, u_int8_t reg, u_int8_t val)
53105 +{
53106 + int ret;
53107 +
53108 + mutex_lock(&pca->lock);
53109 + ret = __reg_write(pca, reg, val);
53110 + mutex_unlock(&pca->lock);
53111 +
53112 + return ret;
53113 +}
53114 +
53115 +static int32_t __reg_read(struct pca9632_data *pca, u_int8_t reg)
53116 +{
53117 + int32_t ret;
53118 +
53119 + ret = i2c_smbus_read_byte_data(&pca->client, reg);
53120 +
53121 + return ret;
53122 +}
53123 +
53124 +static u_int8_t reg_read(struct pca9632_data *pca, u_int8_t reg)
53125 +{
53126 + int32_t ret;
53127 +
53128 + mutex_lock(&pca->lock);
53129 + ret = __reg_read(pca, reg);
53130 + mutex_unlock(&pca->lock);
53131 +
53132 + return ret & 0xff;
53133 +}
53134 +
53135 +static int reg_set_bit_mask(struct pca9632_data *pca,
53136 + u_int8_t reg, u_int8_t mask, u_int8_t val)
53137 +{
53138 + int ret;
53139 + u_int8_t tmp;
53140 +
53141 + val &= mask;
53142 +
53143 + mutex_lock(&pca->lock);
53144 +
53145 + tmp = __reg_read(pca, reg);
53146 + tmp &= ~mask;
53147 + tmp |= val;
53148 + ret = __reg_write(pca, reg, tmp);
53149 +
53150 + mutex_unlock(&pca->lock);
53151 +
53152 + return ret;
53153 +}
53154 +
53155 +static inline int calc_dc(uint8_t idc)
53156 +{
53157 + return (idc * 100) / 256;
53158 +}
53159 +
53160 +/*
53161 + * Software reset
53162 + */
53163 +static int software_rst(struct i2c_adapter *adapter)
53164 +{
53165 + u8 buf[] = { 0xa5, 0x5a };
53166 +
53167 + struct i2c_msg msg[] = {
53168 + {
53169 + .addr = 0x3,
53170 + .flags = 0,
53171 + .buf = &buf,
53172 + .len = sizeof(buf)
53173 + }
53174 + };
53175 +
53176 + return i2c_transfer(adapter, msg, 1);
53177 +}
53178 +
53179 +/*
53180 + * Group dmblnk control
53181 + */
53182 +static void config_group_dmblnk(struct pca9632_data *pca, int group_dmblnk_mode)
53183 +{
53184 + reg_set_bit_mask(pca, PCA9632_REG_MODE2, 0x20,
53185 + group_dmblnk_mode << PCA9632_DMBLNK_SHIFT);
53186 +}
53187 +
53188 +static int get_group_dmblnk(struct pca9632_data *pca)
53189 +{
53190 + return reg_read(pca, PCA9632_REG_MODE2) >> PCA9632_DMBLNK_SHIFT;
53191 +}
53192 +
53193 +static ssize_t show_group_dmblnk(struct device *dev, struct device_attribute
53194 + *attr, char *buf)
53195 +{
53196 + struct i2c_client *client = to_i2c_client(dev);
53197 + struct pca9632_data *pca = i2c_get_clientdata(client);
53198 +
53199 + if (get_group_dmblnk(pca))
53200 + return sprintf(buf, "blinking\n");
53201 + else
53202 + return sprintf(buf, "dimming\n");
53203 +}
53204 +
53205 +static ssize_t set_group_dmblnk(struct device *dev, struct device_attribute
53206 + *attr, const char *buf, size_t count)
53207 +{
53208 + struct i2c_client *client = to_i2c_client(dev);
53209 + struct pca9632_data *pca = i2c_get_clientdata(client);
53210 + unsigned int mode = simple_strtoul(buf, NULL, 10);
53211 +
53212 + if (mode)
53213 + dev_info(&pca->client.dev, "blinking\n");
53214 + else
53215 + dev_info(&pca->client.dev, "dimming\n");
53216 +
53217 + config_group_dmblnk(pca, mode);
53218 +
53219 + return count;
53220 +}
53221 +
53222 +static DEVICE_ATTR(group_dmblnk, S_IRUGO | S_IWUSR, show_group_dmblnk,
53223 + set_group_dmblnk);
53224 +
53225 +static int reg_id_by_name(const char *name)
53226 +{
53227 + int reg_id = -1;
53228 +
53229 + if (!strncmp(name, "led0", 4))
53230 + reg_id = PCA9632_REG_PWM0;
53231 + else if (!strncmp(name, "led1", 4))
53232 + reg_id = PCA9632_REG_PWM1;
53233 + else if (!strncmp(name, "led2", 4))
53234 + reg_id = PCA9632_REG_PWM2;
53235 + else if (!strncmp(name, "led3", 4))
53236 + reg_id = PCA9632_REG_PWM3;
53237 +
53238 + return reg_id;
53239 +}
53240 +
53241 +static int get_led_output(struct pca9632_data *pca, int ldrx)
53242 +{
53243 + u_int8_t led_state;
53244 +
53245 + ldrx = ldrx - 2;
53246 + led_state = reg_read(pca, PCA9632_REG_LEDOUT);
53247 + led_state = (led_state >> (2 * ldrx)) & 0x03;
53248 +
53249 + return led_state;
53250 +}
53251 +
53252 +static void config_led_output(struct pca9632_data *pca, int ldrx,
53253 + enum pca9632_led_output led_output)
53254 +{
53255 + u_int8_t mask;
53256 + int tmp;
53257 +
53258 + ldrx = ldrx - 2;
53259 + mask = 0x03 << (2 * ldrx);
53260 + tmp = reg_set_bit_mask(pca, PCA9632_REG_LEDOUT,
53261 + mask, led_output << (2 * ldrx));
53262 +}
53263 +
53264 +/*
53265 + * Individual brightness control
53266 + */
53267 +static ssize_t show_brightness(struct device *dev, struct device_attribute
53268 + *attr, char *buf)
53269 +{
53270 + struct i2c_client *client = to_i2c_client(dev);
53271 + struct pca9632_data *pca = i2c_get_clientdata(client);
53272 + int ldrx;
53273 +
53274 + ldrx = reg_id_by_name(attr->attr.name);
53275 +
53276 + switch (get_led_output(pca, ldrx)) {
53277 +
53278 + case PCA9632_OFF:
53279 + case PCA9632_ON:
53280 + return sprintf(buf, "%s",
53281 + led_output_name[get_led_output(pca, ldrx)]);
53282 +
53283 + case PCA9632_CTRL_BY_PWM:
53284 + return sprintf(buf, "%d%% \n", calc_dc(reg_read(pca, ldrx)));
53285 +
53286 + case PCA9632_CTRL_BY_PWM_GRPPWM:
53287 + /* check group dmblnk */
53288 + if (get_group_dmblnk(pca))
53289 + return sprintf(buf, "%d%% \n",
53290 + calc_dc(reg_read(pca, ldrx)));
53291 + return sprintf(buf, "%d%% \n",
53292 + calc_dc((reg_read(pca, ldrx) & 0xfc)));
53293 + default:
53294 + break;
53295 + }
53296 +
53297 + return sprintf(buf, "invalid argument\n");
53298 +}
53299 +
53300 +static ssize_t set_brightness(struct device *dev, struct device_attribute *attr,
53301 + const char *buf, size_t count)
53302 +{
53303 + struct i2c_client *client = to_i2c_client(dev);
53304 + struct pca9632_data *pca = i2c_get_clientdata(client);
53305 + unsigned int pwm = simple_strtoul(buf, NULL, 10);
53306 + int ldrx;
53307 +
53308 + ldrx = reg_id_by_name(attr->attr.name);
53309 + reg_set_bit_mask(pca, ldrx, 0xff, pwm);
53310 +
53311 + return count;
53312 +}
53313 +
53314 +static
53315 +DEVICE_ATTR(led0_pwm, S_IRUGO | S_IWUSR, show_brightness, set_brightness);
53316 +static
53317 +DEVICE_ATTR(led1_pwm, S_IRUGO | S_IWUSR, show_brightness, set_brightness);
53318 +static
53319 +DEVICE_ATTR(led2_pwm, S_IRUGO | S_IWUSR, show_brightness, set_brightness);
53320 +static
53321 +DEVICE_ATTR(led3_pwm, S_IRUGO | S_IWUSR, show_brightness, set_brightness);
53322 +
53323 +/*
53324 + * Group frequency control
53325 + */
53326 +static ssize_t show_group_freq(struct device *dev, struct device_attribute
53327 + *attr, char *buf)
53328 +{
53329 + uint32_t period;
53330 + struct i2c_client *client = to_i2c_client(dev);
53331 + struct pca9632_data *pca = i2c_get_clientdata(client);
53332 +
53333 + period = ((reg_read(pca, PCA9632_REG_GRPFREQ) + 1) * 1000) / 24;
53334 +
53335 + return sprintf(buf, "%d ms\n", period);
53336 +}
53337 +
53338 +static ssize_t set_group_freq(struct device *dev, struct device_attribute *attr,
53339 + const char *buf, size_t count)
53340 +{
53341 + struct i2c_client *client = to_i2c_client(dev);
53342 + struct pca9632_data *pca = i2c_get_clientdata(client);
53343 +
53344 + unsigned int freq = simple_strtoul(buf, NULL, 10);
53345 + reg_write(pca, PCA9632_REG_GRPFREQ, freq);
53346 + return count;
53347 +}
53348 +
53349 +static
53350 +DEVICE_ATTR(group_freq, S_IRUGO | S_IWUSR, show_group_freq, set_group_freq);
53351 +
53352 +/*
53353 + * Group duty cycle tonrol*
53354 + */
53355 +static ssize_t show_group_dc(struct device *dev, struct device_attribute *attr,
53356 + char *buf)
53357 +{
53358 + struct i2c_client *client = to_i2c_client(dev);
53359 + struct pca9632_data *pca = i2c_get_clientdata(client);
53360 +
53361 + if (get_group_dmblnk(pca)) {
53362 +
53363 + if (reg_read(pca, PCA9632_REG_GRPFREQ) <= 0x03)
53364 + return sprintf(buf, "%d%% \n",
53365 + calc_dc(reg_read(pca, PCA9632_REG_GRPPWM) & 0xfc));
53366 +
53367 + return sprintf(buf, "%d%% \n", calc_dc(reg_read(pca,
53368 + PCA9632_REG_GRPPWM)));
53369 + }
53370 +
53371 + return sprintf(buf, "%d%% \n", calc_dc(reg_read(pca,
53372 + PCA9632_REG_GRPPWM) & 0xf0));
53373 +}
53374 +
53375 +static ssize_t set_group_dc(struct device *dev, struct device_attribute *attr,
53376 + const char *buf, size_t count)
53377 +{
53378 + struct i2c_client *client = to_i2c_client(dev);
53379 + struct pca9632_data *pca = i2c_get_clientdata(client);
53380 +
53381 + unsigned int dc = simple_strtoul(buf, NULL, 10);
53382 +
53383 + reg_set_bit_mask(pca, PCA9632_REG_GRPPWM, 0xff, dc);
53384 +
53385 + return count;
53386 +}
53387 +
53388 +static DEVICE_ATTR(group_dc, S_IRUGO | S_IWUSR, show_group_dc, set_group_dc);
53389 +
53390 +/*
53391 + * LED driver output
53392 + */
53393 +static ssize_t show_led_output(struct device *dev, struct device_attribute
53394 + *attr, char *buf)
53395 +{
53396 + struct i2c_client *client = to_i2c_client(dev);
53397 + struct pca9632_data *pca = i2c_get_clientdata(client);
53398 + int ldrx;
53399 +
53400 + ldrx = reg_id_by_name(attr->attr.name);
53401 +
53402 + return sprintf(buf, "%s \n",
53403 + led_output_name[get_led_output(pca, ldrx)]);
53404 +
53405 +}
53406 +static ssize_t set_led_output(struct device *dev, struct device_attribute *attr,
53407 + const char *buf, size_t count)
53408 +{
53409 + struct i2c_client *client = to_i2c_client(dev);
53410 + struct pca9632_data *pca = i2c_get_clientdata(client);
53411 + enum pca9632_led_output led_output;
53412 + int ldrx;
53413 +
53414 + led_output = simple_strtoul(buf, NULL, 10);
53415 + ldrx = reg_id_by_name(attr->attr.name);
53416 + config_led_output(pca, ldrx, led_output);
53417 +
53418 + return count;
53419 +}
53420 +
53421 +static
53422 +DEVICE_ATTR(led0_output, S_IRUGO | S_IWUSR, show_led_output, set_led_output);
53423 +static
53424 +DEVICE_ATTR(led1_output, S_IRUGO | S_IWUSR, show_led_output, set_led_output);
53425 +static
53426 +DEVICE_ATTR(led2_output, S_IRUGO | S_IWUSR, show_led_output, set_led_output);
53427 +static
53428 +DEVICE_ATTR(led3_output, S_IRUGO | S_IWUSR, show_led_output, set_led_output);
53429 +
53430 +static struct attribute *pca_sysfs_entries[] = {
53431 + &dev_attr_group_dmblnk.attr,
53432 + &dev_attr_led0_pwm.attr,
53433 + &dev_attr_led1_pwm.attr,
53434 + &dev_attr_led2_pwm.attr,
53435 + &dev_attr_led3_pwm.attr,
53436 + &dev_attr_group_dc.attr,
53437 + &dev_attr_group_freq.attr,
53438 + &dev_attr_led0_output.attr,
53439 + &dev_attr_led1_output.attr,
53440 + &dev_attr_led2_output.attr,
53441 + &dev_attr_led3_output.attr,
53442 + NULL
53443 +};
53444 +
53445 +static struct attribute_group pca_attr_group = {
53446 + .name = NULL, /* put in device directory */
53447 + .attrs = pca_sysfs_entries,
53448 +};
53449 +
53450 +#ifdef CONFIG_PM
53451 +static int pca9632_suspend(struct device *dev, pm_message_t state)
53452 +{
53453 + /* FIXME: Not implemented */
53454 + return 0;
53455 +}
53456 +
53457 +static int pca9632_resume(struct device *dev)
53458 +{
53459 + /* FIXME: Not implemented */
53460 + return 0;
53461 +}
53462 +#else
53463 +#define pca9632_suspend NULL
53464 +#define pca9632_resume NULL
53465 +#endif
53466 +
53467 +static struct i2c_driver pca9632_driver = {
53468 + .driver = {
53469 + .name = "pca9632",
53470 + .suspend = pca9632_suspend,
53471 + .resume = pca9632_resume,
53472 + },
53473 + .id = I2C_DRIVERID_PCA9632,
53474 + .attach_adapter = pca9632_attach_adapter,
53475 + .detach_client = pca9632_detach_client,
53476 +};
53477 +
53478 +static int pca9632_detect(struct i2c_adapter *adapter, int address, int kind)
53479 +{
53480 + struct i2c_client *new_client;
53481 + struct pca9632_data *pca;
53482 + int err;
53483 +
53484 + pca = kzalloc(sizeof(struct pca9632_data), GFP_KERNEL);
53485 + if (!pca)
53486 + return -ENOMEM;
53487 +
53488 + mutex_init(&pca->lock);
53489 +
53490 + new_client = &pca->client;
53491 + i2c_set_clientdata(new_client, pca);
53492 + new_client->addr = address;
53493 + new_client->adapter = adapter;
53494 + new_client->driver = &pca9632_driver;
53495 + new_client->flags = 0;
53496 +
53497 + strlcpy(new_client->name, "pca9632", I2C_NAME_SIZE);
53498 +
53499 + /* register with i2c core */
53500 + err = i2c_attach_client(new_client);
53501 + if (err)
53502 + goto exit_kfree;
53503 +
53504 + err = sysfs_create_group(&new_client->dev.kobj, &pca_attr_group);
53505 + if (err)
53506 + goto exit_detach;
53507 +
53508 + /* software reset */
53509 + if (!software_rst(adapter))
53510 + dev_info(&pca->client.dev, "pca9632 sw-rst done\n");
53511 +
53512 + /* enter normal mode */
53513 + reg_set_bit_mask(pca, PCA9632_REG_MODE1, 0x10, PCA9632_NORMAL);
53514 +
53515 + return 0;
53516 +
53517 +exit_detach:
53518 + i2c_detach_client(new_client);
53519 +exit_kfree:
53520 + kfree(pca);
53521 +
53522 + return err;
53523 +}
53524 +
53525 +static int pca9632_attach_adapter(struct i2c_adapter *adapter)
53526 +{
53527 + return i2c_probe(adapter, &addr_data, pca9632_detect);
53528 +}
53529 +
53530 +static int pca9632_detach_client(struct i2c_client *client)
53531 +{
53532 + int err;
53533 +
53534 + sysfs_remove_group(&client->dev.kobj, &pca_attr_group);
53535 + err = i2c_detach_client(client);
53536 +
53537 + if (err)
53538 + return err;
53539 +
53540 + kfree(i2c_get_clientdata(client));
53541 +
53542 + return 0;
53543 +}
53544 +
53545 +static int __init pca9632_plat_probe(struct platform_device *pdev)
53546 +{
53547 + /* FIXME: platform data should be attached here */
53548 + pca9632_pdev = pdev;
53549 +
53550 + return 0;
53551 +}
53552 +
53553 +static int pca9632_plat_remove(struct platform_device *pdev)
53554 +{
53555 + return 0;
53556 +}
53557 +
53558 +static struct platform_driver pca9632_plat_driver = {
53559 + .probe = pca9632_plat_probe,
53560 + .remove = pca9632_plat_remove,
53561 + .driver = {
53562 + .owner = THIS_MODULE,
53563 + .name = "pca9632",
53564 + },
53565 +};
53566 +
53567 +static int __init pca9632_init(void)
53568 +{
53569 + int rc;
53570 +
53571 + rc = platform_driver_register(&pca9632_plat_driver);
53572 + if (!rc)
53573 + i2c_add_driver(&pca9632_driver);
53574 +
53575 + return rc;
53576 +}
53577 +
53578 +static void __exit pca9632_exit(void)
53579 +{
53580 + i2c_del_driver(&pca9632_driver);
53581 +
53582 + platform_driver_unregister(&pca9632_plat_driver);
53583 +}
53584 +
53585 +MODULE_AUTHOR("Matt Hsu <matt_hsu@openmoko.org>");
53586 +MODULE_DESCRIPTION("NXP PCA9632 driver");
53587 +MODULE_LICENSE("GPL");
53588 +
53589 +module_init(pca9632_init);
53590 +module_exit(pca9632_exit);
53591 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/chips/pca9632.h linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pca9632.h
53592 --- linux-2.6.29-rc3.owrt/drivers/i2c/chips/pca9632.h 1970-01-01 01:00:00.000000000 +0100
53593 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pca9632.h 2009-05-10 22:27:59.000000000 +0200
53594 @@ -0,0 +1,24 @@
53595 +#ifndef _PCA9632_H
53596 +#define _PCA9632_H
53597 +
53598 +
53599 +enum pca9632_regs{
53600 +
53601 + PCA9632_REG_MODE1 = 0x00,
53602 + PCA9632_REG_MODE2 = 0x01,
53603 + PCA9632_REG_PWM0 = 0x02,
53604 + PCA9632_REG_PWM1 = 0x03,
53605 + PCA9632_REG_PWM2 = 0x04,
53606 + PCA9632_REG_PWM3 = 0x05,
53607 + PCA9632_REG_GRPPWM = 0x06,
53608 + PCA9632_REG_GRPFREQ = 0x07,
53609 + PCA9632_REG_LEDOUT = 0x08,
53610 + PCA9632_REG_SUBADDR1 = 0x09,
53611 + PCA9632_REG_SUBADDR2 = 0x0a,
53612 + PCA9632_REG_SUBADDR3 = 0x0b,
53613 + PCA9632_REG_ALLCALLADR1 = 0x0c,
53614 +};
53615 +
53616 +#define PCA9632_DMBLNK_SHIFT 5
53617 +
53618 +#endif /* _PCA9632_H */
53619 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/chips/pcf50606.c linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pcf50606.c
53620 --- linux-2.6.29-rc3.owrt/drivers/i2c/chips/pcf50606.c 1970-01-01 01:00:00.000000000 +0100
53621 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pcf50606.c 2009-05-10 22:27:59.000000000 +0200
53622 @@ -0,0 +1,2193 @@
53623 +/* Philips/NXP PCF50606 Power Management Unit (PMU) driver
53624 + *
53625 + * (C) 2006-2007 by Openmoko, Inc.
53626 + * Authors: Harald Welte <laforge@openmoko.org>,
53627 + * Matt Hsu <matt@openmoko.org>
53628 + * All rights reserved.
53629 + *
53630 + * This program is free software; you can redistribute it and/or
53631 + * modify it under the terms of the GNU General Public License as
53632 + * published by the Free Software Foundation; either version 2 of
53633 + * the License, or (at your option) any later version.
53634 + *
53635 + * This program is distributed in the hope that it will be useful,
53636 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
53637 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
53638 + * GNU General Public License for more details.
53639 + *
53640 + * You should have received a copy of the GNU General Public License
53641 + * along with this program; if not, write to the Free Software
53642 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
53643 + * MA 02111-1307 USA
53644 + *
53645 + * This driver is a monster ;) It provides the following features
53646 + * - voltage control for a dozen different voltage domains
53647 + * - charging control for main and backup battery
53648 + * - rtc / alarm
53649 + * - watchdog
53650 + * - adc driver (hw_sensors like)
53651 + * - pwm driver
53652 + * - backlight
53653 + *
53654 + */
53655 +
53656 +#include <linux/module.h>
53657 +#include <linux/init.h>
53658 +#include <linux/i2c.h>
53659 +#include <linux/types.h>
53660 +#include <linux/interrupt.h>
53661 +#include <linux/irq.h>
53662 +#include <linux/workqueue.h>
53663 +#include <linux/delay.h>
53664 +#include <linux/rtc.h>
53665 +#include <linux/bcd.h>
53666 +#include <linux/watchdog.h>
53667 +#include <linux/miscdevice.h>
53668 +#include <linux/input.h>
53669 +#include <linux/fb.h>
53670 +#include <linux/backlight.h>
53671 +#include <linux/sched.h>
53672 +#include <linux/platform_device.h>
53673 +#include <linux/pcf50606.h>
53674 +#include <linux/apm-emulation.h>
53675 +
53676 +#include <asm/mach-types.h>
53677 +#include <mach/gta01.h>
53678 +
53679 +#include "pcf50606.h"
53680 +
53681 +/* we use dev_dbg() throughout the code, but sometimes don't want to
53682 + * write an entire line of debug related information. This DEBUGPC
53683 + * macro is a continuation for dev_dbg() */
53684 +#ifdef DEBUG
53685 +#define DEBUGPC(x, args ...) printk(x, ## args)
53686 +#else
53687 +#define DEBUGPC(x, args ...)
53688 +#endif
53689 +
53690 +/***********************************************************************
53691 + * Static data / structures
53692 + ***********************************************************************/
53693 +
53694 +static unsigned short normal_i2c[] = { 0x08, I2C_CLIENT_END };
53695 +
53696 +I2C_CLIENT_INSMOD_1(pcf50606);
53697 +
53698 +#define PCF50606_B_CHG_FAST 0 /* Charger Fast allowed */
53699 +#define PCF50606_B_CHG_PRESENT 1 /* Charger present */
53700 +#define PCF50606_B_CHG_FOK 2 /* Fast OK for battery */
53701 +#define PCF50606_B_CHG_ERR 3 /* Charger Error */
53702 +#define PCF50606_B_CHG_PROT 4 /* Charger Protection */
53703 +#define PCF50606_B_CHG_READY 5 /* Charging completed */
53704 +
53705 +#define PCF50606_F_CHG_FAST (1<<PCF50606_B_CHG_FAST)
53706 +#define PCF50606_F_CHG_PRESENT (1<<PCF50606_B_CHG_PRESENT)
53707 +#define PCF50606_F_CHG_FOK (1<<PCF50606_B_CHG_FOK)
53708 +#define PCF50606_F_CHG_ERR (1<<PCF50606_B_CHG_ERR)
53709 +#define PCF50606_F_CHG_PROT (1<<PCF50606_B_CHG_PROT)
53710 +#define PCF50606_F_CHG_READY (1<<PCF50606_B_CHG_READY)
53711 +#define PCF50606_F_CHG_MASK 0x000000fc
53712 +
53713 +#define PCF50606_F_PWR_PRESSED 0x00000100
53714 +#define PCF50606_F_RTC_SECOND 0x00000200
53715 +
53716 +enum close_state {
53717 + CLOSE_STATE_NOT,
53718 + CLOSE_STATE_ALLOW = 0x2342,
53719 +};
53720 +
53721 +enum pcf50606_suspend_states {
53722 + PCF50606_SS_RUNNING,
53723 + PCF50606_SS_STARTING_SUSPEND,
53724 + PCF50606_SS_COMPLETED_SUSPEND,
53725 + PCF50606_SS_RESUMING_BUT_NOT_US_YET,
53726 + PCF50606_SS_STARTING_RESUME,
53727 + PCF50606_SS_COMPLETED_RESUME,
53728 +};
53729 +
53730 +struct pcf50606_data {
53731 + struct i2c_client client;
53732 + struct pcf50606_platform_data *pdata;
53733 + struct backlight_device *backlight;
53734 + struct mutex lock;
53735 + unsigned int flags;
53736 + unsigned int working;
53737 + struct mutex working_lock;
53738 + struct work_struct work;
53739 + struct rtc_device *rtc;
53740 + struct input_dev *input_dev;
53741 + int allow_close;
53742 + int onkey_seconds;
53743 + int irq;
53744 + int coldplug_done;
53745 + int suppress_onkey_events;
53746 + enum pcf50606_suspend_states suspend_state;
53747 +#ifdef CONFIG_PM
53748 + struct {
53749 + u_int8_t dcdc1, dcdc2;
53750 + u_int8_t dcdec1;
53751 + u_int8_t dcudc1;
53752 + u_int8_t ioregc;
53753 + u_int8_t d1regc1;
53754 + u_int8_t d2regc1;
53755 + u_int8_t d3regc1;
53756 + u_int8_t lpregc1;
53757 + u_int8_t adcc1, adcc2;
53758 + u_int8_t pwmc1;
53759 + u_int8_t int1m, int2m, int3m;
53760 + } standby_regs;
53761 +#endif
53762 +};
53763 +
53764 +static struct i2c_driver pcf50606_driver;
53765 +
53766 +/* This is an ugly construct on how to access the (currently single/global)
53767 + * pcf50606 handle from other code in the kernel. I didn't really come up with
53768 + * a more decent method of dynamically resolving this */
53769 +struct pcf50606_data *pcf50606_global;
53770 +EXPORT_SYMBOL_GPL(pcf50606_global);
53771 +
53772 +static struct platform_device *pcf50606_pdev;
53773 +
53774 +/* This is a 10k, B=3370 NTC Thermistor -10..79 centigrade */
53775 +/* Table entries are offset by +0.5C so a properly rounded value is generated */
53776 +static const u_int16_t ntc_table_10k_3370B[] = {
53777 + /* -10 */
53778 + 43888, 41819, 39862, 38010, 36257, 34596, 33024, 31534, 30121, 28781,
53779 + 27510, 26304, 25159, 24071, 23038, 22056, 21122, 20234, 19390, 18586,
53780 + 17821, 17093, 16399, 15738, 15107, 14506, 13933, 13387, 12865, 12367,
53781 + 11891, 11437, 11003, 10588, 10192, 9813, 9450, 9103, 8771, 8453,
53782 + 8149, 7857, 7578, 7310, 7054, 6808, 6572, 6346, 6129, 5920,
53783 + 5720, 5528, 5344, 5167, 4996, 4833, 4675, 4524, 4379, 4239,
53784 + 4104, 3975, 3850, 3730, 3614, 3503, 3396, 3292, 3193, 3097,
53785 + 3004, 2915, 2829, 2745, 2665, 2588, 2513, 2441, 2371, 2304,
53786 + 2239, 2176, 2116, 2057, 2000, 1945, 1892, 1841, 1791, 1743,
53787 +};
53788 +
53789 +
53790 +/***********************************************************************
53791 + * Low-Level routines
53792 + ***********************************************************************/
53793 +
53794 +static inline int __reg_write(struct pcf50606_data *pcf, u_int8_t reg,
53795 + u_int8_t val)
53796 +{
53797 + if (pcf->suspend_state == PCF50606_SS_COMPLETED_SUSPEND) {
53798 + dev_err(&pcf->client.dev, "__reg_write while suspended.\n");
53799 + dump_stack();
53800 + }
53801 + return i2c_smbus_write_byte_data(&pcf->client, reg, val);
53802 +}
53803 +
53804 +static int reg_write(struct pcf50606_data *pcf, u_int8_t reg, u_int8_t val)
53805 +{
53806 + int ret;
53807 +
53808 + mutex_lock(&pcf->lock);
53809 + ret = __reg_write(pcf, reg, val);
53810 + mutex_unlock(&pcf->lock);
53811 +
53812 + return ret;
53813 +}
53814 +
53815 +static inline int32_t __reg_read(struct pcf50606_data *pcf, u_int8_t reg)
53816 +{
53817 + int32_t ret;
53818 +
53819 + if (pcf->suspend_state == PCF50606_SS_COMPLETED_SUSPEND) {
53820 + dev_err(&pcf->client.dev, "__reg_read while suspended.\n");
53821 + dump_stack();
53822 + }
53823 + ret = i2c_smbus_read_byte_data(&pcf->client, reg);
53824 +
53825 + return ret;
53826 +}
53827 +
53828 +static u_int8_t reg_read(struct pcf50606_data *pcf, u_int8_t reg)
53829 +{
53830 + int32_t ret;
53831 +
53832 + mutex_lock(&pcf->lock);
53833 + ret = __reg_read(pcf, reg);
53834 + mutex_unlock(&pcf->lock);
53835 +
53836 + return ret & 0xff;
53837 +}
53838 +
53839 +static int reg_set_bit_mask(struct pcf50606_data *pcf,
53840 + u_int8_t reg, u_int8_t mask, u_int8_t val)
53841 +{
53842 + int ret;
53843 + u_int8_t tmp;
53844 +
53845 + val &= mask;
53846 +
53847 + mutex_lock(&pcf->lock);
53848 +
53849 + tmp = __reg_read(pcf, reg);
53850 + tmp &= ~mask;
53851 + tmp |= val;
53852 + ret = __reg_write(pcf, reg, tmp);
53853 +
53854 + mutex_unlock(&pcf->lock);
53855 +
53856 + return ret;
53857 +}
53858 +
53859 +static int reg_clear_bits(struct pcf50606_data *pcf, u_int8_t reg, u_int8_t val)
53860 +{
53861 + int ret;
53862 + u_int8_t tmp;
53863 +
53864 + mutex_lock(&pcf->lock);
53865 +
53866 + tmp = __reg_read(pcf, reg);
53867 + tmp &= ~val;
53868 + ret = __reg_write(pcf, reg, tmp);
53869 +
53870 + mutex_unlock(&pcf->lock);
53871 +
53872 + return ret;
53873 +}
53874 +
53875 +/* synchronously read one ADC channel (busy-wait for result to be complete) */
53876 +static u_int16_t adc_read(struct pcf50606_data *pcf, int channel,
53877 + u_int16_t *data2)
53878 +{
53879 + u_int8_t adcs2, adcs1;
53880 + u_int16_t ret;
53881 +
53882 + dev_dbg(&pcf->client.dev, "entering (pcf=%p, channel=%u, data2=%p)\n",
53883 + pcf, channel, data2);
53884 +
53885 + channel &= PCF50606_ADCC2_ADCMUX_MASK;
53886 +
53887 + mutex_lock(&pcf->lock);
53888 +
53889 + /* start ADC conversion of selected channel */
53890 + __reg_write(pcf, PCF50606_REG_ADCC2, channel |
53891 + PCF50606_ADCC2_ADCSTART | PCF50606_ADCC2_RES_10BIT);
53892 +
53893 + do {
53894 + adcs2 = __reg_read(pcf, PCF50606_REG_ADCS2);
53895 + } while (!(adcs2 & PCF50606_ADCS2_ADCRDY));
53896 +
53897 + adcs1 = __reg_read(pcf, PCF50606_REG_ADCS1);
53898 + ret = (adcs1 << 2) | (adcs2 & 0x03);
53899 +
53900 + if (data2) {
53901 + adcs1 = __reg_read(pcf, PCF50606_REG_ADCS3);
53902 + *data2 = (adcs1 << 2) | ((adcs2 & 0x0c) >> 2);
53903 + }
53904 +
53905 + mutex_unlock(&pcf->lock);
53906 +
53907 + dev_dbg(&pcf->client.dev, "returning %u %u\n", ret,
53908 + data2 ? *data2 : 0);
53909 +
53910 + return ret;
53911 +}
53912 +
53913 +/***********************************************************************
53914 + * Voltage / ADC
53915 + ***********************************************************************/
53916 +
53917 +static u_int8_t dcudc_voltage(unsigned int millivolts)
53918 +{
53919 + if (millivolts < 900)
53920 + return 0;
53921 + if (millivolts > 5500)
53922 + return 0x1f;
53923 + if (millivolts <= 3300) {
53924 + millivolts -= 900;
53925 + return millivolts/300;
53926 + }
53927 + if (millivolts < 4000)
53928 + return 0x0f;
53929 + else {
53930 + millivolts -= 4000;
53931 + return millivolts/100;
53932 + }
53933 +}
53934 +
53935 +static unsigned int dcudc_2voltage(u_int8_t bits)
53936 +{
53937 + bits &= 0x1f;
53938 + if (bits < 0x08)
53939 + return 900 + bits * 300;
53940 + else if (bits < 0x10)
53941 + return 3300;
53942 + else
53943 + return 4000 + bits * 100;
53944 +}
53945 +
53946 +static u_int8_t dcdec_voltage(unsigned int millivolts)
53947 +{
53948 + if (millivolts < 900)
53949 + return 0;
53950 + else if (millivolts > 3300)
53951 + return 0x0f;
53952 +
53953 + millivolts -= 900;
53954 + return millivolts/300;
53955 +}
53956 +
53957 +static unsigned int dcdec_2voltage(u_int8_t bits)
53958 +{
53959 + bits &= 0x0f;
53960 + return 900 + bits*300;
53961 +}
53962 +
53963 +static u_int8_t dcdc_voltage(unsigned int millivolts)
53964 +{
53965 + if (millivolts < 900)
53966 + return 0;
53967 + else if (millivolts > 3600)
53968 + return 0x1f;
53969 +
53970 + if (millivolts < 1500) {
53971 + millivolts -= 900;
53972 + return millivolts/25;
53973 + } else {
53974 + millivolts -= 1500;
53975 + return 0x18 + millivolts/300;
53976 + }
53977 +}
53978 +
53979 +static unsigned int dcdc_2voltage(u_int8_t bits)
53980 +{
53981 + bits &= 0x1f;
53982 + if ((bits & 0x18) == 0x18)
53983 + return 1500 + ((bits & 0x7) * 300);
53984 + else
53985 + return 900 + (bits * 25);
53986 +}
53987 +
53988 +static u_int8_t dx_voltage(unsigned int millivolts)
53989 +{
53990 + if (millivolts < 900)
53991 + return 0;
53992 + else if (millivolts > 3300)
53993 + return 0x18;
53994 +
53995 + millivolts -= 900;
53996 + return millivolts/100;
53997 +}
53998 +
53999 +static unsigned int dx_2voltage(u_int8_t bits)
54000 +{
54001 + bits &= 0x1f;
54002 + return 900 + (bits * 100);
54003 +}
54004 +
54005 +static const u_int8_t regulator_registers[__NUM_PCF50606_REGULATORS] = {
54006 + [PCF50606_REGULATOR_DCD] = PCF50606_REG_DCDC1,
54007 + [PCF50606_REGULATOR_DCDE] = PCF50606_REG_DCDEC1,
54008 + [PCF50606_REGULATOR_DCUD] = PCF50606_REG_DCUDC1,
54009 + [PCF50606_REGULATOR_D1REG] = PCF50606_REG_D1REGC1,
54010 + [PCF50606_REGULATOR_D2REG] = PCF50606_REG_D2REGC1,
54011 + [PCF50606_REGULATOR_D3REG] = PCF50606_REG_D3REGC1,
54012 + [PCF50606_REGULATOR_LPREG] = PCF50606_REG_LPREGC1,
54013 + [PCF50606_REGULATOR_IOREG] = PCF50606_REG_IOREGC,
54014 +};
54015 +
54016 +int pcf50606_onoff_set(struct pcf50606_data *pcf,
54017 + enum pcf50606_regulator_id reg, int on)
54018 +{
54019 + u_int8_t addr;
54020 +
54021 + if (reg >= __NUM_PCF50606_REGULATORS)
54022 + return -EINVAL;
54023 +
54024 + /* IOREG cannot be powered off since it powers the PMU I2C */
54025 + if (reg == PCF50606_REGULATOR_IOREG)
54026 + return -EIO;
54027 +
54028 + addr = regulator_registers[reg];
54029 +
54030 + if (on == 0)
54031 + reg_set_bit_mask(pcf, addr, 0xe0, 0x00);
54032 + else
54033 + reg_set_bit_mask(pcf, addr, 0xe0, 0xe0);
54034 +
54035 + return 0;
54036 +}
54037 +EXPORT_SYMBOL_GPL(pcf50606_onoff_set);
54038 +
54039 +int pcf50606_onoff_get(struct pcf50606_data *pcf,
54040 + enum pcf50606_regulator_id reg)
54041 +{
54042 + u_int8_t val, addr;
54043 +
54044 + if (reg >= __NUM_PCF50606_REGULATORS)
54045 + return -EINVAL;
54046 +
54047 + addr = regulator_registers[reg];
54048 + val = (reg_read(pcf, addr) & 0xe0) >> 5;
54049 +
54050 + /* PWREN1 = 1, PWREN2 = 1, see table 16 of datasheet */
54051 + switch (val) {
54052 + case 0:
54053 + case 5:
54054 + return 0;
54055 + default:
54056 + return 1;
54057 + }
54058 +}
54059 +EXPORT_SYMBOL_GPL(pcf50606_onoff_get);
54060 +
54061 +int pcf50606_voltage_set(struct pcf50606_data *pcf,
54062 + enum pcf50606_regulator_id reg,
54063 + unsigned int millivolts)
54064 +{
54065 + u_int8_t volt_bits;
54066 + u_int8_t regnr;
54067 + int rc;
54068 +
54069 + dev_dbg(&pcf->client.dev, "pcf=%p, reg=%d, mvolts=%d\n", pcf, reg,
54070 + millivolts);
54071 +
54072 + if (reg >= __NUM_PCF50606_REGULATORS)
54073 + return -EINVAL;
54074 +
54075 + if (millivolts > pcf->pdata->rails[reg].voltage.max)
54076 + return -EINVAL;
54077 +
54078 + switch (reg) {
54079 + case PCF50606_REGULATOR_DCD:
54080 + volt_bits = dcdc_voltage(millivolts);
54081 + rc = reg_set_bit_mask(pcf, PCF50606_REG_DCDC1, 0x1f,
54082 + volt_bits);
54083 + break;
54084 + case PCF50606_REGULATOR_DCDE:
54085 + volt_bits = dcdec_voltage(millivolts);
54086 + rc = reg_set_bit_mask(pcf, PCF50606_REG_DCDEC1, 0x0f,
54087 + volt_bits);
54088 + break;
54089 + case PCF50606_REGULATOR_DCUD:
54090 + volt_bits = dcudc_voltage(millivolts);
54091 + rc = reg_set_bit_mask(pcf, PCF50606_REG_DCUDC1, 0x1f,
54092 + volt_bits);
54093 + break;
54094 + case PCF50606_REGULATOR_D1REG:
54095 + case PCF50606_REGULATOR_D2REG:
54096 + case PCF50606_REGULATOR_D3REG:
54097 + regnr = PCF50606_REG_D1REGC1 + (reg - PCF50606_REGULATOR_D1REG);
54098 + volt_bits = dx_voltage(millivolts);
54099 + rc = reg_set_bit_mask(pcf, regnr, 0x1f, volt_bits);
54100 + break;
54101 + case PCF50606_REGULATOR_LPREG:
54102 + volt_bits = dx_voltage(millivolts);
54103 + rc = reg_set_bit_mask(pcf, PCF50606_REG_LPREGC1, 0x1f,
54104 + volt_bits);
54105 + break;
54106 + case PCF50606_REGULATOR_IOREG:
54107 + if (millivolts < 1800)
54108 + return -EINVAL;
54109 + volt_bits = dx_voltage(millivolts);
54110 + rc = reg_set_bit_mask(pcf, PCF50606_REG_IOREGC, 0x1f,
54111 + volt_bits);
54112 + break;
54113 + default:
54114 + return -EINVAL;
54115 + }
54116 +
54117 + return rc;
54118 +}
54119 +EXPORT_SYMBOL_GPL(pcf50606_voltage_set);
54120 +
54121 +unsigned int pcf50606_voltage_get(struct pcf50606_data *pcf,
54122 + enum pcf50606_regulator_id reg)
54123 +{
54124 + u_int8_t volt_bits;
54125 + u_int8_t regnr;
54126 + unsigned int rc = 0;
54127 +
54128 + if (reg >= __NUM_PCF50606_REGULATORS)
54129 + return -EINVAL;
54130 +
54131 + switch (reg) {
54132 + case PCF50606_REGULATOR_DCD:
54133 + volt_bits = reg_read(pcf, PCF50606_REG_DCDC1) & 0x1f;
54134 + rc = dcdc_2voltage(volt_bits);
54135 + break;
54136 + case PCF50606_REGULATOR_DCDE:
54137 + volt_bits = reg_read(pcf, PCF50606_REG_DCDEC1) & 0x0f;
54138 + rc = dcdec_2voltage(volt_bits);
54139 + break;
54140 + case PCF50606_REGULATOR_DCUD:
54141 + volt_bits = reg_read(pcf, PCF50606_REG_DCUDC1) & 0x1f;
54142 + rc = dcudc_2voltage(volt_bits);
54143 + break;
54144 + case PCF50606_REGULATOR_D1REG:
54145 + case PCF50606_REGULATOR_D2REG:
54146 + case PCF50606_REGULATOR_D3REG:
54147 + regnr = PCF50606_REG_D1REGC1 + (reg - PCF50606_REGULATOR_D1REG);
54148 + volt_bits = reg_read(pcf, regnr) & 0x1f;
54149 + if (volt_bits > 0x18)
54150 + volt_bits = 0x18;
54151 + rc = dx_2voltage(volt_bits);
54152 + break;
54153 + case PCF50606_REGULATOR_LPREG:
54154 + volt_bits = reg_read(pcf, PCF50606_REG_LPREGC1) & 0x1f;
54155 + if (volt_bits > 0x18)
54156 + volt_bits = 0x18;
54157 + rc = dx_2voltage(volt_bits);
54158 + break;
54159 + case PCF50606_REGULATOR_IOREG:
54160 + volt_bits = reg_read(pcf, PCF50606_REG_IOREGC) & 0x1f;
54161 + if (volt_bits > 0x18)
54162 + volt_bits = 0x18;
54163 + rc = dx_2voltage(volt_bits);
54164 + break;
54165 + default:
54166 + return -EINVAL;
54167 + }
54168 +
54169 + return rc;
54170 +}
54171 +EXPORT_SYMBOL_GPL(pcf50606_voltage_get);
54172 +
54173 +/* go into 'STANDBY' mode, i.e. power off the main CPU and peripherals */
54174 +void pcf50606_go_standby(void)
54175 +{
54176 + reg_write(pcf50606_global, PCF50606_REG_OOCC1,
54177 + PCF50606_OOCC1_GOSTDBY);
54178 +}
54179 +EXPORT_SYMBOL_GPL(pcf50606_go_standby);
54180 +
54181 +void pcf50606_gpo0_set(struct pcf50606_data *pcf, int on)
54182 +{
54183 + u_int8_t val;
54184 +
54185 + if (on)
54186 + val = 0x07;
54187 + else
54188 + val = 0x0f;
54189 +
54190 + reg_set_bit_mask(pcf, PCF50606_REG_GPOC1, 0x0f, val);
54191 +}
54192 +EXPORT_SYMBOL_GPL(pcf50606_gpo0_set);
54193 +
54194 +int pcf50606_gpo0_get(struct pcf50606_data *pcf)
54195 +{
54196 + u_int8_t reg = reg_read(pcf, PCF50606_REG_GPOC1) & 0x0f;
54197 +
54198 + if (reg == 0x07 || reg == 0x08)
54199 + return 1;
54200 +
54201 + return 0;
54202 +}
54203 +EXPORT_SYMBOL_GPL(pcf50606_gpo0_get);
54204 +
54205 +static void pcf50606_work(struct work_struct *work)
54206 +{
54207 + struct pcf50606_data *pcf =
54208 + container_of(work, struct pcf50606_data, work);
54209 + u_int8_t pcfirq[3];
54210 + int ret;
54211 +
54212 + mutex_lock(&pcf->working_lock);
54213 + pcf->working = 1;
54214 +
54215 + /* sanity */
54216 + if (!&pcf->client.dev)
54217 + goto bail;
54218 +
54219 + /*
54220 + * if we are presently suspending, we are not in a position to deal
54221 + * with pcf50606 interrupts at all.
54222 + *
54223 + * Because we didn't clear the int pending registers, there will be
54224 + * no edge / interrupt waiting for us when we wake. But it is OK
54225 + * because at the end of our resume, we call this workqueue function
54226 + * gratuitously, clearing the pending register and re-enabling
54227 + * servicing this interrupt.
54228 + */
54229 +
54230 + if ((pcf->suspend_state == PCF50606_SS_STARTING_SUSPEND) ||
54231 + (pcf->suspend_state == PCF50606_SS_COMPLETED_SUSPEND))
54232 + goto bail;
54233 +
54234 + /*
54235 + * If we are inside suspend -> resume completion time we don't attempt
54236 + * service until we have fully resumed. Although we could talk to the
54237 + * device as soon as I2C is up, the regs in the device which we might
54238 + * choose to modify as part of the service action have not been
54239 + * reloaded with their pre-suspend states yet. Therefore we will
54240 + * defer our service if we are called like that until our resume has
54241 + * completed.
54242 + *
54243 + * This shouldn't happen any more because we disable servicing this
54244 + * interrupt in suspend and don't re-enable it until resume is
54245 + * completed.
54246 + */
54247 +
54248 + if (pcf->suspend_state &&
54249 + (pcf->suspend_state != PCF50606_SS_COMPLETED_RESUME))
54250 + goto reschedule;
54251 +
54252 + /* this is the case early in resume! Sanity check! */
54253 + if (i2c_get_clientdata(&pcf->client) == NULL)
54254 + goto reschedule;
54255 +
54256 + /*
54257 + * p35 pcf50606 datasheet rev 2.2:
54258 + * ''The system controller shall read all interrupt registers in
54259 + * one I2C read action''
54260 + * because if you don't INT# gets stuck asserted forever after a
54261 + * while
54262 + */
54263 + ret = i2c_smbus_read_i2c_block_data(&pcf->client, PCF50606_REG_INT1,
54264 + sizeof(pcfirq), pcfirq);
54265 + if (ret != sizeof(pcfirq)) {
54266 + DEBUGPC("Oh crap PMU IRQ register read failed %d\n", ret);
54267 + /*
54268 + * it shouldn't fail, we no longer attempt to use
54269 + * I2C while it can be suspended. But we don't have
54270 + * much option but to retry if if it ever did fail,
54271 + * because if we don't service the interrupt to clear
54272 + * it, we will never see another PMU interrupt edge.
54273 + */
54274 + goto reschedule;
54275 + }
54276 +
54277 + /* hey did we just resume? (because we don't get here unless we are
54278 + * running normally or the first call after resumption)
54279 + *
54280 + * pcf50606 resume is really really over now then.
54281 + */
54282 + if (pcf->suspend_state != PCF50606_SS_RUNNING) {
54283 + pcf->suspend_state = PCF50606_SS_RUNNING;
54284 +
54285 + /* peek at the IRQ reason, if power button then set a flag
54286 + * so that we do not signal the event to userspace
54287 + */
54288 + if (pcfirq[0] & (PCF50606_INT1_ONKEYF | PCF50606_INT1_ONKEYR)) {
54289 + pcf->suppress_onkey_events = 1;
54290 + dev_dbg(&pcf->client.dev,
54291 + "Wake by ONKEY, suppressing ONKEY events");
54292 + } else {
54293 + pcf->suppress_onkey_events = 0;
54294 + }
54295 + }
54296 +
54297 + if (!pcf->coldplug_done) {
54298 + DEBUGPC("PMU Coldplug init\n");
54299 +
54300 + /* we used SECOND to kick ourselves started -- turn it off */
54301 + pcfirq[0] &= ~PCF50606_INT1_SECOND;
54302 + reg_set_bit_mask(pcf, PCF50606_REG_INT1M, PCF50606_INT1_SECOND,
54303 + PCF50606_INT1_SECOND);
54304 +
54305 + /* coldplug the USB if present */
54306 + if (__reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON) {
54307 + /* Charger inserted */
54308 + DEBUGPC("COLD CHGINS ");
54309 + input_report_key(pcf->input_dev, KEY_BATTERY, 1);
54310 + apm_queue_event(APM_POWER_STATUS_CHANGE);
54311 + pcf->flags |= PCF50606_F_CHG_PRESENT;
54312 + if (pcf->pdata->cb)
54313 + pcf->pdata->cb(&pcf->client.dev,
54314 + PCF50606_FEAT_MBC,
54315 + PMU_EVT_INSERT);
54316 + }
54317 +
54318 + pcf->coldplug_done = 1;
54319 + }
54320 +
54321 +
54322 + dev_dbg(&pcf->client.dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x:",
54323 + pcfirq[0], pcfirq[1], pcfirq[2]);
54324 +
54325 + if (pcfirq[0] & PCF50606_INT1_ONKEYF) {
54326 + /* ONKEY falling edge (start of button press) */
54327 + pcf->flags |= PCF50606_F_PWR_PRESSED;
54328 + if (!pcf->suppress_onkey_events) {
54329 + DEBUGPC("ONKEYF ");
54330 + input_report_key(pcf->input_dev, KEY_POWER, 1);
54331 + } else {
54332 + DEBUGPC("ONKEYF(unreported) ");
54333 + }
54334 + }
54335 + if (pcfirq[0] & PCF50606_INT1_ONKEY1S) {
54336 + /* ONKEY pressed for more than 1 second */
54337 + pcf->onkey_seconds = 0;
54338 + DEBUGPC("ONKEY1S ");
54339 + /* Tell PMU we are taking care of this */
54340 + reg_set_bit_mask(pcf, PCF50606_REG_OOCC1,
54341 + PCF50606_OOCC1_TOTRST,
54342 + PCF50606_OOCC1_TOTRST);
54343 + /* enable SECOND interrupt (hz tick) */
54344 + reg_clear_bits(pcf, PCF50606_REG_INT1M, PCF50606_INT1_SECOND);
54345 + }
54346 + if (pcfirq[0] & PCF50606_INT1_ONKEYR) {
54347 + /* ONKEY rising edge (end of button press) */
54348 + pcf->flags &= ~PCF50606_F_PWR_PRESSED;
54349 + pcf->onkey_seconds = -1;
54350 + if (!pcf->suppress_onkey_events) {
54351 + DEBUGPC("ONKEYR ");
54352 + input_report_key(pcf->input_dev, KEY_POWER, 0);
54353 + } else {
54354 + DEBUGPC("ONKEYR(suppressed) ");
54355 + /* don't suppress any more power button events */
54356 + pcf->suppress_onkey_events = 0;
54357 + }
54358 + /* disable SECOND interrupt in case RTC didn't
54359 + * request it */
54360 + if (!(pcf->flags & PCF50606_F_RTC_SECOND))
54361 + reg_set_bit_mask(pcf, PCF50606_REG_INT1M,
54362 + PCF50606_INT1_SECOND,
54363 + PCF50606_INT1_SECOND);
54364 + }
54365 + if (pcfirq[0] & PCF50606_INT1_EXTONR) {
54366 + DEBUGPC("EXTONR ");
54367 + input_report_key(pcf->input_dev, KEY_POWER2, 1);
54368 + }
54369 + if (pcfirq[0] & PCF50606_INT1_EXTONF) {
54370 + DEBUGPC("EXTONF ");
54371 + input_report_key(pcf->input_dev, KEY_POWER2, 0);
54372 + }
54373 + if (pcfirq[0] & PCF50606_INT1_SECOND) {
54374 + DEBUGPC("SECOND ");
54375 + if (pcf->flags & PCF50606_F_RTC_SECOND)
54376 + rtc_update_irq(pcf->rtc, 1,
54377 + RTC_PF | RTC_IRQF);
54378 +
54379 + if (pcf->onkey_seconds >= 0 &&
54380 + pcf->flags & PCF50606_F_PWR_PRESSED) {
54381 + DEBUGPC("ONKEY_SECONDS(%u, OOCC1=0x%02x) ",
54382 + pcf->onkey_seconds,
54383 + reg_read(pcf, PCF50606_REG_OOCC1));
54384 + pcf->onkey_seconds++;
54385 + if (pcf->onkey_seconds >=
54386 + pcf->pdata->onkey_seconds_required) {
54387 + /* Ask init to do 'ctrlaltdel' */
54388 + /*
54389 + * currently Linux reacts badly to issuing a
54390 + * signal to PID #1 before init is started.
54391 + * What happens is that the next kernel thread
54392 + * to start, which is the JFFS2 Garbage
54393 + * collector in our case, gets the signal
54394 + * instead and proceeds to fail to fork --
54395 + * which is very bad. Therefore we confirm
54396 + * PID #1 exists before issuing the signal
54397 + */
54398 + if (find_task_by_pid_ns(1, &init_pid_ns)) {
54399 + kill_pid(task_pid(find_task_by_pid_ns(1,
54400 + &init_pid_ns)), SIGINT, 1);
54401 + DEBUGPC("SIGINT(init) ");
54402 + }
54403 + /* FIXME: what to do if userspace doesn't
54404 + * shut down? Do we want to force it? */
54405 + }
54406 + }
54407 + }
54408 + if (pcfirq[0] & PCF50606_INT1_ALARM) {
54409 + DEBUGPC("ALARM ");
54410 + if (pcf->pdata->used_features & PCF50606_FEAT_RTC)
54411 + rtc_update_irq(pcf->rtc, 1,
54412 + RTC_AF | RTC_IRQF);
54413 + }
54414 +
54415 + if (pcfirq[1] & PCF50606_INT2_CHGINS) {
54416 + /* Charger inserted */
54417 + DEBUGPC("CHGINS ");
54418 + input_report_key(pcf->input_dev, KEY_BATTERY, 1);
54419 + apm_queue_event(APM_POWER_STATUS_CHANGE);
54420 + pcf->flags |= PCF50606_F_CHG_PRESENT;
54421 + if (pcf->pdata->cb)
54422 + pcf->pdata->cb(&pcf->client.dev,
54423 + PCF50606_FEAT_MBC, PMU_EVT_INSERT);
54424 + /* FIXME: how to signal this to userspace */
54425 + }
54426 + if (pcfirq[1] & PCF50606_INT2_CHGRM) {
54427 + /* Charger removed */
54428 + DEBUGPC("CHGRM ");
54429 + input_report_key(pcf->input_dev, KEY_BATTERY, 0);
54430 + apm_queue_event(APM_POWER_STATUS_CHANGE);
54431 + pcf->flags &= ~(PCF50606_F_CHG_MASK|PCF50606_F_CHG_PRESENT);
54432 + if (pcf->pdata->cb)
54433 + pcf->pdata->cb(&pcf->client.dev,
54434 + PCF50606_FEAT_MBC, PMU_EVT_INSERT);
54435 + /* FIXME: how signal this to userspace */
54436 + }
54437 + if (pcfirq[1] & PCF50606_INT2_CHGFOK) {
54438 + /* Battery ready for fast charging */
54439 + DEBUGPC("CHGFOK ");
54440 + pcf->flags |= PCF50606_F_CHG_FOK;
54441 + /* FIXME: how to signal this to userspace */
54442 + }
54443 + if (pcfirq[1] & PCF50606_INT2_CHGERR) {
54444 + /* Error in charge mode */
54445 + DEBUGPC("CHGERR ");
54446 + pcf->flags |= PCF50606_F_CHG_ERR;
54447 + pcf->flags &= ~(PCF50606_F_CHG_FOK|PCF50606_F_CHG_READY);
54448 + /* FIXME: how to signal this to userspace */
54449 + }
54450 + if (pcfirq[1] & PCF50606_INT2_CHGFRDY) {
54451 + /* Fast charge completed */
54452 + DEBUGPC("CHGFRDY ");
54453 + pcf->flags |= PCF50606_F_CHG_READY;
54454 + pcf->flags &= ~PCF50606_F_CHG_FOK;
54455 + /* FIXME: how to signal this to userspace */
54456 + }
54457 + if (pcfirq[1] & PCF50606_INT2_CHGPROT) {
54458 + /* Charging protection interrupt */
54459 + DEBUGPC("CHGPROT ");
54460 + pcf->flags &= ~(PCF50606_F_CHG_FOK|PCF50606_F_CHG_READY);
54461 + /* FIXME: signal this to userspace */
54462 + }
54463 + if (pcfirq[1] & PCF50606_INT2_CHGWD10S) {
54464 + /* Charger watchdog will expire in 10 seconds */
54465 + DEBUGPC("CHGWD10S ");
54466 + reg_set_bit_mask(pcf, PCF50606_REG_OOCC1,
54467 + PCF50606_OOCC1_WDTRST,
54468 + PCF50606_OOCC1_WDTRST);
54469 + }
54470 + if (pcfirq[1] & PCF50606_INT2_CHGWDEXP) {
54471 + /* Charger watchdog expires */
54472 + DEBUGPC("CHGWDEXP ");
54473 + /* FIXME: how to signal this to userspace */
54474 + }
54475 +
54476 + if (pcfirq[2] & PCF50606_INT3_ADCRDY) {
54477 + /* ADC result ready */
54478 + DEBUGPC("ADCRDY ");
54479 + }
54480 + if (pcfirq[2] & PCF50606_INT3_ACDINS) {
54481 + /* Accessory insertion detected */
54482 + DEBUGPC("ACDINS ");
54483 + if (pcf->pdata->cb)
54484 + pcf->pdata->cb(&pcf->client.dev,
54485 + PCF50606_FEAT_ACD, PMU_EVT_INSERT);
54486 + }
54487 + if (pcfirq[2] & PCF50606_INT3_ACDREM) {
54488 + /* Accessory removal detected */
54489 + DEBUGPC("ACDREM ");
54490 + if (pcf->pdata->cb)
54491 + pcf->pdata->cb(&pcf->client.dev,
54492 + PCF50606_FEAT_ACD, PMU_EVT_REMOVE);
54493 + }
54494 + /* FIXME: TSCPRES */
54495 + if (pcfirq[2] & PCF50606_INT3_LOWBAT) {
54496 + if (__reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON) {
54497 + /*
54498 + * hey no need to freak out, we have some kind of
54499 + * valid charger power
54500 + */
54501 + DEBUGPC("(NO)BAT ");
54502 + } else {
54503 + /* Really low battery voltage, we have 8 seconds left */
54504 + DEBUGPC("LOWBAT ");
54505 + /*
54506 + * currently Linux reacts badly to issuing a signal to
54507 + * PID #1 before init is started. What happens is that
54508 + * the next kernel thread to start, which is the JFFS2
54509 + * Garbage collector in our case, gets the signal
54510 + * instead and proceeds to fail to fork -- which is
54511 + * very bad. Therefore we confirm PID #1 exists
54512 + * before issuing SPIGPWR
54513 + */
54514 + if (find_task_by_pid_ns(1, &init_pid_ns)) {
54515 + apm_queue_event(APM_LOW_BATTERY);
54516 + DEBUGPC("SIGPWR(init) ");
54517 + kill_pid(task_pid(find_task_by_pid_ns(1, &init_pid_ns)), SIGPWR, 1);
54518 + } else
54519 + /*
54520 + * well, our situation is like this: we do not
54521 + * have any external power, we have a low
54522 + * battery and since PID #1 doesn't exist yet,
54523 + * we are early in the boot, likely before
54524 + * rootfs mount. We should just call it a day
54525 + */
54526 + apm_queue_event(APM_CRITICAL_SUSPEND);
54527 + }
54528 + /* Tell PMU we are taking care of this */
54529 + reg_set_bit_mask(pcf, PCF50606_REG_OOCC1,
54530 + PCF50606_OOCC1_TOTRST,
54531 + PCF50606_OOCC1_TOTRST);
54532 + }
54533 + if (pcfirq[2] & PCF50606_INT3_HIGHTMP) {
54534 + /* High temperature */
54535 + DEBUGPC("HIGHTMP ");
54536 + apm_queue_event(APM_CRITICAL_SUSPEND);
54537 + }
54538 +
54539 + DEBUGPC("\n");
54540 +
54541 +bail:
54542 + pcf->working = 0;
54543 + input_sync(pcf->input_dev);
54544 + put_device(&pcf->client.dev);
54545 + mutex_unlock(&pcf->working_lock);
54546 +
54547 + return;
54548 +
54549 +reschedule:
54550 +
54551 + if ((pcf->suspend_state != PCF50606_SS_STARTING_SUSPEND) &&
54552 + (pcf->suspend_state != PCF50606_SS_COMPLETED_SUSPEND)) {
54553 + msleep(10);
54554 + dev_info(&pcf->client.dev, "rescheduling interrupt service\n");
54555 + }
54556 + if (!schedule_work(&pcf->work))
54557 + dev_err(&pcf->client.dev, "int service reschedule failed\n");
54558 +
54559 + /* we don't put the device here, hold it for next time */
54560 + mutex_unlock(&pcf->working_lock);
54561 +}
54562 +
54563 +static irqreturn_t pcf50606_irq(int irq, void *_pcf)
54564 +{
54565 + struct pcf50606_data *pcf = _pcf;
54566 +
54567 + dev_dbg(&pcf->client.dev, "entering(irq=%u, pcf=%p): scheduling work\n",
54568 + irq, _pcf);
54569 + get_device(&pcf->client.dev);
54570 + if (!schedule_work(&pcf->work) && !pcf->working)
54571 + dev_err(&pcf->client.dev, "pcf irq work already queued.\n");
54572 +
54573 + return IRQ_HANDLED;
54574 +}
54575 +
54576 +static u_int16_t adc_to_batt_millivolts(u_int16_t adc)
54577 +{
54578 + u_int16_t mvolts;
54579 +
54580 + mvolts = (adc * 6000) / 1024;
54581 +
54582 + return mvolts;
54583 +}
54584 +
54585 +#define BATTVOLT_SCALE_START 2800
54586 +#define BATTVOLT_SCALE_END 4200
54587 +#define BATTVOLT_SCALE_DIVIDER ((BATTVOLT_SCALE_END - BATTVOLT_SCALE_START)/100)
54588 +
54589 +static u_int8_t battvolt_scale(u_int16_t battvolt)
54590 +{
54591 + /* FIXME: this linear scale is completely bogus */
54592 + u_int16_t battvolt_relative = battvolt - BATTVOLT_SCALE_START;
54593 + unsigned int percent = battvolt_relative / BATTVOLT_SCALE_DIVIDER;
54594 +
54595 + return percent;
54596 +}
54597 +
54598 +u_int16_t pcf50606_battvolt(struct pcf50606_data *pcf)
54599 +{
54600 + u_int16_t adc;
54601 + adc = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_RES, NULL);
54602 +
54603 + return adc_to_batt_millivolts(adc);
54604 +}
54605 +EXPORT_SYMBOL_GPL(pcf50606_battvolt);
54606 +
54607 +static ssize_t show_battvolt(struct device *dev, struct device_attribute *attr,
54608 + char *buf)
54609 +{
54610 + struct i2c_client *client = to_i2c_client(dev);
54611 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54612 +
54613 + return sprintf(buf, "%u\n", pcf50606_battvolt(pcf));
54614 +}
54615 +static DEVICE_ATTR(battvolt, S_IRUGO | S_IWUSR, show_battvolt, NULL);
54616 +
54617 +static int reg_id_by_name(const char *name)
54618 +{
54619 + int reg_id;
54620 +
54621 + if (!strcmp(name, "voltage_dcd"))
54622 + reg_id = PCF50606_REGULATOR_DCD;
54623 + else if (!strcmp(name, "voltage_dcde"))
54624 + reg_id = PCF50606_REGULATOR_DCDE;
54625 + else if (!strcmp(name, "voltage_dcud"))
54626 + reg_id = PCF50606_REGULATOR_DCUD;
54627 + else if (!strcmp(name, "voltage_d1reg"))
54628 + reg_id = PCF50606_REGULATOR_D1REG;
54629 + else if (!strcmp(name, "voltage_d2reg"))
54630 + reg_id = PCF50606_REGULATOR_D2REG;
54631 + else if (!strcmp(name, "voltage_d3reg"))
54632 + reg_id = PCF50606_REGULATOR_D3REG;
54633 + else if (!strcmp(name, "voltage_lpreg"))
54634 + reg_id = PCF50606_REGULATOR_LPREG;
54635 + else if (!strcmp(name, "voltage_ioreg"))
54636 + reg_id = PCF50606_REGULATOR_IOREG;
54637 + else
54638 + reg_id = -1;
54639 +
54640 + return reg_id;
54641 +}
54642 +
54643 +static ssize_t show_vreg(struct device *dev, struct device_attribute *attr,
54644 + char *buf)
54645 +{
54646 + struct i2c_client *client = to_i2c_client(dev);
54647 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54648 + unsigned int reg_id;
54649 +
54650 + reg_id = reg_id_by_name(attr->attr.name);
54651 + if (reg_id < 0)
54652 + return 0;
54653 +
54654 + if (pcf50606_onoff_get(pcf, reg_id) > 0)
54655 + return sprintf(buf, "%u\n", pcf50606_voltage_get(pcf, reg_id));
54656 + else
54657 + return strlcpy(buf, "0\n", PAGE_SIZE);
54658 +}
54659 +
54660 +static ssize_t set_vreg(struct device *dev, struct device_attribute *attr,
54661 + const char *buf, size_t count)
54662 +{
54663 + struct i2c_client *client = to_i2c_client(dev);
54664 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54665 + unsigned long mvolts = simple_strtoul(buf, NULL, 10);
54666 + unsigned int reg_id;
54667 +
54668 + reg_id = reg_id_by_name(attr->attr.name);
54669 + if (reg_id < 0)
54670 + return -EIO;
54671 +
54672 + dev_dbg(dev, "attempting to set %s(%d) to %lu mvolts\n",
54673 + attr->attr.name, reg_id, mvolts);
54674 +
54675 + if (mvolts == 0) {
54676 + pcf50606_onoff_set(pcf, reg_id, 0);
54677 + } else {
54678 + if (pcf50606_voltage_set(pcf, reg_id, mvolts) < 0) {
54679 + dev_warn(dev, "refusing to set %s(%d) to %lu mvolts "
54680 + "(max=%u)\n", attr->attr.name, reg_id, mvolts,
54681 + pcf->pdata->rails[reg_id].voltage.max);
54682 + return -EINVAL;
54683 + }
54684 + pcf50606_onoff_set(pcf, reg_id, 1);
54685 + }
54686 +
54687 + return count;
54688 +}
54689 +
54690 +static DEVICE_ATTR(voltage_dcd, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
54691 +static DEVICE_ATTR(voltage_dcde, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
54692 +static DEVICE_ATTR(voltage_dcud, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
54693 +static DEVICE_ATTR(voltage_d1reg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
54694 +static DEVICE_ATTR(voltage_d2reg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
54695 +static DEVICE_ATTR(voltage_d3reg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
54696 +static DEVICE_ATTR(voltage_lpreg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
54697 +static DEVICE_ATTR(voltage_ioreg, S_IRUGO | S_IWUSR, show_vreg, set_vreg);
54698 +
54699 +/***********************************************************************
54700 + * Charger Control
54701 + ***********************************************************************/
54702 +
54703 +/* Enable/disable fast charging (500mA in the GTA01) */
54704 +void pcf50606_charge_fast(struct pcf50606_data *pcf, int on)
54705 +{
54706 + if (!(pcf->pdata->used_features & PCF50606_FEAT_MBC))
54707 + return;
54708 +
54709 + if (on) {
54710 + /* We can allow PCF to automatically charge
54711 + * using Ifast */
54712 + pcf->flags |= PCF50606_F_CHG_FAST;
54713 + reg_set_bit_mask(pcf, PCF50606_REG_MBCC1,
54714 + PCF50606_MBCC1_AUTOFST,
54715 + PCF50606_MBCC1_AUTOFST);
54716 + } else {
54717 + pcf->flags &= ~PCF50606_F_CHG_FAST;
54718 + /* disable automatic fast-charge */
54719 + reg_clear_bits(pcf, PCF50606_REG_MBCC1,
54720 + PCF50606_MBCC1_AUTOFST);
54721 + /* switch to idle mode to abort existing charge
54722 + * process */
54723 + reg_set_bit_mask(pcf, PCF50606_REG_MBCC1,
54724 + PCF50606_MBCC1_CHGMOD_MASK,
54725 + PCF50606_MBCC1_CHGMOD_IDLE);
54726 + }
54727 +}
54728 +EXPORT_SYMBOL_GPL(pcf50606_charge_fast);
54729 +
54730 +static inline u_int16_t adc_to_rntc(struct pcf50606_data *pcf, u_int16_t adc)
54731 +{
54732 + u_int32_t r_ntc = (adc * (u_int32_t)pcf->pdata->r_fix_batt)
54733 + / (1023 - adc);
54734 +
54735 + return r_ntc;
54736 +}
54737 +
54738 +static inline int16_t rntc_to_temp(u_int16_t rntc)
54739 +{
54740 + int i;
54741 +
54742 + for (i = 0; i < ARRAY_SIZE(ntc_table_10k_3370B); i++) {
54743 + if (rntc > ntc_table_10k_3370B[i])
54744 + return i - 10; /* First element is -10 */
54745 + }
54746 + return -99; /* Below our range */
54747 +}
54748 +
54749 +static ssize_t show_battemp(struct device *dev, struct device_attribute *attr,
54750 + char *buf)
54751 +{
54752 + struct i2c_client *client = to_i2c_client(dev);
54753 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54754 + u_int16_t adc;
54755 +
54756 + adc = adc_read(pcf, PCF50606_ADCMUX_BATTEMP, NULL);
54757 +
54758 + return sprintf(buf, "%d\n", rntc_to_temp(adc_to_rntc(pcf, adc)));
54759 +}
54760 +static DEVICE_ATTR(battemp, S_IRUGO | S_IWUSR, show_battemp, NULL);
54761 +
54762 +static inline int16_t adc_to_chg_milliamps(struct pcf50606_data *pcf,
54763 + u_int16_t adc_adcin1,
54764 + u_int16_t adc_batvolt)
54765 +{
54766 + int32_t res = (adc_adcin1 - adc_batvolt) * 2400;
54767 + return (res * 1000) / (pcf->pdata->r_sense_milli * 1024);
54768 +}
54769 +
54770 +static ssize_t show_chgcur(struct device *dev, struct device_attribute *attr,
54771 + char *buf)
54772 +{
54773 + struct i2c_client *client = to_i2c_client(dev);
54774 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54775 + u_int16_t adc_batvolt, adc_adcin1;
54776 + int16_t ma;
54777 +
54778 + adc_batvolt = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_ADCIN1,
54779 + &adc_adcin1);
54780 + ma = adc_to_chg_milliamps(pcf, adc_adcin1, adc_batvolt);
54781 +
54782 + return sprintf(buf, "%d\n", ma);
54783 +}
54784 +static DEVICE_ATTR(chgcur, S_IRUGO | S_IWUSR, show_chgcur, NULL);
54785 +
54786 +static const char *chgmode_names[] = {
54787 + [PCF50606_MBCC1_CHGMOD_QUAL] = "qualification",
54788 + [PCF50606_MBCC1_CHGMOD_PRE] = "pre",
54789 + [PCF50606_MBCC1_CHGMOD_TRICKLE] = "trickle",
54790 + [PCF50606_MBCC1_CHGMOD_FAST_CCCV] = "fast_cccv",
54791 + [PCF50606_MBCC1_CHGMOD_FAST_NOCC] = "fast_nocc",
54792 + [PCF50606_MBCC1_CHGMOD_FAST_NOCV] = "fast_nocv",
54793 + [PCF50606_MBCC1_CHGMOD_FAST_SW] = "fast_switch",
54794 + [PCF50606_MBCC1_CHGMOD_IDLE] = "idle",
54795 +};
54796 +
54797 +static ssize_t show_chgmode(struct device *dev, struct device_attribute *attr,
54798 + char *buf)
54799 +{
54800 + struct i2c_client *client = to_i2c_client(dev);
54801 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54802 + u_int8_t mbcc1 = reg_read(pcf, PCF50606_REG_MBCC1);
54803 + u_int8_t chgmod = (mbcc1 & PCF50606_MBCC1_CHGMOD_MASK);
54804 +
54805 + return sprintf(buf, "%s\n", chgmode_names[chgmod]);
54806 +}
54807 +
54808 +static ssize_t set_chgmode(struct device *dev, struct device_attribute *attr,
54809 + const char *buf, size_t count)
54810 +{
54811 + struct i2c_client *client = to_i2c_client(dev);
54812 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54813 + u_int8_t mbcc1 = reg_read(pcf, PCF50606_REG_MBCC1);
54814 +
54815 + mbcc1 &= ~PCF50606_MBCC1_CHGMOD_MASK;
54816 +
54817 + if (!strcmp(buf, "qualification"))
54818 + mbcc1 |= PCF50606_MBCC1_CHGMOD_QUAL;
54819 + else if (!strcmp(buf, "pre"))
54820 + mbcc1 |= PCF50606_MBCC1_CHGMOD_PRE;
54821 + else if (!strcmp(buf, "trickle"))
54822 + mbcc1 |= PCF50606_MBCC1_CHGMOD_TRICKLE;
54823 + else if (!strcmp(buf, "fast_cccv"))
54824 + mbcc1 |= PCF50606_MBCC1_CHGMOD_FAST_CCCV;
54825 + /* We don't allow the other fast modes for security reasons */
54826 + else if (!strcmp(buf, "idle"))
54827 + mbcc1 |= PCF50606_MBCC1_CHGMOD_IDLE;
54828 + else
54829 + return -EINVAL;
54830 +
54831 + reg_write(pcf, PCF50606_REG_MBCC1, mbcc1);
54832 +
54833 + return count;
54834 +}
54835 +
54836 +static DEVICE_ATTR(chgmode, S_IRUGO | S_IWUSR, show_chgmode, set_chgmode);
54837 +
54838 +static const char *chgstate_names[] = {
54839 + [PCF50606_B_CHG_FAST] = "fast_enabled",
54840 + [PCF50606_B_CHG_PRESENT] = "present",
54841 + [PCF50606_B_CHG_FOK] = "fast_ok",
54842 + [PCF50606_B_CHG_ERR] = "error",
54843 + [PCF50606_B_CHG_PROT] = "protection",
54844 + [PCF50606_B_CHG_READY] = "ready",
54845 +};
54846 +
54847 +static ssize_t show_chgstate(struct device *dev, struct device_attribute *attr,
54848 + char *buf)
54849 +{
54850 + struct i2c_client *client = to_i2c_client(dev);
54851 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54852 + char *b = buf;
54853 + int i;
54854 +
54855 + for (i = 0; i < 32; i++)
54856 + if (pcf->flags & (1 << i) && i < ARRAY_SIZE(chgstate_names))
54857 + b += sprintf(b, "%s ", chgstate_names[i]);
54858 +
54859 + if (b > buf)
54860 + b += sprintf(b, "\n");
54861 +
54862 + return b - buf;
54863 +}
54864 +static DEVICE_ATTR(chgstate, S_IRUGO | S_IWUSR, show_chgstate, NULL);
54865 +
54866 +/***********************************************************************
54867 + * APM emulation
54868 + ***********************************************************************/
54869 +
54870 +static void pcf50606_get_power_status(struct apm_power_info *info)
54871 +{
54872 + struct pcf50606_data *pcf = pcf50606_global;
54873 + u_int8_t mbcc1 = reg_read(pcf, PCF50606_REG_MBCC1);
54874 + u_int8_t chgmod = mbcc1 & PCF50606_MBCC1_CHGMOD_MASK;
54875 + u_int16_t battvolt = pcf50606_battvolt(pcf);
54876 +
54877 + if (reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON)
54878 + info->ac_line_status = APM_AC_ONLINE;
54879 + else
54880 + info->ac_line_status = APM_AC_OFFLINE;
54881 +
54882 + switch (chgmod) {
54883 + case PCF50606_MBCC1_CHGMOD_QUAL:
54884 + case PCF50606_MBCC1_CHGMOD_PRE:
54885 + case PCF50606_MBCC1_CHGMOD_IDLE:
54886 + info->battery_life = battvolt_scale(battvolt);
54887 + break;
54888 + default:
54889 + info->battery_status = APM_BATTERY_STATUS_CHARGING;
54890 + info->battery_flag = APM_BATTERY_FLAG_CHARGING;
54891 + break;
54892 + }
54893 +}
54894 +
54895 +/***********************************************************************
54896 + * RTC
54897 + ***********************************************************************/
54898 +
54899 +struct pcf50606_time {
54900 + u_int8_t sec;
54901 + u_int8_t min;
54902 + u_int8_t hour;
54903 + u_int8_t wkday;
54904 + u_int8_t day;
54905 + u_int8_t month;
54906 + u_int8_t year;
54907 +};
54908 +
54909 +static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50606_time *pcf)
54910 +{
54911 + rtc->tm_sec = bcd2bin(pcf->sec);
54912 + rtc->tm_min = bcd2bin(pcf->min);
54913 + rtc->tm_hour = bcd2bin(pcf->hour);
54914 + rtc->tm_wday = bcd2bin(pcf->wkday);
54915 + rtc->tm_mday = bcd2bin(pcf->day);
54916 + rtc->tm_mon = bcd2bin(pcf->month);
54917 + rtc->tm_year = bcd2bin(pcf->year) + 100;
54918 +}
54919 +
54920 +static void rtc2pcf_time(struct pcf50606_time *pcf, struct rtc_time *rtc)
54921 +{
54922 + pcf->sec = bin2bcd(rtc->tm_sec);
54923 + pcf->min = bin2bcd(rtc->tm_min);
54924 + pcf->hour = bin2bcd(rtc->tm_hour);
54925 + pcf->wkday = bin2bcd(rtc->tm_wday);
54926 + pcf->day = bin2bcd(rtc->tm_mday);
54927 + pcf->month = bin2bcd(rtc->tm_mon);
54928 + pcf->year = bin2bcd(rtc->tm_year - 100);
54929 +}
54930 +
54931 +static int pcf50606_rtc_ioctl(struct device *dev, unsigned int cmd,
54932 + unsigned long arg)
54933 +{
54934 + struct i2c_client *client = to_i2c_client(dev);
54935 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54936 +
54937 + switch (cmd) {
54938 + case RTC_AIE_OFF:
54939 + /* disable the alarm interrupt */
54940 + reg_set_bit_mask(pcf, PCF50606_REG_INT1M,
54941 + PCF50606_INT1_ALARM, PCF50606_INT1_ALARM);
54942 + return 0;
54943 + case RTC_AIE_ON:
54944 + /* enable the alarm interrupt */
54945 + reg_clear_bits(pcf, PCF50606_REG_INT1M, PCF50606_INT1_ALARM);
54946 + return 0;
54947 + case RTC_PIE_OFF:
54948 + /* disable periodic interrupt (hz tick) */
54949 + pcf->flags &= ~PCF50606_F_RTC_SECOND;
54950 + reg_set_bit_mask(pcf, PCF50606_REG_INT1M,
54951 + PCF50606_INT1_SECOND, PCF50606_INT1_SECOND);
54952 + return 0;
54953 + case RTC_PIE_ON:
54954 + /* ensable periodic interrupt (hz tick) */
54955 + pcf->flags |= PCF50606_F_RTC_SECOND;
54956 + reg_clear_bits(pcf, PCF50606_REG_INT1M, PCF50606_INT1_SECOND);
54957 + return 0;
54958 + }
54959 + return -ENOIOCTLCMD;
54960 +}
54961 +
54962 +static int pcf50606_rtc_read_time(struct device *dev, struct rtc_time *tm)
54963 +{
54964 + struct i2c_client *client = to_i2c_client(dev);
54965 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54966 + struct pcf50606_time pcf_tm;
54967 +
54968 + mutex_lock(&pcf->lock);
54969 + pcf_tm.sec = __reg_read(pcf, PCF50606_REG_RTCSC);
54970 + pcf_tm.min = __reg_read(pcf, PCF50606_REG_RTCMN);
54971 + pcf_tm.hour = __reg_read(pcf, PCF50606_REG_RTCHR);
54972 + pcf_tm.wkday = __reg_read(pcf, PCF50606_REG_RTCWD);
54973 + pcf_tm.day = __reg_read(pcf, PCF50606_REG_RTCDT);
54974 + pcf_tm.month = __reg_read(pcf, PCF50606_REG_RTCMT);
54975 + pcf_tm.year = __reg_read(pcf, PCF50606_REG_RTCYR);
54976 + mutex_unlock(&pcf->lock);
54977 +
54978 + dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
54979 + pcf_tm.day, pcf_tm.month, pcf_tm.year,
54980 + pcf_tm.hour, pcf_tm.min, pcf_tm.sec);
54981 +
54982 + pcf2rtc_time(tm, &pcf_tm);
54983 +
54984 + dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
54985 + tm->tm_mday, tm->tm_mon, tm->tm_year,
54986 + tm->tm_hour, tm->tm_min, tm->tm_sec);
54987 +
54988 + return 0;
54989 +}
54990 +
54991 +static int pcf50606_rtc_set_time(struct device *dev, struct rtc_time *tm)
54992 +{
54993 + struct i2c_client *client = to_i2c_client(dev);
54994 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54995 + struct pcf50606_time pcf_tm;
54996 + u_int8_t int1m;
54997 +
54998 + dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
54999 + tm->tm_mday, tm->tm_mon, tm->tm_year,
55000 + tm->tm_hour, tm->tm_min, tm->tm_sec);
55001 + rtc2pcf_time(&pcf_tm, tm);
55002 + dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
55003 + pcf_tm.day, pcf_tm.month, pcf_tm.year,
55004 + pcf_tm.hour, pcf_tm.min, pcf_tm.sec);
55005 +
55006 + mutex_lock(&pcf->lock);
55007 +
55008 + /* disable SECOND interrupt */
55009 + int1m = __reg_read(pcf, PCF50606_REG_INT1M);
55010 + __reg_write(pcf, PCF50606_REG_INT1M, int1m | PCF50606_INT1_SECOND);
55011 +
55012 + __reg_write(pcf, PCF50606_REG_RTCSC, pcf_tm.sec);
55013 + __reg_write(pcf, PCF50606_REG_RTCMN, pcf_tm.min);
55014 + __reg_write(pcf, PCF50606_REG_RTCHR, pcf_tm.hour);
55015 + __reg_write(pcf, PCF50606_REG_RTCWD, pcf_tm.wkday);
55016 + __reg_write(pcf, PCF50606_REG_RTCDT, pcf_tm.day);
55017 + __reg_write(pcf, PCF50606_REG_RTCMT, pcf_tm.month);
55018 + __reg_write(pcf, PCF50606_REG_RTCYR, pcf_tm.year);
55019 +
55020 + /* restore INT1M, potentially re-enable SECOND interrupt */
55021 + __reg_write(pcf, PCF50606_REG_INT1M, int1m);
55022 +
55023 + mutex_unlock(&pcf->lock);
55024 +
55025 + return 0;
55026 +}
55027 +
55028 +static int pcf50606_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
55029 +{
55030 + struct i2c_client *client = to_i2c_client(dev);
55031 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55032 + struct pcf50606_time pcf_tm;
55033 +
55034 + mutex_lock(&pcf->lock);
55035 + alrm->enabled =
55036 + __reg_read(pcf, PCF50606_REG_INT1M) & PCF50606_INT1_ALARM
55037 + ? 0 : 1;
55038 + pcf_tm.sec = __reg_read(pcf, PCF50606_REG_RTCSCA);
55039 + pcf_tm.min = __reg_read(pcf, PCF50606_REG_RTCMNA);
55040 + pcf_tm.hour = __reg_read(pcf, PCF50606_REG_RTCHRA);
55041 + pcf_tm.wkday = __reg_read(pcf, PCF50606_REG_RTCWDA);
55042 + pcf_tm.day = __reg_read(pcf, PCF50606_REG_RTCDTA);
55043 + pcf_tm.month = __reg_read(pcf, PCF50606_REG_RTCMTA);
55044 + pcf_tm.year = __reg_read(pcf, PCF50606_REG_RTCYRA);
55045 + mutex_unlock(&pcf->lock);
55046 +
55047 + pcf2rtc_time(&alrm->time, &pcf_tm);
55048 +
55049 + return 0;
55050 +}
55051 +
55052 +static int pcf50606_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
55053 +{
55054 + struct i2c_client *client = to_i2c_client(dev);
55055 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55056 + struct pcf50606_time pcf_tm;
55057 + u_int8_t irqmask;
55058 +
55059 + rtc2pcf_time(&pcf_tm, &alrm->time);
55060 +
55061 + mutex_lock(&pcf->lock);
55062 +
55063 + /* disable alarm interrupt */
55064 + irqmask = __reg_read(pcf, PCF50606_REG_INT1M);
55065 + irqmask |= PCF50606_INT1_ALARM;
55066 + __reg_write(pcf, PCF50606_REG_INT1M, irqmask);
55067 +
55068 + __reg_write(pcf, PCF50606_REG_RTCSCA, pcf_tm.sec);
55069 + __reg_write(pcf, PCF50606_REG_RTCMNA, pcf_tm.min);
55070 + __reg_write(pcf, PCF50606_REG_RTCHRA, pcf_tm.hour);
55071 + __reg_write(pcf, PCF50606_REG_RTCWDA, pcf_tm.wkday);
55072 + __reg_write(pcf, PCF50606_REG_RTCDTA, pcf_tm.day);
55073 + __reg_write(pcf, PCF50606_REG_RTCMTA, pcf_tm.month);
55074 + __reg_write(pcf, PCF50606_REG_RTCYRA, pcf_tm.year);
55075 +
55076 + if (alrm->enabled) {
55077 + /* (re-)enaable alarm interrupt */
55078 + irqmask = __reg_read(pcf, PCF50606_REG_INT1M);
55079 + irqmask &= ~PCF50606_INT1_ALARM;
55080 + __reg_write(pcf, PCF50606_REG_INT1M, irqmask);
55081 + }
55082 +
55083 + mutex_unlock(&pcf->lock);
55084 +
55085 + /* FIXME */
55086 + return 0;
55087 +}
55088 +
55089 +static struct rtc_class_ops pcf50606_rtc_ops = {
55090 + .ioctl = pcf50606_rtc_ioctl,
55091 + .read_time = pcf50606_rtc_read_time,
55092 + .set_time = pcf50606_rtc_set_time,
55093 + .read_alarm = pcf50606_rtc_read_alarm,
55094 + .set_alarm = pcf50606_rtc_set_alarm,
55095 +};
55096 +
55097 +/***********************************************************************
55098 + * Watchdog
55099 + ***********************************************************************/
55100 +
55101 +static void pcf50606_wdt_start(struct pcf50606_data *pcf)
55102 +{
55103 + reg_set_bit_mask(pcf, PCF50606_REG_OOCC1, PCF50606_OOCC1_WDTRST,
55104 + PCF50606_OOCC1_WDTRST);
55105 +}
55106 +
55107 +static void pcf50606_wdt_stop(struct pcf50606_data *pcf)
55108 +{
55109 + reg_clear_bits(pcf, PCF50606_REG_OOCS, PCF50606_OOCS_WDTEXP);
55110 +}
55111 +
55112 +static void pcf50606_wdt_keepalive(struct pcf50606_data *pcf)
55113 +{
55114 + pcf50606_wdt_start(pcf);
55115 +}
55116 +
55117 +static int pcf50606_wdt_open(struct inode *inode, struct file *file)
55118 +{
55119 + struct pcf50606_data *pcf = pcf50606_global;
55120 +
55121 + file->private_data = pcf;
55122 +
55123 + /* start the timer */
55124 + pcf50606_wdt_start(pcf);
55125 +
55126 + return nonseekable_open(inode, file);
55127 +}
55128 +
55129 +static int pcf50606_wdt_release(struct inode *inode, struct file *file)
55130 +{
55131 + struct pcf50606_data *pcf = file->private_data;
55132 +
55133 + if (pcf->allow_close == CLOSE_STATE_ALLOW)
55134 + pcf50606_wdt_stop(pcf);
55135 + else {
55136 + printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
55137 + pcf50606_wdt_keepalive(pcf);
55138 + }
55139 +
55140 + pcf->allow_close = CLOSE_STATE_NOT;
55141 +
55142 + return 0;
55143 +}
55144 +
55145 +static ssize_t pcf50606_wdt_write(struct file *file, const char __user *data,
55146 + size_t len, loff_t *ppos)
55147 +{
55148 + struct pcf50606_data *pcf = file->private_data;
55149 + if (len) {
55150 + size_t i;
55151 +
55152 + for (i = 0; i != len; i++) {
55153 + char c;
55154 + if (get_user(c, data + i))
55155 + return -EFAULT;
55156 + if (c == 'V')
55157 + pcf->allow_close = CLOSE_STATE_ALLOW;
55158 + }
55159 + pcf50606_wdt_keepalive(pcf);
55160 + }
55161 +
55162 + return len;
55163 +}
55164 +
55165 +static struct watchdog_info pcf50606_wdt_ident = {
55166 + .options = WDIOF_MAGICCLOSE,
55167 + .firmware_version = 0,
55168 + .identity = "PCF50606 Watchdog",
55169 +};
55170 +
55171 +static int pcf50606_wdt_ioctl(struct inode *inode, struct file *file,
55172 + unsigned int cmd, unsigned long arg)
55173 +{
55174 + struct pcf50606_data *pcf = file->private_data;
55175 + void __user *argp = (void __user *)arg;
55176 + int __user *p = argp;
55177 +
55178 + switch (cmd) {
55179 + case WDIOC_GETSUPPORT:
55180 + return copy_to_user(argp, &pcf50606_wdt_ident,
55181 + sizeof(pcf50606_wdt_ident)) ? -EFAULT : 0;
55182 + break;
55183 + case WDIOC_GETSTATUS:
55184 + case WDIOC_GETBOOTSTATUS:
55185 + return put_user(0, p);
55186 + case WDIOC_KEEPALIVE:
55187 + pcf50606_wdt_keepalive(pcf);
55188 + return 0;
55189 + case WDIOC_GETTIMEOUT:
55190 + return put_user(8, p);
55191 + default:
55192 + return -ENOIOCTLCMD;
55193 + }
55194 +}
55195 +
55196 +static struct file_operations pcf50606_wdt_fops = {
55197 + .owner = THIS_MODULE,
55198 + .llseek = no_llseek,
55199 + .write = &pcf50606_wdt_write,
55200 + .ioctl = &pcf50606_wdt_ioctl,
55201 + .open = &pcf50606_wdt_open,
55202 + .release = &pcf50606_wdt_release,
55203 +};
55204 +
55205 +static struct miscdevice pcf50606_wdt_miscdev = {
55206 + .minor = WATCHDOG_MINOR,
55207 + .name = "watchdog",
55208 + .fops = &pcf50606_wdt_fops,
55209 +};
55210 +
55211 +/***********************************************************************
55212 + * PWM
55213 + ***********************************************************************/
55214 +
55215 +static const char *pwm_dc_table[] = {
55216 + "0/16", "1/16", "2/16", "3/16",
55217 + "4/16", "5/16", "6/16", "7/16",
55218 + "8/16", "9/16", "10/16", "11/16",
55219 + "12/16", "13/16", "14/16", "15/16",
55220 +};
55221 +
55222 +static ssize_t show_pwm_dc(struct device *dev, struct device_attribute *attr,
55223 + char *buf)
55224 +{
55225 + struct i2c_client *client = to_i2c_client(dev);
55226 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55227 + u_int8_t val;
55228 +
55229 + val = reg_read(pcf, PCF50606_REG_PWMC1) >> PCF50606_PWMC1_DC_SHIFT;
55230 + val &= 0xf;
55231 +
55232 + return sprintf(buf, "%s\n", pwm_dc_table[val]);
55233 +}
55234 +
55235 +static ssize_t set_pwm_dc(struct device *dev, struct device_attribute *attr,
55236 + const char *buf, size_t count)
55237 +{
55238 + struct i2c_client *client = to_i2c_client(dev);
55239 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55240 + u_int8_t i;
55241 +
55242 + for (i = 0; i < ARRAY_SIZE(pwm_dc_table); i++) {
55243 + if (!strncmp(buf, pwm_dc_table[i], strlen(pwm_dc_table[i]))) {
55244 + dev_dbg(dev, "setting pwm dc %s\n\r", pwm_dc_table[i]);
55245 + reg_set_bit_mask(pcf, PCF50606_REG_PWMC1, 0x1e,
55246 + (i << PCF50606_PWMC1_DC_SHIFT));
55247 + }
55248 + }
55249 + return count;
55250 +}
55251 +
55252 +static DEVICE_ATTR(pwm_dc, S_IRUGO | S_IWUSR, show_pwm_dc, set_pwm_dc);
55253 +
55254 +static const char *pwm_clk_table[] = {
55255 + "512", "256", "128", "64",
55256 + "56300", "28100", "14100", "7000",
55257 +};
55258 +
55259 +static ssize_t show_pwm_clk(struct device *dev, struct device_attribute *attr,
55260 + char *buf)
55261 +{
55262 + struct i2c_client *client = to_i2c_client(dev);
55263 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55264 + u_int8_t val;
55265 +
55266 + val = reg_read(pcf, PCF50606_REG_PWMC1) >> PCF50606_PWMC1_CLK_SHIFT;
55267 + val &= 0x7;
55268 +
55269 + return sprintf(buf, "%s\n", pwm_clk_table[val]);
55270 +}
55271 +
55272 +static ssize_t set_pwm_clk(struct device *dev, struct device_attribute *attr,
55273 + const char *buf, size_t count)
55274 +{
55275 + struct i2c_client *client = to_i2c_client(dev);
55276 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55277 + u_int8_t i;
55278 +
55279 + for (i = 0; i < ARRAY_SIZE(pwm_clk_table); i++) {
55280 + if (!strncmp(buf, pwm_clk_table[i], strlen(pwm_clk_table[i]))) {
55281 + dev_dbg(dev, "setting pwm clk %s\n\r",
55282 + pwm_clk_table[i]);
55283 + reg_set_bit_mask(pcf, PCF50606_REG_PWMC1, 0xe0,
55284 + (i << PCF50606_PWMC1_CLK_SHIFT));
55285 + }
55286 + }
55287 + return count;
55288 +}
55289 +
55290 +static DEVICE_ATTR(pwm_clk, S_IRUGO | S_IWUSR, show_pwm_clk, set_pwm_clk);
55291 +
55292 +static int pcf50606bl_get_intensity(struct backlight_device *bd)
55293 +{
55294 + struct pcf50606_data *pcf = bl_get_data(bd);
55295 + int intensity = reg_read(pcf, PCF50606_REG_PWMC1);
55296 + intensity = (intensity >> PCF50606_PWMC1_DC_SHIFT);
55297 +
55298 + return intensity & 0xf;
55299 +}
55300 +
55301 +static int pcf50606bl_set_intensity(struct backlight_device *bd)
55302 +{
55303 + struct pcf50606_data *pcf = bl_get_data(bd);
55304 + int intensity = bd->props.brightness;
55305 +
55306 + if (bd->props.power != FB_BLANK_UNBLANK)
55307 + intensity = 0;
55308 + if (bd->props.fb_blank != FB_BLANK_UNBLANK)
55309 + intensity = 0;
55310 +
55311 + return reg_set_bit_mask(pcf, PCF50606_REG_PWMC1, 0x1e,
55312 + (intensity << PCF50606_PWMC1_DC_SHIFT));
55313 +}
55314 +
55315 +static struct backlight_ops pcf50606bl_ops = {
55316 + .get_brightness = pcf50606bl_get_intensity,
55317 + .update_status = pcf50606bl_set_intensity,
55318 +};
55319 +
55320 +/***********************************************************************
55321 + * Driver initialization
55322 + ***********************************************************************/
55323 +
55324 +#ifdef CONFIG_MACH_NEO1973_GTA01
55325 +/* We currently place those platform devices here to make sure the device
55326 + * suspend/resume order is correct */
55327 +static struct platform_device gta01_pm_gps_dev = {
55328 + .name = "neo1973-pm-gps",
55329 +};
55330 +
55331 +static struct platform_device gta01_pm_bt_dev = {
55332 + .name = "neo1973-pm-bt",
55333 +};
55334 +#endif
55335 +
55336 +static struct attribute *pcf_sysfs_entries[16] = {
55337 + &dev_attr_voltage_dcd.attr,
55338 + &dev_attr_voltage_dcde.attr,
55339 + &dev_attr_voltage_dcud.attr,
55340 + &dev_attr_voltage_d1reg.attr,
55341 + &dev_attr_voltage_d2reg.attr,
55342 + &dev_attr_voltage_d3reg.attr,
55343 + &dev_attr_voltage_lpreg.attr,
55344 + &dev_attr_voltage_ioreg.attr,
55345 + NULL
55346 +};
55347 +
55348 +static struct attribute_group pcf_attr_group = {
55349 + .name = NULL, /* put in device directory */
55350 + .attrs = pcf_sysfs_entries,
55351 +};
55352 +
55353 +static void populate_sysfs_group(struct pcf50606_data *pcf)
55354 +{
55355 + int i = 0;
55356 + struct attribute **attr;
55357 +
55358 + for (attr = pcf_sysfs_entries; *attr; attr++)
55359 + i++;
55360 +
55361 + if (pcf->pdata->used_features & PCF50606_FEAT_MBC) {
55362 + pcf_sysfs_entries[i++] = &dev_attr_chgstate.attr;
55363 + pcf_sysfs_entries[i++] = &dev_attr_chgmode.attr;
55364 + }
55365 +
55366 + if (pcf->pdata->used_features & PCF50606_FEAT_CHGCUR)
55367 + pcf_sysfs_entries[i++] = &dev_attr_chgcur.attr;
55368 +
55369 + if (pcf->pdata->used_features & PCF50606_FEAT_BATVOLT)
55370 + pcf_sysfs_entries[i++] = &dev_attr_battvolt.attr;
55371 +
55372 + if (pcf->pdata->used_features & PCF50606_FEAT_BATTEMP)
55373 + pcf_sysfs_entries[i++] = &dev_attr_battemp.attr;
55374 +
55375 + if (pcf->pdata->used_features & PCF50606_FEAT_PWM) {
55376 + pcf_sysfs_entries[i++] = &dev_attr_pwm_dc.attr;
55377 + pcf_sysfs_entries[i++] = &dev_attr_pwm_clk.attr;
55378 + }
55379 +}
55380 +
55381 +static int pcf50606_detect(struct i2c_adapter *adapter, int address, int kind)
55382 +{
55383 + struct i2c_client *new_client;
55384 + struct pcf50606_data *data;
55385 + int err = 0;
55386 + int irq;
55387 +
55388 + if (!pcf50606_pdev) {
55389 + printk(KERN_ERR "pcf50606: driver needs a platform_device!\n");
55390 + return -EIO;
55391 + }
55392 +
55393 + irq = platform_get_irq(pcf50606_pdev, 0);
55394 + if (irq < 0) {
55395 + dev_err(&pcf50606_pdev->dev, "no irq in platform resources!\n");
55396 + return -EIO;
55397 + }
55398 +
55399 + /* At the moment, we only support one PCF50606 in a system */
55400 + if (pcf50606_global) {
55401 + dev_err(&pcf50606_pdev->dev,
55402 + "currently only one chip supported\n");
55403 + return -EBUSY;
55404 + }
55405 +
55406 + data = kzalloc(sizeof(*data), GFP_KERNEL);
55407 + if (!data)
55408 + return -ENOMEM;
55409 +
55410 + mutex_init(&data->lock);
55411 + mutex_init(&data->working_lock);
55412 + INIT_WORK(&data->work, pcf50606_work);
55413 + data->irq = irq;
55414 + data->working = 0;
55415 + data->suppress_onkey_events = 0;
55416 + data->onkey_seconds = -1;
55417 + data->pdata = pcf50606_pdev->dev.platform_data;
55418 +
55419 + new_client = &data->client;
55420 + i2c_set_clientdata(new_client, data);
55421 + new_client->addr = address;
55422 + new_client->adapter = adapter;
55423 + new_client->driver = &pcf50606_driver;
55424 + new_client->flags = 0;
55425 + strlcpy(new_client->name, "pcf50606", I2C_NAME_SIZE);
55426 +
55427 + /* now we try to detect the chip */
55428 +
55429 + /* register with i2c core */
55430 + err = i2c_attach_client(new_client);
55431 + if (err) {
55432 + dev_err(&new_client->dev,
55433 + "error during i2c_attach_client()\n");
55434 + goto exit_free;
55435 + }
55436 +
55437 + populate_sysfs_group(data);
55438 +
55439 + err = sysfs_create_group(&new_client->dev.kobj, &pcf_attr_group);
55440 + if (err) {
55441 + dev_err(&new_client->dev, "error creating sysfs group\n");
55442 + goto exit_detach;
55443 + }
55444 +
55445 + /* create virtual charger 'device' */
55446 +
55447 + /* input device registration */
55448 + data->input_dev = input_allocate_device();
55449 + if (!data->input_dev)
55450 + goto exit_sysfs;
55451 +
55452 + data->input_dev->name = "FIC Neo1973 PMU events";
55453 + data->input_dev->phys = "I2C";
55454 + data->input_dev->id.bustype = BUS_I2C;
55455 +
55456 + data->input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);
55457 + set_bit(KEY_POWER, data->input_dev->keybit);
55458 + set_bit(KEY_POWER2, data->input_dev->keybit);
55459 + set_bit(KEY_BATTERY, data->input_dev->keybit);
55460 +
55461 + err = input_register_device(data->input_dev);
55462 + if (err)
55463 + goto exit_sysfs;
55464 +
55465 + /* register power off handler with core power management */
55466 + pm_power_off = &pcf50606_go_standby;
55467 +
55468 + /* configure interrupt mask */
55469 + /* we don't mask SECOND here, because we want one to do coldplug with */
55470 + reg_write(data, PCF50606_REG_INT1M, 0x00);
55471 + reg_write(data, PCF50606_REG_INT2M, 0x00);
55472 + reg_write(data, PCF50606_REG_INT3M, PCF50606_INT3_TSCPRES);
55473 +
55474 + err = request_irq(irq, pcf50606_irq, IRQF_TRIGGER_FALLING,
55475 + "pcf50606", data);
55476 + if (err < 0)
55477 + goto exit_input;
55478 +
55479 + if (enable_irq_wake(irq) < 0)
55480 + dev_err(&new_client->dev, "IRQ %u cannot be enabled as wake-up"
55481 + "source in this hardware revision!", irq);
55482 +
55483 + pcf50606_global = data;
55484 +
55485 + if (data->pdata->used_features & PCF50606_FEAT_RTC) {
55486 + data->rtc = rtc_device_register("pcf50606", &new_client->dev,
55487 + &pcf50606_rtc_ops, THIS_MODULE);
55488 + if (IS_ERR(data->rtc)) {
55489 + err = PTR_ERR(data->rtc);
55490 + goto exit_irq;
55491 + }
55492 + }
55493 +
55494 + if (data->pdata->used_features & PCF50606_FEAT_WDT) {
55495 + err = misc_register(&pcf50606_wdt_miscdev);
55496 + if (err) {
55497 + dev_err(&new_client->dev, "cannot register miscdev on "
55498 + "minor=%d (%d)\n", WATCHDOG_MINOR, err);
55499 + goto exit_rtc;
55500 + }
55501 + }
55502 +
55503 + if (data->pdata->used_features & PCF50606_FEAT_PWM) {
55504 + /* enable PWM controller */
55505 + reg_set_bit_mask(data, PCF50606_REG_PWMC1,
55506 + PCF50606_PWMC1_ACTSET,
55507 + PCF50606_PWMC1_ACTSET);
55508 + }
55509 +
55510 + if (data->pdata->used_features & PCF50606_FEAT_PWM_BL) {
55511 + data->backlight = backlight_device_register("pcf50606-bl",
55512 + &new_client->dev,
55513 + data,
55514 + &pcf50606bl_ops);
55515 + if (!data->backlight)
55516 + goto exit_misc;
55517 + data->backlight->props.max_brightness = 16;
55518 + data->backlight->props.power = FB_BLANK_UNBLANK;
55519 + data->backlight->props.brightness =
55520 + data->pdata->init_brightness;
55521 + backlight_update_status(data->backlight);
55522 + }
55523 +
55524 + apm_get_power_status = pcf50606_get_power_status;
55525 +
55526 +#ifdef CONFIG_MACH_NEO1973_GTA01
55527 + if (machine_is_neo1973_gta01()) {
55528 + gta01_pm_gps_dev.dev.parent = &new_client->dev;
55529 + switch (system_rev) {
55530 + case GTA01Bv2_SYSTEM_REV:
55531 + case GTA01Bv3_SYSTEM_REV:
55532 + case GTA01Bv4_SYSTEM_REV:
55533 + gta01_pm_bt_dev.dev.parent = &new_client->dev;
55534 + platform_device_register(&gta01_pm_bt_dev);
55535 + break;
55536 + }
55537 + platform_device_register(&gta01_pm_gps_dev);
55538 + /* a link for gllin compatibility */
55539 + err = bus_create_device_link(&platform_bus_type,
55540 + &gta01_pm_gps_dev.dev.kobj, "gta01-pm-gps.0");
55541 + if (err)
55542 + printk(KERN_ERR
55543 + "sysfs_create_link (gta01-pm-gps.0): %d\n", err);
55544 + }
55545 +#endif
55546 +
55547 + if (data->pdata->used_features & PCF50606_FEAT_ACD)
55548 + reg_set_bit_mask(data, PCF50606_REG_ACDC1,
55549 + PCF50606_ACDC1_ACDAPE, PCF50606_ACDC1_ACDAPE);
55550 + else
55551 + reg_clear_bits(data, PCF50606_REG_ACDC1,
55552 + PCF50606_ACDC1_ACDAPE);
55553 +
55554 + return 0;
55555 +
55556 +exit_misc:
55557 + if (data->pdata->used_features & PCF50606_FEAT_WDT)
55558 + misc_deregister(&pcf50606_wdt_miscdev);
55559 +exit_rtc:
55560 + if (data->pdata->used_features & PCF50606_FEAT_RTC)
55561 + rtc_device_unregister(pcf50606_global->rtc);
55562 +exit_irq:
55563 + free_irq(pcf50606_global->irq, pcf50606_global);
55564 + pcf50606_global = NULL;
55565 +exit_input:
55566 + pm_power_off = NULL;
55567 + input_unregister_device(data->input_dev);
55568 +exit_sysfs:
55569 + sysfs_remove_group(&new_client->dev.kobj, &pcf_attr_group);
55570 +exit_detach:
55571 + i2c_detach_client(new_client);
55572 +exit_free:
55573 + kfree(data);
55574 + return err;
55575 +}
55576 +
55577 +static int pcf50606_attach_adapter(struct i2c_adapter *adapter)
55578 +{
55579 + return i2c_probe(adapter, &addr_data, &pcf50606_detect);
55580 +}
55581 +
55582 +static int pcf50606_detach_client(struct i2c_client *client)
55583 +{
55584 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55585 +
55586 + apm_get_power_status = NULL;
55587 + input_unregister_device(pcf->input_dev);
55588 +
55589 + if (pcf->pdata->used_features & PCF50606_FEAT_PWM_BL)
55590 + backlight_device_unregister(pcf->backlight);
55591 +
55592 + if (pcf->pdata->used_features & PCF50606_FEAT_WDT)
55593 + misc_deregister(&pcf50606_wdt_miscdev);
55594 +
55595 + if (pcf->pdata->used_features & PCF50606_FEAT_RTC)
55596 + rtc_device_unregister(pcf->rtc);
55597 +
55598 + free_irq(pcf->irq, pcf);
55599 +
55600 + sysfs_remove_group(&client->dev.kobj, &pcf_attr_group);
55601 +
55602 + pm_power_off = NULL;
55603 +
55604 + kfree(pcf);
55605 +
55606 + return 0;
55607 +}
55608 +
55609 +#ifdef CONFIG_PM
55610 +#define INT1M_RESUMERS (PCF50606_INT1_ALARM | \
55611 + PCF50606_INT1_ONKEYF | \
55612 + PCF50606_INT1_EXTONR)
55613 +#define INT2M_RESUMERS (PCF50606_INT2_CHGWD10S | \
55614 + PCF50606_INT2_CHGPROT | \
55615 + PCF50606_INT2_CHGERR)
55616 +#define INT3M_RESUMERS (PCF50606_INT3_LOWBAT | \
55617 + PCF50606_INT3_HIGHTMP | \
55618 + PCF50606_INT3_ACDINS)
55619 +static int pcf50606_suspend(struct device *dev, pm_message_t state)
55620 +{
55621 + struct i2c_client *client = to_i2c_client(dev);
55622 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55623 + int i;
55624 +
55625 + /* we suspend once (!) as late as possible in the suspend sequencing */
55626 +
55627 + if ((state.event != PM_EVENT_SUSPEND) ||
55628 + (pcf->suspend_state != PCF50606_SS_RUNNING))
55629 + return -EBUSY;
55630 +
55631 + /* The general idea is to power down all unused power supplies,
55632 + * and then mask all PCF50606 interrup sources but EXTONR, ONKEYF
55633 + * and ALARM */
55634 +
55635 + mutex_lock(&pcf->lock);
55636 +
55637 + pcf->suspend_state = PCF50606_SS_STARTING_SUSPEND;
55638 +
55639 + /* we are not going to service any further interrupts until we
55640 + * resume. If the IRQ workqueue is still pending in the background,
55641 + * it will bail when it sees we set suspend state above.
55642 + */
55643 +
55644 + disable_irq(pcf->irq);
55645 +
55646 + /* Save all registers that don't "survive" standby state */
55647 + pcf->standby_regs.dcdc1 = __reg_read(pcf, PCF50606_REG_DCDC1);
55648 + pcf->standby_regs.dcdc2 = __reg_read(pcf, PCF50606_REG_DCDC2);
55649 + pcf->standby_regs.dcdec1 = __reg_read(pcf, PCF50606_REG_DCDEC1);
55650 + pcf->standby_regs.dcudc1 = __reg_read(pcf, PCF50606_REG_DCUDC1);
55651 + pcf->standby_regs.ioregc = __reg_read(pcf, PCF50606_REG_IOREGC);
55652 + pcf->standby_regs.d1regc1 = __reg_read(pcf, PCF50606_REG_D1REGC1);
55653 + pcf->standby_regs.d2regc1 = __reg_read(pcf, PCF50606_REG_D2REGC1);
55654 + pcf->standby_regs.d3regc1 = __reg_read(pcf, PCF50606_REG_D3REGC1);
55655 + pcf->standby_regs.lpregc1 = __reg_read(pcf, PCF50606_REG_LPREGC1);
55656 + pcf->standby_regs.adcc1 = __reg_read(pcf, PCF50606_REG_ADCC1);
55657 + pcf->standby_regs.adcc2 = __reg_read(pcf, PCF50606_REG_ADCC2);
55658 + pcf->standby_regs.pwmc1 = __reg_read(pcf, PCF50606_REG_PWMC1);
55659 +
55660 + /* switch off power supplies that are not needed during suspend */
55661 + for (i = 0; i < __NUM_PCF50606_REGULATORS; i++) {
55662 + if (!(pcf->pdata->rails[i].flags & PMU_VRAIL_F_SUSPEND_ON)) {
55663 + u_int8_t tmp;
55664 +
55665 + /* IOREG powers the I@C interface so we cannot switch
55666 + * it off */
55667 + if (i == PCF50606_REGULATOR_IOREG)
55668 + continue;
55669 +
55670 + dev_dbg(dev, "disabling pcf50606 regulator %u\n", i);
55671 + /* we cannot use pcf50606_onoff_set() because we're
55672 + * already under the mutex */
55673 + tmp = __reg_read(pcf, regulator_registers[i]);
55674 + tmp &= 0x1f;
55675 + __reg_write(pcf, regulator_registers[i], tmp);
55676 + }
55677 + }
55678 +
55679 + pcf->standby_regs.int1m = __reg_read(pcf, PCF50606_REG_INT1M);
55680 + pcf->standby_regs.int2m = __reg_read(pcf, PCF50606_REG_INT2M);
55681 + pcf->standby_regs.int3m = __reg_read(pcf, PCF50606_REG_INT3M);
55682 + __reg_write(pcf, PCF50606_REG_INT1M, ~INT1M_RESUMERS & 0xff);
55683 + __reg_write(pcf, PCF50606_REG_INT2M, ~INT2M_RESUMERS & 0xff);
55684 + __reg_write(pcf, PCF50606_REG_INT3M, ~INT3M_RESUMERS & 0xff);
55685 +
55686 + pcf->suspend_state = PCF50606_SS_COMPLETED_SUSPEND;
55687 +
55688 + mutex_unlock(&pcf->lock);
55689 +
55690 + return 0;
55691 +}
55692 +
55693 +static int pcf50606_resume(struct device *dev)
55694 +{
55695 + struct i2c_client *client = to_i2c_client(dev);
55696 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55697 +
55698 + mutex_lock(&pcf->lock);
55699 +
55700 + pcf->suspend_state = PCF50606_SS_STARTING_RESUME;
55701 +
55702 + /* Resume all saved registers that don't "survive" standby state */
55703 + __reg_write(pcf, PCF50606_REG_INT1M, pcf->standby_regs.int1m);
55704 + __reg_write(pcf, PCF50606_REG_INT2M, pcf->standby_regs.int2m);
55705 + __reg_write(pcf, PCF50606_REG_INT3M, pcf->standby_regs.int3m);
55706 +
55707 + __reg_write(pcf, PCF50606_REG_DCDC1, pcf->standby_regs.dcdc1);
55708 + __reg_write(pcf, PCF50606_REG_DCDC2, pcf->standby_regs.dcdc2);
55709 + __reg_write(pcf, PCF50606_REG_DCDEC1, pcf->standby_regs.dcdec1);
55710 + __reg_write(pcf, PCF50606_REG_DCUDC1, pcf->standby_regs.dcudc1);
55711 + __reg_write(pcf, PCF50606_REG_IOREGC, pcf->standby_regs.ioregc);
55712 + __reg_write(pcf, PCF50606_REG_D1REGC1, pcf->standby_regs.d1regc1);
55713 + __reg_write(pcf, PCF50606_REG_D2REGC1, pcf->standby_regs.d2regc1);
55714 + __reg_write(pcf, PCF50606_REG_D3REGC1, pcf->standby_regs.d3regc1);
55715 + __reg_write(pcf, PCF50606_REG_LPREGC1, pcf->standby_regs.lpregc1);
55716 + __reg_write(pcf, PCF50606_REG_ADCC1, pcf->standby_regs.adcc1);
55717 + __reg_write(pcf, PCF50606_REG_ADCC2, pcf->standby_regs.adcc2);
55718 + __reg_write(pcf, PCF50606_REG_PWMC1, pcf->standby_regs.pwmc1);
55719 +
55720 + pcf->suspend_state = PCF50606_SS_COMPLETED_RESUME;
55721 +
55722 + enable_irq(pcf->irq);
55723 +
55724 + mutex_unlock(&pcf->lock);
55725 +
55726 + /* Call PCF work function; this fixes an issue on the gta01 where
55727 + * the power button "goes away" if it is used to wake the device.
55728 + */
55729 + get_device(&pcf->client.dev);
55730 + pcf50606_work(&pcf->work);
55731 +
55732 + return 0;
55733 +}
55734 +#else
55735 +#define pcf50606_suspend NULL
55736 +#define pcf50606_resume NULL
55737 +#endif
55738 +
55739 +static struct i2c_driver pcf50606_driver = {
55740 + .driver = {
55741 + .name = "pcf50606",
55742 + .suspend = pcf50606_suspend,
55743 + .resume = pcf50606_resume,
55744 + },
55745 + .id = I2C_DRIVERID_PCF50606,
55746 + .attach_adapter = pcf50606_attach_adapter,
55747 + .detach_client = pcf50606_detach_client,
55748 +};
55749 +
55750 +/* platform driver, since i2c devices don't have platform_data */
55751 +static int __init pcf50606_plat_probe(struct platform_device *pdev)
55752 +{
55753 + struct pcf50606_platform_data *pdata = pdev->dev.platform_data;
55754 +
55755 + if (!pdata)
55756 + return -ENODEV;
55757 +
55758 + pcf50606_pdev = pdev;
55759 +
55760 + return 0;
55761 +}
55762 +
55763 +static int pcf50606_plat_remove(struct platform_device *pdev)
55764 +{
55765 + return 0;
55766 +}
55767 +
55768 +/* We have this purely to capture an early indication that we are coming out
55769 + * of suspend, before our device resume got called; async interrupt service is
55770 + * interested in this.
55771 + */
55772 +
55773 +static int pcf50606_plat_resume(struct platform_device *pdev)
55774 +{
55775 + /* i2c_get_clientdata(to_i2c_client(&pdev->dev)) returns NULL at this
55776 + * early resume time so we have to use pcf50606_global
55777 + */
55778 + pcf50606_global->suspend_state = PCF50606_SS_RESUMING_BUT_NOT_US_YET;
55779 +
55780 + return 0;
55781 +}
55782 +
55783 +static struct platform_driver pcf50606_plat_driver = {
55784 + .probe = pcf50606_plat_probe,
55785 + .remove = pcf50606_plat_remove,
55786 + .resume_early = pcf50606_plat_resume,
55787 + .driver = {
55788 + .owner = THIS_MODULE,
55789 + .name = "pcf50606",
55790 + },
55791 +};
55792 +
55793 +static int __init pcf50606_init(void)
55794 +{
55795 + int rc;
55796 +
55797 + rc = platform_driver_register(&pcf50606_plat_driver);
55798 + if (!rc)
55799 + rc = i2c_add_driver(&pcf50606_driver);
55800 +
55801 + return rc;
55802 +}
55803 +
55804 +static void pcf50606_exit(void)
55805 +{
55806 + i2c_del_driver(&pcf50606_driver);
55807 + platform_driver_unregister(&pcf50606_plat_driver);
55808 +}
55809 +
55810 +MODULE_DESCRIPTION("I2C chip driver for NXP PCF50606 power management unit");
55811 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
55812 +MODULE_LICENSE("GPL");
55813 +
55814 +module_init(pcf50606_init);
55815 +module_exit(pcf50606_exit);
55816 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/chips/pcf50606.h linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pcf50606.h
55817 --- linux-2.6.29-rc3.owrt/drivers/i2c/chips/pcf50606.h 1970-01-01 01:00:00.000000000 +0100
55818 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pcf50606.h 2009-05-10 22:27:59.000000000 +0200
55819 @@ -0,0 +1,302 @@
55820 +#ifndef _PCF50606_H
55821 +#define _PCF50606_H
55822 +
55823 +/* Philips PCF50606 Power Managemnt Unit (PMU) driver
55824 + * (C) 2006-2007 by Openmoko, Inc.
55825 + * Author: Harald Welte <laforge@openmoko.org>
55826 + *
55827 + */
55828 +
55829 +enum pfc50606_regs {
55830 + PCF50606_REG_ID = 0x00,
55831 + PCF50606_REG_OOCS = 0x01,
55832 + PCF50606_REG_INT1 = 0x02, /* Interrupt Status */
55833 + PCF50606_REG_INT2 = 0x03, /* Interrupt Status */
55834 + PCF50606_REG_INT3 = 0x04, /* Interrupt Status */
55835 + PCF50606_REG_INT1M = 0x05, /* Interrupt Mask */
55836 + PCF50606_REG_INT2M = 0x06, /* Interrupt Mask */
55837 + PCF50606_REG_INT3M = 0x07, /* Interrupt Mask */
55838 + PCF50606_REG_OOCC1 = 0x08,
55839 + PCF50606_REG_OOCC2 = 0x09,
55840 + PCF50606_REG_RTCSC = 0x0a, /* Second */
55841 + PCF50606_REG_RTCMN = 0x0b, /* Minute */
55842 + PCF50606_REG_RTCHR = 0x0c, /* Hour */
55843 + PCF50606_REG_RTCWD = 0x0d, /* Weekday */
55844 + PCF50606_REG_RTCDT = 0x0e, /* Day */
55845 + PCF50606_REG_RTCMT = 0x0f, /* Month */
55846 + PCF50606_REG_RTCYR = 0x10, /* Year */
55847 + PCF50606_REG_RTCSCA = 0x11, /* Alarm Second */
55848 + PCF50606_REG_RTCMNA = 0x12, /* Alarm Minute */
55849 + PCF50606_REG_RTCHRA = 0x13, /* Alarm Hour */
55850 + PCF50606_REG_RTCWDA = 0x14, /* Alarm Weekday */
55851 + PCF50606_REG_RTCDTA = 0x15, /* Alarm Day */
55852 + PCF50606_REG_RTCMTA = 0x16, /* Alarm Month */
55853 + PCF50606_REG_RTCYRA = 0x17, /* Alarm Year */
55854 + PCF50606_REG_PSSC = 0x18, /* Power sequencing */
55855 + PCF50606_REG_PWROKM = 0x19, /* PWROK mask */
55856 + PCF50606_REG_PWROKS = 0x1a, /* PWROK status */
55857 + PCF50606_REG_DCDC1 = 0x1b,
55858 + PCF50606_REG_DCDC2 = 0x1c,
55859 + PCF50606_REG_DCDC3 = 0x1d,
55860 + PCF50606_REG_DCDC4 = 0x1e,
55861 + PCF50606_REG_DCDEC1 = 0x1f,
55862 + PCF50606_REG_DCDEC2 = 0x20,
55863 + PCF50606_REG_DCUDC1 = 0x21,
55864 + PCF50606_REG_DCUDC2 = 0x22,
55865 + PCF50606_REG_IOREGC = 0x23,
55866 + PCF50606_REG_D1REGC1 = 0x24,
55867 + PCF50606_REG_D2REGC1 = 0x25,
55868 + PCF50606_REG_D3REGC1 = 0x26,
55869 + PCF50606_REG_LPREGC1 = 0x27,
55870 + PCF50606_REG_LPREGC2 = 0x28,
55871 + PCF50606_REG_MBCC1 = 0x29,
55872 + PCF50606_REG_MBCC2 = 0x2a,
55873 + PCF50606_REG_MBCC3 = 0x2b,
55874 + PCF50606_REG_MBCS1 = 0x2c,
55875 + PCF50606_REG_BBCC = 0x2d,
55876 + PCF50606_REG_ADCC1 = 0x2e,
55877 + PCF50606_REG_ADCC2 = 0x2f,
55878 + PCF50606_REG_ADCS1 = 0x30,
55879 + PCF50606_REG_ADCS2 = 0x31,
55880 + PCF50606_REG_ADCS3 = 0x32,
55881 + PCF50606_REG_ACDC1 = 0x33,
55882 + PCF50606_REG_BVMC = 0x34,
55883 + PCF50606_REG_PWMC1 = 0x35,
55884 + PCF50606_REG_LEDC1 = 0x36,
55885 + PCF50606_REG_LEDC2 = 0x37,
55886 + PCF50606_REG_GPOC1 = 0x38,
55887 + PCF50606_REG_GPOC2 = 0x39,
55888 + PCF50606_REG_GPOC3 = 0x3a,
55889 + PCF50606_REG_GPOC4 = 0x3b,
55890 + PCF50606_REG_GPOC5 = 0x3c,
55891 + __NUM_PCF50606_REGS
55892 +};
55893 +
55894 +enum pcf50606_reg_oocs {
55895 + PFC50606_OOCS_ONKEY = 0x01,
55896 + PCF50606_OOCS_EXTON = 0x02,
55897 + PCF50606_OOCS_PWROKRST = 0x04,
55898 + PCF50606_OOCS_BATOK = 0x08,
55899 + PCF50606_OOCS_BACKOK = 0x10,
55900 + PCF50606_OOCS_CHGOK = 0x20,
55901 + PCF50606_OOCS_TEMPOK = 0x40,
55902 + PCF50606_OOCS_WDTEXP = 0x80,
55903 +};
55904 +
55905 +enum pcf50606_reg_oocc1 {
55906 + PCF50606_OOCC1_GOSTDBY = 0x01,
55907 + PCF50606_OOCC1_TOTRST = 0x02,
55908 + PCF50606_OOCC1_CLK32ON = 0x04,
55909 + PCF50606_OOCC1_WDTRST = 0x08,
55910 + PCF50606_OOCC1_RTCWAK = 0x10,
55911 + PCF50606_OOCC1_CHGWAK = 0x20,
55912 + PCF50606_OOCC1_EXTONWAK_HIGH = 0x40,
55913 + PCF50606_OOCC1_EXTONWAK_LOW = 0x80,
55914 +};
55915 +
55916 +enum pcf50606_reg_oocc2 {
55917 + PCF50606_OOCC2_ONKEYDB_NONE = 0x00,
55918 + PCF50606_OOCC2_ONKEYDB_14ms = 0x01,
55919 + PCF50606_OOCC2_ONKEYDB_62ms = 0x02,
55920 + PCF50606_OOCC2_ONKEYDB_500ms = 0x03,
55921 + PCF50606_OOCC2_EXTONDB_NONE = 0x00,
55922 + PCF50606_OOCC2_EXTONDB_14ms = 0x04,
55923 + PCF50606_OOCC2_EXTONDB_62ms = 0x08,
55924 + PCF50606_OOCC2_EXTONDB_500ms = 0x0c,
55925 +};
55926 +
55927 +enum pcf50606_reg_int1 {
55928 + PCF50606_INT1_ONKEYR = 0x01, /* ONKEY rising edge */
55929 + PCF50606_INT1_ONKEYF = 0x02, /* ONKEY falling edge */
55930 + PCF50606_INT1_ONKEY1S = 0x04, /* OMKEY at least 1sec low */
55931 + PCF50606_INT1_EXTONR = 0x08, /* EXTON rising edge */
55932 + PCF50606_INT1_EXTONF = 0x10, /* EXTON falling edge */
55933 + PCF50606_INT1_SECOND = 0x40, /* RTC periodic second interrupt */
55934 + PCF50606_INT1_ALARM = 0x80, /* RTC alarm time is reached */
55935 +};
55936 +
55937 +enum pcf50606_reg_int2 {
55938 + PCF50606_INT2_CHGINS = 0x01, /* Charger inserted */
55939 + PCF50606_INT2_CHGRM = 0x02, /* Charger removed */
55940 + PCF50606_INT2_CHGFOK = 0x04, /* Fast charging OK */
55941 + PCF50606_INT2_CHGERR = 0x08, /* Error in charging mode */
55942 + PCF50606_INT2_CHGFRDY = 0x10, /* Fast charge completed */
55943 + PCF50606_INT2_CHGPROT = 0x20, /* Charging protection interrupt */
55944 + PCF50606_INT2_CHGWD10S = 0x40, /* Charger watchdig expires in 10s */
55945 + PCF50606_INT2_CHGWDEXP = 0x80, /* Charger watchdog expires */
55946 +};
55947 +
55948 +enum pcf50606_reg_int3 {
55949 + PCF50606_INT3_ADCRDY = 0x01, /* ADC conversion finished */
55950 + PCF50606_INT3_ACDINS = 0x02, /* Accessory inserted */
55951 + PCF50606_INT3_ACDREM = 0x04, /* Accessory removed */
55952 + PCF50606_INT3_TSCPRES = 0x08, /* Touch screen pressed */
55953 + PCF50606_INT3_LOWBAT = 0x40, /* Low battery voltage */
55954 + PCF50606_INT3_HIGHTMP = 0x80, /* High temperature */
55955 +};
55956 +
55957 +/* used by PSSC, PWROKM, PWROKS, */
55958 +enum pcf50606_regu {
55959 + PCF50606_REGU_DCD = 0x01, /* DCD in phase 2 */
55960 + PCF50606_REGU_DCDE = 0x02, /* DCDE in phase 2 */
55961 + PCF50606_REGU_DCUD = 0x04, /* DCDU in phase 2 */
55962 + PCF50606_REGU_IO = 0x08, /* IO in phase 2 */
55963 + PCF50606_REGU_D1 = 0x10, /* D1 in phase 2 */
55964 + PCF50606_REGU_D2 = 0x20, /* D2 in phase 2 */
55965 + PCF50606_REGU_D3 = 0x40, /* D3 in phase 2 */
55966 + PCF50606_REGU_LP = 0x80, /* LP in phase 2 */
55967 +};
55968 +
55969 +enum pcf50606_reg_dcdc4 {
55970 + PCF50606_DCDC4_MODE_AUTO = 0x00,
55971 + PCF50606_DCDC4_MODE_PWM = 0x01,
55972 + PCF50606_DCDC4_MODE_PCF = 0x02,
55973 + PCF50606_DCDC4_OFF_FLOAT = 0x00,
55974 + PCF50606_DCDC4_OFF_BYPASS = 0x04,
55975 + PCF50606_DCDC4_OFF_PULLDOWN = 0x08,
55976 + PCF50606_DCDC4_CURLIM_500mA = 0x00,
55977 + PCF50606_DCDC4_CURLIM_750mA = 0x10,
55978 + PCF50606_DCDC4_CURLIM_1000mA = 0x20,
55979 + PCF50606_DCDC4_CURLIM_1250mA = 0x30,
55980 + PCF50606_DCDC4_TOGGLE = 0x40,
55981 + PCF50606_DCDC4_REGSEL_DCDC2 = 0x80,
55982 +};
55983 +
55984 +enum pcf50606_reg_dcdec2 {
55985 + PCF50606_DCDEC2_MODE_AUTO = 0x00,
55986 + PCF50606_DCDEC2_MODE_PWM = 0x01,
55987 + PCF50606_DCDEC2_MODE_PCF = 0x02,
55988 + PCF50606_DCDEC2_OFF_FLOAT = 0x00,
55989 + PCF50606_DCDEC2_OFF_BYPASS = 0x04,
55990 +};
55991 +
55992 +enum pcf50606_reg_dcudc2 {
55993 + PCF50606_DCUDC2_MODE_AUTO = 0x00,
55994 + PCF50606_DCUDC2_MODE_PWM = 0x01,
55995 + PCF50606_DCUDC2_MODE_PCF = 0x02,
55996 + PCF50606_DCUDC2_OFF_FLOAT = 0x00,
55997 + PCF50606_DCUDC2_OFF_BYPASS = 0x04,
55998 +};
55999 +
56000 +enum pcf50606_reg_adcc1 {
56001 + PCF50606_ADCC1_TSCMODACT = 0x01,
56002 + PCF50606_ADCC1_TSCMODSTB = 0x02,
56003 + PCF50606_ADCC1_TRATSET = 0x04,
56004 + PCF50606_ADCC1_NTCSWAPE = 0x08,
56005 + PCF50606_ADCC1_NTCSWAOFF = 0x10,
56006 + PCF50606_ADCC1_EXTSYNCBREAK = 0x20,
56007 + /* reserved */
56008 + PCF50606_ADCC1_TSCINT = 0x80,
56009 +};
56010 +
56011 +enum pcf50606_reg_adcc2 {
56012 + PCF50606_ADCC2_ADCSTART = 0x01,
56013 + /* see enum pcf50606_adcc2_adcmux */
56014 + PCF50606_ADCC2_SYNC_NONE = 0x00,
56015 + PCF50606_ADCC2_SYNC_TXON = 0x20,
56016 + PCF50606_ADCC2_SYNC_PWREN1 = 0x40,
56017 + PCF50606_ADCC2_SYNC_PWREN2 = 0x60,
56018 + PCF50606_ADCC2_RES_10BIT = 0x00,
56019 + PCF50606_ADCC2_RES_8BIT = 0x80,
56020 +};
56021 +
56022 +#define PCF50606_ADCC2_ADCMUX_MASK (0xf << 1)
56023 +
56024 +#define ADCMUX_SHIFT 1
56025 +enum pcf50606_adcc2_adcmux {
56026 + PCF50606_ADCMUX_BATVOLT_RES = 0x0 << ADCMUX_SHIFT,
56027 + PCF50606_ADCMUX_BATVOLT_SUBTR = 0x1 << ADCMUX_SHIFT,
56028 + PCF50606_ADCMUX_ADCIN1_RES = 0x2 << ADCMUX_SHIFT,
56029 + PCF50606_ADCMUX_ADCIN1_SUBTR = 0x3 << ADCMUX_SHIFT,
56030 + PCF50606_ADCMUX_BATTEMP = 0x4 << ADCMUX_SHIFT,
56031 + PCF50606_ADCMUX_ADCIN2 = 0x5 << ADCMUX_SHIFT,
56032 + PCF50606_ADCMUX_ADCIN3 = 0x6 << ADCMUX_SHIFT,
56033 + PCF50606_ADCMUX_ADCIN3_RATIO = 0x7 << ADCMUX_SHIFT,
56034 + PCF50606_ADCMUX_XPOS = 0x8 << ADCMUX_SHIFT,
56035 + PCF50606_ADCMUX_YPOS = 0x9 << ADCMUX_SHIFT,
56036 + PCF50606_ADCMUX_P1 = 0xa << ADCMUX_SHIFT,
56037 + PCF50606_ADCMUX_P2 = 0xb << ADCMUX_SHIFT,
56038 + PCF50606_ADCMUX_BATVOLT_ADCIN1 = 0xc << ADCMUX_SHIFT,
56039 + PCF50606_ADCMUX_XY_SEQUENCE = 0xe << ADCMUX_SHIFT,
56040 + PCF50606_P1_P2_RESISTANCE = 0xf << ADCMUX_SHIFT,
56041 +};
56042 +
56043 +enum pcf50606_adcs2 {
56044 + PCF50606_ADCS2_ADCRDY = 0x80,
56045 +};
56046 +
56047 +enum pcf50606_reg_mbcc1 {
56048 + PCF50606_MBCC1_CHGAPE = 0x01,
56049 + PCF50606_MBCC1_AUTOFST = 0x02,
56050 +#define PCF50606_MBCC1_CHGMOD_MASK 0x1c
56051 +#define PCF50606_MBCC1_CHGMOD_SHIFT 2
56052 + PCF50606_MBCC1_CHGMOD_QUAL = 0x00,
56053 + PCF50606_MBCC1_CHGMOD_PRE = 0x04,
56054 + PCF50606_MBCC1_CHGMOD_TRICKLE = 0x08,
56055 + PCF50606_MBCC1_CHGMOD_FAST_CCCV = 0x0c,
56056 + PCF50606_MBCC1_CHGMOD_FAST_NOCC = 0x10,
56057 + PCF50606_MBCC1_CHGMOD_FAST_NOCV = 0x14,
56058 + PCF50606_MBCC1_CHGMOD_FAST_SW = 0x18,
56059 + PCF50606_MBCC1_CHGMOD_IDLE = 0x1c,
56060 + PCF50606_MBCC1_DETMOD_LOWCHG = 0x20,
56061 + PCF50606_MBCC1_DETMOD_WDRST = 0x40,
56062 +};
56063 +
56064 +enum pcf50606_reg_acdc1 {
56065 + PCF50606_ACDC1_ACDDET = 0x01,
56066 + PCF50606_ACDC1_THRSHLD_1V0 = 0x00,
56067 + PCF50606_ACDC1_THRSHLD_1V2 = 0x02,
56068 + PCF50606_ACDC1_THRSHLD_1V4 = 0x04,
56069 + PCF50606_ACDC1_THRSHLD_1V6 = 0x06,
56070 + PCF50606_ACDC1_THRSHLD_1V8 = 0x08,
56071 + PCF50606_ACDC1_THRSHLD_2V0 = 0x0a,
56072 + PCF50606_ACDC1_THRSHLD_2V2 = 0x0c,
56073 + PCF50606_ACDC1_THRSHLD_2V4 = 0x0e,
56074 + PCF50606_ACDC1_DISDB = 0x10,
56075 + PCF50606_ACDC1_ACDAPE = 0x80,
56076 +};
56077 +
56078 +enum pcf50606_reg_bvmc {
56079 + PCF50606_BVMC_LOWBAT = 0x01,
56080 + PCF50606_BVMC_THRSHLD_NULL = 0x00,
56081 + PCF50606_BVMC_THRSHLD_2V8 = 0x02,
56082 + PCF50606_BVMC_THRSHLD_2V9 = 0x04,
56083 + PCF50606_BVMC_THRSHLD_3V = 0x08,
56084 + PCF50606_BVMC_THRSHLD_3V1 = 0x08,
56085 + PCF50606_BVMC_THRSHLD_3V2 = 0x0a,
56086 + PCF50606_BVMC_THRSHLD_3V3 = 0x0c,
56087 + PCF50606_BVMC_THRSHLD_3V4 = 0x0e,
56088 + PCF50606_BVMC_DISDB = 0x10,
56089 +};
56090 +
56091 +enum pcf50606_reg_pwmc1 {
56092 + PCF50606_PWMC1_ACTSET = 0x01,
56093 + PCF50606_PWMC1_PWMDC_0_16 = 0x00,
56094 + PCF50606_PWMC1_PWMDC_1_16 = 0x02,
56095 + PCF50606_PWMC1_PWMDC_2_16 = 0x04,
56096 + PCF50606_PWMC1_PWMDC_3_16 = 0x06,
56097 + PCF50606_PWMC1_PWMDC_4_16 = 0x08,
56098 + PCF50606_PWMC1_PWMDC_5_16 = 0x0a,
56099 + PCF50606_PWMC1_PWMDC_6_16 = 0x0c,
56100 + PCF50606_PWMC1_PWMDC_7_16 = 0x0e,
56101 + PCF50606_PWMC1_PWMDC_8_16 = 0x10,
56102 + PCF50606_PWMC1_PWMDC_9_16 = 0x12,
56103 + PCF50606_PWMC1_PWMDC_10_16 = 0x14,
56104 + PCF50606_PWMC1_PWMDC_11_16 = 0x16,
56105 + PCF50606_PWMC1_PWMDC_12_16 = 0x18,
56106 + PCF50606_PWMC1_PWMDC_13_16 = 0x1a,
56107 + PCF50606_PWMC1_PWMDC_14_16 = 0x1c,
56108 + PCF50606_PWMC1_PWMDC_15_16 = 0x1e,
56109 + PCF50606_PWMC1_PRESC_512Hz = 0x20,
56110 + PCF50606_PWMC1_PRESC_256Hz = 0x40,
56111 + PCF50606_PWMC1_PRESC_64Hz = 0x60,
56112 + PCF50606_PWMC1_PRESC_56kHz = 0x80,
56113 + PCF50606_PWMC1_PRESC_28kHz = 0xa0,
56114 + PCF50606_PWMC1_PRESC_14kHz = 0xc0,
56115 + PCF50606_PWMC1_PRESC_7kHz = 0xe0,
56116 +};
56117 +#define PCF50606_PWMC1_CLK_SHIFT 5
56118 +#define PCF50606_PWMC1_DC_SHIFT 1
56119 +
56120 +#endif /* _PCF50606_H */
56121 +
56122 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/chips/pcf50633.h linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pcf50633.h
56123 --- linux-2.6.29-rc3.owrt/drivers/i2c/chips/pcf50633.h 1970-01-01 01:00:00.000000000 +0100
56124 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/chips/pcf50633.h 2009-05-10 22:27:59.000000000 +0200
56125 @@ -0,0 +1,349 @@
56126 +#ifndef _PCF50633_H
56127 +#define _PCF50633_H
56128 +
56129 +/* Philips PCF50633 Power Managemnt Unit (PMU) driver
56130 + * (C) 2006-2007 by Openmoko, Inc.
56131 + * Author: Harald Welte <laforge@openmoko.org>
56132 + *
56133 + */
56134 +
56135 +enum pfc50633_regs {
56136 + PCF50633_REG_VERSION = 0x00,
56137 + PCF50633_REG_VARIANT = 0x01,
56138 + PCF50633_REG_INT1 = 0x02, /* Interrupt Status */
56139 + PCF50633_REG_INT2 = 0x03, /* Interrupt Status */
56140 + PCF50633_REG_INT3 = 0x04, /* Interrupt Status */
56141 + PCF50633_REG_INT4 = 0x05, /* Interrupt Status */
56142 + PCF50633_REG_INT5 = 0x06, /* Interrupt Status */
56143 + PCF50633_REG_INT1M = 0x07, /* Interrupt Mask */
56144 + PCF50633_REG_INT2M = 0x08, /* Interrupt Mask */
56145 + PCF50633_REG_INT3M = 0x09, /* Interrupt Mask */
56146 + PCF50633_REG_INT4M = 0x0a, /* Interrupt Mask */
56147 + PCF50633_REG_INT5M = 0x0b, /* Interrupt Mask */
56148 + PCF50633_REG_OOCSHDWN = 0x0c,
56149 + PCF50633_REG_OOCWAKE = 0x0d,
56150 + PCF50633_REG_OOCTIM1 = 0x0e,
56151 + PCF50633_REG_OOCTIM2 = 0x0f,
56152 + PCF50633_REG_OOCMODE = 0x10,
56153 + PCF50633_REG_OOCCTL = 0x11,
56154 + PCF50633_REG_OOCSTAT = 0x12,
56155 + PCF50633_REG_GPIOCTL = 0x13,
56156 + PCF50633_REG_GPIO1CFG = 0x14,
56157 + PCF50633_REG_GPIO2CFG = 0x15,
56158 + PCF50633_REG_GPIO3CFG = 0x16,
56159 + PCF50633_REG_GPOCFG = 0x17,
56160 + PCF50633_REG_BVMCTL = 0x18,
56161 + PCF50633_REG_SVMCTL = 0x19,
56162 + PCF50633_REG_AUTOOUT = 0x1a,
56163 + PCF50633_REG_AUTOENA = 0x1b,
56164 + PCF50633_REG_AUTOCTL = 0x1c,
56165 + PCF50633_REG_AUTOMXC = 0x1d,
56166 + PCF50633_REG_DOWN1OUT = 0x1e,
56167 + PCF50633_REG_DOWN1ENA = 0x1f,
56168 + PCF50633_REG_DOWN1CTL = 0x20,
56169 + PCF50633_REG_DOWN1MXC = 0x21,
56170 + PCF50633_REG_DOWN2OUT = 0x22,
56171 + PCF50633_REG_DOWN2ENA = 0x23,
56172 + PCF50633_REG_DOWN2CTL = 0x24,
56173 + PCF50633_REG_DOWN2MXC = 0x25,
56174 + PCF50633_REG_MEMLDOOUT = 0x26,
56175 + PCF50633_REG_MEMLDOENA = 0x27,
56176 + PCF50633_REG_LEDOUT = 0x28,
56177 + PCF50633_REG_LEDENA = 0x29,
56178 + PCF50633_REG_LEDCTL = 0x2a,
56179 + PCF50633_REG_LEDDIM = 0x2b,
56180 + /* reserved */
56181 + PCF50633_REG_LDO1OUT = 0x2d,
56182 + PCF50633_REG_LDO1ENA = 0x2e,
56183 + PCF50633_REG_LDO2OUT = 0x2f,
56184 + PCF50633_REG_LDO2ENA = 0x30,
56185 + PCF50633_REG_LDO3OUT = 0x31,
56186 + PCF50633_REG_LDO3ENA = 0x32,
56187 + PCF50633_REG_LDO4OUT = 0x33,
56188 + PCF50633_REG_LDO4ENA = 0x34,
56189 + PCF50633_REG_LDO5OUT = 0x35,
56190 + PCF50633_REG_LDO5ENA = 0x36,
56191 + PCF50633_REG_LDO6OUT = 0x37,
56192 + PCF50633_REG_LDO6ENA = 0x38,
56193 + PCF50633_REG_HCLDOOUT = 0x39,
56194 + PCF50633_REG_HCLDOENA = 0x3a,
56195 + PCF50633_REG_STBYCTL1 = 0x3b,
56196 + PCF50633_REG_STBYCTL2 = 0x3c,
56197 + PCF50633_REG_DEBPF1 = 0x3d,
56198 + PCF50633_REG_DEBPF2 = 0x3e,
56199 + PCF50633_REG_DEBPF3 = 0x3f,
56200 + PCF50633_REG_HCLDOOVL = 0x40,
56201 + PCF50633_REG_DCDCSTAT = 0x41,
56202 + PCF50633_REG_LDOSTAT = 0x42,
56203 + PCF50633_REG_MBCC1 = 0x43,
56204 + PCF50633_REG_MBCC2 = 0x44,
56205 + PCF50633_REG_MBCC3 = 0x45,
56206 + PCF50633_REG_MBCC4 = 0x46,
56207 + PCF50633_REG_MBCC5 = 0x47,
56208 + PCF50633_REG_MBCC6 = 0x48,
56209 + PCF50633_REG_MBCC7 = 0x49,
56210 + PCF50633_REG_MBCC8 = 0x4a,
56211 + PCF50633_REG_MBCS1 = 0x4b,
56212 + PCF50633_REG_MBCS2 = 0x4c,
56213 + PCF50633_REG_MBCS3 = 0x4d,
56214 + PCF50633_REG_BBCCTL = 0x4e,
56215 + PCF50633_REG_ALMGAIN = 0x4f,
56216 + PCF50633_REG_ALMDATA = 0x50,
56217 + /* reserved */
56218 + PCF50633_REG_ADCC3 = 0x52,
56219 + PCF50633_REG_ADCC2 = 0x53,
56220 + PCF50633_REG_ADCC1 = 0x54,
56221 + PCF50633_REG_ADCS1 = 0x55,
56222 + PCF50633_REG_ADCS2 = 0x56,
56223 + PCF50633_REG_ADCS3 = 0x57,
56224 + /* reserved */
56225 + PCF50633_REG_RTCSC = 0x59, /* Second */
56226 + PCF50633_REG_RTCMN = 0x5a, /* Minute */
56227 + PCF50633_REG_RTCHR = 0x5b, /* Hour */
56228 + PCF50633_REG_RTCWD = 0x5c, /* Weekday */
56229 + PCF50633_REG_RTCDT = 0x5d, /* Day */
56230 + PCF50633_REG_RTCMT = 0x5e, /* Month */
56231 + PCF50633_REG_RTCYR = 0x5f, /* Year */
56232 + PCF50633_REG_RTCSCA = 0x60, /* Alarm Second */
56233 + PCF50633_REG_RTCMNA = 0x61, /* Alarm Minute */
56234 + PCF50633_REG_RTCHRA = 0x62, /* Alarm Hour */
56235 + PCF50633_REG_RTCWDA = 0x63, /* Alarm Weekday */
56236 + PCF50633_REG_RTCDTA = 0x64, /* Alarm Day */
56237 + PCF50633_REG_RTCMTA = 0x65, /* Alarm Month */
56238 + PCF50633_REG_RTCYRA = 0x66, /* Alarm Year */
56239 +
56240 + PCF50633_REG_MEMBYTE0 = 0x67,
56241 + PCF50633_REG_MEMBYTE1 = 0x68,
56242 + PCF50633_REG_MEMBYTE2 = 0x69,
56243 + PCF50633_REG_MEMBYTE3 = 0x6a,
56244 + PCF50633_REG_MEMBYTE4 = 0x6b,
56245 + PCF50633_REG_MEMBYTE5 = 0x6c,
56246 + PCF50633_REG_MEMBYTE6 = 0x6d,
56247 + PCF50633_REG_MEMBYTE7 = 0x6e,
56248 + /* reserved */
56249 + PCF50633_REG_DCDCPFM = 0x84,
56250 + __NUM_PCF50633_REGS
56251 +};
56252 +
56253 +
56254 +enum pcf50633_reg_oocshdwn {
56255 + PCF50633_OOCSHDWN_GOSTDBY = 0x01,
56256 + PCF50633_OOCSHDWN_TOTRST = 0x04,
56257 + PCF50633_OOCSHDWN_COLDBOOT = 0x08,
56258 +};
56259 +
56260 +enum pcf50633_reg_oocwake {
56261 + PCF50633_OOCWAKE_ONKEY = 0x01,
56262 + PCF50633_OOCWAKE_EXTON1 = 0x02,
56263 + PCF50633_OOCWAKE_EXTON2 = 0x04,
56264 + PCF50633_OOCWAKE_EXTON3 = 0x08,
56265 + PCF50633_OOCWAKE_RTC = 0x10,
56266 + /* reserved */
56267 + PCF50633_OOCWAKE_USB = 0x40,
56268 + PCF50633_OOCWAKE_ADP = 0x80,
56269 +};
56270 +
56271 +enum pcf50633_reg_mbcc1 {
56272 + PCF50633_MBCC1_CHGENA = 0x01, /* Charger enable */
56273 + PCF50633_MBCC1_AUTOSTOP = 0x02,
56274 + PCF50633_MBCC1_AUTORES = 0x04, /* automatic resume */
56275 + PCF50633_MBCC1_RESUME = 0x08, /* explicit resume cmd */
56276 + PCF50633_MBCC1_RESTART = 0x10, /* restart charging */
56277 + PCF50633_MBCC1_PREWDTIME_60M = 0x20, /* max. precharging time */
56278 + PCF50633_MBCC1_WDTIME_1H = 0x00,
56279 + PCF50633_MBCC1_WDTIME_2H = 0x40,
56280 + PCF50633_MBCC1_WDTIME_4H = 0x80,
56281 + PCF50633_MBCC1_WDTIME_6H = 0xc0,
56282 +};
56283 +#define PCF50633_MBCC1_WDTIME_MASK 0xc0
56284 +
56285 +enum pcf50633_reg_mbcc2 {
56286 + PCF50633_MBCC2_VBATCOND_2V7 = 0x00,
56287 + PCF50633_MBCC2_VBATCOND_2V85 = 0x01,
56288 + PCF50633_MBCC2_VBATCOND_3V0 = 0x02,
56289 + PCF50633_MBCC2_VBATCOND_3V15 = 0x03,
56290 + PCF50633_MBCC2_VMAX_4V = 0x00,
56291 + PCF50633_MBCC2_VMAX_4V20 = 0x28,
56292 + PCF50633_MBCC2_VRESDEBTIME_64S = 0x80, /* debounce time (32/64sec) */
56293 +};
56294 +#define PCF50633_MBCC2_VBATCOND_MASK 0x03
56295 +#define PCF50633_MBCC2_VMAX_MASK 0x3c
56296 +
56297 +enum pcf50633_reg_adcc1 {
56298 + PCF50633_ADCC1_ADCSTART = 0x01,
56299 + PCF50633_ADCC1_RES_10BIT = 0x02,
56300 + PCF50633_ADCC1_AVERAGE_NO = 0x00,
56301 + PCF50633_ADCC1_AVERAGE_4 = 0x04,
56302 + PCF50633_ADCC1_AVERAGE_8 = 0x08,
56303 + PCF50633_ADCC1_AVERAGE_16 = 0x0c,
56304 +
56305 + PCF50633_ADCC1_MUX_BATSNS_RES = 0x00,
56306 + PCF50633_ADCC1_MUX_BATSNS_SUBTR = 0x10,
56307 + PCF50633_ADCC1_MUX_ADCIN2_RES = 0x20,
56308 + PCF50633_ADCC1_MUX_ADCIN2_SUBTR = 0x30,
56309 + PCF50633_ADCC1_MUX_BATTEMP = 0x60,
56310 + PCF50633_ADCC1_MUX_ADCIN1 = 0x70,
56311 +};
56312 +#define PCF50633_ADCC1_AVERAGE_MASK 0x0c
56313 +#define PCF50633_ADCC1_ADCMUX_MASK 0xf0
56314 +
56315 +enum pcf50633_reg_adcc2 {
56316 + PCF50633_ADCC2_RATIO_NONE = 0x00,
56317 + PCF50633_ADCC2_RATIO_BATTEMP = 0x01,
56318 + PCF50633_ADCC2_RATIO_ADCIN1 = 0x02,
56319 + PCF50633_ADCC2_RATIO_BOTH = 0x03,
56320 + PCF50633_ADCC2_RATIOSETTL_100US = 0x04,
56321 +};
56322 +#define PCF50633_ADCC2_RATIO_MASK 0x03
56323 +
56324 +enum pcf50633_reg_adcc3 {
56325 + PCF50633_ADCC3_ACCSW_EN = 0x01,
56326 + PCF50633_ADCC3_NTCSW_EN = 0x04,
56327 + PCF50633_ADCC3_RES_DIV_TWO = 0x10,
56328 + PCF50633_ADCC3_RES_DIV_THREE = 0x00,
56329 +};
56330 +
56331 +enum pcf50633_reg_adcs3 {
56332 + PCF50633_ADCS3_REF_NTCSW = 0x00,
56333 + PCF50633_ADCS3_REF_ACCSW = 0x10,
56334 + PCF50633_ADCS3_REF_2V0 = 0x20,
56335 + PCF50633_ADCS3_REF_VISA = 0x30,
56336 + PCF50633_ADCS3_REF_2V0_2 = 0x70,
56337 + PCF50633_ADCS3_ADCRDY = 0x80,
56338 +};
56339 +#define PCF50633_ADCS3_ADCDAT1L_MASK 0x03
56340 +#define PCF50633_ADCS3_ADCDAT2L_MASK 0x0c
56341 +#define PCF50633_ADCS3_ADCDAT2L_SHIFT 2
56342 +#define PCF50633_ASCS3_REF_MASK 0x70
56343 +
56344 +enum pcf50633_regulator_enable {
56345 + PCF50633_REGULATOR_ON = 0x01,
56346 + PCF50633_REGULATOR_ON_GPIO1 = 0x02,
56347 + PCF50633_REGULATOR_ON_GPIO2 = 0x04,
56348 + PCF50633_REGULATOR_ON_GPIO3 = 0x08,
56349 +};
56350 +#define PCF50633_REGULATOR_ON_MASK 0x0f
56351 +
56352 +enum pcf50633_regulator_phase {
56353 + PCF50633_REGULATOR_ACTPH1 = 0x00,
56354 + PCF50633_REGULATOR_ACTPH2 = 0x10,
56355 + PCF50633_REGULATOR_ACTPH3 = 0x20,
56356 + PCF50633_REGULATOR_ACTPH4 = 0x30,
56357 +};
56358 +#define PCF50633_REGULATOR_ACTPH_MASK 0x30
56359 +
56360 +enum pcf50633_reg_gpocfg {
56361 + PCF50633_GPOCFG_GPOSEL_0 = 0x00,
56362 + PCF50633_GPOCFG_GPOSEL_LED_NFET = 0x01,
56363 + PCF50633_GPOCFG_GPOSEL_SYSxOK = 0x02,
56364 + PCF50633_GPOCFG_GPOSEL_CLK32K = 0x03,
56365 + PCF50633_GPOCFG_GPOSEL_ADAPUSB = 0x04,
56366 + PCF50633_GPOCFG_GPOSEL_USBxOK = 0x05,
56367 + PCF50633_GPOCFG_GPOSEL_ACTPH4 = 0x06,
56368 + PCF50633_GPOCFG_GPOSEL_1 = 0x07,
56369 + PCF50633_GPOCFG_GPOSEL_INVERSE = 0x08,
56370 +};
56371 +#define PCF50633_GPOCFG_GPOSEL_MASK 0x07
56372 +
56373 +#if 0
56374 +enum pcf50633_reg_mbcc1 {
56375 + PCF50633_MBCC1_CHGENA = 0x01,
56376 + PCF50633_MBCC1_AUTOSTOP = 0x02,
56377 + PCF50633_MBCC1_AUTORES = 0x04,
56378 + PCF50633_MBCC1_RESUME = 0x08,
56379 + PCF50633_MBCC1_RESTART = 0x10,
56380 + PCF50633_MBCC1_PREWDTIME_30MIN = 0x00,
56381 + PCF50633_MBCC1_PREWDTIME_60MIN = 0x20,
56382 + PCF50633_MBCC1_WDTIME_2HRS = 0x40,
56383 + PCF50633_MBCC1_WDTIME_4HRS = 0x80,
56384 + PCF50633_MBCC1_WDTIME_6HRS = 0xc0,
56385 +};
56386 +
56387 +enum pcf50633_reg_mbcc2 {
56388 + PCF50633_MBCC2_VBATCOND_2V7 = 0x00,
56389 + PCF50633_MBCC2_VBATCOND_2V85 = 0x01,
56390 + PCF50633_MBCC2_VBATCOND_3V0 = 0x02,
56391 + PCF50633_MBCC2_VBATCOND_3V15 = 0x03,
56392 + PCF50633_MBCC2_VRESDEBTIME_64S = 0x80,
56393 +};
56394 +#define PCF50633_MBCC2_VMAX_MASK 0x3c
56395 +#endif
56396 +
56397 +enum pcf50633_reg_mbcc7 {
56398 + PCF50633_MBCC7_USB_100mA = 0x00,
56399 + PCF50633_MBCC7_USB_500mA = 0x01,
56400 + PCF50633_MBCC7_USB_1000mA = 0x02,
56401 + PCF50633_MBCC7_USB_SUSPEND = 0x03,
56402 + PCF50633_MBCC7_BATTEMP_EN = 0x04,
56403 + PCF50633_MBCC7_BATSYSIMAX_1A6 = 0x00,
56404 + PCF50633_MBCC7_BATSYSIMAX_1A8 = 0x40,
56405 + PCF50633_MBCC7_BATSYSIMAX_2A0 = 0x80,
56406 + PCF50633_MBCC7_BATSYSIMAX_2A2 = 0xc0,
56407 +};
56408 +#define PCF56033_MBCC7_USB_MASK 0x03
56409 +
56410 +enum pcf50633_reg_mbcc8 {
56411 + PCF50633_MBCC8_USBENASUS = 0x10,
56412 +};
56413 +
56414 +enum pcf50633_reg_mbcs1 {
56415 + PCF50633_MBCS1_USBPRES = 0x01,
56416 + PCF50633_MBCS1_USBOK = 0x02,
56417 + PCF50633_MBCS1_ADAPTPRES = 0x04,
56418 + PCF50633_MBCS1_ADAPTOK = 0x08,
56419 + PCF50633_MBCS1_TBAT_OK = 0x00,
56420 + PCF50633_MBCS1_TBAT_ABOVE = 0x10,
56421 + PCF50633_MBCS1_TBAT_BELOW = 0x20,
56422 + PCF50633_MBCS1_TBAT_UNDEF = 0x30,
56423 + PCF50633_MBCS1_PREWDTEXP = 0x40,
56424 + PCF50633_MBCS1_WDTEXP = 0x80,
56425 +};
56426 +
56427 +enum pcf50633_reg_mbcs2_mbcmod {
56428 + PCF50633_MBCS2_MBC_PLAY = 0x00,
56429 + PCF50633_MBCS2_MBC_USB_PRE = 0x01,
56430 + PCF50633_MBCS2_MBC_USB_PRE_WAIT = 0x02,
56431 + PCF50633_MBCS2_MBC_USB_FAST = 0x03,
56432 + PCF50633_MBCS2_MBC_USB_FAST_WAIT= 0x04,
56433 + PCF50633_MBCS2_MBC_USB_SUSPEND = 0x05,
56434 + PCF50633_MBCS2_MBC_ADP_PRE = 0x06,
56435 + PCF50633_MBCS2_MBC_ADP_PRE_WAIT = 0x07,
56436 + PCF50633_MBCS2_MBC_ADP_FAST = 0x08,
56437 + PCF50633_MBCS2_MBC_ADP_FAST_WAIT= 0x09,
56438 + PCF50633_MBCS2_MBC_BAT_FULL = 0x0a,
56439 + PCF50633_MBCS2_MBC_HALT = 0x0b,
56440 +};
56441 +#define PCF50633_MBCS2_MBC_MASK 0x0f
56442 +enum pcf50633_reg_mbcs2_chgstat {
56443 + PCF50633_MBCS2_CHGS_NONE = 0x00,
56444 + PCF50633_MBCS2_CHGS_ADAPTER = 0x10,
56445 + PCF50633_MBCS2_CHGS_USB = 0x20,
56446 + PCF50633_MBCS2_CHGS_BOTH = 0x30,
56447 +};
56448 +#define PCF50633_MBCS2_RESSTAT_AUTO 0x40
56449 +
56450 +enum pcf50633_reg_mbcs3 {
56451 + PCF50633_MBCS3_USBLIM_PLAY = 0x01,
56452 + PCF50633_MBCS3_USBLIM_CGH = 0x02,
56453 + PCF50633_MBCS3_TLIM_PLAY = 0x04,
56454 + PCF50633_MBCS3_TLIM_CHG = 0x08,
56455 + PCF50633_MBCS3_ILIM = 0x10, /* 1: Ibat > Icutoff */
56456 + PCF50633_MBCS3_VLIM = 0x20, /* 1: Vbat == Vmax */
56457 + PCF50633_MBCS3_VBATSTAT = 0x40, /* 1: Vbat > Vbatcond */
56458 + PCF50633_MBCS3_VRES = 0x80, /* 1: Vbat > Vth(RES) */
56459 +};
56460 +
56461 +/* this is to be provided by the board implementation */
56462 +extern const u_int8_t pcf50633_initial_regs[__NUM_PCF50633_REGS];
56463 +
56464 +void pcf50633_reg_write(u_int8_t reg, u_int8_t val);
56465 +
56466 +u_int8_t pcf50633_reg_read(u_int8_t reg);
56467 +
56468 +void pcf50633_reg_set_bit_mask(u_int8_t reg, u_int8_t mask, u_int8_t val);
56469 +void pcf50633_reg_clear_bits(u_int8_t reg, u_int8_t bits);
56470 +
56471 +void pcf50633_charge_autofast(int on);
56472 +
56473 +#endif /* _PCF50606_H */
56474 +
56475 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/i2c/i2c-core.c linux-2.6.29-rc3.owrt.om/drivers/i2c/i2c-core.c
56476 --- linux-2.6.29-rc3.owrt/drivers/i2c/i2c-core.c 2009-05-10 22:08:42.000000000 +0200
56477 +++ linux-2.6.29-rc3.owrt.om/drivers/i2c/i2c-core.c 2009-05-10 22:27:59.000000000 +0200
56478 @@ -1,4 +1,3 @@
56479 -/* i2c-core.c - a device driver for the iic-bus interface */
56480 /* ------------------------------------------------------------------------- */
56481 /* Copyright (C) 1995-99 Simon G. Vogl
56482
56483 @@ -158,10 +157,16 @@
56484
56485 if (!dev->driver)
56486 return 0;
56487 +#if 0
56488 driver = to_i2c_driver(dev->driver);
56489 if (!driver->suspend)
56490 return 0;
56491 return driver->suspend(to_i2c_client(dev), mesg);
56492 +#else
56493 + if (!dev->driver->suspend)
56494 + return 0;
56495 + return dev->driver->suspend(dev, mesg);
56496 +#endif
56497 }
56498
56499 static int i2c_device_resume(struct device * dev)
56500 @@ -170,10 +175,16 @@
56501
56502 if (!dev->driver)
56503 return 0;
56504 +#if 0
56505 driver = to_i2c_driver(dev->driver);
56506 if (!driver->resume)
56507 return 0;
56508 return driver->resume(to_i2c_client(dev));
56509 +#else
56510 + if (!dev->driver->resume)
56511 + return 0;
56512 + return dev->driver->resume(dev);
56513 +#endif
56514 }
56515
56516 static void i2c_client_release(struct device *dev)
56517 @@ -1129,11 +1140,11 @@
56518 int err;
56519
56520 /* Make sure the address is valid */
56521 - if (addr < 0x03 || addr > 0x77) {
56522 + /*if (addr < 0x03 || addr > 0x77) {
56523 dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
56524 addr);
56525 return -EINVAL;
56526 - }
56527 + }*/
56528
56529 /* Skip if already in use */
56530 if (i2c_check_addr(adapter, addr))
56531 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/keyboard/gpio_keys.c linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/gpio_keys.c
56532 --- linux-2.6.29-rc3.owrt/drivers/input/keyboard/gpio_keys.c 2009-05-10 22:04:49.000000000 +0200
56533 +++ linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/gpio_keys.c 2009-05-10 22:27:59.000000000 +0200
56534 @@ -23,7 +23,7 @@
56535 #include <linux/input.h>
56536 #include <linux/gpio_keys.h>
56537
56538 -#include <asm/gpio.h>
56539 +#include <mach/gpio.h>
56540
56541 struct gpio_button_data {
56542 struct gpio_keys_button *button;
56543 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/keyboard/Kconfig linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/Kconfig
56544 --- linux-2.6.29-rc3.owrt/drivers/input/keyboard/Kconfig 2009-05-10 22:04:49.000000000 +0200
56545 +++ linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/Kconfig 2009-05-10 22:27:59.000000000 +0200
56546 @@ -332,4 +332,21 @@
56547
56548 To compile this driver as a module, choose M here: the
56549 module will be called sh_keysc.
56550 +config KEYBOARD_NEO1973
56551 + tristate "FIC Neo1973 buttons"
56552 + depends on MACH_NEO1973
56553 + default y
56554 + help
56555 + Say Y here to enable the buttons on the FIC Neo1973
56556 + GSM phone.
56557 +
56558 + To compile this driver as a module, choose M here: the
56559 + module will be called neo1973kbd.
56560 +
56561 +config KEYBOARD_QT2410
56562 + tristate "QT2410 buttons"
56563 + depends on MACH_QT2410
56564 + default y
56565 +
56566 +
56567 endif
56568 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/keyboard/Makefile linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/Makefile
56569 --- linux-2.6.29-rc3.owrt/drivers/input/keyboard/Makefile 2009-05-10 22:04:49.000000000 +0200
56570 +++ linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/Makefile 2009-05-10 22:27:59.000000000 +0200
56571 @@ -14,6 +14,8 @@
56572 obj-$(CONFIG_KEYBOARD_NEWTON) += newtonkbd.o
56573 obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o
56574 obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o
56575 +obj-$(CONFIG_KEYBOARD_NEO1973) += neo1973kbd.o
56576 +obj-$(CONFIG_KEYBOARD_QT2410) += qt2410kbd.o
56577 obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o
56578 obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o
56579 obj-$(CONFIG_KEYBOARD_HIL) += hil_kbd.o
56580 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/keyboard/neo1973kbd.c linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/neo1973kbd.c
56581 --- linux-2.6.29-rc3.owrt/drivers/input/keyboard/neo1973kbd.c 1970-01-01 01:00:00.000000000 +0100
56582 +++ linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/neo1973kbd.c 2009-05-10 22:27:59.000000000 +0200
56583 @@ -0,0 +1,467 @@
56584 +/*
56585 + * Keyboard driver for FIC Neo1973 GSM phone
56586 + *
56587 + * (C) 2006-2007 by Openmoko, Inc.
56588 + * Author: Harald Welte <laforge@openmoko.org>
56589 + * All rights reserved.
56590 + *
56591 + * inspired by corkgbd.c by Richard Purdie
56592 + *
56593 + * This program is free software; you can redistribute it and/or modify
56594 + * it under the terms of the GNU General Public License version 2 as
56595 + * published by the Free Software Foundation.
56596 + *
56597 + */
56598 +
56599 +#include <linux/delay.h>
56600 +#include <linux/platform_device.h>
56601 +#include <linux/init.h>
56602 +#include <linux/input.h>
56603 +#include <linux/interrupt.h>
56604 +#include <linux/jiffies.h>
56605 +#include <linux/module.h>
56606 +#include <linux/slab.h>
56607 +#include <linux/workqueue.h>
56608 +
56609 +#include <mach/gpio.h>
56610 +#include <asm/mach-types.h>
56611 +
56612 +#ifdef CONFIG_PM
56613 +extern int global_inside_suspend;
56614 +#else
56615 +#define global_inside_suspend 0
56616 +#endif
56617 +
56618 +struct neo1973kbd {
56619 + struct platform_device *pdev;
56620 + struct input_dev *input;
56621 + struct device *cdev;
56622 + struct work_struct work;
56623 + int aux_state;
56624 + int work_in_progress;
56625 + int hp_irq_count_in_work;
56626 + int hp_irq_count;
56627 + int jack_irq;
56628 +};
56629 +
56630 +static struct class *neo1973kbd_switch_class;
56631 +
56632 +enum keys {
56633 + NEO1973_KEY_AUX, /* GTA01 / 02 only */
56634 + NEO1973_KEY_HOLD,
56635 + NEO1973_KEY_JACK,
56636 + NEO1973_KEY_PLUS, /* GTA03 only */
56637 + NEO1973_KEY_MINUS, /* GTA03 only */
56638 +};
56639 +
56640 +struct neo1973kbd_key {
56641 + const char * name;
56642 + irqreturn_t (*isr)(int irq, void *dev_id);
56643 + int irq;
56644 + int input_key;
56645 +};
56646 +
56647 +static irqreturn_t neo1973kbd_aux_irq(int irq, void *dev_id);
56648 +static irqreturn_t neo1973kbd_headphone_irq(int irq, void *dev_id);
56649 +static irqreturn_t neo1973kbd_default_key_irq(int irq, void *dev_id);
56650 +
56651 +
56652 +static struct neo1973kbd_key keys[] = {
56653 + [NEO1973_KEY_AUX] = {
56654 + .name = "Neo1973 AUX button",
56655 + .isr = neo1973kbd_aux_irq,
56656 + .input_key = KEY_PHONE,
56657 + },
56658 + [NEO1973_KEY_HOLD] = {
56659 + .name = "Neo1973 HOLD button",
56660 + .isr = neo1973kbd_default_key_irq,
56661 + .input_key = KEY_PAUSE,
56662 + },
56663 + [NEO1973_KEY_JACK] = {
56664 + .name = "Neo1973 Headphone jack",
56665 + .isr = neo1973kbd_headphone_irq,
56666 + },
56667 + [NEO1973_KEY_PLUS] = {
56668 + .name = "GTA03 PLUS button",
56669 + .isr = neo1973kbd_default_key_irq,
56670 + .input_key = KEY_KPPLUS,
56671 + },
56672 + [NEO1973_KEY_MINUS] = {
56673 + .name = "GTA03 MINUS button",
56674 + .isr = neo1973kbd_default_key_irq,
56675 + .input_key = KEY_KPMINUS,
56676 + },
56677 +};
56678 +
56679 +/* This timer section filters AUX button IRQ bouncing */
56680 +
56681 +static void aux_key_timer_f(unsigned long data);
56682 +
56683 +static struct timer_list aux_key_timer =
56684 + TIMER_INITIALIZER(aux_key_timer_f, 0, 0);
56685 +
56686 +#define AUX_TIMER_TIMEOUT (HZ >> 7)
56687 +#define AUX_TIMER_ALLOWED_NOOP 2
56688 +#define AUX_TIMER_CONSECUTIVE_EVENTS 5
56689 +
56690 +struct neo1973kbd *timer_kbd;
56691 +
56692 +static void aux_key_timer_f(unsigned long data)
56693 +{
56694 + static int noop_counter;
56695 + static int last_key = -1;
56696 + static int last_count;
56697 + int key_pressed;
56698 +
56699 + key_pressed =
56700 + !gpio_get_value(timer_kbd->pdev->resource[NEO1973_KEY_AUX].start);
56701 + if (machine_is_neo1973_gta02())
56702 + key_pressed = !key_pressed;
56703 +
56704 + if (likely(key_pressed == last_key))
56705 + last_count++;
56706 + else {
56707 + last_count = 1;
56708 + last_key = key_pressed;
56709 + }
56710 +
56711 + if (unlikely(last_count >= AUX_TIMER_CONSECUTIVE_EVENTS)) {
56712 + if (timer_kbd->aux_state != last_key) {
56713 + input_report_key(timer_kbd->input, KEY_PHONE, last_key);
56714 + input_sync(timer_kbd->input);
56715 +
56716 + timer_kbd->aux_state = last_key;
56717 + noop_counter = 0;
56718 + }
56719 + last_count = 0;
56720 + if (unlikely(++noop_counter > AUX_TIMER_ALLOWED_NOOP)) {
56721 + noop_counter = 0;
56722 + return;
56723 + }
56724 + }
56725 +
56726 + mod_timer(&aux_key_timer, jiffies + AUX_TIMER_TIMEOUT);
56727 +}
56728 +
56729 +static irqreturn_t neo1973kbd_aux_irq(int irq, void *dev)
56730 +{
56731 + mod_timer(&aux_key_timer, jiffies + AUX_TIMER_TIMEOUT);
56732 +
56733 + return IRQ_HANDLED;
56734 +}
56735 +
56736 +static irqreturn_t neo1973kbd_default_key_irq(int irq, void *dev_id)
56737 +{
56738 + struct neo1973kbd *kbd = dev_id;
56739 + int n;
56740 +
56741 + for (n = 0; n < ARRAY_SIZE(keys); n++) {
56742 +
56743 + if (irq != keys[n].irq)
56744 + continue;
56745 +
56746 + input_report_key(kbd->input, keys[n].input_key,
56747 + gpio_get_value(kbd->pdev->resource[n].start));
56748 + input_sync(kbd->input);
56749 + }
56750 +
56751 + return IRQ_HANDLED;
56752 +}
56753 +
56754 +
56755 +static const char *event_array_jack[2][4] = {
56756 + [0] = {
56757 + "SWITCH_NAME=headset",
56758 + "SWITCH_STATE=0",
56759 + "EVENT=remove",
56760 + NULL
56761 + },
56762 + [1] = {
56763 + "SWITCH_NAME=headset",
56764 + "SWITCH_STATE=1",
56765 + "EVENT=insert",
56766 + NULL
56767 + },
56768 +};
56769 +
56770 +static void neo1973kbd_jack_event(struct device *dev, int num)
56771 +{
56772 + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, (char **)event_array_jack[!!num]);
56773 +}
56774 +
56775 +
56776 +static void neo1973kbd_debounce_jack(struct work_struct *work)
56777 +{
56778 + struct neo1973kbd *kbd = container_of(work, struct neo1973kbd, work);
56779 + unsigned long flags;
56780 + int loop = 0;
56781 + int level;
56782 +
56783 + do {
56784 + /*
56785 + * we wait out any multiple interrupt
56786 + * stuttering in 100ms lumps
56787 + */
56788 + do {
56789 + kbd->hp_irq_count_in_work = kbd->hp_irq_count;
56790 + msleep(100);
56791 + } while (kbd->hp_irq_count != kbd->hp_irq_count_in_work);
56792 + /*
56793 + * no new interrupts on jack for 100ms...
56794 + * ok we will report it
56795 + */
56796 + level = gpio_get_value(kbd->pdev->resource[NEO1973_KEY_JACK].start);
56797 + input_report_switch(kbd->input, SW_HEADPHONE_INSERT, level);
56798 + input_sync(kbd->input);
56799 + neo1973kbd_jack_event(kbd->cdev, level);
56800 + /*
56801 + * we go around the outer loop again if we detect that more
56802 + * interrupts came while we are servicing here. But we have
56803 + * to sequence it carefully with interrupts off
56804 + */
56805 + local_save_flags(flags);
56806 + /* no interrupts during this work means we can exit the work */
56807 + loop = !!(kbd->hp_irq_count != kbd->hp_irq_count_in_work);
56808 + if (!loop)
56809 + kbd->work_in_progress = 0;
56810 + local_irq_restore(flags);
56811 + /*
56812 + * interrupt that comes here will either queue a new work action
56813 + * since work_in_progress is cleared now, or be dealt with
56814 + * when we loop.
56815 + */
56816 + } while (loop);
56817 +}
56818 +
56819 +
56820 +static irqreturn_t neo1973kbd_headphone_irq(int irq, void *dev_id)
56821 +{
56822 + struct neo1973kbd *neo1973kbd_data = dev_id;
56823 +
56824 + /*
56825 + * this interrupt is prone to bouncing and userspace doesn't like
56826 + * to have to deal with that kind of thing. So we do not accept
56827 + * that a jack interrupt is equal to a jack event. Instead we fire
56828 + * some work on the first interrupt, and it hangs about in 100ms units
56829 + * until no more interrupts come. Then it accepts the state it finds
56830 + * for jack insert and reports it once
56831 + */
56832 +
56833 + neo1973kbd_data->hp_irq_count++;
56834 + /*
56835 + * the first interrupt we see for a while, we fire the work item
56836 + * and record the interrupt count when we did that. If more interrupts
56837 + * come in the meanwhile, we can tell by the difference in that
56838 + * stored count and hp_irq_count which increments every interrupt
56839 + */
56840 + if (!neo1973kbd_data->work_in_progress) {
56841 + neo1973kbd_data->jack_irq = irq;
56842 + neo1973kbd_data->hp_irq_count_in_work =
56843 + neo1973kbd_data->hp_irq_count;
56844 + if (!schedule_work(&neo1973kbd_data->work))
56845 + printk(KERN_ERR
56846 + "Unable to schedule headphone debounce\n");
56847 + else
56848 + neo1973kbd_data->work_in_progress = 1;
56849 + }
56850 +
56851 + return IRQ_HANDLED;
56852 +}
56853 +
56854 +#ifdef CONFIG_PM
56855 +static int neo1973kbd_suspend(struct platform_device *dev, pm_message_t state)
56856 +{
56857 + if (machine_is_neo1973_gta02()) {
56858 + disable_irq(keys[NEO1973_KEY_AUX].irq);
56859 + del_timer_sync(&aux_key_timer);
56860 + }
56861 + return 0;
56862 +}
56863 +
56864 +static int neo1973kbd_resume(struct platform_device *dev)
56865 +{
56866 + if (machine_is_neo1973_gta02())
56867 + enable_irq(keys[NEO1973_KEY_AUX].irq);
56868 +
56869 + return 0;
56870 +}
56871 +#else
56872 +#define neo1973kbd_suspend NULL
56873 +#define neo1973kbd_resume NULL
56874 +#endif
56875 +
56876 +static ssize_t neo1973kbd_switch_name_show(struct device *dev,
56877 + struct device_attribute *attr, char *buf)
56878 +{
56879 + return sprintf(buf, "%s\n", "neo1973 Headset Jack");
56880 +}
56881 +
56882 +static ssize_t neo1973kbd_switch_state_show(struct device *dev,
56883 + struct device_attribute *attr, char *buf)
56884 +{
56885 + struct neo1973kbd *kbd = dev_get_drvdata(dev);
56886 + return sprintf(buf, "%d\n",
56887 + gpio_get_value(kbd->pdev->resource[NEO1973_KEY_JACK].start));
56888 +}
56889 +
56890 +static DEVICE_ATTR(name, S_IRUGO , neo1973kbd_switch_name_show, NULL);
56891 +static DEVICE_ATTR(state, S_IRUGO , neo1973kbd_switch_state_show, NULL);
56892 +
56893 +static int neo1973kbd_probe(struct platform_device *pdev)
56894 +{
56895 + struct neo1973kbd *neo1973kbd;
56896 + struct input_dev *input_dev;
56897 + int rc;
56898 + int irq;
56899 + int n;
56900 +
56901 + neo1973kbd = kzalloc(sizeof(struct neo1973kbd), GFP_KERNEL);
56902 + input_dev = input_allocate_device();
56903 + if (!neo1973kbd || !input_dev) {
56904 + kfree(neo1973kbd);
56905 + input_free_device(input_dev);
56906 + return -ENOMEM;
56907 + }
56908 +
56909 + neo1973kbd->pdev = pdev;
56910 + timer_kbd = neo1973kbd;
56911 +
56912 + if (pdev->resource[0].flags != 0)
56913 + return -EINVAL;
56914 +
56915 + platform_set_drvdata(pdev, neo1973kbd);
56916 +
56917 + neo1973kbd->input = input_dev;
56918 +
56919 + INIT_WORK(&neo1973kbd->work, neo1973kbd_debounce_jack);
56920 +
56921 + input_dev->name = "Neo1973 Buttons";
56922 + input_dev->phys = "neo1973kbd/input0";
56923 + input_dev->id.bustype = BUS_HOST;
56924 + input_dev->id.vendor = 0x0001;
56925 + input_dev->id.product = 0x0001;
56926 + input_dev->id.version = 0x0100;
56927 + input_dev->dev.parent = &pdev->dev;
56928 +
56929 + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_SW);
56930 + set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
56931 + set_bit(KEY_PHONE, input_dev->keybit);
56932 + set_bit(KEY_PAUSE, input_dev->keybit);
56933 +
56934 + rc = input_register_device(neo1973kbd->input);
56935 + if (rc)
56936 + goto out_register;
56937 +
56938 + neo1973kbd->cdev = device_create(neo1973kbd_switch_class,
56939 + &pdev->dev, 0, neo1973kbd, "headset");
56940 + if (unlikely(IS_ERR(neo1973kbd->cdev))) {
56941 + rc = PTR_ERR(neo1973kbd->cdev);
56942 + goto out_device_create;
56943 + }
56944 +
56945 + rc = device_create_file(neo1973kbd->cdev, &dev_attr_name);
56946 + if(rc)
56947 + goto out_device_create_file;
56948 +
56949 + rc = device_create_file(neo1973kbd->cdev, &dev_attr_state);
56950 + if(rc)
56951 + goto out_device_create_file;
56952 +
56953 + /* register GPIO IRQs */
56954 + for(n = 0; n < min(pdev->num_resources, ARRAY_SIZE(keys)); n++) {
56955 +
56956 + if (!pdev->resource[0].start)
56957 + continue;
56958 +
56959 + irq = gpio_to_irq(pdev->resource[n].start);
56960 + if (irq < 0)
56961 + continue;
56962 +
56963 + if (request_irq(irq, keys[n].isr, IRQF_DISABLED |
56964 + IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
56965 + keys[n].name, neo1973kbd)) {
56966 + dev_err(&pdev->dev, "Can't get IRQ %u\n", irq);
56967 +
56968 + /* unwind any irq registrations and fail */
56969 +
56970 + while (n > 0) {
56971 + n--;
56972 + free_irq(gpio_to_irq(pdev->resource[n].start),
56973 + neo1973kbd);
56974 + }
56975 + goto out_device_create_file;
56976 + }
56977 +
56978 + keys[n].irq = irq;
56979 + }
56980 +
56981 + /*
56982 + * GTA01 revisions before Bv4 can't be resumed by the PMU, so we use
56983 + * resume by AUX.
56984 + */
56985 + if (machine_is_neo1973_gta01())
56986 + enable_irq_wake(keys[NEO1973_KEY_AUX].irq);
56987 +
56988 + enable_irq_wake(keys[NEO1973_KEY_JACK].irq);
56989 +
56990 + return 0;
56991 +
56992 +out_device_create_file:
56993 + device_unregister(neo1973kbd->cdev);
56994 +out_device_create:
56995 + input_unregister_device(neo1973kbd->input);
56996 +out_register:
56997 + input_free_device(neo1973kbd->input);
56998 + platform_set_drvdata(pdev, NULL);
56999 + kfree(neo1973kbd);
57000 +
57001 + return -ENODEV;
57002 +}
57003 +
57004 +static int neo1973kbd_remove(struct platform_device *pdev)
57005 +{
57006 + struct neo1973kbd *neo1973kbd = platform_get_drvdata(pdev);
57007 +
57008 + free_irq(gpio_to_irq(pdev->resource[2].start), neo1973kbd);
57009 + free_irq(gpio_to_irq(pdev->resource[1].start), neo1973kbd);
57010 + free_irq(gpio_to_irq(pdev->resource[0].start), neo1973kbd);
57011 +
57012 + device_unregister(neo1973kbd->cdev);
57013 + input_unregister_device(neo1973kbd->input);
57014 + input_free_device(neo1973kbd->input);
57015 + platform_set_drvdata(pdev, NULL);
57016 + kfree(neo1973kbd);
57017 +
57018 + return 0;
57019 +}
57020 +
57021 +static struct platform_driver neo1973kbd_driver = {
57022 + .probe = neo1973kbd_probe,
57023 + .remove = neo1973kbd_remove,
57024 + .suspend = neo1973kbd_suspend,
57025 + .resume = neo1973kbd_resume,
57026 + .driver = {
57027 + .name = "neo1973-button",
57028 + },
57029 +};
57030 +
57031 +static int __devinit neo1973kbd_init(void)
57032 +{
57033 + neo1973kbd_switch_class = class_create(THIS_MODULE, "switch");
57034 + if (IS_ERR(neo1973kbd_switch_class))
57035 + return PTR_ERR(neo1973kbd_switch_class);
57036 + return platform_driver_register(&neo1973kbd_driver);
57037 +}
57038 +
57039 +static void __exit neo1973kbd_exit(void)
57040 +{
57041 + platform_driver_unregister(&neo1973kbd_driver);
57042 + class_destroy(neo1973kbd_switch_class);
57043 +}
57044 +
57045 +module_init(neo1973kbd_init);
57046 +module_exit(neo1973kbd_exit);
57047 +
57048 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
57049 +MODULE_DESCRIPTION("FIC Neo1973 buttons input driver");
57050 +MODULE_LICENSE("GPL");
57051 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/keyboard/qt2410kbd.c linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/qt2410kbd.c
57052 --- linux-2.6.29-rc3.owrt/drivers/input/keyboard/qt2410kbd.c 1970-01-01 01:00:00.000000000 +0100
57053 +++ linux-2.6.29-rc3.owrt.om/drivers/input/keyboard/qt2410kbd.c 2009-05-10 22:27:59.000000000 +0200
57054 @@ -0,0 +1,231 @@
57055 +/*
57056 + * Keyboard driver for Armzone QT2410
57057 + *
57058 + * (C) 2006 by Openmoko, Inc.
57059 + * Author: Harald Welte <laforge@openmoko.org>
57060 + * All rights reserved.
57061 + *
57062 + * This program is free software; you can redistribute it and/or modify
57063 + * it under the terms of the GNU General Public License version 2 as
57064 + * published by the Free Software Foundation.
57065 + *
57066 + */
57067 +
57068 +#include <linux/delay.h>
57069 +#include <linux/platform_device.h>
57070 +#include <linux/init.h>
57071 +#include <linux/input.h>
57072 +#include <linux/interrupt.h>
57073 +#include <linux/jiffies.h>
57074 +#include <linux/module.h>
57075 +#include <linux/slab.h>
57076 +
57077 +#include <mach/hardware.h>
57078 +#include <mach/gta01.h>
57079 +
57080 +struct gta01kbd {
57081 + struct input_dev *input;
57082 + unsigned int suspended;
57083 + unsigned long suspend_jiffies;
57084 +};
57085 +
57086 +static irqreturn_t gta01kbd_interrupt(int irq, void *dev_id)
57087 +{
57088 + struct gta01kbd *gta01kbd_data = dev_id;
57089 +
57090 + /* FIXME: use GPIO from platform_dev resources */
57091 + if (s3c2410_gpio_getpin(S3C2410_GPF0))
57092 + input_report_key(gta01kbd_data->input, KEY_PHONE, 1);
57093 + else
57094 + input_report_key(gta01kbd_data->input, KEY_PHONE, 0);
57095 +
57096 + input_sync(gta01kbd_data->input);
57097 +
57098 + return IRQ_HANDLED;
57099 +}
57100 +
57101 +
57102 +#ifdef CONFIG_PM
57103 +static int gta01kbd_suspend(struct platform_device *dev, pm_message_t state)
57104 +{
57105 + struct gta01kbd *gta01kbd = platform_get_drvdata(dev);
57106 +
57107 + gta01kbd->suspended = 1;
57108 +
57109 + return 0;
57110 +}
57111 +
57112 +static int gta01kbd_resume(struct platform_device *dev)
57113 +{
57114 + struct gta01kbd *gta01kbd = platform_get_drvdata(dev);
57115 +
57116 + gta01kbd->suspended = 0;
57117 +
57118 + return 0;
57119 +}
57120 +#else
57121 +#define gta01kbd_suspend NULL
57122 +#define gta01kbd_resume NULL
57123 +#endif
57124 +
57125 +static int gta01kbd_probe(struct platform_device *pdev)
57126 +{
57127 + struct gta01kbd *gta01kbd;
57128 + struct input_dev *input_dev;
57129 + int irq_911;
57130 + int rc = 0;
57131 +
57132 + gta01kbd = kzalloc(sizeof(struct gta01kbd), GFP_KERNEL);
57133 + if (!gta01kbd) {
57134 + rc = -ENOMEM;
57135 + goto bail;
57136 + }
57137 + input_dev = input_allocate_device();
57138 + if (!gta01kbd || !input_dev) {
57139 + rc = -ENOMEM;
57140 + goto bail_free;
57141 + }
57142 +
57143 + if (pdev->resource[0].flags != 0) {\
57144 + rc = -EINVAL;
57145 + goto bail_free_dev;
57146 + }
57147 +
57148 + irq_911 = s3c2410_gpio_getirq(pdev->resource[0].start);
57149 + if (irq_911 < 0) {
57150 + rc = -EINVAL;
57151 + goto bail_free_dev;
57152 + }
57153 +
57154 + platform_set_drvdata(pdev, gta01kbd);
57155 +
57156 + gta01kbd->input = input_dev;
57157 +
57158 +#if 0
57159 + spin_lock_init(&gta01kbd->lock);
57160 + /* Init Keyboard rescan timer */
57161 + init_timer(&corgikbd->timer);
57162 + corgikbd->timer.function = corgikbd_timer_callback;
57163 + corgikbd->timer.data = (unsigned long) corgikbd;
57164 +
57165 + /* Init Hinge Timer */
57166 + init_timer(&corgikbd->htimer);
57167 + corgikbd->htimer.function = corgikbd_hinge_timer;
57168 + corgikbd->htimer.data = (unsigned long) corgikbd;
57169 +
57170 + corgikbd->suspend_jiffies=jiffies;
57171 +
57172 + memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
57173 +#endif
57174 +
57175 + input_dev->name = "QT2410 Buttons";
57176 + input_dev->phys = "qt2410kbd/input0";
57177 + input_dev->id.bustype = BUS_HOST;
57178 + input_dev->id.vendor = 0x0001;
57179 + input_dev->id.product = 0x0001;
57180 + input_dev->id.version = 0x0100;
57181 +
57182 + input_dev->evbit[0] = BIT(EV_KEY);
57183 +#if 0
57184 + input_dev->keycode = gta01kbd->keycode;
57185 + input_dev->keycodesize = sizeof(unsigned char);
57186 + input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
57187 +
57188 + for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++)
57189 + set_bit(corgikbd->keycode[i], input_dev->keybit);
57190 + clear_bit(0, input_dev->keybit);
57191 + set_bit(SW_LID, input_dev->swbit);
57192 + set_bit(SW_TABLET_MODE, input_dev->swbit);
57193 + set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
57194 +#endif
57195 +
57196 + rc = input_register_device(gta01kbd->input);
57197 + if (rc)
57198 + goto bail_free_dev;
57199 +
57200 + s3c2410_gpio_cfgpin(S3C2410_GPF0, S3C2410_GPF0_EINT0);
57201 + if (request_irq(irq_911, gta01kbd_interrupt,
57202 + IRQF_DISABLED | IRQF_TRIGGER_RISING |
57203 + IRQF_TRIGGER_FALLING, "qt2410kbd_eint0", gta01kbd))
57204 + printk(KERN_WARNING "gta01kbd: Can't get IRQ\n");
57205 + enable_irq_wake(irq_911);
57206 +
57207 + /* FIXME: headphone insert */
57208 +
57209 +#if 0
57210 + mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
57211 +
57212 + /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */
57213 + for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) {
57214 + pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN);
57215 + if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt,
57216 + SA_INTERRUPT | SA_TRIGGER_RISING,
57217 + "corgikbd", corgikbd))
57218 + printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i);
57219 + }
57220 +
57221 + /* Set Strobe lines as outputs - set high */
57222 + for (i = 0; i < CORGI_KEY_STROBE_NUM; i++)
57223 + pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH);
57224 +
57225 + /* Setup the headphone jack as an input */
57226 + pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
57227 +#endif
57228 +
57229 + return 0;
57230 +
57231 +bail_free_dev:
57232 + input_free_device(input_dev);
57233 +bail_free:
57234 + kfree(gta01kbd);
57235 +bail:
57236 + return rc;
57237 +}
57238 +
57239 +static int gta01kbd_remove(struct platform_device *pdev)
57240 +{
57241 + struct gta01kbd *gta01kbd = platform_get_drvdata(pdev);
57242 +
57243 + free_irq(s3c2410_gpio_getirq(pdev->resource[0].start), gta01kbd);
57244 +#if 0
57245 + int i;
57246 +
57247 + for (i = 0; i < CORGI_KEY_SENSE_NUM; i++)
57248 + free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd);
57249 +
57250 + del_timer_sync(&corgikbd->htimer);
57251 + del_timer_sync(&corgikbd->timer);
57252 +#endif
57253 + input_unregister_device(gta01kbd->input);
57254 +
57255 + kfree(gta01kbd);
57256 +
57257 + return 0;
57258 +}
57259 +
57260 +static struct platform_driver gta01kbd_driver = {
57261 + .probe = gta01kbd_probe,
57262 + .remove = gta01kbd_remove,
57263 + .suspend = gta01kbd_suspend,
57264 + .resume = gta01kbd_resume,
57265 + .driver = {
57266 + .name = "qt2410-button",
57267 + },
57268 +};
57269 +
57270 +static int __devinit gta01kbd_init(void)
57271 +{
57272 + return platform_driver_register(&gta01kbd_driver);
57273 +}
57274 +
57275 +static void __exit gta01kbd_exit(void)
57276 +{
57277 + platform_driver_unregister(&gta01kbd_driver);
57278 +}
57279 +
57280 +module_init(gta01kbd_init);
57281 +module_exit(gta01kbd_exit);
57282 +
57283 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
57284 +MODULE_DESCRIPTION("Armzone QT2410 Buttons Driver");
57285 +MODULE_LICENSE("GPL");
57286 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/misc/Kconfig linux-2.6.29-rc3.owrt.om/drivers/input/misc/Kconfig
57287 --- linux-2.6.29-rc3.owrt/drivers/input/misc/Kconfig 2009-05-10 22:04:49.000000000 +0200
57288 +++ linux-2.6.29-rc3.owrt.om/drivers/input/misc/Kconfig 2009-05-10 22:27:59.000000000 +0200
57289 @@ -220,12 +220,26 @@
57290 Say Y here if you want to support the built-in real time clock
57291 of the HP SDC controller.
57292
57293 +config INPUT_LIS302DL
57294 + tristate "STmicro LIS302DL 3-axis accelerometer"
57295 + depends on SPI_MASTER
57296 + help
57297 + SPI driver for the STmicro LIS302DL 3-axis accelerometer.
57298 +
57299 + The userspece interface is a 3-axis (X/Y/Z) relative movement
57300 + Linux input device, reporting REL_[XYZ] events.
57301 +
57302 config INPUT_PCF50633_PMU
57303 tristate "PCF50633 PMU events"
57304 depends on MFD_PCF50633
57305 help
57306 - Say Y to include support for delivering PMU events via input
57307 - layer on NXP PCF50633.
57308 + Say Y to include support for input events on NXP PCF50633.
57309 +
57310 +config INPUT_PCF50606_PMU
57311 + tristate "PCF50606 PMU events"
57312 + depends on MFD_PCF50606
57313 + help
57314 + Say Y to include support for input events on NXP PCF50606.
57315
57316 config INPUT_GPIO_BUTTONS
57317 tristate "Polled GPIO buttons interface"
57318 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/misc/lis302dl.c linux-2.6.29-rc3.owrt.om/drivers/input/misc/lis302dl.c
57319 --- linux-2.6.29-rc3.owrt/drivers/input/misc/lis302dl.c 1970-01-01 01:00:00.000000000 +0100
57320 +++ linux-2.6.29-rc3.owrt.om/drivers/input/misc/lis302dl.c 2009-05-10 22:27:59.000000000 +0200
57321 @@ -0,0 +1,958 @@
57322 +/* Linux kernel driver for the ST LIS302D 3-axis accelerometer
57323 + *
57324 + * Copyright (C) 2007-2008 by Openmoko, Inc.
57325 + * Author: Harald Welte <laforge@openmoko.org>
57326 + * converted to private bitbang by:
57327 + * Andy Green <andy@openmoko.com>
57328 + * ability to set acceleration threshold added by:
57329 + * Simon Kagstrom <simon.kagstrom@gmail.com>
57330 + * All rights reserved.
57331 + *
57332 + * This program is free software; you can redistribute it and/or
57333 + * modify it under the terms of the GNU General Public License as
57334 + * published by the Free Software Foundation; either version 2 of
57335 + * the License, or (at your option) any later version.
57336 + *
57337 + * This program is distributed in the hope that it will be useful,
57338 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
57339 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
57340 + * GNU General Public License for more details.
57341 + *
57342 + * You should have received a copy of the GNU General Public License
57343 + * along with this program; if not, write to the Free Software
57344 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
57345 + * MA 02111-1307 USA
57346 + *
57347 + * TODO
57348 + * * statistics for overflow events
57349 + * * configuration interface (sysfs) for
57350 + * * enable/disable x/y/z axis data ready
57351 + * * enable/disable resume from freee fall / click
57352 + * * free fall / click parameters
57353 + * * high pass filter parameters
57354 + */
57355 +#include <linux/kernel.h>
57356 +#include <linux/types.h>
57357 +#include <linux/module.h>
57358 +#include <linux/device.h>
57359 +#include <linux/platform_device.h>
57360 +#include <linux/delay.h>
57361 +#include <linux/irq.h>
57362 +#include <linux/interrupt.h>
57363 +#include <linux/sysfs.h>
57364 +#include <linux/spi/spi.h>
57365 +
57366 +#include <linux/lis302dl.h>
57367 +
57368 +/* Utility functions */
57369 +static u8 __reg_read(struct lis302dl_info *lis, u8 reg)
57370 +{
57371 + struct spi_message msg;
57372 + struct spi_transfer t;
57373 + u8 data[2] = {0xc0 | reg};
57374 + int rc;
57375 +
57376 + spi_message_init(&msg);
57377 + memset(&t, 0, sizeof t);
57378 + t.len = 2;
57379 + spi_message_add_tail(&t, &msg);
57380 + t.tx_buf = &data[0];
57381 + t.rx_buf = &data[0];
57382 +
57383 + /* Should complete without blocking */
57384 + rc = spi_non_blocking_transfer(lis->spi, &msg);
57385 + if (rc < 0) {
57386 + dev_err(lis->dev, "Error reading register\n");
57387 + return rc;
57388 + }
57389 +
57390 + return data[1];
57391 +}
57392 +
57393 +static void __reg_write(struct lis302dl_info *lis, u8 reg, u8 val)
57394 +{
57395 + struct spi_message msg;
57396 + struct spi_transfer t;
57397 + u8 data[2] = {reg, val};
57398 +
57399 + spi_message_init(&msg);
57400 + memset(&t, 0, sizeof t);
57401 + t.len = 2;
57402 + spi_message_add_tail(&t, &msg);
57403 + t.tx_buf = &data[0];
57404 + t.rx_buf = &data[0];
57405 +
57406 + /* Completes without blocking */
57407 + if (spi_non_blocking_transfer(lis->spi, &msg) < 0)
57408 + dev_err(lis->dev, "Error writing register\n");
57409 +}
57410 +
57411 +static void __reg_set_bit_mask(struct lis302dl_info *lis, u8 reg, u8 mask,
57412 + u8 val)
57413 +{
57414 + u_int8_t tmp;
57415 +
57416 + val &= mask;
57417 +
57418 + tmp = __reg_read(lis, reg);
57419 + tmp &= ~mask;
57420 + tmp |= val;
57421 + __reg_write(lis, reg, tmp);
57422 +}
57423 +
57424 +static int __ms_to_duration(struct lis302dl_info *lis, int ms)
57425 +{
57426 + /* If we have 400 ms sampling rate, the stepping is 2.5 ms,
57427 + * on 100 ms the stepping is 10ms */
57428 + if (lis->flags & LIS302DL_F_DR)
57429 + return min((ms * 10) / 25, 637);
57430 +
57431 + return min(ms / 10, 2550);
57432 +}
57433 +
57434 +static int __duration_to_ms(struct lis302dl_info *lis, int duration)
57435 +{
57436 + if (lis->flags & LIS302DL_F_DR)
57437 + return (duration * 25) / 10;
57438 +
57439 + return duration * 10;
57440 +}
57441 +
57442 +static u8 __mg_to_threshold(struct lis302dl_info *lis, int mg)
57443 +{
57444 + /* If FS is set each bit is 71mg, otherwise 18mg. The THS register
57445 + * has 7 bits for the threshold value */
57446 + if (lis->flags & LIS302DL_F_FS)
57447 + return min(mg / 71, 127);
57448 +
57449 + return min(mg / 18, 127);
57450 +}
57451 +
57452 +static int __threshold_to_mg(struct lis302dl_info *lis, u8 threshold)
57453 +{
57454 + if (lis->flags & LIS302DL_F_FS)
57455 + return threshold * 71;
57456 +
57457 + return threshold * 18;
57458 +}
57459 +
57460 +/* interrupt handling related */
57461 +
57462 +enum lis302dl_intmode {
57463 + LIS302DL_INTMODE_GND = 0x00,
57464 + LIS302DL_INTMODE_FF_WU_1 = 0x01,
57465 + LIS302DL_INTMODE_FF_WU_2 = 0x02,
57466 + LIS302DL_INTMODE_FF_WU_12 = 0x03,
57467 + LIS302DL_INTMODE_DATA_READY = 0x04,
57468 + LIS302DL_INTMODE_CLICK = 0x07,
57469 +};
57470 +
57471 +static void __lis302dl_int_mode(struct device *dev, int int_pin,
57472 + enum lis302dl_intmode mode)
57473 +{
57474 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57475 +
57476 + switch (int_pin) {
57477 + case 1:
57478 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x07, mode);
57479 + break;
57480 + case 2:
57481 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x38, mode << 3);
57482 + break;
57483 + default:
57484 + BUG();
57485 + }
57486 +}
57487 +
57488 +static void __enable_wakeup(struct lis302dl_info *lis)
57489 +{
57490 + __reg_write(lis, LIS302DL_REG_CTRL1, 0);
57491 +
57492 + /* First zero to get to a known state */
57493 + __reg_write(lis, LIS302DL_REG_FF_WU_CFG_1, LIS302DL_FFWUCFG_XHIE |
57494 + LIS302DL_FFWUCFG_YHIE | LIS302DL_FFWUCFG_ZHIE |
57495 + LIS302DL_FFWUCFG_LIR);
57496 + __reg_write(lis, LIS302DL_REG_FF_WU_THS_1,
57497 + __mg_to_threshold(lis, lis->wakeup.threshold));
57498 + __reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1,
57499 + __ms_to_duration(lis, lis->wakeup.duration));
57500 +
57501 + /* Route the interrupt for wakeup */
57502 + __lis302dl_int_mode(lis->dev, 1,
57503 + LIS302DL_INTMODE_FF_WU_1);
57504 +
57505 + __reg_read(lis, LIS302DL_REG_HP_FILTER_RESET);
57506 + __reg_read(lis, LIS302DL_REG_OUT_X);
57507 + __reg_read(lis, LIS302DL_REG_OUT_Y);
57508 + __reg_read(lis, LIS302DL_REG_OUT_Z);
57509 + __reg_read(lis, LIS302DL_REG_STATUS);
57510 + __reg_read(lis, LIS302DL_REG_FF_WU_SRC_1);
57511 + __reg_read(lis, LIS302DL_REG_FF_WU_SRC_2);
57512 + __reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD | 7);
57513 +}
57514 +
57515 +static void __enable_data_collection(struct lis302dl_info *lis)
57516 +{
57517 + u_int8_t ctrl1 = LIS302DL_CTRL1_PD | LIS302DL_CTRL1_Xen |
57518 + LIS302DL_CTRL1_Yen | LIS302DL_CTRL1_Zen;
57519 +
57520 + /* make sure we're powered up and generate data ready */
57521 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1);
57522 +
57523 + /* If the threshold is zero, let the device generated an interrupt
57524 + * on each datum */
57525 + if (lis->threshold == 0) {
57526 + __reg_write(lis, LIS302DL_REG_CTRL2, 0);
57527 + __lis302dl_int_mode(lis->dev, 1, LIS302DL_INTMODE_DATA_READY);
57528 + __lis302dl_int_mode(lis->dev, 2, LIS302DL_INTMODE_DATA_READY);
57529 + } else {
57530 + __reg_write(lis, LIS302DL_REG_CTRL2,
57531 + LIS302DL_CTRL2_HPFF1);
57532 + __reg_write(lis, LIS302DL_REG_FF_WU_THS_1,
57533 + __mg_to_threshold(lis, lis->threshold));
57534 + __reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1,
57535 + __ms_to_duration(lis, lis->duration));
57536 +
57537 + /* Clear the HP filter "starting point" */
57538 + __reg_read(lis, LIS302DL_REG_HP_FILTER_RESET);
57539 + __reg_write(lis, LIS302DL_REG_FF_WU_CFG_1,
57540 + LIS302DL_FFWUCFG_XHIE | LIS302DL_FFWUCFG_YHIE |
57541 + LIS302DL_FFWUCFG_ZHIE | LIS302DL_FFWUCFG_LIR);
57542 + __lis302dl_int_mode(lis->dev, 1, LIS302DL_INTMODE_FF_WU_12);
57543 + __lis302dl_int_mode(lis->dev, 2, LIS302DL_INTMODE_FF_WU_12);
57544 + }
57545 +}
57546 +
57547 +#if 0
57548 +static void _report_btn_single(struct input_dev *inp, int btn)
57549 +{
57550 + input_report_key(inp, btn, 1);
57551 + input_sync(inp);
57552 + input_report_key(inp, btn, 0);
57553 +}
57554 +
57555 +static void _report_btn_double(struct input_dev *inp, int btn)
57556 +{
57557 + input_report_key(inp, btn, 1);
57558 + input_sync(inp);
57559 + input_report_key(inp, btn, 0);
57560 + input_sync(inp);
57561 + input_report_key(inp, btn, 1);
57562 + input_sync(inp);
57563 + input_report_key(inp, btn, 0);
57564 +}
57565 +#endif
57566 +
57567 +
57568 +static void lis302dl_bitbang_read_sample(struct lis302dl_info *lis)
57569 +{
57570 + u8 data[(LIS302DL_REG_OUT_Z - LIS302DL_REG_STATUS) + 2] = {0xC0 | LIS302DL_REG_STATUS};
57571 + u8 *read = data + 1;
57572 + unsigned long flags;
57573 + int mg_per_sample = __threshold_to_mg(lis, 1);
57574 + struct spi_message msg;
57575 + struct spi_transfer t;
57576 +
57577 + spi_message_init(&msg);
57578 + memset(&t, 0, sizeof t);
57579 + t.len = sizeof(data);
57580 + spi_message_add_tail(&t, &msg);
57581 + t.tx_buf = &data[0];
57582 + t.rx_buf = &data[0];
57583 +
57584 + /* grab the set of register containing status and XYZ data */
57585 +
57586 + local_irq_save(flags);
57587 +
57588 + /* Should complete without blocking */
57589 + if (spi_non_blocking_transfer(lis->spi, &msg) < 0)
57590 + dev_err(lis->dev, "Error reading registers\n");
57591 +
57592 + local_irq_restore(flags);
57593 +
57594 + /*
57595 + * at the minute the test below fails 50% of the time due to
57596 + * a problem with level interrupts causing ISRs to get called twice.
57597 + * This is a workaround for that, but actually this test is still
57598 + * valid and the information can be used for overrrun stats.
57599 + */
57600 +
57601 + /* has any kind of overrun been observed by the lis302dl? */
57602 + if (read[0] & (LIS302DL_STATUS_XOR |
57603 + LIS302DL_STATUS_YOR |
57604 + LIS302DL_STATUS_ZOR))
57605 + lis->overruns++;
57606 +
57607 + /* we have a valid sample set? */
57608 + if (read[0] & LIS302DL_STATUS_XYZDA) {
57609 + input_report_abs(lis->input_dev, ABS_X, mg_per_sample *
57610 + (s8)read[LIS302DL_REG_OUT_X - LIS302DL_REG_STATUS]);
57611 + input_report_abs(lis->input_dev, ABS_Y, mg_per_sample *
57612 + (s8)read[LIS302DL_REG_OUT_Y - LIS302DL_REG_STATUS]);
57613 + input_report_abs(lis->input_dev, ABS_Z, mg_per_sample *
57614 + (s8)read[LIS302DL_REG_OUT_Z - LIS302DL_REG_STATUS]);
57615 +
57616 + input_sync(lis->input_dev);
57617 + }
57618 +
57619 + if (lis->threshold)
57620 + /* acknowledge the wakeup source */
57621 + __reg_read(lis, LIS302DL_REG_FF_WU_SRC_1);
57622 +}
57623 +
57624 +static irqreturn_t lis302dl_interrupt(int irq, void *_lis)
57625 +{
57626 + struct lis302dl_info *lis = _lis;
57627 +
57628 + lis302dl_bitbang_read_sample(lis);
57629 + return IRQ_HANDLED;
57630 +}
57631 +
57632 +/* sysfs */
57633 +
57634 +static ssize_t show_overruns(struct device *dev, struct device_attribute *attr,
57635 + char *buf)
57636 +{
57637 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57638 +
57639 + return sprintf(buf, "%u\n", lis->overruns);
57640 +}
57641 +
57642 +static DEVICE_ATTR(overruns, S_IRUGO, show_overruns, NULL);
57643 +
57644 +static ssize_t show_rate(struct device *dev, struct device_attribute *attr,
57645 + char *buf)
57646 +{
57647 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57648 + u8 ctrl1;
57649 + unsigned long flags;
57650 +
57651 + local_irq_save(flags);
57652 + ctrl1 = __reg_read(lis, LIS302DL_REG_CTRL1);
57653 + local_irq_restore(flags);
57654 +
57655 + return sprintf(buf, "%d\n", ctrl1 & LIS302DL_CTRL1_DR ? 400 : 100);
57656 +}
57657 +
57658 +static ssize_t set_rate(struct device *dev, struct device_attribute *attr,
57659 + const char *buf, size_t count)
57660 +{
57661 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57662 + unsigned long flags;
57663 +
57664 + local_irq_save(flags);
57665 +
57666 + if (!strcmp(buf, "400\n")) {
57667 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR,
57668 + LIS302DL_CTRL1_DR);
57669 + lis->flags |= LIS302DL_F_DR;
57670 + } else {
57671 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR,
57672 + 0);
57673 + lis->flags &= ~LIS302DL_F_DR;
57674 + }
57675 + local_irq_restore(flags);
57676 +
57677 + return count;
57678 +}
57679 +
57680 +static DEVICE_ATTR(sample_rate, S_IRUGO | S_IWUSR, show_rate, set_rate);
57681 +
57682 +static ssize_t show_scale(struct device *dev, struct device_attribute *attr,
57683 + char *buf)
57684 +{
57685 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57686 + u_int8_t ctrl1;
57687 + unsigned long flags;
57688 +
57689 + local_irq_save(flags);
57690 + ctrl1 = __reg_read(lis, LIS302DL_REG_CTRL1);
57691 + local_irq_restore(flags);
57692 +
57693 + return sprintf(buf, "%s\n", ctrl1 & LIS302DL_CTRL1_FS ? "9.2" : "2.3");
57694 +}
57695 +
57696 +static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
57697 + const char *buf, size_t count)
57698 +{
57699 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57700 + unsigned long flags;
57701 +
57702 + local_irq_save(flags);
57703 +
57704 + if (!strcmp(buf, "9.2\n")) {
57705 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_FS,
57706 + LIS302DL_CTRL1_FS);
57707 + lis->flags |= LIS302DL_F_FS;
57708 + } else {
57709 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_FS,
57710 + 0);
57711 + lis->flags &= ~LIS302DL_F_FS;
57712 + }
57713 +
57714 + if (lis->flags & LIS302DL_F_INPUT_OPEN)
57715 + __enable_data_collection(lis);
57716 +
57717 + local_irq_restore(flags);
57718 +
57719 + return count;
57720 +}
57721 +
57722 +static DEVICE_ATTR(full_scale, S_IRUGO | S_IWUSR, show_scale, set_scale);
57723 +
57724 +static ssize_t show_threshold(struct device *dev, struct device_attribute *attr,
57725 + char *buf)
57726 +{
57727 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57728 +
57729 + /* Display the device view of the threshold setting */
57730 + return sprintf(buf, "%d\n", __threshold_to_mg(lis,
57731 + __mg_to_threshold(lis, lis->threshold)));
57732 +}
57733 +
57734 +static ssize_t set_threshold(struct device *dev, struct device_attribute *attr,
57735 + const char *buf, size_t count)
57736 +{
57737 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57738 + unsigned int val;
57739 +
57740 + if (sscanf(buf, "%u\n", &val) != 1)
57741 + return -EINVAL;
57742 + /* 8g is the maximum if FS is 1 */
57743 + if (val > 8000)
57744 + return -ERANGE;
57745 +
57746 + /* Set the threshold and write it out if the device is used */
57747 + lis->threshold = val;
57748 +
57749 + if (lis->flags & LIS302DL_F_INPUT_OPEN) {
57750 + unsigned long flags;
57751 +
57752 + local_irq_save(flags);
57753 + __enable_data_collection(lis);
57754 + local_irq_restore(flags);
57755 + }
57756 +
57757 + return count;
57758 +}
57759 +
57760 +static DEVICE_ATTR(threshold, S_IRUGO | S_IWUSR, show_threshold, set_threshold);
57761 +
57762 +static ssize_t show_duration(struct device *dev, struct device_attribute *attr,
57763 + char *buf)
57764 +{
57765 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57766 +
57767 + return sprintf(buf, "%d\n", __duration_to_ms(lis,
57768 + __ms_to_duration(lis, lis->duration)));
57769 +}
57770 +
57771 +static ssize_t set_duration(struct device *dev, struct device_attribute *attr,
57772 + const char *buf, size_t count)
57773 +{
57774 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57775 + unsigned int val;
57776 +
57777 + if (sscanf(buf, "%u\n", &val) != 1)
57778 + return -EINVAL;
57779 + if (val > 2550)
57780 + return -ERANGE;
57781 +
57782 + lis->duration = val;
57783 + if (lis->flags & LIS302DL_F_INPUT_OPEN)
57784 + __reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1,
57785 + __ms_to_duration(lis, lis->duration));
57786 +
57787 + return count;
57788 +}
57789 +
57790 +static DEVICE_ATTR(duration, S_IRUGO | S_IWUSR, show_duration, set_duration);
57791 +
57792 +static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr,
57793 + char *buf)
57794 +{
57795 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57796 + int n = 0;
57797 + u8 reg[0x40];
57798 + char *end = buf;
57799 + unsigned long flags;
57800 +
57801 + local_irq_save(flags);
57802 +
57803 + for (n = 0; n < sizeof(reg); n++)
57804 + reg[n] = __reg_read(lis, n);
57805 +
57806 + local_irq_restore(flags);
57807 +
57808 + for (n = 0; n < sizeof(reg); n += 16) {
57809 + hex_dump_to_buffer(reg + n, 16, 16, 1, end, 128, 0);
57810 + end += strlen(end);
57811 + *end++ = '\n';
57812 + *end++ = '\0';
57813 + }
57814 +
57815 + return end - buf;
57816 +}
57817 +static DEVICE_ATTR(dump, S_IRUGO, lis302dl_dump, NULL);
57818 +
57819 +/* Configure freefall/wakeup interrupts */
57820 +static ssize_t set_wakeup_threshold(struct device *dev,
57821 + struct device_attribute *attr, const char *buf, size_t count)
57822 +{
57823 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57824 + unsigned int threshold;
57825 +
57826 + if (sscanf(buf, "%u\n", &threshold) != 1)
57827 + return -EINVAL;
57828 +
57829 + if (threshold > 8000)
57830 + return -ERANGE;
57831 +
57832 + /* Zero turns the feature off */
57833 + if (threshold == 0) {
57834 + if (lis->flags & LIS302DL_F_IRQ_WAKE) {
57835 + disable_irq_wake(lis->pdata->interrupt);
57836 + lis->flags &= ~LIS302DL_F_IRQ_WAKE;
57837 + }
57838 +
57839 + return count;
57840 + }
57841 +
57842 + lis->wakeup.threshold = threshold;
57843 +
57844 + if (!(lis->flags & LIS302DL_F_IRQ_WAKE)) {
57845 + enable_irq_wake(lis->pdata->interrupt);
57846 + lis->flags |= LIS302DL_F_IRQ_WAKE;
57847 + }
57848 +
57849 + return count;
57850 +}
57851 +
57852 +static ssize_t show_wakeup_threshold(struct device *dev,
57853 + struct device_attribute *attr, char *buf)
57854 +{
57855 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57856 +
57857 + /* All events off? */
57858 + if (lis->wakeup.threshold == 0)
57859 + return sprintf(buf, "off\n");
57860 +
57861 + return sprintf(buf, "%u\n", lis->wakeup.threshold);
57862 +}
57863 +
57864 +static DEVICE_ATTR(wakeup_threshold, S_IRUGO | S_IWUSR, show_wakeup_threshold,
57865 + set_wakeup_threshold);
57866 +
57867 +static ssize_t set_wakeup_duration(struct device *dev,
57868 + struct device_attribute *attr, const char *buf, size_t count)
57869 +{
57870 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57871 + unsigned int duration;
57872 +
57873 + if (sscanf(buf, "%u\n", &duration) != 1)
57874 + return -EINVAL;
57875 +
57876 + if (duration > 2550)
57877 + return -ERANGE;
57878 +
57879 + lis->wakeup.duration = duration;
57880 +
57881 + return count;
57882 +}
57883 +
57884 +static ssize_t show_wakeup_duration(struct device *dev,
57885 + struct device_attribute *attr, char *buf)
57886 +{
57887 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57888 +
57889 + return sprintf(buf, "%u\n", lis->wakeup.duration);
57890 +}
57891 +
57892 +static DEVICE_ATTR(wakeup_duration, S_IRUGO | S_IWUSR, show_wakeup_duration,
57893 + set_wakeup_duration);
57894 +
57895 +static struct attribute *lis302dl_sysfs_entries[] = {
57896 + &dev_attr_sample_rate.attr,
57897 + &dev_attr_full_scale.attr,
57898 + &dev_attr_threshold.attr,
57899 + &dev_attr_duration.attr,
57900 + &dev_attr_dump.attr,
57901 + &dev_attr_wakeup_threshold.attr,
57902 + &dev_attr_wakeup_duration.attr,
57903 + &dev_attr_overruns.attr,
57904 + NULL
57905 +};
57906 +
57907 +static struct attribute_group lis302dl_attr_group = {
57908 + .name = NULL,
57909 + .attrs = lis302dl_sysfs_entries,
57910 +};
57911 +
57912 +/* input device handling and driver core interaction */
57913 +
57914 +static int lis302dl_input_open(struct input_dev *inp)
57915 +{
57916 + struct lis302dl_info *lis = input_get_drvdata(inp);
57917 + unsigned long flags;
57918 +
57919 + local_irq_save(flags);
57920 +
57921 + __enable_data_collection(lis);
57922 + lis->flags |= LIS302DL_F_INPUT_OPEN;
57923 +
57924 + local_irq_restore(flags);
57925 +
57926 + return 0;
57927 +}
57928 +
57929 +static void lis302dl_input_close(struct input_dev *inp)
57930 +{
57931 + struct lis302dl_info *lis = input_get_drvdata(inp);
57932 + u_int8_t ctrl1 = LIS302DL_CTRL1_Xen | LIS302DL_CTRL1_Yen |
57933 + LIS302DL_CTRL1_Zen;
57934 + unsigned long flags;
57935 +
57936 + local_irq_save(flags);
57937 +
57938 + /* since the input core already serializes access and makes sure we
57939 + * only see close() for the close of the last user, we can safely
57940 + * disable the data ready events */
57941 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, 0x00);
57942 + lis->flags &= ~LIS302DL_F_INPUT_OPEN;
57943 +
57944 + /* however, don't power down the whole device if still needed */
57945 + if (!(lis->flags & LIS302DL_F_WUP_FF ||
57946 + lis->flags & LIS302DL_F_WUP_CLICK)) {
57947 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD,
57948 + 0x00);
57949 + }
57950 + local_irq_restore(flags);
57951 +}
57952 +
57953 +/* get the device to reload its coefficients from EEPROM and wait for it
57954 + * to complete
57955 + */
57956 +
57957 +static int __lis302dl_reset_device(struct lis302dl_info *lis)
57958 +{
57959 + int timeout = 10;
57960 +
57961 + __reg_write(lis, LIS302DL_REG_CTRL2,
57962 + LIS302DL_CTRL2_BOOT | LIS302DL_CTRL2_FDS);
57963 +
57964 + while ((__reg_read(lis, LIS302DL_REG_CTRL2)
57965 + & LIS302DL_CTRL2_BOOT) && (timeout--))
57966 + mdelay(1);
57967 +
57968 + return !!(timeout < 0);
57969 +}
57970 +
57971 +static int __devinit lis302dl_probe(struct spi_device *spi)
57972 +{
57973 + int rc;
57974 + struct lis302dl_info *lis;
57975 + u_int8_t wai;
57976 + unsigned long flags;
57977 + struct lis302dl_platform_data *pdata = spi->dev.platform_data;
57978 +
57979 + spi->mode = SPI_MODE_3;
57980 + rc = spi_setup(spi);
57981 + if (rc < 0) {
57982 + dev_err(&spi->dev, "spi_setup failed\n");
57983 + return rc;
57984 + }
57985 +
57986 + lis = kzalloc(sizeof(*lis), GFP_KERNEL);
57987 + if (!lis)
57988 + return -ENOMEM;
57989 +
57990 + lis->dev = &spi->dev;
57991 + lis->spi = spi;
57992 +
57993 + dev_set_drvdata(lis->dev, lis);
57994 +
57995 + lis->pdata = pdata;
57996 +
57997 + rc = sysfs_create_group(&lis->dev->kobj, &lis302dl_attr_group);
57998 + if (rc) {
57999 + dev_err(lis->dev, "error creating sysfs group\n");
58000 + goto bail_free_lis;
58001 + }
58002 +
58003 + /* initialize input layer details */
58004 + lis->input_dev = input_allocate_device();
58005 + if (!lis->input_dev) {
58006 + dev_err(lis->dev, "Unable to allocate input device\n");
58007 + goto bail_sysfs;
58008 + }
58009 +
58010 + input_set_drvdata(lis->input_dev, lis);
58011 + lis->input_dev->name = pdata->name;
58012 + /* SPI Bus not defined as a valid bus for input subsystem*/
58013 + lis->input_dev->id.bustype = BUS_I2C; /* lie about it */
58014 + lis->input_dev->open = lis302dl_input_open;
58015 + lis->input_dev->close = lis302dl_input_close;
58016 +
58017 + rc = input_register_device(lis->input_dev);
58018 + if (rc) {
58019 + dev_err(lis->dev, "error %d registering input device\n", rc);
58020 + goto bail_inp_dev;
58021 + }
58022 +
58023 + local_irq_save(flags);
58024 + /* Configure our IO */
58025 + (lis->pdata->lis302dl_suspend_io)(lis, 1);
58026 +
58027 + wai = __reg_read(lis, LIS302DL_REG_WHO_AM_I);
58028 + if (wai != LIS302DL_WHO_AM_I_MAGIC) {
58029 + dev_err(lis->dev, "unknown who_am_i signature 0x%02x\n", wai);
58030 + dev_set_drvdata(lis->dev, NULL);
58031 + rc = -ENODEV;
58032 + local_irq_restore(flags);
58033 + goto bail_inp_reg;
58034 + }
58035 +
58036 + set_bit(EV_ABS, lis->input_dev->evbit);
58037 + input_set_abs_params(lis->input_dev, ABS_X, 0, 0, 0, 0);
58038 + input_set_abs_params(lis->input_dev, ABS_Y, 0, 0, 0, 0);
58039 + input_set_abs_params(lis->input_dev, ABS_Z, 0, 0, 0, 0);
58040 +
58041 +
58042 + lis->threshold = 0;
58043 + lis->duration = 0;
58044 + memset(&lis->wakeup, 0, sizeof(lis->wakeup));
58045 +
58046 + if (__lis302dl_reset_device(lis))
58047 + dev_err(lis->dev, "device BOOT reload failed\n");
58048 +
58049 + /* force us powered */
58050 + __reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_PD |
58051 + LIS302DL_CTRL1_Xen |
58052 + LIS302DL_CTRL1_Yen |
58053 + LIS302DL_CTRL1_Zen);
58054 + mdelay(1);
58055 +
58056 + __reg_write(lis, LIS302DL_REG_CTRL2, 0);
58057 + __reg_write(lis, LIS302DL_REG_CTRL3,
58058 + LIS302DL_CTRL3_PP_OD | LIS302DL_CTRL3_IHL);
58059 + __reg_write(lis, LIS302DL_REG_FF_WU_THS_1, 0x0);
58060 + __reg_write(lis, LIS302DL_REG_FF_WU_DURATION_1, 0x00);
58061 + __reg_write(lis, LIS302DL_REG_FF_WU_CFG_1, 0x0);
58062 +
58063 + /* start off in powered down mode; we power up when someone opens us */
58064 + __reg_write(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_Xen |
58065 + LIS302DL_CTRL1_Yen | LIS302DL_CTRL1_Zen);
58066 +
58067 + if (pdata->open_drain)
58068 + /* switch interrupt to open collector, active-low */
58069 + __reg_write(lis, LIS302DL_REG_CTRL3,
58070 + LIS302DL_CTRL3_PP_OD | LIS302DL_CTRL3_IHL);
58071 + else
58072 + /* push-pull, active-low */
58073 + __reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_IHL);
58074 +
58075 + __lis302dl_int_mode(lis->dev, 1, LIS302DL_INTMODE_GND);
58076 + __lis302dl_int_mode(lis->dev, 2, LIS302DL_INTMODE_GND);
58077 +
58078 + __reg_read(lis, LIS302DL_REG_STATUS);
58079 + __reg_read(lis, LIS302DL_REG_FF_WU_SRC_1);
58080 + __reg_read(lis, LIS302DL_REG_FF_WU_SRC_2);
58081 + __reg_read(lis, LIS302DL_REG_CLICK_SRC);
58082 + local_irq_restore(flags);
58083 +
58084 + dev_info(lis->dev, "Found %s\n", pdata->name);
58085 +
58086 + lis->pdata = pdata;
58087 +
58088 + set_irq_handler(lis->pdata->interrupt, handle_level_irq);
58089 +
58090 + rc = request_irq(lis->pdata->interrupt, lis302dl_interrupt,
58091 + IRQF_TRIGGER_LOW, "lis302dl", lis);
58092 +
58093 + if (rc < 0) {
58094 + dev_err(lis->dev, "error requesting IRQ %d\n",
58095 + lis->pdata->interrupt);
58096 + goto bail_inp_reg;
58097 + }
58098 + return 0;
58099 +
58100 +bail_inp_reg:
58101 + input_unregister_device(lis->input_dev);
58102 +bail_inp_dev:
58103 + input_free_device(lis->input_dev);
58104 +bail_sysfs:
58105 + sysfs_remove_group(&lis->dev->kobj, &lis302dl_attr_group);
58106 +bail_free_lis:
58107 + kfree(lis);
58108 + return rc;
58109 +}
58110 +
58111 +static int __devexit lis302dl_remove(struct spi_device *spi)
58112 +{
58113 + struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
58114 + unsigned long flags;
58115 +
58116 + /* Disable interrupts */
58117 + if (lis->flags & LIS302DL_F_IRQ_WAKE)
58118 + disable_irq_wake(lis->pdata->interrupt);
58119 + free_irq(lis->pdata->interrupt, lis);
58120 +
58121 + /* Reset and power down the device */
58122 + local_irq_save(flags);
58123 + __reg_write(lis, LIS302DL_REG_CTRL3, 0x00);
58124 + __reg_write(lis, LIS302DL_REG_CTRL2, 0x00);
58125 + __reg_write(lis, LIS302DL_REG_CTRL1, 0x00);
58126 + local_irq_restore(flags);
58127 +
58128 + /* Cleanup resources */
58129 + sysfs_remove_group(&spi->dev.kobj, &lis302dl_attr_group);
58130 + input_unregister_device(lis->input_dev);
58131 + if (lis->input_dev)
58132 + input_free_device(lis->input_dev);
58133 + dev_set_drvdata(lis->dev, NULL);
58134 + kfree(lis);
58135 +
58136 + return 0;
58137 +}
58138 +
58139 +#ifdef CONFIG_PM
58140 +
58141 +static u8 regs_to_save[] = {
58142 + LIS302DL_REG_CTRL1,
58143 + LIS302DL_REG_CTRL2,
58144 + LIS302DL_REG_CTRL3,
58145 + LIS302DL_REG_FF_WU_CFG_1,
58146 + LIS302DL_REG_FF_WU_THS_1,
58147 + LIS302DL_REG_FF_WU_DURATION_1,
58148 + LIS302DL_REG_FF_WU_CFG_2,
58149 + LIS302DL_REG_FF_WU_THS_2,
58150 + LIS302DL_REG_FF_WU_DURATION_2,
58151 + LIS302DL_REG_CLICK_CFG,
58152 + LIS302DL_REG_CLICK_THSY_X,
58153 + LIS302DL_REG_CLICK_THSZ,
58154 + LIS302DL_REG_CLICK_TIME_LIMIT,
58155 + LIS302DL_REG_CLICK_LATENCY,
58156 + LIS302DL_REG_CLICK_WINDOW,
58157 +
58158 +};
58159 +
58160 +static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
58161 +{
58162 + struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
58163 + unsigned long flags;
58164 + u_int8_t tmp;
58165 + int n;
58166 +
58167 + /* determine if we want to wake up from the accel. */
58168 + if (lis->flags & LIS302DL_F_WUP_CLICK)
58169 + return 0;
58170 +
58171 + disable_irq(lis->pdata->interrupt);
58172 + local_irq_save(flags);
58173 +
58174 + /*
58175 + * When we share SPI over multiple sensors, there is a race here
58176 + * that one or more sensors will lose. In that case, the shared
58177 + * SPI bus GPIO will be in sleep mode and partially pulled down. So
58178 + * we explicitly put our IO into "wake" mode here before the final
58179 + * traffic to the sensor.
58180 + */
58181 + (lis->pdata->lis302dl_suspend_io)(lis, 1);
58182 +
58183 + /* save registers */
58184 + for (n = 0; n < ARRAY_SIZE(regs_to_save); n++)
58185 + lis->regs[regs_to_save[n]] =
58186 + __reg_read(lis, regs_to_save[n]);
58187 +
58188 + /* power down or enable wakeup */
58189 +
58190 + if (lis->wakeup.threshold == 0) {
58191 + tmp = __reg_read(lis, LIS302DL_REG_CTRL1);
58192 + tmp &= ~LIS302DL_CTRL1_PD;
58193 + __reg_write(lis, LIS302DL_REG_CTRL1, tmp);
58194 + } else
58195 + __enable_wakeup(lis);
58196 +
58197 + /* place our IO to the device in sleep-compatible states */
58198 + (lis->pdata->lis302dl_suspend_io)(lis, 0);
58199 +
58200 + local_irq_restore(flags);
58201 +
58202 + return 0;
58203 +}
58204 +
58205 +static int lis302dl_resume(struct spi_device *spi)
58206 +{
58207 + struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
58208 + unsigned long flags;
58209 + int n;
58210 +
58211 + if (lis->flags & LIS302DL_F_WUP_CLICK)
58212 + return 0;
58213 +
58214 + local_irq_save(flags);
58215 +
58216 + /* get our IO to the device back in operational states */
58217 + (lis->pdata->lis302dl_suspend_io)(lis, 1);
58218 +
58219 + /* resume from powerdown first! */
58220 + __reg_write(lis, LIS302DL_REG_CTRL1,
58221 + LIS302DL_CTRL1_PD |
58222 + LIS302DL_CTRL1_Xen |
58223 + LIS302DL_CTRL1_Yen |
58224 + LIS302DL_CTRL1_Zen);
58225 + mdelay(1);
58226 +
58227 + if (__lis302dl_reset_device(lis))
58228 + dev_err(&spi->dev, "device BOOT reload failed\n");
58229 +
58230 + lis->regs[LIS302DL_REG_CTRL1] |= LIS302DL_CTRL1_PD |
58231 + LIS302DL_CTRL1_Xen |
58232 + LIS302DL_CTRL1_Yen |
58233 + LIS302DL_CTRL1_Zen;
58234 +
58235 + /* restore registers after resume */
58236 + for (n = 0; n < ARRAY_SIZE(regs_to_save); n++)
58237 + __reg_write(lis, regs_to_save[n], lis->regs[regs_to_save[n]]);
58238 +
58239 + /* if someone had us open, reset the non-wake threshold stuff */
58240 + if (lis->flags & LIS302DL_F_INPUT_OPEN)
58241 + __enable_data_collection(lis);
58242 +
58243 + local_irq_restore(flags);
58244 + enable_irq(lis->pdata->interrupt);
58245 +
58246 + return 0;
58247 +}
58248 +#else
58249 +#define lis302dl_suspend NULL
58250 +#define lis302dl_resume NULL
58251 +#endif
58252 +
58253 +static struct spi_driver lis302dl_spi_driver = {
58254 + .driver = {
58255 + .name = "lis302dl",
58256 + .owner = THIS_MODULE,
58257 + },
58258 +
58259 + .probe = lis302dl_probe,
58260 + .remove = __devexit_p(lis302dl_remove),
58261 + .suspend = lis302dl_suspend,
58262 + .resume = lis302dl_resume,
58263 +};
58264 +
58265 +static int __devinit lis302dl_init(void)
58266 +{
58267 + return spi_register_driver(&lis302dl_spi_driver);
58268 +}
58269 +
58270 +static void __exit lis302dl_exit(void)
58271 +{
58272 + spi_unregister_driver(&lis302dl_spi_driver);
58273 +}
58274 +
58275 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
58276 +MODULE_LICENSE("GPL");
58277 +
58278 +module_init(lis302dl_init);
58279 +module_exit(lis302dl_exit);
58280 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/misc/Makefile linux-2.6.29-rc3.owrt.om/drivers/input/misc/Makefile
58281 --- linux-2.6.29-rc3.owrt/drivers/input/misc/Makefile 2009-05-10 22:04:49.000000000 +0200
58282 +++ linux-2.6.29-rc3.owrt.om/drivers/input/misc/Makefile 2009-05-10 22:29:16.000000000 +0200
58283 @@ -21,5 +21,7 @@
58284 obj-$(CONFIG_INPUT_UINPUT) += uinput.o
58285 obj-$(CONFIG_INPUT_APANEL) += apanel.o
58286 obj-$(CONFIG_INPUT_SGI_BTNS) += sgi_btns.o
58287 +obj-$(CONFIG_INPUT_LIS302DL) += lis302dl.o
58288 obj-$(CONFIG_INPUT_PCF50633_PMU) += pcf50633-input.o
58289 +obj-$(CONFIG_INPUT_PCF50606_PMU) += pcf50606-input.o
58290 obj-$(CONFIG_INPUT_GPIO_BUTTONS) += gpio_buttons.o
58291 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/misc/pcf50606-input.c linux-2.6.29-rc3.owrt.om/drivers/input/misc/pcf50606-input.c
58292 --- linux-2.6.29-rc3.owrt/drivers/input/misc/pcf50606-input.c 1970-01-01 01:00:00.000000000 +0100
58293 +++ linux-2.6.29-rc3.owrt.om/drivers/input/misc/pcf50606-input.c 2009-05-10 22:27:59.000000000 +0200
58294 @@ -0,0 +1,140 @@
58295 +/* Philips PCF50606 Input Driver
58296 + *
58297 + * (C) 2006-2008 by Openmoko, Inc.
58298 + * Author: Balaji Rao <balajirrao@openmoko.org>
58299 + * All rights reserved.
58300 + *
58301 + * Broken down from monstrous PCF50606 driver mainly by
58302 + * Harald Welte, Matt Hsu, Andy Green and Werner Almesberger
58303 + *
58304 + * This program is free software; you can redistribute it and/or
58305 + * modify it under the terms of the GNU General Public License as
58306 + * published by the Free Software Foundation; either version 2 of
58307 + * the License, or (at your option) any later version.
58308 + *
58309 + */
58310 +
58311 +#include <linux/kernel.h>
58312 +#include <linux/module.h>
58313 +#include <linux/init.h>
58314 +#include <linux/device.h>
58315 +#include <linux/platform_device.h>
58316 +#include <linux/input.h>
58317 +
58318 +#include <linux/mfd/pcf50606/core.h>
58319 +
58320 +#define PCF50606_OOCS_ONKEY 0x01
58321 +#define PCF50606_OOCS_EXTON 0x02
58322 +
58323 +#define PCF50606_OOCC2_ONKEYDB_NONE 0x00
58324 +#define PCF50606_OOCC2_ONKEYDB_14ms 0x01
58325 +#define PCF50606_OOCC2_ONKEYDB_62ms 0x02
58326 +#define PCF50606_OOCC2_ONKEYDB_500ms 0x03
58327 +#define PCF50606_OOCC2_EXTONDB_NONE 0x00
58328 +#define PCF50606_OOCC2_EXTONDB_14ms 0x04
58329 +#define PCF50606_OOCC2_EXTONDB_62ms 0x08
58330 +#define PCF50606_OOCC2_EXTONDB_500ms 0x0c
58331 +
58332 +#define PCF50606_REG_OOCS 0x01
58333 +
58334 +struct pcf50606_input {
58335 + struct pcf50606 *pcf;
58336 + struct input_dev *input_dev;
58337 +};
58338 +
58339 +static void
58340 +pcf50606_input_irq(int irq, void *data)
58341 +{
58342 + struct pcf50606_input *input;
58343 + int onkey_released;
58344 +
58345 + input = data;
58346 + onkey_released = pcf50606_reg_read(input->pcf, PCF50606_REG_OOCS) &
58347 + PCF50606_OOCS_ONKEY;
58348 +
58349 + if (irq == PCF50606_IRQ_ONKEYF && !onkey_released)
58350 + input_report_key(input->input_dev, KEY_POWER, 1);
58351 + else if (irq == PCF50606_IRQ_ONKEYR && onkey_released)
58352 + input_report_key(input->input_dev, KEY_POWER, 0);
58353 +
58354 + input_sync(input->input_dev);
58355 +}
58356 +
58357 +static int __devinit pcf50606_input_probe(struct platform_device *pdev)
58358 +{
58359 + struct pcf50606_input *input;
58360 + struct pcf50606_subdev_pdata *pdata = pdev->dev.platform_data;
58361 + struct input_dev *input_dev;
58362 + int ret;
58363 +
58364 +
58365 + input = kzalloc(sizeof(*input), GFP_KERNEL);
58366 + if (!input)
58367 + return -ENOMEM;
58368 +
58369 + input_dev = input_allocate_device();
58370 + if (!input_dev) {
58371 + kfree(input);
58372 + return -ENOMEM;
58373 + }
58374 +
58375 + platform_set_drvdata(pdev, input);
58376 + input->pcf = pdata->pcf;
58377 + input->input_dev = input_dev;
58378 +
58379 + input_dev->name = "PCF50606 PMU events";
58380 + input_dev->id.bustype = BUS_I2C;
58381 + input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_PWR);
58382 + set_bit(KEY_POWER, input_dev->keybit);
58383 +
58384 + ret = input_register_device(input_dev);
58385 + if (ret) {
58386 + input_free_device(input_dev);
58387 + kfree(input);
58388 + return ret;
58389 + }
58390 + pcf50606_register_irq(pdata->pcf, PCF50606_IRQ_ONKEYR,
58391 + pcf50606_input_irq, input);
58392 + pcf50606_register_irq(pdata->pcf, PCF50606_IRQ_ONKEYF,
58393 + pcf50606_input_irq, input);
58394 +
58395 + return 0;
58396 +}
58397 +
58398 +static int __devexit pcf50606_input_remove(struct platform_device *pdev)
58399 +{
58400 + struct pcf50606_input *input = platform_get_drvdata(pdev);
58401 +
58402 + input_unregister_device(input->input_dev);
58403 + pcf50606_free_irq(input->pcf, PCF50606_IRQ_ONKEYR);
58404 + pcf50606_free_irq(input->pcf, PCF50606_IRQ_ONKEYF);
58405 +
58406 + kfree(input);
58407 +
58408 + return 0;
58409 +}
58410 +
58411 +static struct platform_driver pcf50606_input_driver = {
58412 + .driver = {
58413 + .name = "pcf50606-input",
58414 + },
58415 + .probe = pcf50606_input_probe,
58416 + .remove = __devexit_p(pcf50606_input_remove),
58417 +};
58418 +
58419 +static int __init pcf50606_input_init(void)
58420 +{
58421 + return platform_driver_register(&pcf50606_input_driver);
58422 +}
58423 +module_init(pcf50606_input_init);
58424 +
58425 +static void __exit pcf50606_input_exit(void)
58426 +{
58427 + platform_driver_unregister(&pcf50606_input_driver);
58428 +}
58429 +module_exit(pcf50606_input_exit);
58430 +
58431 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
58432 +MODULE_DESCRIPTION("PCF50606 input driver");
58433 +MODULE_LICENSE("GPL");
58434 +MODULE_ALIAS("platform:pcf50606-input");
58435 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/mousedev.c linux-2.6.29-rc3.owrt.om/drivers/input/mousedev.c
58436 --- linux-2.6.29-rc3.owrt/drivers/input/mousedev.c 2009-05-10 22:04:49.000000000 +0200
58437 +++ linux-2.6.29-rc3.owrt.om/drivers/input/mousedev.c 2009-05-10 22:27:59.000000000 +0200
58438 @@ -1015,6 +1015,7 @@
58439 .evbit = { BIT_MASK(EV_KEY) | BIT_MASK(EV_REL) },
58440 .relbit = { BIT_MASK(REL_WHEEL) },
58441 }, /* A separate scrollwheel */
58442 +#if 0
58443 {
58444 .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
58445 INPUT_DEVICE_ID_MATCH_KEYBIT |
58446 @@ -1024,6 +1025,7 @@
58447 .absbit = { BIT_MASK(ABS_X) | BIT_MASK(ABS_Y) },
58448 }, /* A tablet like device, at least touch detection,
58449 two absolute axes */
58450 +#endif
58451 {
58452 .flags = INPUT_DEVICE_ID_MATCH_EVBIT |
58453 INPUT_DEVICE_ID_MATCH_KEYBIT |
58454 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/Kconfig linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/Kconfig
58455 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/Kconfig 2009-05-10 22:04:49.000000000 +0200
58456 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/Kconfig 2009-05-10 22:27:59.000000000 +0200
58457 @@ -11,6 +11,54 @@
58458
58459 if INPUT_TOUCHSCREEN
58460
58461 +menuconfig TOUCHSCREEN_FILTER
58462 + boolean "Touchscreen Filtering"
58463 + depends on INPUT_TOUCHSCREEN
58464 + select TOUCHSCREEN_FILTER_GROUP
58465 + select TOUCHSCREEN_FILTER_MEDIAN
58466 + select TOUCHSCREEN_FILTER_MEAN
58467 + select TOUCHSCREEN_FILTER_LINEAR
58468 + help
58469 + Select this to include kernel touchscreen filter support. The filters
58470 + can be combined in any order in your machine init and the parameters
58471 + for them can also be set there.
58472 +
58473 +if TOUCHSCREEN_FILTER
58474 +
58475 +config TOUCHSCREEN_FILTER_GROUP
58476 + bool "Group Touchscreen Filter"
58477 + depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
58478 + default Y
58479 + help
58480 + Say Y here if you want to use the Group touchscreen filter, it
58481 + avoids using atypical samples.
58482 +
58483 +config TOUCHSCREEN_FILTER_MEDIAN
58484 + bool "Median Average Touchscreen Filter"
58485 + depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
58486 + default Y
58487 + help
58488 + Say Y here if you want to use the Median touchscreen filter, it's
58489 + highly effective if you data is noisy with occasional excursions.
58490 +
58491 +config TOUCHSCREEN_FILTER_MEAN
58492 + bool "Mean Average Touchscreen Filter"
58493 + depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
58494 + default Y
58495 + help
58496 + Say Y here if you want to use the Mean touchscreen filter, it
58497 + can further improve decent quality data by removing jitter
58498 +
58499 +config TOUCHSCREEN_FILTER_LINEAR
58500 + bool "Linear Touchscreen Filter"
58501 + depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
58502 + default Y
58503 + help
58504 + Say Y here if you want to use the Linear touchscreen filter, it
58505 + enables the use of calibration data for the touchscreen.
58506 +
58507 +endif
58508 +
58509 config TOUCHSCREEN_ADS7846
58510 tristate "ADS7846/TSC2046 and ADS7843 based touchscreens"
58511 depends on SPI_MASTER
58512 @@ -79,6 +127,24 @@
58513 To compile this driver as a module, choose M here: the
58514 module will be called fujitsu-ts.
58515
58516 +config TOUCHSCREEN_S3C2410
58517 + tristate "Samsung S3C2410 touchscreen input driver"
58518 + depends on ARCH_S3C2410 && INPUT && INPUT_TOUCHSCREEN
58519 + select SERIO
58520 + help
58521 + Say Y here if you have the s3c2410 touchscreen.
58522 +
58523 + If unsure, say N.
58524 +
58525 + To compile this driver as a module, choose M here: the
58526 + module will be called s3c2410_ts.
58527 +
58528 +config TOUCHSCREEN_S3C2410_DEBUG
58529 + boolean "Samsung S3C2410 touchscreen debug messages"
58530 + depends on TOUCHSCREEN_S3C2410
58531 + help
58532 + Select this if you want debug messages
58533 +
58534 config TOUCHSCREEN_GUNZE
58535 tristate "Gunze AHL-51S touchscreen"
58536 select SERIO
58537 @@ -408,4 +474,15 @@
58538 To compile this driver as a module, choose M here: the
58539 module will be called tsc2007.
58540
58541 +config TOUCHSCREEN_PCAP7200
58542 + tristate "EETI Projected capacitive touchscreen controller"
58543 + help
58544 + Say Y here if you have the EETI PCAP7200 touchscreen
58545 + controller chip in your system.
58546 +
58547 + If unsure, say N.
58548 +
58549 + To compile this driver as a module, choose M here: the
58550 + module will be called pcap7200.
58551 endif
58552 +
58553 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/Makefile linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/Makefile
58554 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/Makefile 2009-05-10 22:04:49.000000000 +0200
58555 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/Makefile 2009-05-10 22:27:59.000000000 +0200
58556 @@ -34,3 +34,10 @@
58557 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712) += wm9712.o
58558 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9713) += wm9713.o
58559 obj-$(CONFIG_TOUCHSCREEN_WM97XX_MAINSTONE) += mainstone-wm97xx.o
58560 +obj-$(CONFIG_TOUCHSCREEN_S3C2410) += s3c2410_ts.o
58561 +obj-$(CONFIG_TOUCHSCREEN_FILTER) += ts_filter_chain.o
58562 +obj-$(CONFIG_TOUCHSCREEN_FILTER_GROUP) += ts_filter_group.o
58563 +obj-$(CONFIG_TOUCHSCREEN_FILTER_LINEAR) += ts_filter_linear.o
58564 +obj-$(CONFIG_TOUCHSCREEN_FILTER_MEDIAN) += ts_filter_median.o
58565 +obj-$(CONFIG_TOUCHSCREEN_FILTER_MEAN) += ts_filter_mean.o
58566 +obj-$(CONFIG_TOUCHSCREEN_PCAP7200) += pcap7200_ts.o
58567 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/pcap7200_ts.c linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/pcap7200_ts.c
58568 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/pcap7200_ts.c 1970-01-01 01:00:00.000000000 +0100
58569 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/pcap7200_ts.c 2009-05-10 22:27:59.000000000 +0200
58570 @@ -0,0 +1,309 @@
58571 + /* Projected capacitive touchscreen controller driver.
58572 + *
58573 + * Copyright(c) 2008 Openmoko Inc.
58574 + *
58575 + * Author: Matt Hsu <matt_hsu@openmoko.org>
58576 + *
58577 + * This program is free software; you can redistribute it and/or modify
58578 + * it under the terms of the GNU General Public License as published by
58579 + * the Free Software Foundation; either version 2 of the License, or
58580 + * (at your option) any later version.
58581 + *
58582 + * TODO
58583 + * - apply ts_filter
58584 + * - add support for gesture event
58585 + *
58586 + */
58587 +
58588 +#include <linux/kernel.h>
58589 +#include <linux/module.h>
58590 +#include <linux/init.h>
58591 +#include <linux/input.h>
58592 +#include <linux/i2c.h>
58593 +#include <linux/platform_device.h>
58594 +#include <linux/interrupt.h>
58595 +#include <linux/workqueue.h>
58596 +#include <linux/input.h>
58597 +#include <linux/device.h>
58598 +
58599 +#include <linux/pcap7200.h>
58600 +#include <../drivers/input/touchscreen/ts_filter.h>
58601 +
58602 +#include <mach/om-3d7k.h>
58603 +
58604 +#define PCAP7200_OP_MODE_REG 0x07
58605 +#define RPT_PKT_SIZE 5
58606 +#define EVENT_UP 0x80
58607 +#define EVENT_DOWN 0x81
58608 +
58609 +
58610 +#define coord_interpret(msb_byte, lsb_byte) \
58611 + (msb_byte << 7 | lsb_byte)
58612 +
58613 +struct pcap7200_data{
58614 + struct i2c_client *client;
58615 + struct input_dev *dev;
58616 + struct ts_filter **tsf;
58617 + struct mutex lock;
58618 + int irq;
58619 + struct work_struct work;
58620 +};
58621 +
58622 +static void pcap7200_work(struct work_struct *work)
58623 +{
58624 + struct pcap7200_data *pcap =
58625 + container_of(work, struct pcap7200_data, work);
58626 + uint8_t rpt_pkt[RPT_PKT_SIZE], event;
58627 + int coords[2];
58628 + int ret;
58629 +
58630 + mutex_lock(&pcap->lock);
58631 +
58632 + memset(rpt_pkt, 0, sizeof(rpt_pkt));
58633 +
58634 + BUG_ON(pcap == NULL);
58635 +
58636 + ret = i2c_master_recv(pcap->client, rpt_pkt, RPT_PKT_SIZE);
58637 +
58638 + event = rpt_pkt[0];
58639 +
58640 + /*
58641 + * this is annonying. system would receive two consecutive interrupts if we set INT
58642 + * type as LOW_LEVEL. the data we pull from pcap7200 are invalid which are all
58643 + * zero in the second interrupt.
58644 + */
58645 + if (event != 0) {
58646 + dev_dbg(&pcap->client->dev, "[%2x][%2x][%2x][%2x][%2x]: %d bytes return \n",
58647 + rpt_pkt[0], rpt_pkt[1], rpt_pkt[2],
58648 + rpt_pkt[3], rpt_pkt[4], ret);
58649 +
58650 + coords[0] = coord_interpret(rpt_pkt[1], rpt_pkt[2]);
58651 + coords[1] = coord_interpret(rpt_pkt[3], rpt_pkt[4]);
58652 +
58653 + if (event == EVENT_DOWN) {
58654 + input_report_abs(pcap->dev, ABS_X, coords[0]);
58655 + input_report_abs(pcap->dev, ABS_Y, coords[1]);
58656 + input_report_key(pcap->dev, BTN_TOUCH, 1);
58657 + input_report_abs(pcap->dev, ABS_PRESSURE, 1);
58658 + } else if (event == EVENT_UP) {
58659 + input_report_key(pcap->dev, BTN_TOUCH, 0);
58660 + input_report_abs(pcap->dev, ABS_PRESSURE, 0);
58661 + } else {
58662 + /* FIMXE: gesture events should be reported here. */
58663 + }
58664 +
58665 + input_sync(pcap->dev);
58666 + }
58667 +
58668 + mutex_unlock(&pcap->lock);
58669 + enable_irq(pcap->irq);
58670 +}
58671 +
58672 +static const char *op_mode_name[] = {
58673 + [SLEEP] = "sleep",
58674 + [WAKEUP] = "wakeup",
58675 + [SINGLE_TOUCH] = "single_touch",
58676 + [MULTI_TOUCH] = "multi_touch",
58677 +};
58678 +
58679 +static struct i2c_driver pcap7200_driver;
58680 +
58681 +static int __set_op_mode(struct pcap7200_data *pcap, u_int8_t val)
58682 +{
58683 + u8 buf[] = { PCAP7200_OP_MODE_REG, val};
58684 + int ret, i;
58685 +
58686 + mutex_lock(&pcap->lock);
58687 +
58688 + val = val & 0x03;
58689 +
58690 + /* this chip has an issue.
58691 + * you need to give wakeup call for 3 times if it's
58692 + * in sleep mode.
58693 + */
58694 + if (val == WAKEUP) {
58695 + for (i = 0; i < 3; i++)
58696 + ret = i2c_master_send(pcap->client, buf, sizeof(buf));
58697 + } else
58698 + ret = i2c_master_send(pcap->client, buf, sizeof(buf));
58699 +
58700 + mutex_unlock(&pcap->lock);
58701 + return ret;
58702 +}
58703 +
58704 +static ssize_t set_op_mode(struct device *dev, struct device_attribute *attr,
58705 + const char *buf, size_t count)
58706 +{
58707 + struct i2c_client *client = to_i2c_client(dev);
58708 + struct pcap7200_data *pcap = i2c_get_clientdata(client);
58709 + u_int8_t i;
58710 +
58711 + for (i = 0; i < ARRAY_SIZE(op_mode_name); i++) {
58712 + if (!strncmp(buf, op_mode_name[i], strlen(op_mode_name[i])))
58713 + __set_op_mode(pcap, i);
58714 + }
58715 +
58716 + return count;
58717 +}
58718 +
58719 +static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR, NULL, set_op_mode);
58720 +
58721 +static irqreturn_t pcap7200_irq(int irq, void *_pcap)
58722 +{
58723 + struct pcap7200_data *pcap = _pcap;
58724 +
58725 + disable_irq(pcap->irq);
58726 + schedule_work(&pcap->work);
58727 +
58728 + return IRQ_HANDLED;
58729 +}
58730 +
58731 +static int
58732 +pcap7200_probe(struct i2c_client *client, const struct i2c_device_id *ids)
58733 +{
58734 + struct pcap7200_data *pcap;
58735 + struct input_dev *input_dev;
58736 + int err;
58737 + struct pcap7200_platform_data *pdata = client->dev.platform_data;
58738 +
58739 + /* allocate pcap7200 data */
58740 + pcap = kzalloc(sizeof(struct pcap7200_data), GFP_KERNEL);
58741 + if (!pcap)
58742 + return -ENOMEM;
58743 +
58744 + i2c_set_clientdata(client, pcap);
58745 + pcap->client = client;
58746 +
58747 + mutex_init(&pcap->lock);
58748 +
58749 + /* reset */
58750 + if (pdata->reset) {
58751 + pdata->reset();
58752 + dev_dbg(&client->dev, "hard reset\n");
58753 + }
58754 +
58755 + /* operating mode */
58756 + __set_op_mode(pcap, pdata->mode);
58757 +
58758 + /* initialize input device */
58759 + input_dev = input_allocate_device();
58760 + if (!input_dev) {
58761 + dev_err(&client->dev, "Unable to allocate the input device\n");
58762 + err = -ENOMEM;
58763 + goto exit_kfree;
58764 + }
58765 +
58766 + pcap->dev = input_dev;
58767 + input_dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) |
58768 + BIT_MASK(EV_ABS);
58769 + input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
58770 +
58771 + /* configurable resolution 2048x2048 */
58772 + input_set_abs_params(pcap->dev, ABS_X, 0, 0x7FF, 0, 0);
58773 + input_set_abs_params(pcap->dev, ABS_Y, 0, 0x7FF, 0, 0);
58774 + input_set_abs_params(pcap->dev, ABS_PRESSURE, 0, 1, 0, 0);
58775 +
58776 + input_dev->name = client->name;
58777 + input_dev->id.bustype = BUS_I2C;
58778 + input_dev->dev.parent = &client->dev;
58779 +
58780 + err = input_register_device(input_dev);
58781 +
58782 + if (err)
58783 + goto exit_unreg;
58784 +
58785 + INIT_WORK(&pcap->work, pcap7200_work);
58786 +
58787 + err = sysfs_create_file(&client->dev.kobj, &dev_attr_op_mode.attr);
58788 +
58789 + if (err) {
58790 + dev_err(&client->dev, "Failed to create sysfs\n");
58791 + goto exit_unreg;
58792 + }
58793 +
58794 + /* setup IRQ */
58795 + if (client->irq < 0) {
58796 + dev_err(&client->dev,
58797 + "No irq allocated in client resources!\n");
58798 + goto exit_rmsysfs;
58799 + }
58800 +
58801 + pcap->irq = client->irq;
58802 + err = request_irq(pcap->irq, pcap7200_irq, IRQF_TRIGGER_LOW, "pcap7200", pcap);
58803 +
58804 + if (err < 0)
58805 + goto exit_rmsysfs;
58806 +
58807 + return 0;
58808 +
58809 +exit_rmsysfs:
58810 + sysfs_remove_file(&client->dev.kobj, &dev_attr_op_mode.attr);
58811 +exit_unreg:
58812 + input_unregister_device(input_dev);
58813 +exit_kfree:
58814 + kfree(pcap);
58815 + return err;
58816 +}
58817 +
58818 +static int pcap7200_remove(struct i2c_client *client)
58819 +{
58820 + struct pcap7200_data *pcap = i2c_get_clientdata(client);
58821 +
58822 + free_irq(pcap->irq, pcap);
58823 + input_unregister_device(pcap->dev);
58824 + kfree(pcap);
58825 + return 0;
58826 +}
58827 +
58828 +#ifdef CONFIG_PM
58829 +static int pcap7200_suspend(struct device *dev, pm_message_t state)
58830 +{
58831 + struct i2c_client *client = to_i2c_client(dev);
58832 + struct pcap7200_data *pcap = i2c_get_clientdata(client);
58833 +
58834 + __set_op_mode(pcap, SLEEP);
58835 + return 0;
58836 +}
58837 +
58838 +static int pcap7200_resume(struct device *dev)
58839 +{
58840 + struct i2c_client *client = to_i2c_client(dev);
58841 + struct pcap7200_data *pcap = i2c_get_clientdata(client);
58842 +
58843 + __set_op_mode(pcap, WAKEUP);
58844 + return 0;
58845 +}
58846 +#else
58847 +#define pcap7200_suspend NULL
58848 +#define pcap7200_resume NULL
58849 +#endif
58850 +
58851 +static struct i2c_device_id pcap7200_id_table[] = {
58852 + {"pcap7200", 0x0a},
58853 +};
58854 +
58855 +static struct i2c_driver pcap7200_driver = {
58856 + .driver = {
58857 + .name = "pcap7200",
58858 + .suspend = pcap7200_suspend,
58859 + .resume = pcap7200_resume,
58860 + },
58861 + .id_table = pcap7200_id_table,
58862 + .probe = pcap7200_probe,
58863 + .remove = pcap7200_remove,
58864 +};
58865 +
58866 +static int __init pcap7200_init(void)
58867 +{
58868 + return i2c_add_driver(&pcap7200_driver);
58869 +}
58870 +
58871 +static void pcap7200_exit(void)
58872 +{
58873 + i2c_del_driver(&pcap7200_driver);
58874 +}
58875 +module_init(pcap7200_init);
58876 +module_exit(pcap7200_exit);
58877 +
58878 +MODULE_AUTHOR("Matt Hsu <matt_hsu@openmoko.org>");
58879 +MODULE_LICENSE("GPLv2");
58880 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/s3c2410_ts.c linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/s3c2410_ts.c
58881 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/s3c2410_ts.c 1970-01-01 01:00:00.000000000 +0100
58882 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/s3c2410_ts.c 2009-05-10 22:27:59.000000000 +0200
58883 @@ -0,0 +1,593 @@
58884 +/*
58885 + * This program is free software; you can redistribute it and/or modify
58886 + * it under the terms of the GNU General Public License as published by
58887 + * the Free Software Foundation; either version 2 of the License, or
58888 + * (at your option) any later version.
58889 + *
58890 + * This program is distributed in the hope that it will be useful,
58891 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
58892 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
58893 + * GNU General Public License for more details.
58894 + *
58895 + * You should have received a copy of the GNU General Public License
58896 + * along with this program; if not, write to the Free Software
58897 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
58898 + *
58899 + * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
58900 + * iPAQ H1940 touchscreen support
58901 + *
58902 + * ChangeLog
58903 + *
58904 + * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
58905 + * - added clock (de-)allocation code
58906 + *
58907 + * 2005-03-06: Arnaud Patard <arnaud.patard@rtp-net.org>
58908 + * - h1940_ -> s3c2410 (this driver is now also used on the n30
58909 + * machines :P)
58910 + * - Debug messages are now enabled with the config option
58911 + * TOUCHSCREEN_S3C2410_DEBUG
58912 + * - Changed the way the value are read
58913 + * - Input subsystem should now work
58914 + * - Use ioremap and readl/writel
58915 + *
58916 + * 2005-03-23: Arnaud Patard <arnaud.patard@rtp-net.org>
58917 + * - Make use of some undocumented features of the touchscreen
58918 + * controller
58919 + *
58920 + * 2007-05-23: Harald Welte <laforge@openmoko.org>
58921 + * - Add proper support for S32440
58922 + *
58923 + * 2008-06-23: Andy Green <andy@openmoko.com>
58924 + * - removed averaging system
58925 + * - added generic Touchscreen filter stuff
58926 + *
58927 + * 2008-11-27: Nelson Castillo <arhuaco@freaks-unidos.net>
58928 + * - improve interrupt handling
58929 + */
58930 +
58931 +#include <linux/errno.h>
58932 +#include <linux/kernel.h>
58933 +#include <linux/module.h>
58934 +#include <linux/slab.h>
58935 +#include <linux/input.h>
58936 +#include <linux/init.h>
58937 +#include <linux/serio.h>
58938 +#include <linux/timer.h>
58939 +#include <linux/kfifo.h>
58940 +#include <linux/delay.h>
58941 +#include <linux/platform_device.h>
58942 +#include <linux/clk.h>
58943 +#include <asm/io.h>
58944 +#include <asm/irq.h>
58945 +
58946 +#include <mach/regs-gpio.h>
58947 +#include <mach/ts.h>
58948 +#include <mach/hardware.h>
58949 +#include <plat/regs-adc.h>
58950 +
58951 +#include "ts_filter_chain.h"
58952 +
58953 +/* For ts.dev.id.version */
58954 +#define S3C2410TSVERSION 0x0101
58955 +
58956 +#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
58957 +
58958 +#define WAIT4INT(x) (((x)<<8) | \
58959 + S3C2410_ADCTSC_YM_SEN | \
58960 + S3C2410_ADCTSC_YP_SEN | \
58961 + S3C2410_ADCTSC_XP_SEN | \
58962 + S3C2410_ADCTSC_XY_PST(3))
58963 +
58964 +#define AUTOPST (S3C2410_ADCTSC_YM_SEN | \
58965 + S3C2410_ADCTSC_YP_SEN | \
58966 + S3C2410_ADCTSC_XP_SEN | \
58967 + S3C2410_ADCTSC_AUTO_PST | \
58968 + S3C2410_ADCTSC_XY_PST(0))
58969 +
58970 +#define DEBUG_LVL KERN_DEBUG
58971 +
58972 +MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
58973 +MODULE_DESCRIPTION("s3c2410 touchscreen driver");
58974 +MODULE_LICENSE("GPL");
58975 +
58976 +/*
58977 + * Definitions & global arrays.
58978 + */
58979 +
58980 +static char *s3c2410ts_name = "s3c2410 TouchScreen";
58981 +
58982 +#define TS_RELEASE_TIMEOUT (HZ >> 7 ? HZ >> 7 : 1) /* 8ms (5ms if HZ is 200) */
58983 +#define TS_EVENT_FIFO_SIZE (2 << 6) /* must be a power of 2 */
58984 +
58985 +#define TS_STATE_STANDBY 0 /* initial state */
58986 +#define TS_STATE_PRESSED 1
58987 +#define TS_STATE_RELEASE_PENDING 2
58988 +#define TS_STATE_RELEASE 3
58989 +
58990 +/*
58991 + * Per-touchscreen data.
58992 + */
58993 +
58994 +struct s3c2410ts {
58995 + struct input_dev *dev;
58996 + struct ts_filter_chain *chain;
58997 + int is_down;
58998 + int state;
58999 + struct kfifo *event_fifo;
59000 +};
59001 +
59002 +static struct s3c2410ts ts;
59003 +
59004 +static void __iomem *base_addr;
59005 +
59006 +/*
59007 + * A few low level functions.
59008 + */
59009 +
59010 +static inline void s3c2410_ts_connect(void)
59011 +{
59012 + s3c2410_gpio_cfgpin(S3C2410_GPG12, S3C2410_GPG12_XMON);
59013 + s3c2410_gpio_cfgpin(S3C2410_GPG13, S3C2410_GPG13_nXPON);
59014 + s3c2410_gpio_cfgpin(S3C2410_GPG14, S3C2410_GPG14_YMON);
59015 + s3c2410_gpio_cfgpin(S3C2410_GPG15, S3C2410_GPG15_nYPON);
59016 +}
59017 +
59018 +static void s3c2410_ts_start_adc_conversion(void)
59019 +{
59020 + writel(S3C2410_ADCTSC_PULL_UP_DISABLE | AUTOPST,
59021 + base_addr + S3C2410_ADCTSC);
59022 + writel(readl(base_addr + S3C2410_ADCCON) | S3C2410_ADCCON_ENABLE_START,
59023 + base_addr + S3C2410_ADCCON);
59024 +}
59025 +
59026 +/*
59027 + * Just send the input events.
59028 + */
59029 +
59030 +enum ts_input_event {IE_DOWN = 0, IE_UP};
59031 +
59032 +static void ts_input_report(int event, int coords[])
59033 +{
59034 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
59035 + static char *s[] = {"down", "up"};
59036 + struct timeval tv;
59037 +
59038 + do_gettimeofday(&tv);
59039 +#endif
59040 +
59041 + if (event == IE_DOWN) {
59042 + input_report_abs(ts.dev, ABS_X, coords[0]);
59043 + input_report_abs(ts.dev, ABS_Y, coords[1]);
59044 + input_report_key(ts.dev, BTN_TOUCH, 1);
59045 + input_report_abs(ts.dev, ABS_PRESSURE, 1);
59046 +
59047 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
59048 + printk(DEBUG_LVL "T:%06d %6s (X:%03d, Y:%03d)\n",
59049 + (int)tv.tv_usec, s[event], coords[0], coords[1]);
59050 +#endif
59051 + } else {
59052 + input_report_key(ts.dev, BTN_TOUCH, 0);
59053 + input_report_abs(ts.dev, ABS_PRESSURE, 0);
59054 +
59055 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
59056 + printk(DEBUG_LVL "T:%06d %6s\n",
59057 + (int)tv.tv_usec, s[event]);
59058 +#endif
59059 + }
59060 +
59061 + input_sync(ts.dev);
59062 +}
59063 +
59064 +/*
59065 + * Manage the state of the touchscreen.
59066 + */
59067 +
59068 +static void event_send_timer_f(unsigned long data);
59069 +
59070 +static struct timer_list event_send_timer =
59071 + TIMER_INITIALIZER(event_send_timer_f, 0, 0);
59072 +
59073 +static void event_send_timer_f(unsigned long data)
59074 +{
59075 + static int noop_counter;
59076 + int event_type;
59077 +
59078 + while (__kfifo_get(ts.event_fifo, (unsigned char *)&event_type,
59079 + sizeof(int))) {
59080 + int buf[2];
59081 +
59082 + switch (event_type) {
59083 + case 'D':
59084 + if (ts.state == TS_STATE_RELEASE_PENDING)
59085 + /* Ignore short UP event */
59086 + ts.state = TS_STATE_PRESSED;
59087 + break;
59088 +
59089 + case 'U':
59090 + ts.state = TS_STATE_RELEASE_PENDING;
59091 + break;
59092 +
59093 + case 'P':
59094 + if (ts.is_down) /* stylus_action needs a conversion */
59095 + s3c2410_ts_start_adc_conversion();
59096 +
59097 + if (unlikely(__kfifo_get(ts.event_fifo,
59098 + (unsigned char *)buf,
59099 + sizeof(int) * 2)
59100 + != sizeof(int) * 2))
59101 + goto ts_exit_error;
59102 +
59103 + ts_input_report(IE_DOWN, buf);
59104 + ts.state = TS_STATE_PRESSED;
59105 + break;
59106 +
59107 + default:
59108 + goto ts_exit_error;
59109 + }
59110 +
59111 + noop_counter = 0;
59112 + }
59113 +
59114 + if (noop_counter++ >= 1) {
59115 + noop_counter = 0;
59116 + if (ts.state == TS_STATE_RELEASE_PENDING) {
59117 + /*
59118 + * We delay the UP event for a while to avoid jitter.
59119 + * If we get a DOWN event we do not send it.
59120 + */
59121 + ts_input_report(IE_UP, NULL);
59122 + ts.state = TS_STATE_STANDBY;
59123 +
59124 + ts_filter_chain_clear(ts.chain);
59125 + }
59126 + } else {
59127 + mod_timer(&event_send_timer, jiffies + TS_RELEASE_TIMEOUT);
59128 + }
59129 +
59130 + return;
59131 +
59132 +ts_exit_error: /* should not happen unless we have a bug */
59133 + printk(KERN_ERR __FILE__ ": event_send_timer_f failed\n");
59134 +}
59135 +
59136 +/*
59137 + * Manage interrupts.
59138 + */
59139 +
59140 +static irqreturn_t stylus_updown(int irq, void *dev_id)
59141 +{
59142 + unsigned long data0;
59143 + unsigned long data1;
59144 + int event_type;
59145 +
59146 + data0 = readl(base_addr+S3C2410_ADCDAT0);
59147 + data1 = readl(base_addr+S3C2410_ADCDAT1);
59148 +
59149 + ts.is_down = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
59150 + (!(data1 & S3C2410_ADCDAT0_UPDOWN));
59151 +
59152 + event_type = ts.is_down ? 'D' : 'U';
59153 +
59154 + if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)&event_type,
59155 + sizeof(int)) != sizeof(int))) /* should not happen */
59156 + printk(KERN_ERR __FILE__": stylus_updown lost event!\n");
59157 +
59158 + if (ts.is_down)
59159 + s3c2410_ts_start_adc_conversion();
59160 + else
59161 + writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
59162 +
59163 + mod_timer(&event_send_timer, jiffies + 1);
59164 +
59165 + return IRQ_HANDLED;
59166 +}
59167 +
59168 +static irqreturn_t stylus_action(int irq, void *dev_id)
59169 +{
59170 + int buf[3];
59171 +
59172 + /* Grab the ADC results. */
59173 + buf[1] = readl(base_addr + S3C2410_ADCDAT0) &
59174 + S3C2410_ADCDAT0_XPDATA_MASK;
59175 + buf[2] = readl(base_addr + S3C2410_ADCDAT1) &
59176 + S3C2410_ADCDAT1_YPDATA_MASK;
59177 +
59178 + switch (ts_filter_chain_feed(ts.chain, &buf[1])) {
59179 + case 0:
59180 + /* The filter wants more points. */
59181 + s3c2410_ts_start_adc_conversion();
59182 + return IRQ_HANDLED;
59183 + case 1:
59184 + /* We have a point from the filters or no filtering enabled. */
59185 + buf[0] = 'P';
59186 + break;
59187 + default:
59188 + printk(KERN_ERR __FILE__
59189 + ":%d Invalid ts_filter_chain_feed return value.\n",
59190 + __LINE__);
59191 + case -1:
59192 + /* Error. Ignore the event. */
59193 + ts_filter_chain_clear(ts.chain);
59194 + writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
59195 + return IRQ_HANDLED;
59196 + };
59197 +
59198 + if (unlikely(__kfifo_put(ts.event_fifo, (unsigned char *)buf,
59199 + sizeof(int) * 3) != sizeof(int) * 3))
59200 + printk(KERN_ERR __FILE__":stylus_action bug.\n");
59201 +
59202 + writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
59203 + mod_timer(&event_send_timer, jiffies + 1);
59204 +
59205 + return IRQ_HANDLED;
59206 +}
59207 +
59208 +static struct clk *adc_clock;
59209 +
59210 +/*
59211 + * The functions for inserting/removing us as a module.
59212 + */
59213 +
59214 +static int __init s3c2410ts_probe(struct platform_device *pdev)
59215 +{
59216 + int rc;
59217 + struct s3c2410_ts_mach_info *info;
59218 + struct input_dev *input_dev;
59219 + int ret = 0;
59220 +
59221 + dev_info(&pdev->dev, "Starting\n");
59222 +
59223 + info = (struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
59224 +
59225 + if (!info)
59226 + {
59227 + dev_err(&pdev->dev, "Hm... too bad: no platform data for ts\n");
59228 + return -EINVAL;
59229 + }
59230 +
59231 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
59232 + printk(DEBUG_LVL "Entering s3c2410ts_init\n");
59233 +#endif
59234 +
59235 + adc_clock = clk_get(NULL, "adc");
59236 + if (!adc_clock) {
59237 + dev_err(&pdev->dev, "failed to get adc clock source\n");
59238 + return -ENOENT;
59239 + }
59240 + clk_enable(adc_clock);
59241 +
59242 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
59243 + printk(DEBUG_LVL "got and enabled clock\n");
59244 +#endif
59245 +
59246 + base_addr = ioremap(S3C2410_PA_ADC,0x20);
59247 + if (base_addr == NULL) {
59248 + dev_err(&pdev->dev, "Failed to remap register block\n");
59249 + ret = -ENOMEM;
59250 + goto bail0;
59251 + }
59252 +
59253 +
59254 + /* If we acutally are a S3C2410: Configure GPIOs */
59255 + if (!strcmp(pdev->name, "s3c2410-ts"))
59256 + s3c2410_ts_connect();
59257 +
59258 + if ((info->presc & 0xff) > 0)
59259 + writel(S3C2410_ADCCON_PRSCEN |
59260 + S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
59261 + base_addr + S3C2410_ADCCON);
59262 + else
59263 + writel(0, base_addr+S3C2410_ADCCON);
59264 +
59265 + /* Initialise registers */
59266 + if ((info->delay & 0xffff) > 0)
59267 + writel(info->delay & 0xffff, base_addr + S3C2410_ADCDLY);
59268 +
59269 + writel(WAIT4INT(0), base_addr + S3C2410_ADCTSC);
59270 +
59271 + /* Initialise input stuff */
59272 + memset(&ts, 0, sizeof(struct s3c2410ts));
59273 + input_dev = input_allocate_device();
59274 +
59275 + if (!input_dev) {
59276 + dev_err(&pdev->dev, "Unable to allocate the input device\n");
59277 + ret = -ENOMEM;
59278 + goto bail1;
59279 + }
59280 +
59281 + ts.dev = input_dev;
59282 + ts.dev->evbit[0] = BIT_MASK(EV_SYN) | BIT_MASK(EV_KEY) |
59283 + BIT_MASK(EV_ABS);
59284 + ts.dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
59285 + input_set_abs_params(ts.dev, ABS_X, 0, 0x3FF, 0, 0);
59286 + input_set_abs_params(ts.dev, ABS_Y, 0, 0x3FF, 0, 0);
59287 + input_set_abs_params(ts.dev, ABS_PRESSURE, 0, 1, 0, 0);
59288 +
59289 + ts.dev->name = s3c2410ts_name;
59290 + ts.dev->id.bustype = BUS_RS232;
59291 + ts.dev->id.vendor = 0xDEAD;
59292 + ts.dev->id.product = 0xBEEF;
59293 + ts.dev->id.version = S3C2410TSVERSION;
59294 + ts.state = TS_STATE_STANDBY;
59295 + ts.event_fifo = kfifo_alloc(TS_EVENT_FIFO_SIZE, GFP_KERNEL, NULL);
59296 + if (IS_ERR(ts.event_fifo)) {
59297 + ret = -EIO;
59298 + goto bail2;
59299 + }
59300 +
59301 + /* create the filter chain set up for the 2 coordinates we produce */
59302 + ts.chain = ts_filter_chain_create(pdev, info->filter_config, 2);
59303 +
59304 + if (IS_ERR(ts.chain))
59305 + goto bail2;
59306 +
59307 + ts_filter_chain_clear(ts.chain);
59308 +
59309 + /* Get irqs */
59310 + if (request_irq(IRQ_ADC, stylus_action, IRQF_SAMPLE_RANDOM,
59311 + "s3c2410_action", ts.dev)) {
59312 + dev_err(&pdev->dev, "Could not allocate ts IRQ_ADC !\n");
59313 + iounmap(base_addr);
59314 + ret = -EIO;
59315 + goto bail3;
59316 + }
59317 + if (request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM,
59318 + "s3c2410_action", ts.dev)) {
59319 + dev_err(&pdev->dev, "Could not allocate ts IRQ_TC !\n");
59320 + free_irq(IRQ_ADC, ts.dev);
59321 + iounmap(base_addr);
59322 + ret = -EIO;
59323 + goto bail4;
59324 + }
59325 +
59326 + dev_info(&pdev->dev, "Successfully loaded\n");
59327 +
59328 + /* All went ok, so register to the input system */
59329 + rc = input_register_device(ts.dev);
59330 + if (rc) {
59331 + ret = -EIO;
59332 + goto bail5;
59333 + }
59334 +
59335 + return 0;
59336 +
59337 +bail5:
59338 + free_irq(IRQ_TC, ts.dev);
59339 + free_irq(IRQ_ADC, ts.dev);
59340 + clk_disable(adc_clock);
59341 + iounmap(base_addr);
59342 + disable_irq(IRQ_TC);
59343 +bail4:
59344 + disable_irq(IRQ_ADC);
59345 +bail3:
59346 + ts_filter_chain_destroy(ts.chain);
59347 + kfifo_free(ts.event_fifo);
59348 +bail2:
59349 + input_unregister_device(ts.dev);
59350 +bail1:
59351 + iounmap(base_addr);
59352 +bail0:
59353 +
59354 + return ret;
59355 +}
59356 +
59357 +static int s3c2410ts_remove(struct platform_device *pdev)
59358 +{
59359 + disable_irq(IRQ_ADC);
59360 + disable_irq(IRQ_TC);
59361 + free_irq(IRQ_TC,ts.dev);
59362 + free_irq(IRQ_ADC,ts.dev);
59363 +
59364 + if (adc_clock) {
59365 + clk_disable(adc_clock);
59366 + clk_put(adc_clock);
59367 + adc_clock = NULL;
59368 + }
59369 +
59370 + input_unregister_device(ts.dev);
59371 + iounmap(base_addr);
59372 +
59373 + ts_filter_chain_destroy(ts.chain);
59374 +
59375 + kfifo_free(ts.event_fifo);
59376 +
59377 + return 0;
59378 +}
59379 +
59380 +#ifdef CONFIG_PM
59381 +static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state)
59382 +{
59383 + writel(TSC_SLEEP, base_addr+S3C2410_ADCTSC);
59384 + writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_STDBM,
59385 + base_addr+S3C2410_ADCCON);
59386 +
59387 + disable_irq(IRQ_ADC);
59388 + disable_irq(IRQ_TC);
59389 +
59390 + clk_disable(adc_clock);
59391 +
59392 + return 0;
59393 +}
59394 +
59395 +static int s3c2410ts_resume(struct platform_device *pdev)
59396 +{
59397 + struct s3c2410_ts_mach_info *info =
59398 + ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
59399 +
59400 + clk_enable(adc_clock);
59401 + mdelay(1);
59402 +
59403 + ts_filter_chain_clear(ts.chain);
59404 +
59405 + enable_irq(IRQ_ADC);
59406 + enable_irq(IRQ_TC);
59407 +
59408 + if ((info->presc&0xff) > 0)
59409 + writel(S3C2410_ADCCON_PRSCEN |
59410 + S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
59411 + base_addr+S3C2410_ADCCON);
59412 + else
59413 + writel(0,base_addr+S3C2410_ADCCON);
59414 +
59415 + /* Initialise registers */
59416 + if ((info->delay & 0xffff) > 0)
59417 + writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);
59418 +
59419 + writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
59420 +
59421 + return 0;
59422 +}
59423 +
59424 +#else
59425 +#define s3c2410ts_suspend NULL
59426 +#define s3c2410ts_resume NULL
59427 +#endif
59428 +
59429 +static struct platform_driver s3c2410ts_driver = {
59430 + .driver = {
59431 + .name = "s3c2410-ts",
59432 + .owner = THIS_MODULE,
59433 + },
59434 + .probe = s3c2410ts_probe,
59435 + .remove = s3c2410ts_remove,
59436 + .suspend = s3c2410ts_suspend,
59437 + .resume = s3c2410ts_resume,
59438 +
59439 +};
59440 +
59441 +static struct platform_driver s3c2440ts_driver = {
59442 + .driver = {
59443 + .name = "s3c2440-ts",
59444 + .owner = THIS_MODULE,
59445 + },
59446 + .probe = s3c2410ts_probe,
59447 + .remove = s3c2410ts_remove,
59448 + .suspend = s3c2410ts_suspend,
59449 + .resume = s3c2410ts_resume,
59450 +
59451 +};
59452 +
59453 +static int __init s3c2410ts_init(void)
59454 +{
59455 + int rc;
59456 +
59457 + rc = platform_driver_register(&s3c2410ts_driver);
59458 + if (rc < 0)
59459 + return rc;
59460 +
59461 + rc = platform_driver_register(&s3c2440ts_driver);
59462 + if (rc < 0)
59463 + platform_driver_unregister(&s3c2410ts_driver);
59464 +
59465 + return rc;
59466 +}
59467 +
59468 +static void __exit s3c2410ts_exit(void)
59469 +{
59470 + platform_driver_unregister(&s3c2440ts_driver);
59471 + platform_driver_unregister(&s3c2410ts_driver);
59472 +}
59473 +
59474 +module_init(s3c2410ts_init);
59475 +module_exit(s3c2410ts_exit);
59476 +
59477 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_chain.c linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_chain.c
59478 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_chain.c 1970-01-01 01:00:00.000000000 +0100
59479 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_chain.c 2009-05-10 22:27:59.000000000 +0200
59480 @@ -0,0 +1,183 @@
59481 +/*
59482 + * This program is free software; you can redistribute it and/or modify
59483 + * it under the terms of the GNU General Public License as published by
59484 + * the Free Software Foundation; either version 2 of the License, or
59485 + * (at your option) any later version.
59486 + *
59487 + * This program is distributed in the hope that it will be useful,
59488 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
59489 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59490 + * GNU General Public License for more details.
59491 + *
59492 + * You should have received a copy of the GNU General Public License
59493 + * along with this program; if not, write to the Free Software
59494 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
59495 + *
59496 + * Copyright (c) 2008,2009 Andy Green <andy@openmoko.com>
59497 + */
59498 +
59499 +#include <linux/kernel.h>
59500 +#include <linux/device.h>
59501 +
59502 +#include "ts_filter_chain.h"
59503 +#include "ts_filter.h"
59504 +
59505 +/*
59506 + * Tux, would you like the following function in /lib?
59507 + * It helps us avoid silly code.
59508 + */
59509 +
59510 +/**
59511 + * sptrlen - Count how many non-null pointers are in a pointer array
59512 + * @arr: The array of pointers
59513 + */
59514 +static int sptrlen(const void *arr)
59515 +{
59516 + /* All pointers have the same size. */
59517 + const int **p = (const int **)arr;
59518 + int len = 0;
59519 +
59520 + while (*(p++))
59521 + len++;
59522 +
59523 + return len;
59524 +}
59525 +
59526 +
59527 +struct ts_filter_chain {
59528 + /* All of the filters. */
59529 + struct ts_filter **arr;
59530 + /* Filters that can propagate values in the chain. */
59531 + struct ts_filter **pchain;
59532 + /* Length of the pchain array. */
59533 + int pchain_len;
59534 + /* FIXME: Add a spinlock and use it. */
59535 +};
59536 +
59537 +struct ts_filter_chain *ts_filter_chain_create(
59538 + struct platform_device *pdev,
59539 + const struct ts_filter_chain_configuration conf[],
59540 + int count_coords)
59541 +{
59542 + struct ts_filter_chain *c;
59543 + int count = 0;
59544 + int len;
59545 +
59546 + BUG_ON((count_coords < 1));
59547 + BUG_ON(count_coords > MAX_TS_FILTER_COORDS);
59548 +
59549 + c = kzalloc(sizeof(struct ts_filter_chain), GFP_KERNEL);
59550 + if (!c)
59551 + goto create_err_1;
59552 +
59553 + len = (sptrlen(conf) + 1);
59554 + /* Memory for two null-terminated arrays of filters. */
59555 + c->arr = kzalloc(2 * sizeof(struct ts_filter *) * len, GFP_KERNEL);
59556 + if (!c->arr)
59557 + goto create_err_1;
59558 + c->pchain = c->arr + len;
59559 +
59560 + while (conf->api) {
59561 + /* TODO: Can we get away with only sending pdev->dev? */
59562 + struct ts_filter *f =
59563 + (conf->api->create)(pdev, conf->config, count_coords);
59564 + if (!f) {
59565 + dev_info(&pdev->dev, "Filter %d creation failed\n",
59566 + count);
59567 + goto create_err_2;
59568 + }
59569 +
59570 + f->api = conf->api;
59571 + c->arr[count++] = f;
59572 +
59573 + if (f->api->haspoint && f->api->getpoint && f->api->process)
59574 + c->pchain[c->pchain_len++] = f;
59575 +
59576 + conf++;
59577 + }
59578 +
59579 + dev_info(&pdev->dev, "%d filter(s) initialized\n", count);
59580 +
59581 + return c;
59582 +
59583 +create_err_2:
59584 + ts_filter_chain_destroy(c); /* Also frees c. */
59585 +create_err_1:
59586 + dev_info(&pdev->dev, "Error in filter chain initialization\n");
59587 + /*
59588 + * FIXME: Individual filters have to return errors this way.
59589 + * We only have to forward the errors we find.
59590 + */
59591 + return ERR_PTR(-ENOMEM);
59592 +}
59593 +EXPORT_SYMBOL_GPL(ts_filter_chain_create);
59594 +
59595 +void ts_filter_chain_destroy(struct ts_filter_chain *c)
59596 +{
59597 + if (c->arr) {
59598 + struct ts_filter **a = c->arr;
59599 + while (*a) {
59600 + ((*a)->api->destroy)(*a);
59601 + a++;
59602 + }
59603 + kfree(c->arr);
59604 + }
59605 + kfree(c);
59606 +}
59607 +EXPORT_SYMBOL_GPL(ts_filter_chain_destroy);
59608 +
59609 +void ts_filter_chain_clear(struct ts_filter_chain *c)
59610 +{
59611 + struct ts_filter **a = c->arr;
59612 +
59613 + while (*a) {
59614 + if ((*a)->api->clear)
59615 + ((*a)->api->clear)(*a);
59616 + a++;
59617 + }
59618 +}
59619 +EXPORT_SYMBOL_GPL(ts_filter_chain_clear);
59620 +
59621 +static void ts_filter_chain_scale(struct ts_filter_chain *c, int *coords)
59622 +{
59623 + struct ts_filter **a = c->arr;
59624 + while (*a) {
59625 + if ((*a)->api->scale)
59626 + ((*a)->api->scale)(*a, coords);
59627 + a++;
59628 + }
59629 +}
59630 +
59631 +int ts_filter_chain_feed(struct ts_filter_chain *c, int *coords)
59632 +{
59633 + int len = c->pchain_len;
59634 + int i = len - 1;
59635 +
59636 + if (!c->pchain[0])
59637 + return 1; /* Nothing to do. */
59638 +
59639 + BUG_ON(c->pchain[0]->api->haspoint(c->pchain[0]));
59640 +
59641 + if (c->pchain[0]->api->process(c->pchain[0], coords))
59642 + return -1;
59643 +
59644 + while (i >= 0 && i < len) {
59645 + if (c->pchain[i]->api->haspoint(c->pchain[i])) {
59646 + c->pchain[i]->api->getpoint(c->pchain[i], coords);
59647 + if (++i < len &&
59648 + c->pchain[i]->api->process(c->pchain[i], coords))
59649 + return -1; /* Error. */
59650 + } else {
59651 + i--;
59652 + }
59653 + }
59654 +
59655 + if (i >= 0) { /* Same as i == len. */
59656 + ts_filter_chain_scale(c, coords);
59657 + return 1;
59658 + }
59659 +
59660 + return 0;
59661 +}
59662 +EXPORT_SYMBOL_GPL(ts_filter_chain_feed);
59663 +
59664 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_chain.h linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_chain.h
59665 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_chain.h 1970-01-01 01:00:00.000000000 +0100
59666 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_chain.h 2009-05-10 22:27:59.000000000 +0200
59667 @@ -0,0 +1,58 @@
59668 +#ifndef __TS_FILTER_CHAIN_H__
59669 +#define __TS_FILTER_CHAIN_H__
59670 +
59671 +/*
59672 + * Touchscreen filter chains.
59673 + *
59674 + * (c) 2008,2009 Andy Green <andy@openmoko.com>
59675 + */
59676 +
59677 +#include "ts_filter.h"
59678 +
59679 +#include <linux/err.h>
59680 +
59681 +struct ts_filter_chain_configuration {
59682 + /* API to use. */
59683 + const struct ts_filter_api *api;
59684 + /* Generic filter configuration. Different for each filter. */
59685 + const struct ts_filter_configuration *config;
59686 +};
59687 +
59688 +struct ts_filter_chain;
59689 +
59690 +#ifdef CONFIG_TOUCHSCREEN_FILTER
59691 +
59692 +/*
59693 + * Create a filter chain. It will allocate an array of
59694 + * null-terminated pointers to filters. On error it will return
59695 + * an error you can check with IS_ERR.
59696 + */
59697 +extern struct ts_filter_chain *ts_filter_chain_create(
59698 + struct platform_device *pdev,
59699 + const struct ts_filter_chain_configuration conf[],
59700 + int count_coords);
59701 +
59702 +/* Destroy the chain. */
59703 +extern void ts_filter_chain_destroy(struct ts_filter_chain *c);
59704 +
59705 +/* Clear the filter chain. */
59706 +extern void ts_filter_chain_clear(struct ts_filter_chain *c);
59707 +
59708 +/*
59709 + * Try to get one point. Returns 0 if no points are available.
59710 + * coords will be used as temporal space, thus you supply a point
59711 + * using coords but you shouldn't rely on its value on return unless
59712 + * it returns a nonzero value that is not -1.
59713 + * If one of the filters find an error then this function will
59714 + * return -1.
59715 + */
59716 +int ts_filter_chain_feed(struct ts_filter_chain *c, int *coords);
59717 +
59718 +#else /* !CONFIG_TOUCHSCREEN_FILTER */
59719 +#define ts_filter_chain_create(pdev, config, count_coords) (NULL)
59720 +#define ts_filter_chain_destroy(c) do { } while (0)
59721 +#define ts_filter_chain_clear(c) do { } while (0)
59722 +#define ts_filter_chain_feed(c, coords) (1)
59723 +#endif
59724 +
59725 +#endif
59726 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_group.c linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_group.c
59727 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_group.c 1970-01-01 01:00:00.000000000 +0100
59728 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_group.c 2009-05-10 22:27:59.000000000 +0200
59729 @@ -0,0 +1,296 @@
59730 +/*
59731 + * This program is free software; you can redistribute it and/or modify
59732 + * it under the terms of the GNU General Public License as published by
59733 + * the Free Software Foundation; either version 2 of the License, or
59734 + * (at your option) any later version.
59735 + *
59736 + * This program is distributed in the hope that it will be useful,
59737 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
59738 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
59739 + * GNU General Public License for more details.
59740 + *
59741 + * You should have received a copy of the GNU General Public License
59742 + * along with this program; if not, write to the Free Software
59743 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
59744 + *
59745 + * Copyright (C) 2008,2009 by Openmoko, Inc.
59746 + * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
59747 + * All rights reserved.
59748 + *
59749 + *
59750 + * This filter is useful to reject samples that are not reliable. We consider
59751 + * that a sample is not reliable if it deviates form the Majority.
59752 + *
59753 + * 1) We collect S samples.
59754 + *
59755 + * 2) For each dimension:
59756 + *
59757 + * - We sort the points.
59758 + * - Points that are "close enough" are considered to be in the same set.
59759 + * - We choose the set with more elements. If more than "threshold"
59760 + * points are in this set we use the first and the last point of the set
59761 + * to define the valid range for this dimension [min, max], otherwise we
59762 + * discard all the points and go to step 1.
59763 + *
59764 + * 3) We consider the unsorted S samples and try to feed them to the next
59765 + * filter in the chain. If one of the points of each sample
59766 + * is not in the allowed range for its dimension, we discard the sample.
59767 + *
59768 + */
59769 +
59770 +#include <linux/kernel.h>
59771 +#include <linux/slab.h>
59772 +#include <linux/sort.h>
59773 +#include "ts_filter_group.h"
59774 +
59775 +struct ts_filter_group {
59776 + /* Private filter configuration. */
59777 + struct ts_filter_group_configuration *config;
59778 + /* Filter API. */
59779 + struct ts_filter tsf;
59780 +
59781 + int N; /* How many samples we have. */
59782 + int *samples[MAX_TS_FILTER_COORDS]; /* The samples: our input. */
59783 +
59784 + int *group_size; /* Used for temporal computations. */
59785 + int *sorted_samples; /* Used for temporal computations. */
59786 +
59787 + int range_max[MAX_TS_FILTER_COORDS]; /* Max. computed ranges. */
59788 + int range_min[MAX_TS_FILTER_COORDS]; /* Min. computed ranges. */
59789 +
59790 + int tries_left; /* We finish if we don't get enough samples. */
59791 + int ready; /* If we are ready to deliver samples. */
59792 + int result; /* Index of the point being returned. */
59793 +};
59794 +
59795 +#define ts_filter_to_filter_group(f) \
59796 + container_of(f, struct ts_filter_group, tsf)
59797 +
59798 +
59799 +static void ts_filter_group_clear_internal(struct ts_filter_group *tsfg,
59800 + int attempts)
59801 +{
59802 + tsfg->N = 0;
59803 + tsfg->tries_left = attempts;
59804 + tsfg->ready = 0;
59805 + tsfg->result = 0;
59806 +}
59807 +
59808 +static void ts_filter_group_clear(struct ts_filter *tsf)
59809 +{
59810 + struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf);
59811 +
59812 + ts_filter_group_clear_internal(tsfg, tsfg->config->attempts);
59813 +}
59814 +
59815 +static struct ts_filter *ts_filter_group_create(
59816 + struct platform_device *pdev,
59817 + const struct ts_filter_configuration *conf,
59818 + int count_coords)
59819 +{
59820 + struct ts_filter_group *tsfg;
59821 + int i;
59822 +
59823 + tsfg = kzalloc(sizeof(struct ts_filter_group), GFP_KERNEL);
59824 + if (!tsfg)
59825 + return NULL;
59826 +
59827 + tsfg->config = container_of(conf,
59828 + struct ts_filter_group_configuration,
59829 + config);
59830 + tsfg->tsf.count_coords = count_coords;
59831 +
59832 + BUG_ON(tsfg->config->attempts <= 0);
59833 +
59834 + tsfg->samples[0] = kmalloc((2 + count_coords) * sizeof(int) *
59835 + tsfg->config->length, GFP_KERNEL);
59836 + if (!tsfg->samples[0]) {
59837 + kfree(tsfg);
59838 + return NULL;
59839 + }
59840 + for (i = 1; i < count_coords; ++i)
59841 + tsfg->samples[i] = tsfg->samples[0] + i * tsfg->config->length;
59842 + tsfg->sorted_samples = tsfg->samples[0] + count_coords *
59843 + tsfg->config->length;
59844 + tsfg->group_size = tsfg->samples[0] + (1 + count_coords) *
59845 + tsfg->config->length;
59846 +
59847 + ts_filter_group_clear_internal(tsfg, tsfg->config->attempts);
59848 +
59849 + dev_info(&pdev->dev, "Created Group filter len:%d coords:%d close:%d "
59850 + "thresh:%d\n", tsfg->config->length, count_coords,
59851 + tsfg->config->close_enough, tsfg->config->threshold);
59852 +
59853 + return &tsfg->tsf;
59854 +}
59855 +
59856 +static void ts_filter_group_destroy(struct ts_filter *tsf)
59857 +{
59858 + struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf);
59859 +
59860 + kfree(tsfg->samples[0]); /* first guy has pointer from kmalloc */
59861 + kfree(tsf);
59862 +}
59863 +
59864 +static int int_cmp(const void *_a, const void *_b)
59865 +{
59866 + const int *a = _a;
59867 + const int *b = _b;
59868 +
59869 + if (*a > *b)
59870 + return 1;
59871 + if (*a < *b)
59872 + return -1;
59873 + return 0;
59874 +}
59875 +
59876 +static void ts_filter_group_prepare_next(struct ts_filter *tsf);
59877 +
59878 +static int ts_filter_group_process(struct ts_filter *tsf, int *coords)
59879 +{
59880 + struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf);
59881 + int n;
59882 + int i;
59883 +
59884 + BUG_ON(tsfg->N >= tsfg->config->length);
59885 + BUG_ON(tsfg->ready);
59886 +
59887 + for (n = 0; n < tsf->count_coords; n++)
59888 + tsfg->samples[n][tsfg->N] = coords[n];
59889 +
59890 + if (++tsfg->N < tsfg->config->length)
59891 + return 0; /* We need more samples. */
59892 +
59893 + for (n = 0; n < tsfg->tsf.count_coords; n++) {
59894 + int *v = tsfg->sorted_samples;
59895 + int ngroups = 0;
59896 + int best_size;
59897 + int best_idx = 0;
59898 + int idx = 0;
59899 +
59900 + memcpy(v, tsfg->samples[n], tsfg->N * sizeof(int));
59901 + /*
59902 + * FIXME: Remove this sort call. We already have the
59903 + * algorithm for this modification. The filter will
59904 + * need less points (about half) if there is not a
59905 + * lot of noise. Right now we are doing a constant
59906 + * amount of work no matter how much noise we are
59907 + * dealing with.
59908 + */
59909 + sort(v, tsfg->N, sizeof(int), int_cmp, NULL);
59910 +
59911 + tsfg->group_size[0] = 1;
59912 + for (i = 1; i < tsfg->N; ++i) {
59913 + if (v[i] - v[i - 1] <= tsfg->config->close_enough)
59914 + tsfg->group_size[ngroups]++;
59915 + else
59916 + tsfg->group_size[++ngroups] = 1;
59917 + }
59918 + ngroups++;
59919 +
59920 + best_size = tsfg->group_size[0];
59921 + for (i = 1; i < ngroups; i++) {
59922 + idx += tsfg->group_size[i - 1];
59923 + if (best_size < tsfg->group_size[i]) {
59924 + best_size = tsfg->group_size[i];
59925 + best_idx = idx;
59926 + }
59927 + }
59928 +
59929 + if (best_size < tsfg->config->threshold) {
59930 + /* This set is not good enough for us. */
59931 + if (--tsfg->tries_left) {
59932 + ts_filter_group_clear_internal
59933 + (tsfg, tsfg->tries_left);
59934 + /* No errors but we need more samples. */
59935 + return 0;
59936 + }
59937 + return 1; /* We give up: error. */
59938 + }
59939 +
59940 + tsfg->range_min[n] = v[best_idx];
59941 + tsfg->range_max[n] = v[best_idx + best_size - 1];
59942 + }
59943 +
59944 + ts_filter_group_prepare_next(tsf);
59945 +
59946 + return 0;
59947 +}
59948 +
59949 +/*
59950 + * This private function prepares a point that will be returned
59951 + * in ts_filter_group_getpoint if it is available. It updates
59952 + * the priv->ready state also.
59953 + */
59954 +static void ts_filter_group_prepare_next(struct ts_filter *tsf)
59955 +{
59956 + struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
59957 + int n;
59958 +
59959 + while (priv->result < priv->N) {
59960 + for (n = 0; n < priv->tsf.count_coords; ++n) {
59961 + if (priv->samples[n][priv->result] <
59962 + priv->range_min[n] ||
59963 + priv->samples[n][priv->result] > priv->range_max[n])
59964 + break;
59965 + }
59966 +
59967 + if (n == priv->tsf.count_coords) /* Sample is OK. */
59968 + break;
59969 +
59970 + priv->result++;
59971 + }
59972 +
59973 + if (unlikely(priv->result >= priv->N)) { /* No sample to deliver. */
59974 + ts_filter_group_clear_internal(priv, priv->config->attempts);
59975 + priv->ready = 0;
59976 + } else {
59977 + priv->ready = 1;
59978 + }
59979 +}
59980 +
59981 +static int ts_filter_group_haspoint(struct ts_filter *tsf)
59982 +{
59983 + struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
59984 +
59985 + return priv->ready;
59986 +}
59987 +
59988 +static void ts_filter_group_getpoint(struct ts_filter *tsf, int *point)
59989 +{
59990 + struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
59991 + int n;
59992 +
59993 + BUG_ON(!priv->ready);
59994 +
59995 + for (n = 0; n < priv->tsf.count_coords; n++)
59996 + point[n] = priv->samples[n][priv->result];
59997 +
59998 + priv->result++;
59999 +
60000 + /* This call will update priv->ready. */
60001 + ts_filter_group_prepare_next(tsf);
60002 +}
60003 +
60004 +/*
60005 + * Get ready to process the next batch of points, forget
60006 + * points we could have delivered.
60007 + */
60008 +static void ts_filter_group_scale(struct ts_filter *tsf, int *coords)
60009 +{
60010 + struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
60011 +
60012 + ts_filter_group_clear_internal(priv, priv->config->attempts);
60013 +}
60014 +
60015 +const struct ts_filter_api ts_filter_group_api = {
60016 + .create = ts_filter_group_create,
60017 + .destroy = ts_filter_group_destroy,
60018 + .clear = ts_filter_group_clear,
60019 + .process = ts_filter_group_process,
60020 + .haspoint = ts_filter_group_haspoint,
60021 + .getpoint = ts_filter_group_getpoint,
60022 + .scale = ts_filter_group_scale,
60023 +};
60024 +EXPORT_SYMBOL_GPL(ts_filter_group_api);
60025 +
60026 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_group.h linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_group.h
60027 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_group.h 1970-01-01 01:00:00.000000000 +0100
60028 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_group.h 2009-05-10 22:27:59.000000000 +0200
60029 @@ -0,0 +1,36 @@
60030 +#ifndef __TS_FILTER_GROUP_H__
60031 +#define __TS_FILTER_GROUP_H__
60032 +
60033 +#include "ts_filter.h"
60034 +
60035 +/*
60036 + * Touchscreen group filter.
60037 + *
60038 + * Copyright (C) 2008,2009 by Openmoko, Inc.
60039 + * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
60040 + *
60041 + */
60042 +
60043 +struct ts_filter_group_configuration {
60044 + /* Size of the filter. */
60045 + int length;
60046 + /*
60047 + * If two points are separated by this distance or less they
60048 + * are considered to be members of the same group.
60049 + */
60050 + int close_enough;
60051 + /* Minimum allowed size for the biggest group in the sample set. */
60052 + int threshold;
60053 + /*
60054 + * Number of times we try to get a group of points with at least
60055 + * threshold points.
60056 + */
60057 + int attempts;
60058 +
60059 + /* Generic filter configuration. */
60060 + struct ts_filter_configuration config;
60061 +};
60062 +
60063 +extern const struct ts_filter_api ts_filter_group_api;
60064 +
60065 +#endif
60066 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter.h linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter.h
60067 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter.h 1970-01-01 01:00:00.000000000 +0100
60068 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter.h 2009-05-10 22:27:59.000000000 +0200
60069 @@ -0,0 +1,74 @@
60070 +#ifndef __TS_FILTER_H__
60071 +#define __TS_FILTER_H__
60072 +
60073 +/*
60074 + * Touchscreen filter.
60075 + *
60076 + * (c) 2008,2009 Andy Green <andy@openmoko.com>
60077 + */
60078 +
60079 +#include <linux/platform_device.h>
60080 +
60081 +#define MAX_TS_FILTER_COORDS 3 /* X, Y and Z (pressure). */
60082 +
60083 +struct ts_filter;
60084 +struct ts_filter_configuration;
60085 +
60086 +/* Operations that a filter can perform. */
60087 +
60088 +struct ts_filter_api {
60089 + /* Create the filter - mandatory. */
60090 + struct ts_filter * (*create)(
60091 + struct platform_device *pdev,
60092 + const struct ts_filter_configuration *config,
60093 + int count_coords);
60094 + /* Destroy the filter - mandatory. */
60095 + void (*destroy)(struct ts_filter *filter);
60096 + /* Clear the filter - optional. */
60097 + void (*clear)(struct ts_filter *filter);
60098 +
60099 +
60100 + /*
60101 + * The next three API functions only make sense if all of them are
60102 + * set for a filter. If a filter has the next three methods then
60103 + * it can propagate coordinates in the chain.
60104 + */
60105 +
60106 + /*
60107 + * Process the filter.
60108 + * It returns non-zero if the filter reaches an error.
60109 + */
60110 + int (*process)(struct ts_filter *filter, int *coords);
60111 + /*
60112 + * Is the filter ready to return a point?
60113 + * Please do not code side effects in this function.
60114 + */
60115 + int (*haspoint)(struct ts_filter *filter);
60116 + /*
60117 + * Get a point.
60118 + * Do not call unless the filter actually has a point to deliver.
60119 + */
60120 + void (*getpoint)(struct ts_filter *filter, int *coords);
60121 +
60122 + /*
60123 + * Scale the points - optional.
60124 + * A filter could only scale coordinates.
60125 + */
60126 + void (*scale)(struct ts_filter *filter, int *coords);
60127 +};
60128 +
60129 +/*
60130 + * Generic filter configuration. Actual configurations have this structure
60131 + * as a member.
60132 + */
60133 +struct ts_filter_configuration {
60134 +};
60135 +
60136 +struct ts_filter {
60137 + /* Operations for this filter. */
60138 + const struct ts_filter_api *api;
60139 + /* Number of coordinates to process. */
60140 + int count_coords;
60141 +};
60142 +
60143 +#endif
60144 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_linear.c linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_linear.c
60145 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_linear.c 1970-01-01 01:00:00.000000000 +0100
60146 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_linear.c 2009-05-10 22:27:59.000000000 +0200
60147 @@ -0,0 +1,212 @@
60148 +/*
60149 + * This program is free software; you can redistribute it and/or modify
60150 + * it under the terms of the GNU General Public License as published by
60151 + * the Free Software Foundation; version 2 of the License, or
60152 + * (at your option) any later version.
60153 + *
60154 + * This program is distributed in the hope that it will be useful,
60155 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
60156 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60157 + * GNU General Public License for more details.
60158 + *
60159 + * You should have received a copy of the GNU General Public License
60160 + * along with this program; if not, write to the Free Software
60161 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
60162 + *
60163 + * Copyright (C) 2008,2009 by Openmoko, Inc.
60164 + * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
60165 + * All rights reserved.
60166 + *
60167 + * Linearly scale touchscreen values.
60168 + *
60169 + * Expose the TS_FILTER_LINEAR_NCONSTANTS for the linear transformation
60170 + * using sysfs.
60171 + *
60172 + */
60173 +
60174 +#include <linux/kernel.h>
60175 +#include <linux/slab.h>
60176 +#include <linux/string.h>
60177 +
60178 +#include "ts_filter_linear.h"
60179 +
60180 +struct ts_filter_linear;
60181 +
60182 +/* Sysfs code. */
60183 +
60184 +struct const_obj {
60185 + /* The actual private object. */
60186 + struct ts_filter_linear *tsfl;
60187 + /* Our kobject. */
60188 + struct kobject kobj;
60189 +};
60190 +
60191 +#define to_const_obj(x) container_of(x, struct const_obj, kobj)
60192 +
60193 +struct const_attribute {
60194 + struct attribute attr;
60195 + ssize_t (*show)(struct const_obj *const, struct const_attribute *attr,
60196 + char *buf);
60197 + ssize_t (*store)(struct const_obj *const, struct const_attribute *attr,
60198 + const char *buf, size_t count);
60199 +};
60200 +
60201 +#define to_const_attr(x) container_of(x, struct const_attribute, attr)
60202 +
60203 +
60204 +/* Private linear filter structure. */
60205 +
60206 +struct ts_filter_linear {
60207 + /* Private configuration for this filter. */
60208 + struct ts_filter_linear_configuration *config;
60209 +
60210 + /* Generic filter API. */
60211 + struct ts_filter tsf;
60212 +
60213 + /* Linear constants for the transformation. */
60214 + int constants[TS_FILTER_LINEAR_NCONSTANTS];
60215 +
60216 + /* Sysfs. */
60217 +
60218 + /* Our const_object. */
60219 + struct const_obj c_obj;
60220 + /* Our type. We will stick operations to it. */
60221 + struct kobj_type const_ktype;
60222 + /* Attrs. of the virtual files. */
60223 + struct const_attribute kattrs[TS_FILTER_LINEAR_NCONSTANTS];
60224 + /* Default Attrs. Always NULL for us. */
60225 + struct attribute *attrs[TS_FILTER_LINEAR_NCONSTANTS + 1];
60226 + /* Storage for the name of the virtual files. */
60227 + char attr_names[TS_FILTER_LINEAR_NCONSTANTS][2];
60228 +};
60229 +
60230 +#define ts_filter_to_filter_linear(f) \
60231 + container_of(f, struct ts_filter_linear, tsf)
60232 +
60233 +/* Sysfs functions. */
60234 +
60235 +static ssize_t const_attr_show(struct kobject *kobj,
60236 + struct attribute *attr,
60237 + char *buf)
60238 +{
60239 + struct const_attribute *a = to_const_attr(attr);
60240 +
60241 + return a->show(to_const_obj(kobj), a, buf);
60242 +}
60243 +
60244 +static ssize_t const_attr_store(struct kobject *kobj,
60245 + struct attribute *attr,
60246 + const char *buf, size_t len)
60247 +{
60248 + struct const_attribute *a = to_const_attr(attr);
60249 +
60250 + return a->store(to_const_obj(kobj), a, buf, len);
60251 +}
60252 +
60253 +static struct sysfs_ops const_sysfs_ops = {
60254 + .show = const_attr_show,
60255 + .store = const_attr_store,
60256 +};
60257 +
60258 +static void const_release(struct kobject *kobj)
60259 +{
60260 + kfree(to_const_obj(kobj)->tsfl);
60261 +}
60262 +
60263 +static ssize_t const_show(struct const_obj *obj, struct const_attribute *attr,
60264 + char *buf)
60265 +{
60266 + int who;
60267 +
60268 + sscanf(attr->attr.name, "%d", &who);
60269 + return sprintf(buf, "%d\n", obj->tsfl->constants[who]);
60270 +}
60271 +
60272 +static ssize_t const_store(struct const_obj *obj, struct const_attribute *attr,
60273 + const char *buf, size_t count)
60274 +{
60275 + int who;
60276 +
60277 + sscanf(attr->attr.name, "%d", &who);
60278 + sscanf(buf, "%d", &obj->tsfl->constants[who]);
60279 + return count;
60280 +}
60281 +
60282 +/* Filter functions. */
60283 +
60284 +static struct ts_filter *ts_filter_linear_create(
60285 + struct platform_device *pdev,
60286 + const struct ts_filter_configuration *conf,
60287 + int count_coords)
60288 +{
60289 + struct ts_filter_linear *tsfl;
60290 + int i;
60291 + int ret;
60292 +
60293 + tsfl = kzalloc(sizeof(struct ts_filter_linear), GFP_KERNEL);
60294 + if (!tsfl)
60295 + return NULL;
60296 +
60297 + tsfl->config = container_of(conf,
60298 + struct ts_filter_linear_configuration,
60299 + config);
60300 +
60301 + tsfl->tsf.count_coords = count_coords;
60302 +
60303 + for (i = 0; i < TS_FILTER_LINEAR_NCONSTANTS; ++i) {
60304 + tsfl->constants[i] = tsfl->config->constants[i];
60305 +
60306 + /* sysfs */
60307 + sprintf(tsfl->attr_names[i], "%d", i);
60308 + tsfl->kattrs[i].attr.name = tsfl->attr_names[i];
60309 + tsfl->kattrs[i].attr.mode = 0666;
60310 + tsfl->kattrs[i].show = const_show;
60311 + tsfl->kattrs[i].store = const_store;
60312 + tsfl->attrs[i] = &tsfl->kattrs[i].attr;
60313 + }
60314 + tsfl->attrs[i] = NULL;
60315 +
60316 + tsfl->const_ktype.sysfs_ops = &const_sysfs_ops;
60317 + tsfl->const_ktype.release = const_release;
60318 + tsfl->const_ktype.default_attrs = tsfl->attrs;
60319 + tsfl->c_obj.tsfl = tsfl; /* kernel frees tsfl in const_release */
60320 +
60321 + ret = kobject_init_and_add(&tsfl->c_obj.kobj, &tsfl->const_ktype,
60322 + &pdev->dev.kobj, "calibration");
60323 + if (ret) {
60324 + kobject_put(&tsfl->c_obj.kobj);
60325 + return NULL;
60326 + }
60327 +
60328 + dev_info(&pdev->dev, "Created Linear filter coords:%d\n", count_coords);
60329 +
60330 + return &tsfl->tsf;
60331 +}
60332 +
60333 +static void ts_filter_linear_destroy(struct ts_filter *tsf)
60334 +{
60335 + struct ts_filter_linear *tsfl = ts_filter_to_filter_linear(tsf);
60336 +
60337 + /* Kernel frees tsfl in const_release. */
60338 + kobject_put(&tsfl->c_obj.kobj);
60339 +}
60340 +
60341 +static void ts_filter_linear_scale(struct ts_filter *tsf, int *coords)
60342 +{
60343 + struct ts_filter_linear *tsfl = ts_filter_to_filter_linear(tsf);
60344 +
60345 + int *k = tsfl->constants;
60346 + int c0 = coords[tsfl->config->coord0];
60347 + int c1 = coords[tsfl->config->coord1];
60348 +
60349 + coords[tsfl->config->coord0] = (k[2] + k[0] * c0 + k[1] * c1) / k[6];
60350 + coords[tsfl->config->coord1] = (k[5] + k[3] * c0 + k[4] * c1) / k[6];
60351 +}
60352 +
60353 +const struct ts_filter_api ts_filter_linear_api = {
60354 + .create = ts_filter_linear_create,
60355 + .destroy = ts_filter_linear_destroy,
60356 + .scale = ts_filter_linear_scale,
60357 +};
60358 +EXPORT_SYMBOL_GPL(ts_filter_linear_api);
60359 +
60360 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_linear.h linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_linear.h
60361 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_linear.h 1970-01-01 01:00:00.000000000 +0100
60362 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_linear.h 2009-05-10 22:27:59.000000000 +0200
60363 @@ -0,0 +1,31 @@
60364 +#ifndef __TS_FILTER_LINEAR_H__
60365 +#define __TS_FILTER_LINEAR_H__
60366 +
60367 +#include "ts_filter.h"
60368 +#include <linux/kobject.h>
60369 +
60370 +/*
60371 + * Touchscreen linear filter.
60372 + *
60373 + * Copyright (C) 2008,2009 by Openmoko, Inc.
60374 + * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
60375 + *
60376 + */
60377 +
60378 +#define TS_FILTER_LINEAR_NCONSTANTS 7
60379 +
60380 +struct ts_filter_linear_configuration {
60381 + /* Calibration constants. */
60382 + int constants[TS_FILTER_LINEAR_NCONSTANTS];
60383 + /* First coordinate. */
60384 + int coord0;
60385 + /* Second coordinate. */
60386 + int coord1;
60387 +
60388 + /* Generic filter configuration. */
60389 + struct ts_filter_configuration config;
60390 +};
60391 +
60392 +extern const struct ts_filter_api ts_filter_linear_api;
60393 +
60394 +#endif
60395 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_mean.c linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_mean.c
60396 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_mean.c 1970-01-01 01:00:00.000000000 +0100
60397 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_mean.c 2009-05-10 22:27:59.000000000 +0200
60398 @@ -0,0 +1,174 @@
60399 +/*
60400 + * This program is free software; you can redistribute it and/or modify
60401 + * it under the terms of the GNU General Public License as published by
60402 + * the Free Software Foundation; either version 2 of the License, or
60403 + * (at your option) any later version.
60404 + *
60405 + * This program is distributed in the hope that it will be useful,
60406 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
60407 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60408 + * GNU General Public License for more details.
60409 + *
60410 + * You should have received a copy of the GNU General Public License
60411 + * along with this program; if not, write to the Free Software
60412 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
60413 + *
60414 + * Copyright (c) 2008,2009
60415 + * Andy Green <andy@openmoko.com>
60416 + * Nelson Castillo <arhuaco@freaks-unidos.net>
60417 + *
60418 + * Simple mean filter.
60419 + *
60420 + */
60421 +
60422 +#include <linux/errno.h>
60423 +#include <linux/kernel.h>
60424 +#include <linux/slab.h>
60425 +
60426 +#include "ts_filter_mean.h"
60427 +
60428 +struct ts_filter_mean {
60429 + /* Copy of the private filter configuration. */
60430 + struct ts_filter_mean_configuration *config;
60431 + /* Filter API. */
60432 + struct ts_filter tsf;
60433 +
60434 + /* Index on a circular buffer. */
60435 + int curr;
60436 + /* Useful to tell if the circular buffer is full(read:ready). */
60437 + int count;
60438 + /* Sumation used to compute the mean. */
60439 + int sum[MAX_TS_FILTER_COORDS];
60440 + /* Keep point values and decrement them from the sum on time. */
60441 + int *fifo[MAX_TS_FILTER_COORDS];
60442 + /* Store the output of this filter. */
60443 + int ready;
60444 +};
60445 +
60446 +#define ts_filter_to_filter_mean(f) container_of(f, struct ts_filter_mean, tsf)
60447 +
60448 +
60449 +static void ts_filter_mean_clear(struct ts_filter *tsf);
60450 +
60451 +static struct ts_filter *ts_filter_mean_create(
60452 + struct platform_device *pdev,
60453 + const struct ts_filter_configuration *conf,
60454 + int count_coords)
60455 +{
60456 + struct ts_filter_mean *priv;
60457 + int *v;
60458 + int n;
60459 +
60460 + priv = kzalloc(sizeof(struct ts_filter_mean), GFP_KERNEL);
60461 + if (!priv)
60462 + return NULL;
60463 +
60464 + priv->tsf.count_coords = count_coords;
60465 + priv->config = container_of(conf,
60466 + struct ts_filter_mean_configuration,
60467 + config);
60468 +
60469 + BUG_ON(priv->config->length <= 0);
60470 +
60471 + v = kmalloc(priv->config->length * sizeof(int) * count_coords,
60472 + GFP_KERNEL);
60473 + if (!v)
60474 + return NULL;
60475 +
60476 + for (n = 0; n < count_coords; n++) {
60477 + priv->fifo[n] = v;
60478 + v += priv->config->length;
60479 + }
60480 +
60481 + ts_filter_mean_clear(&priv->tsf);
60482 +
60483 + dev_info(&pdev->dev, "Created Mean filter len:%d coords:%d\n",
60484 + priv->config->length, count_coords);
60485 +
60486 + return &priv->tsf;
60487 +}
60488 +
60489 +static void ts_filter_mean_destroy(struct ts_filter *tsf)
60490 +{
60491 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60492 +
60493 + kfree(priv->fifo[0]); /* first guy has pointer from kmalloc */
60494 + kfree(tsf);
60495 +}
60496 +
60497 +static void ts_filter_mean_clear(struct ts_filter *tsf)
60498 +{
60499 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60500 +
60501 + priv->count = 0;
60502 + priv->curr = 0;
60503 + priv->ready = 0;
60504 + memset(priv->sum, 0, tsf->count_coords * sizeof(int));
60505 +}
60506 +
60507 +static int ts_filter_mean_process(struct ts_filter *tsf, int *coords)
60508 +{
60509 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60510 + int n;
60511 +
60512 + BUG_ON(priv->ready);
60513 +
60514 + for (n = 0; n < tsf->count_coords; n++) {
60515 + priv->sum[n] += coords[n];
60516 + priv->fifo[n][priv->curr] = coords[n];
60517 + }
60518 +
60519 + if (priv->count + 1 == priv->config->length)
60520 + priv->ready = 1;
60521 + else
60522 + priv->count++;
60523 +
60524 + priv->curr = (priv->curr + 1) % priv->config->length;
60525 +
60526 + return 0; /* No error. */
60527 +}
60528 +
60529 +static int ts_filter_mean_haspoint(struct ts_filter *tsf)
60530 +{
60531 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60532 +
60533 + return priv->ready;
60534 +}
60535 +
60536 +static void ts_filter_mean_getpoint(struct ts_filter *tsf, int *point)
60537 +{
60538 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60539 + int n;
60540 +
60541 + BUG_ON(!priv->ready);
60542 +
60543 + for (n = 0; n < tsf->count_coords; n++) {
60544 + point[n] = priv->sum[n];
60545 + priv->sum[n] -= priv->fifo[n][priv->curr];
60546 + }
60547 +
60548 + priv->ready = 0;
60549 +}
60550 +
60551 +static void ts_filter_mean_scale(struct ts_filter *tsf, int *coords)
60552 +{
60553 + int n;
60554 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60555 +
60556 + for (n = 0; n < tsf->count_coords; n++) {
60557 + coords[n] += priv->config->length >> 1; /* Rounding. */
60558 + coords[n] /= priv->config->length;
60559 + }
60560 +}
60561 +
60562 +const struct ts_filter_api ts_filter_mean_api = {
60563 + .create = ts_filter_mean_create,
60564 + .destroy = ts_filter_mean_destroy,
60565 + .clear = ts_filter_mean_clear,
60566 + .process = ts_filter_mean_process,
60567 + .scale = ts_filter_mean_scale,
60568 + .haspoint = ts_filter_mean_haspoint,
60569 + .getpoint = ts_filter_mean_getpoint,
60570 +};
60571 +EXPORT_SYMBOL_GPL(ts_filter_mean_api);
60572 +
60573 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_mean.h linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_mean.h
60574 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_mean.h 1970-01-01 01:00:00.000000000 +0100
60575 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_mean.h 2009-05-10 22:27:59.000000000 +0200
60576 @@ -0,0 +1,28 @@
60577 +#ifndef __TS_FILTER_MEAN_H__
60578 +#define __TS_FILTER_MEAN_H__
60579 +
60580 +#include "ts_filter.h"
60581 +
60582 +/*
60583 + * Touchscreen filter.
60584 + *
60585 + * mean
60586 + *
60587 + * (c) 2008,2009
60588 + * Andy Green <andy@openmoko.com>
60589 + * Nelson Castillo <arhuaco@freaks-unidos.net>
60590 + */
60591 +
60592 +/* Configuration for this filter. */
60593 +struct ts_filter_mean_configuration {
60594 + /* Number of points for the mean. */
60595 + int length;
60596 +
60597 + /* Generic filter configuration. */
60598 + struct ts_filter_configuration config;
60599 +};
60600 +
60601 +/* API functions for the mean filter */
60602 +extern const struct ts_filter_api ts_filter_mean_api;
60603 +
60604 +#endif /* __TS_FILTER_MEAN_H__ */
60605 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_median.c linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_median.c
60606 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_median.c 1970-01-01 01:00:00.000000000 +0100
60607 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_median.c 2009-05-10 22:27:59.000000000 +0200
60608 @@ -0,0 +1,261 @@
60609 +/*
60610 + * This program is free software; you can redistribute it and/or modify
60611 + * it under the terms of the GNU General Public License as published by
60612 + * the Free Software Foundation; either version 2 of the License, or
60613 + * (at your option) any later version.
60614 + *
60615 + * This program is distributed in the hope that it will be useful,
60616 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
60617 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60618 + * GNU General Public License for more details.
60619 + *
60620 + * You should have received a copy of the GNU General Public License
60621 + * along with this program; if not, write to the Free Software
60622 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
60623 + *
60624 + * Copyright (c) 2008 Andy Green <andy@openmoko.com>
60625 + *
60626 + *
60627 + * Median averaging stuff. We sort incoming raw samples into an array of
60628 + * MEDIAN_SIZE length, discarding the oldest sample each time once we are full.
60629 + * We then return the sum of the middle three samples for X and Y. It means
60630 + * the final result must be divided by (3 * scaling factor) to correct for
60631 + * avoiding the repeated /3.
60632 + *
60633 + * This strongly rejects brief excursions away from a central point that is
60634 + * sticky in time compared to the excursion duration.
60635 + *
60636 + * Thanks to Dale Schumacher (who wrote some example code) and Carl-Daniel
60637 + * Halifinger who pointed out this would be a good method.
60638 + */
60639 +
60640 +#include <linux/errno.h>
60641 +#include <linux/kernel.h>
60642 +#include <linux/slab.h>
60643 +#include "ts_filter_median.h"
60644 +
60645 +struct ts_filter_median {
60646 + /* Private configuration. */
60647 + struct ts_filter_median_configuration *config;
60648 + /* Generic Filter API. */
60649 + struct ts_filter tsf;
60650 +
60651 + /* Count raw samples we get. */
60652 + int samples_count;
60653 + /*
60654 + * Remember the last coordinates we got in order to know if
60655 + * we are moving slow or fast.
60656 + */
60657 + int last_issued[MAX_TS_FILTER_COORDS];
60658 + /* How many samples in the sort buffer are valid. */
60659 + int valid;
60660 + /* Samples taken for median in sorted form. */
60661 + int *sort[MAX_TS_FILTER_COORDS];
60662 + /* Samples taken for median. */
60663 + int *fifo[MAX_TS_FILTER_COORDS];
60664 + /* Where we are in the fifo sample memory. */
60665 + int pos;
60666 + /* Do we have a sample to deliver? */
60667 + int ready;
60668 +};
60669 +
60670 +#define ts_filter_to_filter_median(f) \
60671 + container_of(f, struct ts_filter_median, tsf)
60672 +
60673 +
60674 +static void ts_filter_median_insert(int *p, int sample, int count)
60675 +{
60676 + int n;
60677 +
60678 + /* Search through what we got so far to find where to put sample. */
60679 + for (n = 0; n < count; n++)
60680 + if (sample < p[n]) { /* We met somebody bigger than us? */
60681 + /* Starting from the end, push bigger guys down one. */
60682 + for (count--; count >= n; count--)
60683 + p[count + 1] = p[count];
60684 + p[n] = sample; /* Put us in place of first bigger. */
60685 + return;
60686 + }
60687 +
60688 + p[count] = sample; /* Nobody was bigger than us, add us on the end. */
60689 +}
60690 +
60691 +static void ts_filter_median_del(int *p, int value, int count)
60692 +{
60693 + int index;
60694 +
60695 + for (index = 0; index < count; index++)
60696 + if (p[index] == value) {
60697 + for (; index < count; index++)
60698 + p[index] = p[index + 1];
60699 + return;
60700 + }
60701 +}
60702 +
60703 +
60704 +static void ts_filter_median_clear(struct ts_filter *tsf)
60705 +{
60706 + struct ts_filter_median *tsfm = ts_filter_to_filter_median(tsf);
60707 +
60708 + tsfm->pos = 0;
60709 + tsfm->valid = 0;
60710 + tsfm->ready = 0;
60711 + memset(&tsfm->last_issued[0], 1, tsf->count_coords * sizeof(int));
60712 +}
60713 +
60714 +static struct ts_filter *ts_filter_median_create(
60715 + struct platform_device *pdev,
60716 + const struct ts_filter_configuration *conf,
60717 + int count_coords)
60718 +{
60719 + int *p;
60720 + int n;
60721 + struct ts_filter_median *tsfm = kzalloc(sizeof(struct ts_filter_median),
60722 + GFP_KERNEL);
60723 +
60724 + if (!tsfm)
60725 + return NULL;
60726 +
60727 + tsfm->config = container_of(conf,
60728 + struct ts_filter_median_configuration,
60729 + config);
60730 +
60731 + tsfm->tsf.count_coords = count_coords;
60732 +
60733 + tsfm->config->midpoint = (tsfm->config->extent >> 1) + 1;
60734 +
60735 + p = kmalloc(2 * count_coords * sizeof(int) * (tsfm->config->extent + 1),
60736 + GFP_KERNEL);
60737 + if (!p) {
60738 + kfree(tsfm);
60739 + return NULL;
60740 + }
60741 +
60742 + for (n = 0; n < count_coords; n++) {
60743 + tsfm->sort[n] = p;
60744 + p += tsfm->config->extent + 1;
60745 + tsfm->fifo[n] = p;
60746 + p += tsfm->config->extent + 1;
60747 + }
60748 +
60749 + ts_filter_median_clear(&tsfm->tsf);
60750 +
60751 + dev_info(&pdev->dev,
60752 + "Created Median filter len:%d coords:%d dec_threshold:%d\n",
60753 + tsfm->config->extent, count_coords,
60754 + tsfm->config->decimation_threshold);
60755 +
60756 + return &tsfm->tsf;
60757 +}
60758 +
60759 +static void ts_filter_median_destroy(struct ts_filter *tsf)
60760 +{
60761 + struct ts_filter_median *tsfm = ts_filter_to_filter_median(tsf);
60762 +
60763 + kfree(tsfm->sort[0]); /* First guy has pointer from kmalloc. */
60764 + kfree(tsf);
60765 +}
60766 +
60767 +static void ts_filter_median_scale(struct ts_filter *tsf, int *coords)
60768 +{
60769 + int n;
60770 +
60771 + for (n = 0; n < tsf->count_coords; n++)
60772 + coords[n] = (coords[n] + 2) / 3;
60773 +}
60774 +
60775 +/*
60776 + * Give us the raw sample data coords, and if we return 1 then you can
60777 + * get a filtered coordinate from coords. If we return 0 you didn't
60778 + * fill all the filters with samples yet.
60779 + */
60780 +
60781 +static int ts_filter_median_process(struct ts_filter *tsf, int *coords)
60782 +{
60783 + struct ts_filter_median *tsfm = ts_filter_to_filter_median(tsf);
60784 + int n;
60785 + int movement = 1;
60786 +
60787 + for (n = 0; n < tsf->count_coords; n++) {
60788 + /* Grab copy in insertion order to remove when oldest. */
60789 + tsfm->fifo[n][tsfm->pos] = coords[n];
60790 + /* Insert these samples in sorted order in the median arrays. */
60791 + ts_filter_median_insert(tsfm->sort[n], coords[n], tsfm->valid);
60792 + }
60793 + /* Move us on in the fifo. */
60794 + if (++tsfm->pos == (tsfm->config->extent + 1))
60795 + tsfm->pos = 0;
60796 +
60797 + /* Have we finished a median sampling? */
60798 + if (++tsfm->valid < tsfm->config->extent)
60799 + goto process_exit; /* No valid sample to use. */
60800 +
60801 + BUG_ON(tsfm->valid != tsfm->config->extent);
60802 +
60803 + tsfm->valid--;
60804 +
60805 + /*
60806 + * Sum the middle 3 in the median sorted arrays. We don't divide back
60807 + * down which increases the sum resolution by a factor of 3 until the
60808 + * scale API function is called.
60809 + */
60810 + for (n = 0; n < tsf->count_coords; n++)
60811 + /* Perform the deletion of the oldest sample. */
60812 + ts_filter_median_del(tsfm->sort[n], tsfm->fifo[n][tsfm->pos],
60813 + tsfm->valid);
60814 +
60815 + tsfm->samples_count--;
60816 + if (tsfm->samples_count >= 0)
60817 + goto process_exit;
60818 +
60819 + for (n = 0; n < tsf->count_coords; n++) {
60820 + /* Give the coordinate result from summing median 3. */
60821 + coords[n] = tsfm->sort[n][tsfm->config->midpoint - 1] +
60822 + tsfm->sort[n][tsfm->config->midpoint] +
60823 + tsfm->sort[n][tsfm->config->midpoint + 1];
60824 +
60825 + movement += abs(tsfm->last_issued[n] - coords[n]);
60826 + }
60827 +
60828 + if (movement > tsfm->config->decimation_threshold) /* Moving fast. */
60829 + tsfm->samples_count = tsfm->config->decimation_above;
60830 + else
60831 + tsfm->samples_count = tsfm->config->decimation_below;
60832 +
60833 + memcpy(&tsfm->last_issued[0], coords, tsf->count_coords * sizeof(int));
60834 +
60835 + tsfm->ready = 1;
60836 +
60837 +process_exit:
60838 + return 0;
60839 +}
60840 +
60841 +static int ts_filter_median_haspoint(struct ts_filter *tsf)
60842 +{
60843 + struct ts_filter_median *priv = ts_filter_to_filter_median(tsf);
60844 +
60845 + return priv->ready;
60846 +}
60847 +
60848 +static void ts_filter_median_getpoint(struct ts_filter *tsf, int *point)
60849 +{
60850 + struct ts_filter_median *priv = ts_filter_to_filter_median(tsf);
60851 +
60852 + BUG_ON(!priv->ready);
60853 +
60854 + memcpy(point, &priv->last_issued[0], tsf->count_coords * sizeof(int));
60855 +
60856 + priv->ready = 0;
60857 +}
60858 +
60859 +const struct ts_filter_api ts_filter_median_api = {
60860 + .create = ts_filter_median_create,
60861 + .destroy = ts_filter_median_destroy,
60862 + .clear = ts_filter_median_clear,
60863 + .process = ts_filter_median_process,
60864 + .scale = ts_filter_median_scale,
60865 + .haspoint = ts_filter_median_haspoint,
60866 + .getpoint = ts_filter_median_getpoint,
60867 +};
60868 +EXPORT_SYMBOL_GPL(ts_filter_median_api);
60869 +
60870 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_median.h linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_median.h
60871 --- linux-2.6.29-rc3.owrt/drivers/input/touchscreen/ts_filter_median.h 1970-01-01 01:00:00.000000000 +0100
60872 +++ linux-2.6.29-rc3.owrt.om/drivers/input/touchscreen/ts_filter_median.h 2009-05-10 22:27:59.000000000 +0200
60873 @@ -0,0 +1,32 @@
60874 +#ifndef __TS_FILTER_MEDIAN_H__
60875 +#define __TS_FILTER_MEDIAN_H__
60876 +
60877 +#include "ts_filter.h"
60878 +
60879 +/*
60880 + * Touchscreen filter.
60881 + *
60882 + * median
60883 + *
60884 + * (c) 2008 Andy Green <andy@openmoko.com>
60885 + */
60886 +
60887 +struct ts_filter_median_configuration {
60888 + /* Size of the filter. */
60889 + int extent;
60890 + /* Precomputed midpoint. */
60891 + int midpoint;
60892 + /* A reference value for us to check if we are going fast or slow. */
60893 + int decimation_threshold;
60894 + /* How many points to replace if we're going fast. */
60895 + int decimation_above;
60896 + /* How many points to replace if we're going slow. */
60897 + int decimation_below;
60898 +
60899 + /* Generic configuration. */
60900 + struct ts_filter_configuration config;
60901 +};
60902 +
60903 +extern const struct ts_filter_api ts_filter_median_api;
60904 +
60905 +#endif
60906 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/Kconfig linux-2.6.29-rc3.owrt.om/drivers/Kconfig
60907 --- linux-2.6.29-rc3.owrt/drivers/Kconfig 2009-05-10 22:04:48.000000000 +0200
60908 +++ linux-2.6.29-rc3.owrt.om/drivers/Kconfig 2009-05-10 22:27:59.000000000 +0200
60909 @@ -109,4 +109,5 @@
60910 source "drivers/staging/Kconfig"
60911
60912 source "drivers/platform/Kconfig"
60913 +
60914 endmenu
60915 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/leds/Kconfig linux-2.6.29-rc3.owrt.om/drivers/leds/Kconfig
60916 --- linux-2.6.29-rc3.owrt/drivers/leds/Kconfig 2009-05-10 22:04:48.000000000 +0200
60917 +++ linux-2.6.29-rc3.owrt.om/drivers/leds/Kconfig 2009-05-10 22:27:59.000000000 +0200
60918 @@ -33,7 +33,7 @@
60919
60920 config LEDS_S3C24XX
60921 tristate "LED Support for Samsung S3C24XX GPIO LEDs"
60922 - depends on LEDS_CLASS && ARCH_S3C2410
60923 + depends on LEDS_CLASS && ARCH_S3C2410 && S3C2410_PWM
60924 help
60925 This option enables support for LEDs connected to GPIO lines
60926 on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
60927 @@ -171,6 +171,25 @@
60928 This option enables support for on-chip LED drivers found
60929 on Dialog Semiconductor DA9030/DA9034 PMICs.
60930
60931 +config LEDS_NEO1973_VIBRATOR
60932 + tristate "Vibrator Support for the FIC Neo1973 GSM phone"
60933 + depends on LEDS_CLASS && MACH_NEO1973
60934 + help
60935 + This option enables support for the vibrator on the FIC Neo1973.
60936 +
60937 +config LEDS_NEO1973_GTA02
60938 + tristate "LED Support for the FIC Neo1973 (GTA02)"
60939 + depends on LEDS_CLASS && MACH_NEO1973_GTA02
60940 + help
60941 + This option enables support for the LEDs on the FIC Neo1973.
60942 +
60943 +config LEDS_LP5521
60944 + tristate "LED Support for LP5521 LED I2C chip"
60945 + depends on LEDS_CLASS && I2C
60946 + help
60947 + If you say yes here you get support for the National Semiconductor
60948 + LP5521 LED driver.
60949 +
60950 comment "LED Triggers"
60951
60952 config LEDS_TRIGGERS
60953 @@ -234,4 +253,11 @@
60954 This allows LEDs to be controlled by network device activity.
60955 If unsure, say Y.
60956
60957 +config LEDS_TRIGGER_NETDEV
60958 + tristate "LED Network Device Trigger"
60959 + depends on LEDS_TRIGGERS
60960 + help
60961 + This allows LEDs to be controlled by Network Device activity.
60962 + If unsure, say Y.
60963 +
60964 endif # NEW_LEDS
60965 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/leds/led-class.c linux-2.6.29-rc3.owrt.om/drivers/leds/led-class.c
60966 --- linux-2.6.29-rc3.owrt/drivers/leds/led-class.c 2009-05-10 22:04:48.000000000 +0200
60967 +++ linux-2.6.29-rc3.owrt.om/drivers/leds/led-class.c 2009-05-10 22:27:59.000000000 +0200
60968 @@ -56,8 +56,10 @@
60969 if (count == size) {
60970 ret = count;
60971
60972 +#if 0 /* This is really bad. Don't do it!!!! */
60973 if (state == LED_OFF)
60974 led_trigger_remove(led_cdev);
60975 +#endif
60976 led_set_brightness(led_cdev, state);
60977 }
60978
60979 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/leds/leds-lp5521.c linux-2.6.29-rc3.owrt.om/drivers/leds/leds-lp5521.c
60980 --- linux-2.6.29-rc3.owrt/drivers/leds/leds-lp5521.c 1970-01-01 01:00:00.000000000 +0100
60981 +++ linux-2.6.29-rc3.owrt.om/drivers/leds/leds-lp5521.c 2009-05-10 22:27:59.000000000 +0200
60982 @@ -0,0 +1,386 @@
60983 +/* NS LP5521 Programmable LED driver.
60984 + *
60985 + * (C) 2009 by Openmoko, Inc.
60986 + * Author: Matt Hsu <matt_hsu@openmoko.org>
60987 + *
60988 + * This program is free software; you can redistribute it and/or modify
60989 + * it under the terms of the GNU General Public License as published by
60990 + * the Free Software Foundation; either version 2 of the License, or
60991 + * (at your option) any later version.
60992 + *
60993 + * This program is distributed in the hope that it will be useful,
60994 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
60995 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
60996 + * GNU General Public License for more details.
60997 + *
60998 + * You should have received a copy of the GNU General Public License
60999 + * along with this program; if not, write to the Free Software
61000 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
61001 + */
61002 +#include <linux/module.h>
61003 +#include <linux/init.h>
61004 +#include <linux/i2c.h>
61005 +#include <linux/mutex.h>
61006 +#include <linux/device.h>
61007 +#include <linux/sysfs.h>
61008 +#include <linux/interrupt.h>
61009 +#include <linux/irq.h>
61010 +
61011 +#include <linux/lp5521.h>
61012 +
61013 +#define LP5521_DRIVER_NAME "lp5521"
61014 +
61015 +static int __lp5521_reg_write(struct lp5521 *lp, u8 reg, u8 value)
61016 +{
61017 + return i2c_smbus_write_byte_data(lp->client, reg, value);
61018 +}
61019 +
61020 +static int reg_write(struct lp5521 *lp, u_int8_t reg, u_int8_t val)
61021 +{
61022 + int ret;
61023 +
61024 + mutex_lock(&lp->lock);
61025 + ret = __lp5521_reg_write(lp, reg, val);
61026 + mutex_unlock(&lp->lock);
61027 +
61028 + return ret;
61029 +}
61030 +
61031 +static int __lp5521_reg_read(struct lp5521 *lp, u8 reg)
61032 +{
61033 + int32_t ret;
61034 +
61035 + ret = i2c_smbus_read_byte_data(lp->client, reg);
61036 +
61037 + return ret;
61038 +}
61039 +
61040 +static u_int8_t reg_read(struct lp5521 *lp, u_int8_t reg)
61041 +{
61042 + int32_t ret;
61043 +
61044 + mutex_lock(&lp->lock);
61045 + ret = __lp5521_reg_read(lp, reg);
61046 + mutex_unlock(&lp->lock);
61047 +
61048 + return ret & 0xff;
61049 +}
61050 +
61051 +static int reg_set_bit_mask(struct lp5521 *lp,
61052 + u_int8_t reg, u_int8_t mask, u_int8_t val)
61053 +{
61054 + int ret;
61055 + u_int8_t tmp;
61056 +
61057 + val &= mask;
61058 +
61059 + mutex_lock(&lp->lock);
61060 +
61061 + tmp = __lp5521_reg_read(lp, reg);
61062 + tmp &= ~mask;
61063 + tmp |= val;
61064 + ret = __lp5521_reg_write(lp, reg, tmp);
61065 +
61066 + mutex_unlock(&lp->lock);
61067 +
61068 + return ret;
61069 +}
61070 +
61071 +static const char *lp5521_ch_name[] = {
61072 + "blue", "green", "red",
61073 +};
61074 +
61075 +static inline int channel_id_by_name(const char *name)
61076 +{
61077 + int channel_id = -1;
61078 +
61079 + if (!strncmp(name, lp5521_ch_name[LP5521_BLUE],
61080 + strlen(lp5521_ch_name[LP5521_BLUE])))
61081 + channel_id = LP5521_BLUE;
61082 + else if (!strncmp(name, lp5521_ch_name[LP5521_GREEN],
61083 + strlen(lp5521_ch_name[LP5521_GREEN])))
61084 + channel_id = LP5521_GREEN;
61085 + else if (!strncmp(name, lp5521_ch_name[LP5521_RED],
61086 + strlen(lp5521_ch_name[LP5521_RED])))
61087 + channel_id = LP5521_RED;
61088 +
61089 + return channel_id;
61090 +}
61091 +
61092 +static const char *lp5521_ch_mode[] = {
61093 + "disable", "load", "run",
61094 + "direct",
61095 +};
61096 +
61097 +/*
61098 + * Individual mode control
61099 + */
61100 +static ssize_t show_mode(struct device *dev, struct device_attribute
61101 + *attr, char *buf)
61102 +{
61103 + struct i2c_client *client = to_i2c_client(dev);
61104 + struct lp5521 *lp = i2c_get_clientdata(client);
61105 + int id;
61106 + uint8_t val;
61107 +
61108 + id = channel_id_by_name(attr->attr.name);
61109 + val = reg_read(lp, LP5521_REG_OP_MODE);
61110 +
61111 + val = val >> (id * 2);
61112 + val &= 0x3;
61113 +
61114 + return sprintf(buf, "%s\n", lp5521_ch_mode[val]);
61115 +}
61116 +
61117 +static ssize_t set_mode(struct device *dev, struct device_attribute *attr,
61118 + const char *buf, size_t count)
61119 +{
61120 + struct i2c_client *client = to_i2c_client(dev);
61121 + struct lp5521 *lp = i2c_get_clientdata(client);
61122 + int id;
61123 + uint8_t mask, i;
61124 +
61125 + id = channel_id_by_name(attr->attr.name);
61126 +
61127 + mask = (0x3 << (id * 2));
61128 +
61129 + for (i = LP5521_MODE_DISABLE; i <= LP5521_MODE_DIRECT; i++) {
61130 + if (!strncmp(buf, lp5521_ch_mode[i], strlen(lp5521_ch_mode[i]))) {
61131 + reg_set_bit_mask(lp,
61132 + LP5521_REG_OP_MODE, mask, (i << (id * 2)));
61133 + }
61134 + }
61135 +
61136 + return count;
61137 +}
61138 +
61139 +static DEVICE_ATTR(red_mode, S_IRUGO | S_IWUSR, show_mode, set_mode);
61140 +static DEVICE_ATTR(green_mode, S_IRUGO | S_IWUSR, show_mode, set_mode);
61141 +static DEVICE_ATTR(blue_mode, S_IRUGO | S_IWUSR, show_mode, set_mode);
61142 +
61143 +/*
61144 + * Individual pwm control
61145 + */
61146 +static ssize_t show_pwm(struct device *dev, struct device_attribute
61147 + *attr, char *buf)
61148 +{
61149 + struct i2c_client *client = to_i2c_client(dev);
61150 + struct lp5521 *lp = i2c_get_clientdata(client);
61151 + int id;
61152 + uint8_t val;
61153 +
61154 + id = channel_id_by_name(attr->attr.name);
61155 + val = reg_read(lp, LP5521_REG_B_PWM-id);
61156 +
61157 + return sprintf(buf, "%d\n", val);
61158 +}
61159 +
61160 +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
61161 + const char *buf, size_t count)
61162 +{
61163 + int id;
61164 + struct i2c_client *client = to_i2c_client(dev);
61165 + struct lp5521 *lp = i2c_get_clientdata(client);
61166 + unsigned int pwm = simple_strtoul(buf, NULL, 10);
61167 +
61168 + id = channel_id_by_name(attr->attr.name);
61169 + reg_write(lp, LP5521_REG_B_PWM-id, pwm);
61170 +
61171 + return count;
61172 +}
61173 +
61174 +static DEVICE_ATTR(red_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
61175 +static DEVICE_ATTR(green_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
61176 +static DEVICE_ATTR(blue_pwm, S_IRUGO | S_IWUSR, show_pwm, set_pwm);
61177 +
61178 +/*
61179 + * Individual current control
61180 + */
61181 +static ssize_t show_cur(struct device *dev, struct device_attribute
61182 + *attr, char *buf)
61183 +{
61184 + struct i2c_client *client = to_i2c_client(dev);
61185 + struct lp5521 *lp = i2c_get_clientdata(client);
61186 + int id;
61187 + uint8_t val;
61188 +
61189 + id = channel_id_by_name(attr->attr.name);
61190 + val = reg_read(lp, LP5521_REG_B_CUR-id);
61191 +
61192 + return sprintf(buf, "%d (100uA)\n", val);
61193 +}
61194 +
61195 +static ssize_t set_cur(struct device *dev, struct device_attribute *attr,
61196 + const char *buf, size_t count)
61197 +{
61198 + int id;
61199 + struct i2c_client *client = to_i2c_client(dev);
61200 + struct lp5521 *lp = i2c_get_clientdata(client);
61201 + unsigned int cur = simple_strtoul(buf, NULL, 10);
61202 +
61203 + id = channel_id_by_name(attr->attr.name);
61204 + reg_write(lp, LP5521_REG_B_CUR-id, cur);
61205 +
61206 + return count;
61207 +}
61208 +
61209 +static DEVICE_ATTR(red_cur, S_IRUGO | S_IWUSR, show_cur, set_cur);
61210 +static DEVICE_ATTR(green_cur, S_IRUGO | S_IWUSR, show_cur, set_cur);
61211 +static DEVICE_ATTR(blue_cur, S_IRUGO | S_IWUSR, show_cur, set_cur);
61212 +
61213 +static struct attribute *lp_sysfs_entries[16];
61214 +
61215 +static struct attribute_group lp_attr_group = {
61216 + .name = NULL,
61217 + .attrs = lp_sysfs_entries,
61218 +};
61219 +
61220 +static void populate_sysfs_group(struct lp5521 *lp)
61221 +{
61222 + int i = 0;
61223 +
61224 + if (lp->pdata->channels[LP5521_RED] & LP5521_CONNECTED) {
61225 + lp_sysfs_entries[i++] = &dev_attr_red_mode.attr;
61226 + lp_sysfs_entries[i++] = &dev_attr_red_pwm.attr;
61227 + lp_sysfs_entries[i++] = &dev_attr_red_cur.attr;
61228 + }
61229 +
61230 + if (lp->pdata->channels[LP5521_GREEN] & LP5521_CONNECTED) {
61231 + lp_sysfs_entries[i++] = &dev_attr_green_mode.attr;
61232 + lp_sysfs_entries[i++] = &dev_attr_green_pwm.attr;
61233 + lp_sysfs_entries[i++] = &dev_attr_green_cur.attr;
61234 + }
61235 +
61236 + if (lp->pdata->channels[LP5521_BLUE] & LP5521_CONNECTED) {
61237 + lp_sysfs_entries[i++] = &dev_attr_blue_mode.attr;
61238 + lp_sysfs_entries[i++] = &dev_attr_blue_pwm.attr;
61239 + lp_sysfs_entries[i++] = &dev_attr_blue_cur.attr;
61240 + }
61241 +}
61242 +
61243 +static struct i2c_driver lp5521_driver;
61244 +
61245 +#ifdef CONFIG_PM
61246 +static int lp5521_suspend(struct device *dev, pm_message_t state)
61247 +{
61248 + /* FIXME: Not implemented
61249 + * Here we could upload firmware to perform
61250 + * any scenarios we want and save registers.
61251 + */
61252 + return 0;
61253 +}
61254 +
61255 +static int lp5521_resume(struct device *dev)
61256 +{
61257 + /* FIXME: Not implemented */
61258 + return 0;
61259 +}
61260 +#else
61261 +#define lp5521_suspend NULL
61262 +#define lp5521_resume NULL
61263 +#endif
61264 +
61265 +static irqreturn_t lp5521_irq(int irq, void *_lp)
61266 +{
61267 + struct lp5521 *lp = _lp;
61268 + dev_info(lp->dev, "lp5521 interrupt\n");
61269 +
61270 + return IRQ_HANDLED;
61271 +}
61272 +
61273 +static int __devinit
61274 +lp5521_probe(struct i2c_client *client, const struct i2c_device_id *id)
61275 +{
61276 + struct lp5521 *lp;
61277 + int ret = 0;
61278 + struct lp5521_platform_data *pdata = client->dev.platform_data;
61279 +
61280 + lp = kzalloc(sizeof(*lp), GFP_KERNEL);
61281 + if (!lp)
61282 + return -ENOMEM;
61283 +
61284 + lp->client = client;
61285 + lp->irq = client->irq;
61286 + lp->dev = &client->dev;
61287 + i2c_set_clientdata(client, lp);
61288 +
61289 + lp->pdata = pdata;
61290 + mutex_init(&lp->lock);
61291 +
61292 + /* enter start-up mode */
61293 + if (pdata->ext_enable)
61294 + (pdata->ext_enable)(1);
61295 +
61296 + reg_write(lp, LP5521_REG_ENABLE, 0x40);
61297 +
61298 + /* charge pump mode and clk src selection */
61299 + reg_write(lp, LP5521_REG_CONFIG, 0x11);
61300 +
61301 + /* allocate IRQ resource */
61302 + if (lp->irq) {
61303 + ret = request_irq(client->irq, lp5521_irq,
61304 + IRQF_TRIGGER_LOW, LP5521_DRIVER_NAME, lp);
61305 + if (ret) {
61306 + dev_err(lp->dev, "request IRQ failed\n");
61307 + goto fail;
61308 + }
61309 + } else {
61310 + dev_err(lp->dev, "No IRQ allocated \n");
61311 + }
61312 +
61313 + populate_sysfs_group(lp);
61314 +
61315 + ret = sysfs_create_group(&client->dev.kobj, &lp_attr_group);
61316 +
61317 + if (ret) {
61318 + dev_err(lp->dev, "error creating sysfs group\n");
61319 + goto fail;
61320 + }
61321 +
61322 + return ret;
61323 +
61324 +fail:
61325 + kfree(lp);
61326 + return ret;
61327 +}
61328 +
61329 +static int __devexit lp5521_remove(struct i2c_client *client)
61330 +{
61331 + struct lp5521 *lp = i2c_get_clientdata(client);
61332 +
61333 + kfree(lp);
61334 +
61335 + return 0;
61336 +}
61337 +
61338 +static struct i2c_device_id lp5521_id[] = {
61339 + {LP5521_DRIVER_NAME, },
61340 +};
61341 +
61342 +static struct i2c_driver lp5521_driver = {
61343 + .driver = {
61344 + .name = LP5521_DRIVER_NAME,
61345 + .suspend = lp5521_suspend,
61346 + .resume = lp5521_resume,
61347 + },
61348 + .id_table = lp5521_id,
61349 + .probe = lp5521_probe,
61350 + .remove = __exit_p(lp5521_remove),
61351 +};
61352 +
61353 +static int __init lp5521_init(void)
61354 +{
61355 + return i2c_add_driver(&lp5521_driver);
61356 +}
61357 +
61358 +static void __exit lp5521_exit(void)
61359 +{
61360 + i2c_del_driver(&lp5521_driver);
61361 +}
61362 +
61363 +MODULE_AUTHOR("Matt Hsu <matt_hsu@openmoko.org>");
61364 +MODULE_DESCRIPTION("NS lp5521 LED driver");
61365 +MODULE_LICENSE("GPLv2");
61366 +
61367 +module_init(lp5521_init);
61368 +module_exit(lp5521_exit);
61369 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/leds/leds-neo1973-gta02.c linux-2.6.29-rc3.owrt.om/drivers/leds/leds-neo1973-gta02.c
61370 --- linux-2.6.29-rc3.owrt/drivers/leds/leds-neo1973-gta02.c 1970-01-01 01:00:00.000000000 +0100
61371 +++ linux-2.6.29-rc3.owrt.om/drivers/leds/leds-neo1973-gta02.c 2009-05-10 22:27:59.000000000 +0200
61372 @@ -0,0 +1,179 @@
61373 +/*
61374 + * LED driver for the Openmoko GTA02 GSM phone
61375 + *
61376 + * (C) 2006-2008 by Openmoko, Inc.
61377 + * Author: Harald Welte <laforge@openmoko.org>
61378 + * All rights reserved.
61379 + *
61380 + * This program is free software; you can redistribute it and/or modify
61381 + * it under the terms of the GNU General Public License version 2 as
61382 + * published by the Free Software Foundation.
61383 + *
61384 + */
61385 +
61386 +#include <linux/kernel.h>
61387 +#include <linux/init.h>
61388 +#include <linux/platform_device.h>
61389 +#include <linux/leds.h>
61390 +#include <mach/hardware.h>
61391 +#include <asm/mach-types.h>
61392 +#include <mach/gta02.h>
61393 +#include <plat/regs-timer.h>
61394 +#include <asm/plat-s3c24xx/neo1973.h>
61395 +
61396 +#define MAX_LEDS 3
61397 +#define COUNTER 256
61398 +
61399 +struct gta02_led_priv
61400 +{
61401 + spinlock_t lock;
61402 + struct led_classdev cdev;
61403 + unsigned int gpio;
61404 +};
61405 +
61406 +struct gta02_led_bundle
61407 +{
61408 + int num_leds;
61409 + struct gta02_led_priv led[MAX_LEDS];
61410 +};
61411 +
61412 +static inline struct gta02_led_priv *to_priv(struct led_classdev *led_cdev)
61413 +{
61414 + return container_of(led_cdev, struct gta02_led_priv, cdev);
61415 +}
61416 +
61417 +static inline struct gta02_led_bundle *to_bundle(struct led_classdev *led_cdev)
61418 +{
61419 + return dev_get_drvdata(led_cdev->dev->parent);
61420 +}
61421 +
61422 +static void gta02led_set(struct led_classdev *led_cdev,
61423 + enum led_brightness value)
61424 +{
61425 + unsigned long flags;
61426 + struct gta02_led_priv *lp = to_priv(led_cdev);
61427 +
61428 + spin_lock_irqsave(&lp->lock, flags);
61429 + neo1973_gpb_setpin(lp->gpio, value ? 1 : 0);
61430 + spin_unlock_irqrestore(&lp->lock, flags);
61431 +}
61432 +
61433 +#ifdef CONFIG_PM
61434 +static int gta02led_suspend(struct platform_device *pdev, pm_message_t state)
61435 +{
61436 + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev);
61437 + int i;
61438 +
61439 + for (i = 0; i < bundle->num_leds; i++)
61440 + led_classdev_suspend(&bundle->led[i].cdev);
61441 +
61442 + return 0;
61443 +}
61444 +
61445 +static int gta02led_resume(struct platform_device *pdev)
61446 +{
61447 + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev);
61448 + int i;
61449 +
61450 + for (i = 0; i < bundle->num_leds; i++)
61451 + led_classdev_resume(&bundle->led[i].cdev);
61452 +
61453 + return 0;
61454 +}
61455 +#endif
61456 +
61457 +static int __init gta02led_probe(struct platform_device *pdev)
61458 +{
61459 + int i, rc;
61460 + struct gta02_led_bundle *bundle;
61461 +
61462 + if (!machine_is_neo1973_gta02())
61463 + return -EIO;
61464 +
61465 + bundle = kzalloc(sizeof(struct gta02_led_bundle), GFP_KERNEL);
61466 + if (!bundle)
61467 + return -ENOMEM;
61468 + platform_set_drvdata(pdev, bundle);
61469 +
61470 + for (i = 0; i < pdev->num_resources; i++) {
61471 + struct gta02_led_priv *lp;
61472 + struct resource *r;
61473 +
61474 + if (i >= MAX_LEDS)
61475 + break;
61476 +
61477 + r = platform_get_resource(pdev, 0, i);
61478 + if (!r || !r->start || !r->name)
61479 + continue;
61480 +
61481 + lp = &bundle->led[i];
61482 +
61483 + lp->gpio = r->start;
61484 + lp->cdev.name = r->name;
61485 + lp->cdev.brightness_set = gta02led_set;
61486 +
61487 + switch (lp->gpio) {
61488 + case S3C2410_GPB0:
61489 + case S3C2410_GPB1:
61490 + case S3C2410_GPB2:
61491 + s3c2410_gpio_cfgpin(lp->gpio, S3C2410_GPIO_OUTPUT);
61492 + neo1973_gpb_add_shadow_gpio(lp->gpio);
61493 + break;
61494 + default:
61495 + break;
61496 + }
61497 +
61498 + spin_lock_init(&lp->lock);
61499 + rc = led_classdev_register(&pdev->dev, &lp->cdev);
61500 + }
61501 +
61502 + bundle->num_leds = i;
61503 +
61504 + return 0;
61505 +}
61506 +
61507 +static int gta02led_remove(struct platform_device *pdev)
61508 +{
61509 + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev);
61510 + int i;
61511 +
61512 + for (i = 0; i < bundle->num_leds; i++) {
61513 + struct gta02_led_priv *lp = &bundle->led[i];
61514 + gta02led_set(&lp->cdev, 0);
61515 + led_classdev_unregister(&lp->cdev);
61516 + }
61517 +
61518 + platform_set_drvdata(pdev, NULL);
61519 + kfree(bundle);
61520 +
61521 + return 0;
61522 +}
61523 +
61524 +static struct platform_driver gta02led_driver = {
61525 + .probe = gta02led_probe,
61526 + .remove = gta02led_remove,
61527 +#ifdef CONFIG_PM
61528 + .suspend = gta02led_suspend,
61529 + .resume = gta02led_resume,
61530 +#endif
61531 + .driver = {
61532 + .name = "gta02-led",
61533 + },
61534 +};
61535 +
61536 +static int __init gta02led_init(void)
61537 +{
61538 + return platform_driver_register(&gta02led_driver);
61539 +}
61540 +
61541 +static void __exit gta02led_exit(void)
61542 +{
61543 + platform_driver_unregister(&gta02led_driver);
61544 +}
61545 +
61546 +module_init(gta02led_init);
61547 +module_exit(gta02led_exit);
61548 +
61549 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
61550 +MODULE_DESCRIPTION("Openmoko GTA02 LED driver");
61551 +MODULE_LICENSE("GPL");
61552 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/leds/leds-neo1973-vibrator.c linux-2.6.29-rc3.owrt.om/drivers/leds/leds-neo1973-vibrator.c
61553 --- linux-2.6.29-rc3.owrt/drivers/leds/leds-neo1973-vibrator.c 1970-01-01 01:00:00.000000000 +0100
61554 +++ linux-2.6.29-rc3.owrt.om/drivers/leds/leds-neo1973-vibrator.c 2009-05-10 22:27:59.000000000 +0200
61555 @@ -0,0 +1,241 @@
61556 +/*
61557 + * LED driver for the vibrator of the Openmoko GTA01/GTA02 GSM Phones
61558 + *
61559 + * (C) 2006-2008 by Openmoko, Inc.
61560 + * Author: Harald Welte <laforge@openmoko.org>
61561 + * All rights reserved.
61562 + *
61563 + * This program is free software; you can redistribute it and/or modify
61564 + * it under the terms of the GNU General Public License version 2 as
61565 + * published by the Free Software Foundation.
61566 + *
61567 + * Javi Roman <javiroman@kernel-labs.org>:
61568 + * Implement PWM support for GTA01Bv4 and later
61569 + */
61570 +
61571 +#include <linux/kernel.h>
61572 +#include <linux/init.h>
61573 +#include <linux/platform_device.h>
61574 +#include <linux/leds.h>
61575 +#include <mach/hardware.h>
61576 +#include <asm/mach-types.h>
61577 +#include <plat/pwm.h>
61578 +#include <mach/gta01.h>
61579 +#include <plat/regs-timer.h>
61580 +#include <linux/neo1973_vibrator.h>
61581 +
61582 +#include <asm/plat-s3c24xx/neo1973.h>
61583 +
61584 +#define COUNTER 64
61585 +
61586 +static struct neo1973_vib_priv {
61587 + struct led_classdev cdev;
61588 + unsigned int gpio;
61589 + spinlock_t lock;
61590 + unsigned int has_pwm;
61591 + struct s3c2410_pwm pwm;
61592 +
61593 + unsigned long vib_gpio_pin; /* which pin to meddle with */
61594 + u8 vib_pwm; /* 0 = OFF -- will ensure GPIO deasserted and stop FIQ */
61595 + u8 vib_pwm_latched;
61596 + u32 fiq_count;
61597 +
61598 + struct neo1973_vib_platform_data *pdata;
61599 +} neo1973_vib_priv;
61600 +
61601 +int neo1973_vibrator_fiq_handler(void)
61602 +{
61603 + neo1973_vib_priv.fiq_count++;
61604 +
61605 + if (!neo1973_vib_priv.vib_pwm_latched && !neo1973_vib_priv.vib_pwm)
61606 + /* idle */
61607 + return 0;
61608 +
61609 + if ((u8)neo1973_vib_priv.fiq_count == neo1973_vib_priv.vib_pwm_latched)
61610 + neo1973_gpb_setpin(neo1973_vib_priv.vib_gpio_pin, 0);
61611 +
61612 + if ((u8)neo1973_vib_priv.fiq_count)
61613 + return 1;
61614 +
61615 + neo1973_vib_priv.vib_pwm_latched = neo1973_vib_priv.vib_pwm;
61616 + if (neo1973_vib_priv.vib_pwm_latched)
61617 + neo1973_gpb_setpin(neo1973_vib_priv.vib_gpio_pin, 1);
61618 +
61619 + return 1;
61620 +}
61621 +
61622 +static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
61623 + enum led_brightness value)
61624 +{
61625 + unsigned long flags;
61626 + struct neo1973_vib_priv *vp = container_of(led_cdev,
61627 + struct neo1973_vib_priv,
61628 + cdev);
61629 +
61630 +#ifdef CONFIG_MACH_NEO1973_GTA02
61631 + if (machine_is_neo1973_gta02()) { /* use FIQ to control GPIO */
61632 + neo1973_vib_priv.vib_pwm = value; /* set it for FIQ */
61633 + neo1973_vib_priv.pdata->kick_fiq(); /* start up FIQs if not already going */
61634 + return;
61635 + }
61636 +#endif
61637 + /*
61638 + * value == 255 -> 99% duty cycle (full power)
61639 + * value == 128 -> 50% duty cycle (medium power)
61640 + * value == 0 -> 0% duty cycle (zero power)
61641 + */
61642 + spin_lock_irqsave(&vp->lock, flags);
61643 +
61644 + if (vp->has_pwm)
61645 + s3c2410_pwm_duty_cycle(value / 4, &vp->pwm);
61646 + else
61647 + neo1973_gpb_setpin(vp->gpio, value ? 1 : 0);
61648 +
61649 + spin_unlock_irqrestore(&vp->lock, flags);
61650 +}
61651 +
61652 +static struct neo1973_vib_priv neo1973_vib_led = {
61653 + .cdev = {
61654 + .name = "neo1973:vibrator",
61655 + .brightness_set = neo1973_vib_vib_set,
61656 + },
61657 +};
61658 +
61659 +static int neo1973_vib_init_hw(struct neo1973_vib_priv *vp)
61660 +{
61661 + int rc;
61662 +
61663 + rc = s3c2410_pwm_init(&vp->pwm);
61664 + if (rc)
61665 + return rc;
61666 +
61667 + vp->pwm.timerid = PWM3;
61668 + /* use same prescaler as arch/arm/plat-s3c24xx/time.c */
61669 + vp->pwm.prescaler = (6 - 1) / 2;
61670 + vp->pwm.divider = S3C2410_TCFG1_MUX3_DIV2;
61671 + vp->pwm.counter = COUNTER;
61672 + vp->pwm.comparer = COUNTER;
61673 +
61674 + rc = s3c2410_pwm_enable(&vp->pwm);
61675 + if (rc)
61676 + return rc;
61677 +
61678 + s3c2410_pwm_start(&vp->pwm);
61679 +
61680 + return 0;
61681 +}
61682 +
61683 +#ifdef CONFIG_PM
61684 +static int neo1973_vib_suspend(struct platform_device *dev, pm_message_t state)
61685 +{
61686 + led_classdev_suspend(&neo1973_vib_led.cdev);
61687 + if (neo1973_vib_priv.pdata)
61688 + neo1973_vib_priv.pdata->disable_fiq();
61689 + return 0;
61690 +}
61691 +
61692 +static int neo1973_vib_resume(struct platform_device *dev)
61693 +{
61694 + struct neo1973_vib_priv *vp = platform_get_drvdata(dev);
61695 +
61696 + if (vp->has_pwm)
61697 + neo1973_vib_init_hw(vp);
61698 +
61699 + led_classdev_resume(&neo1973_vib_led.cdev);
61700 + if (neo1973_vib_priv.pdata)
61701 + neo1973_vib_priv.pdata->enable_fiq();
61702 +
61703 + return 0;
61704 +}
61705 +#endif /* CONFIG_PM */
61706 +
61707 +static int __init neo1973_vib_probe(struct platform_device *pdev)
61708 +{
61709 + struct resource *r;
61710 + int rc;
61711 +
61712 + if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
61713 + return -EIO;
61714 +
61715 + r = platform_get_resource(pdev, 0, 0);
61716 + if (!r || !r->start)
61717 + return -EIO;
61718 +
61719 + neo1973_vib_led.gpio = r->start;
61720 +
61721 + neo1973_vib_priv.pdata = pdev->dev.platform_data;
61722 + platform_set_drvdata(pdev, &neo1973_vib_led);
61723 +
61724 +#ifdef CONFIG_MACH_NEO1973_GTA02
61725 + if (machine_is_neo1973_gta02()) { /* use FIQ to control GPIO */
61726 + neo1973_gpb_setpin(neo1973_vib_led.gpio, 0); /* off */
61727 + s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPIO_OUTPUT);
61728 + /* safe, kmalloc'd copy needed for FIQ ISR */
61729 + neo1973_vib_priv.vib_gpio_pin = neo1973_vib_led.gpio;
61730 + neo1973_vib_priv.vib_pwm = 0; /* off */
61731 + goto configured;
61732 + }
61733 +#endif
61734 +
61735 + /* TOUT3 */
61736 + if (neo1973_vib_led.gpio == S3C2410_GPB3) {
61737 + rc = neo1973_vib_init_hw(&neo1973_vib_led);
61738 + if (rc)
61739 + return rc;
61740 +
61741 + s3c2410_pwm_duty_cycle(0, &neo1973_vib_led.pwm);
61742 + s3c2410_gpio_cfgpin(neo1973_vib_led.gpio, S3C2410_GPB3_TOUT3);
61743 + neo1973_vib_led.has_pwm = 1;
61744 + }
61745 +#ifdef CONFIG_MACH_NEO1973_GTA02
61746 +configured:
61747 +#endif
61748 + spin_lock_init(&neo1973_vib_led.lock);
61749 +
61750 + return led_classdev_register(&pdev->dev, &neo1973_vib_led.cdev);
61751 +}
61752 +
61753 +static int neo1973_vib_remove(struct platform_device *pdev)
61754 +{
61755 +#ifdef CONFIG_MACH_NEO1973_GTA02
61756 + if (machine_is_neo1973_gta02()) /* use FIQ to control GPIO */
61757 + neo1973_vib_priv.vib_pwm = 0; /* off */
61758 + /* would only need kick if already off so no kick needed */
61759 +#endif
61760 +
61761 + if (neo1973_vib_led.has_pwm)
61762 + s3c2410_pwm_disable(&neo1973_vib_led.pwm);
61763 +
61764 + led_classdev_unregister(&neo1973_vib_led.cdev);
61765 +
61766 + return 0;
61767 +}
61768 +
61769 +static struct platform_driver neo1973_vib_driver = {
61770 + .probe = neo1973_vib_probe,
61771 + .remove = neo1973_vib_remove,
61772 +#ifdef CONFIG_PM
61773 + .suspend = neo1973_vib_suspend,
61774 + .resume = neo1973_vib_resume,
61775 +#endif
61776 + .driver = {
61777 + .name = "neo1973-vibrator",
61778 + },
61779 +};
61780 +
61781 +static int __init neo1973_vib_init(void)
61782 +{
61783 + return platform_driver_register(&neo1973_vib_driver);
61784 +}
61785 +
61786 +static void __exit neo1973_vib_exit(void)
61787 +{
61788 + platform_driver_unregister(&neo1973_vib_driver);
61789 +}
61790 +
61791 +module_init(neo1973_vib_init);
61792 +module_exit(neo1973_vib_exit);
61793 +
61794 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
61795 +MODULE_DESCRIPTION("Openmoko GTA01/GTA02 vibrator driver");
61796 +MODULE_LICENSE("GPL");
61797 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/leds/Makefile linux-2.6.29-rc3.owrt.om/drivers/leds/Makefile
61798 --- linux-2.6.29-rc3.owrt/drivers/leds/Makefile 2009-05-10 22:04:48.000000000 +0200
61799 +++ linux-2.6.29-rc3.owrt.om/drivers/leds/Makefile 2009-05-10 22:27:59.000000000 +0200
61800 @@ -24,11 +24,15 @@
61801 obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
61802 obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
61803 obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
61804 +obj-$(CONFIG_LEDS_NEO1973_VIBRATOR) += leds-neo1973-vibrator.o
61805 +obj-$(CONFIG_LEDS_NEO1973_GTA02) += leds-neo1973-gta02.o
61806 +obj-$(CONFIG_LEDS_LP5521) += leds-lp5521.o
61807
61808 # LED Triggers
61809 obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
61810 obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
61811 obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
61812 +obj-$(CONFIG_LEDS_TRIGGER_NETDEV) += ledtrig-netdev.o
61813 obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
61814 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
61815 obj-$(CONFIG_LEDS_TRIGGER_MORSE) += ledtrig-morse.o
61816 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/Makefile linux-2.6.29-rc3.owrt.om/drivers/Makefile
61817 --- linux-2.6.29-rc3.owrt/drivers/Makefile 2009-05-10 22:04:49.000000000 +0200
61818 +++ linux-2.6.29-rc3.owrt.om/drivers/Makefile 2009-05-10 22:27:59.000000000 +0200
61819 @@ -90,6 +90,7 @@
61820 obj-y += idle/
61821 obj-$(CONFIG_MMC) += mmc/
61822 obj-$(CONFIG_MEMSTICK) += memstick/
61823 +obj-$(CONFIG_AR6000_WLAN) += ar6000/
61824 obj-$(CONFIG_NEW_LEDS) += leds/
61825 obj-$(CONFIG_INFINIBAND) += infiniband/
61826 obj-$(CONFIG_SGI_SN) += sn/
61827 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/media/video/Kconfig linux-2.6.29-rc3.owrt.om/drivers/media/video/Kconfig
61828 --- linux-2.6.29-rc3.owrt/drivers/media/video/Kconfig 2009-05-10 22:04:49.000000000 +0200
61829 +++ linux-2.6.29-rc3.owrt.om/drivers/media/video/Kconfig 2009-05-10 22:27:59.000000000 +0200
61830 @@ -711,6 +711,25 @@
61831 CMOS camera controller. This is the controller found on first-
61832 generation OLPC systems.
61833
61834 +config VIDEO_SAMSUNG
61835 + bool "S3C SMDK CAMERA support"
61836 + depends on VIDEO_V4L2
61837 +
61838 + default n
61839 + ---help---
61840 + TBA
61841 +
61842 +choice
61843 +depends on VIDEO_SAMSUNG
61844 +prompt "Select CIS module type"
61845 +default VIDEO_SAMSUNG_S5K3BA
61846 +
61847 +config VIDEO_SAMSUNG_S5K4BA
61848 + bool "S5K4BA (2.0M CIS module, 1600x1200)"
61849 + ---help---
61850 + TBA
61851 +endchoice
61852 +
61853 config SOC_CAMERA
61854 tristate "SoC camera support"
61855 depends on VIDEO_V4L2 && HAS_DMA
61856 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/media/video/Makefile linux-2.6.29-rc3.owrt.om/drivers/media/video/Makefile
61857 --- linux-2.6.29-rc3.owrt/drivers/media/video/Makefile 2009-05-10 22:04:49.000000000 +0200
61858 +++ linux-2.6.29-rc3.owrt.om/drivers/media/video/Makefile 2009-05-10 22:27:59.000000000 +0200
61859 @@ -134,6 +134,8 @@
61860 obj-$(CONFIG_VIDEO_VIVI) += vivi.o
61861 obj-$(CONFIG_VIDEO_CX23885) += cx23885/
61862
61863 +obj-$(CONFIG_VIDEO_SAMSUNG) += s3c_camera_driver.o s3c_camif.o samsung/
61864 +
61865 obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o
61866 obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o
61867 obj-$(CONFIG_VIDEO_OMAP2) += omap2cam.o
61868 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/media/video/s3c_camera_driver.c linux-2.6.29-rc3.owrt.om/drivers/media/video/s3c_camera_driver.c
61869 --- linux-2.6.29-rc3.owrt/drivers/media/video/s3c_camera_driver.c 1970-01-01 01:00:00.000000000 +0100
61870 +++ linux-2.6.29-rc3.owrt.om/drivers/media/video/s3c_camera_driver.c 2009-05-10 22:27:59.000000000 +0200
61871 @@ -0,0 +1,1943 @@
61872 +/* drivers/media/video/s3c_camera_driver.c
61873 + *
61874 + * Copyright (c) 2008 Samsung Electronics
61875 + *
61876 + * Samsung S3C Camera driver
61877 + *
61878 + * This program is free software; you can redistribute it and/or modify
61879 + * it under the terms of the GNU General Public License as published by
61880 + * the Free Software Foundation; either version 2 of the License, or
61881 + * (at your option) any later version.
61882 + *
61883 + * This program is distributed in the hope that it will be useful,
61884 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
61885 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
61886 + * GNU General Public License for more details.
61887 + *
61888 + * You should have received a copy of the GNU General Public License
61889 + * along with this program; if not, write to the Free Software
61890 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
61891 + */
61892 +
61893 +#include <linux/version.h>
61894 +#include <linux/module.h>
61895 +#include <linux/delay.h>
61896 +#include <linux/errno.h>
61897 +#include <linux/fs.h>
61898 +#include <linux/kernel.h>
61899 +#include <linux/major.h>
61900 +#include <linux/slab.h>
61901 +#include <linux/poll.h>
61902 +#include <linux/signal.h>
61903 +#include <linux/ioport.h>
61904 +#include <linux/sched.h>
61905 +#include <linux/types.h>
61906 +#include <linux/interrupt.h>
61907 +#include <linux/kmod.h>
61908 +#include <linux/vmalloc.h>
61909 +#include <linux/init.h>
61910 +#include <linux/irq.h>
61911 +#include <linux/mm.h>
61912 +#include <linux/videodev2.h>
61913 +#include <linux/platform_device.h>
61914 +#include <linux/clk.h>
61915 +#include <linux/semaphore.h>
61916 +#include <asm/io.h>
61917 +#include <asm/page.h>
61918 +#include <plat/regs-gpio.h>
61919 +#include <plat/regs-camif.h>
61920 +#include <media/v4l2-dev.h>
61921 +#include <media/v4l2-ioctl.h>
61922 +#include "s3c_camif.h"
61923 +#include "videodev2_s3c.h"
61924 +
61925 +#include <linux/mfd/pcf50633/core.h> /* @@@ hack - WA */
61926 +#include <plat/gpio-bank-f.h>
61927 +#include <plat/gpio-cfg.h>
61928 +#include <mach/gpio.h>
61929 +#include <mach/map.h>
61930 +#include <plat/regs-sys.h>
61931 +#include <plat/regs-syscon-power.h>
61932 +
61933 +
61934 +static struct clk *cam_clock;
61935 +camif_cfg_t s3c_fimc[CAMIF_DEV_NUM];
61936 +extern camif_cis_t msdma_input;
61937 +extern int s3c_camif_do_postprocess(camif_cfg_t *cfg);
61938 +
61939 +/*************************************************************************
61940 + * Utility part
61941 + ************************************************************************/
61942 +camif_cfg_t *s3c_camif_get_fimc_object(int nr)
61943 +{
61944 + camif_cfg_t *ret = NULL;
61945 +
61946 + switch (nr) {
61947 + case CODEC_MINOR:
61948 + ret = &s3c_fimc[FIMC_CODEC_INDEX];
61949 + break;
61950 +
61951 + case PREVIEW_MINOR:
61952 + ret = &s3c_fimc[FIMC_PREVIEW_INDEX];
61953 + break;
61954 +
61955 + default:
61956 + printk(KERN_ERR "Unknown minor number\n");
61957 + ret = &s3c_fimc[FIMC_PREVIEW_INDEX];
61958 + }
61959 +
61960 + return ret;
61961 +}
61962 +
61963 +#if defined(FSM_ON_PREVIEW)
61964 +static int s3c_camif_check_global_status(camif_cfg_t *cfg)
61965 +{
61966 + int ret = 0;
61967 +
61968 + if (down_interruptible(&cfg->cis->lock))
61969 + return -ERESTARTSYS;
61970 +
61971 + if (cfg->cis->status & CWANT2START) {
61972 + cfg->cis->status &= ~CWANT2START;
61973 + cfg->auto_restart = 1;
61974 + ret = 1;
61975 + } else {
61976 + ret = 0; /* There is no codec */
61977 + cfg->auto_restart = 0; /* Duplicated ..Dummy */
61978 + }
61979 +
61980 + up(&cfg->cis->lock);
61981 +
61982 + return ret;
61983 +}
61984 +#endif
61985 +
61986 +static int s3c_camif_convert_format(int pixfmt, int *fmtptr)
61987 +{
61988 + int fmt = CAMIF_YCBCR420;
61989 + int depth = 12;
61990 +
61991 + switch (pixfmt) {
61992 + case V4L2_PIX_FMT_RGB565:
61993 + case V4L2_PIX_FMT_RGB565X:
61994 + fmt = CAMIF_RGB16;
61995 + depth = 16;
61996 + break;
61997 +
61998 + case V4L2_PIX_FMT_BGR24: /* Not tested */
61999 + case V4L2_PIX_FMT_RGB24:
62000 + fmt = CAMIF_RGB24;
62001 + depth = 24;
62002 + break;
62003 +
62004 + case V4L2_PIX_FMT_BGR32:
62005 + case V4L2_PIX_FMT_RGB32:
62006 + fmt = CAMIF_RGB24;
62007 + depth = 32;
62008 + break;
62009 +
62010 + case V4L2_PIX_FMT_GREY: /* Not tested */
62011 + fmt = CAMIF_YCBCR420;
62012 + depth = 8;
62013 + break;
62014 +
62015 + case V4L2_PIX_FMT_YUYV:
62016 + case V4L2_PIX_FMT_UYVY:
62017 + fmt = CAMIF_YCBCR422I;
62018 + depth = 16;
62019 + break;
62020 +
62021 + case V4L2_PIX_FMT_YUV422P:
62022 + fmt = CAMIF_YCBCR422;
62023 + depth = 16;
62024 + break;
62025 +
62026 + case V4L2_PIX_FMT_YUV420:
62027 + fmt = CAMIF_YCBCR420;
62028 + depth = 12;
62029 + break;
62030 + }
62031 +
62032 + if (fmtptr)
62033 + *fmtptr = fmt;
62034 +
62035 + return depth;
62036 +}
62037 +
62038 +static int s3c_camif_set_fb_info(camif_cfg_t *cfg, int depth, int fourcc)
62039 +{
62040 + /* To define v4l2_format used currently */
62041 + cfg->v2.frmbuf.fmt.width = cfg->target_x;
62042 + cfg->v2.frmbuf.fmt.height = cfg->target_y;
62043 + cfg->v2.frmbuf.fmt.field = V4L2_FIELD_NONE;
62044 + cfg->v2.frmbuf.fmt.pixelformat = fourcc;
62045 + cfg->v2.frmbuf.fmt.bytesperline = cfg->v2.frmbuf.fmt.width * depth >> 3;
62046 + cfg->v2.frmbuf.fmt.sizeimage =
62047 + cfg->v2.frmbuf.fmt.height * cfg->v2.frmbuf.fmt.bytesperline;
62048 +
62049 + return 0;
62050 +}
62051 +
62052 +static int s3c_camif_convert_type(camif_cfg_t *cfg, int f)
62053 +{
62054 + int pixfmt;
62055 +
62056 + cfg->target_x = cfg->v2.frmbuf.fmt.width;
62057 + cfg->target_y = cfg->v2.frmbuf.fmt.height;
62058 +
62059 + s3c_camif_convert_format(cfg->v2.frmbuf.fmt.pixelformat, &pixfmt);
62060 +
62061 + cfg->dst_fmt = pixfmt;
62062 +
62063 + return 0;
62064 +}
62065 +
62066 +/*************************************************************************
62067 + * Control part
62068 + ************************************************************************/
62069 +static int s3c_camif_start_capture(camif_cfg_t * cfg)
62070 +{
62071 + int ret = 0;
62072 +
62073 + cfg->capture_enable = CAMIF_DMA_ON;
62074 +
62075 + s3c_camif_start_dma(cfg);
62076 +
62077 + cfg->status = CAMIF_STARTED;
62078 +
62079 + if (!(cfg->fsm == CAMIF_SET_LAST_INT ||
62080 + cfg->fsm == CAMIF_CONTINUOUS_INT)) {
62081 + cfg->fsm = CAMIF_DUMMY_INT;
62082 + cfg->perf.frames = 0;
62083 + }
62084 +
62085 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
62086 + if (cfg->input_channel == MSDMA_FROM_CODEC)
62087 + s3c_camif_start_codec_msdma(cfg);
62088 +#endif
62089 + return ret;
62090 +}
62091 +
62092 +ssize_t s3c_camif_start_preview(camif_cfg_t *cfg)
62093 +{
62094 + cfg->capture_enable = CAMIF_DMA_ON;
62095 +
62096 + s3c_camif_start_dma(cfg);
62097 +
62098 + cfg->status = CAMIF_STARTED;
62099 + cfg->fsm = CAMIF_1st_INT;
62100 + cfg->perf.frames = 0;
62101 +
62102 + return 0;
62103 +}
62104 +
62105 +ssize_t s3c_camif_stop_preview(camif_cfg_t *cfg)
62106 +{
62107 + cfg->capture_enable = CAMIF_DMA_OFF;
62108 + cfg->status = CAMIF_STOPPED;
62109 +
62110 + s3c_camif_stop_dma(cfg);
62111 +
62112 + cfg->perf.frames = 0;
62113 +
62114 + return 0;
62115 +}
62116 +
62117 +ssize_t s3c_camif_stop_capture(camif_cfg_t *cfg)
62118 +{
62119 + cfg->capture_enable = CAMIF_DMA_OFF;
62120 + cfg->status = CAMIF_STOPPED;
62121 +
62122 + s3c_camif_stop_dma(cfg);
62123 +
62124 + cfg->perf.frames = 0;
62125 +
62126 + return 0;
62127 +}
62128 +
62129 +ssize_t s3c_camif_stop_fimc(camif_cfg_t *cfg)
62130 +{
62131 + cfg->capture_enable = CAMIF_BOTH_DMA_OFF;
62132 + cfg->fsm = CAMIF_DUMMY_INT;
62133 + cfg->perf.frames = 0;
62134 +
62135 + s3c_camif_stop_dma(cfg);
62136 +
62137 + return 0;
62138 +}
62139 +
62140 +#if defined(FSM_ON_PREVIEW)
62141 +static void s3c_camif_start_preview_with_codec(camif_cfg_t *cfg)
62142 +{
62143 + camif_cfg_t *other = cfg->other;
62144 +
62145 + /* Preview Stop */
62146 + cfg->capture_enable = CAMIF_DMA_OFF;
62147 + s3c_camif_stop_dma(cfg);
62148 +
62149 + /* Start Preview and CODEC */
62150 + cfg->capture_enable =CAMIF_BOTH_DMA_ON;
62151 +
62152 + s3c_camif_start_dma(cfg);
62153 + cfg->fsm = CAMIF_1st_INT; /* For Preview */
62154 +
62155 + if (!other)
62156 + panic("Unexpected error: other is null\n");
62157 +
62158 + switch (other->pp_num) {
62159 + case 4:
62160 + other->fsm = CAMIF_1st_INT; /* For CODEC */
62161 + break;
62162 +
62163 + case 1:
62164 + other->fsm = CAMIF_Yth_INT;
62165 + break;
62166 +
62167 + default:
62168 + panic("Invalid pingpong number");
62169 + break;
62170 + }
62171 +}
62172 +
62173 +static void s3c_camif_auto_restart(camif_cfg_t *cfg)
62174 +{
62175 + if (cfg->auto_restart)
62176 + s3c_camif_start_preview_with_codec(cfg);
62177 +}
62178 +#endif
62179 +
62180 +static void s3c_camif_change_mode(camif_cfg_t *cfg, int mode)
62181 +{
62182 + camif_cis_t *cis = cfg->cis;
62183 + int res;
62184 +
62185 + if (mode == SENSOR_MAX) {
62186 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K3AA)
62187 + res = SENSOR_SXGA;
62188 +#elif defined(CONFIG_VIDEO_SAMSUNG_S5K3BA)
62189 + res = SENSOR_UXGA;
62190 +
62191 +/* 4BA max is UXGA, but we don't have UXGA control values */
62192 +#elif defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
62193 + res = SENSOR_SVGA;
62194 +#endif
62195 + } else if (mode == SENSOR_DEFAULT) {
62196 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
62197 + res = SENSOR_SVGA;
62198 +#else
62199 + res = SENSOR_VGA;
62200 +#endif
62201 + } else
62202 + res = mode;
62203 +
62204 + s3c_camif_stop_fimc(cfg);
62205 +
62206 + switch (res) {
62207 + case SENSOR_SXGA:
62208 + printk(KERN_INFO
62209 + "Resolution changed into SXGA (1280x1024) mode -> 1.3M\n");
62210 + cis->sensor->driver->command(cis->sensor, SENSOR_SXGA, NULL);
62211 + cis->source_x = 1280;
62212 + cis->source_y = 1024;
62213 + break;
62214 +
62215 + case SENSOR_UXGA:
62216 + printk(KERN_INFO
62217 + "Resolution changed into UXGA (1600x1200) mode -> 2.0M\n");
62218 + cis->sensor->driver->command(cis->sensor, SENSOR_UXGA, NULL);
62219 + cis->source_x = 1600;
62220 + cis->source_y = 1200;
62221 + break;
62222 +
62223 + case SENSOR_SVGA:
62224 + printk(KERN_INFO
62225 + "Resolution changed back to SVGA (800x600) mode\n");
62226 + cis->sensor->driver->command(cis->sensor, SENSOR_SVGA, NULL);
62227 + cis->source_x = 800;
62228 + cis->source_y = 600;
62229 + break;
62230 +
62231 + case SENSOR_VGA:
62232 + printk(KERN_INFO "Resolution changed back to VGA (640x480) "
62233 + "mode (default)\n");
62234 + cis->sensor->driver->command(cis->sensor, SENSOR_VGA, NULL);
62235 + cis->source_x = 640;
62236 + cis->source_y = 480;
62237 + break;
62238 + }
62239 +
62240 + cis->win_hor_ofst = cis->win_hor_ofst2 = 0;
62241 + cis->win_ver_ofst = cis->win_ver_ofst2 = 0;
62242 +
62243 + s3c_camif_set_source_format(cis);
62244 +}
62245 +
62246 +static int s3c_camif_check_zoom_range(camif_cfg_t *cfg, int type)
62247 +{
62248 + switch (type) {
62249 + case V4L2_CID_ZOOMIN:
62250 + if (((cfg->sc.modified_src_x - (cfg->cis->win_hor_ofst +
62251 + ZOOM_AT_A_TIME_IN_PIXELS + cfg->cis->win_hor_ofst2 +
62252 + ZOOM_AT_A_TIME_IN_PIXELS)) / cfg->sc.prehratio) >
62253 + ZOOM_IN_MAX) {
62254 + printk(KERN_INFO "Invalid Zoom-in: this zoom-in on "
62255 + "preview scaler already comes to the maximum\n");
62256 + return 0;
62257 + }
62258 +
62259 + cfg->sc.zoom_in_cnt++;
62260 + break;
62261 +
62262 + case V4L2_CID_ZOOMOUT:
62263 + if (cfg->sc.zoom_in_cnt > 0) {
62264 + cfg->sc.zoom_in_cnt--;
62265 + } else {
62266 + printk(KERN_INFO "Invalid Zoom-out: this zoom-out on "
62267 + "preview scaler already comes to the minimum\n");
62268 + return 0;
62269 + }
62270 +
62271 + break;
62272 +
62273 + default:
62274 + break;
62275 + }
62276 +
62277 + return 1;
62278 +}
62279 +
62280 +static int s3c_camif_restart_preview(camif_cfg_t *cfg)
62281 +{
62282 + int ret = 0;
62283 +
62284 + s3c_camif_stop_preview(cfg);
62285 +
62286 + if (s3c_camif_control_fimc(cfg)) {
62287 + printk(KERN_ERR "S3C fimc control failed\n");
62288 + ret = -1;
62289 + }
62290 +
62291 + s3c_camif_start_preview(cfg);
62292 +
62293 + return ret;
62294 +}
62295 +
62296 +static int s3c_camif_send_sensor_command(camif_cfg_t *cfg, unsigned int cmd,
62297 + int arg)
62298 +{
62299 + cfg->cis->sensor->driver->command(cfg->cis->sensor, cmd, (void *) arg);
62300 +
62301 + return 0;
62302 +}
62303 +
62304 +/*************************************************************************
62305 + * V4L2 part
62306 + ************************************************************************/
62307 +static int s3c_camif_v4l2_querycap(camif_cfg_t *cfg, void *arg)
62308 +{
62309 + struct v4l2_capability *cap = arg;
62310 +
62311 + strcpy(cap->driver, "S3C FIMC Camera driver");
62312 + strlcpy(cap->card, cfg->v->name, sizeof(cap->card));
62313 + sprintf(cap->bus_info, "FIMC AHB Bus");
62314 +
62315 + cap->version = 0;
62316 + cap->capabilities = V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_CAPTURE |
62317 + V4L2_CAP_STREAMING;
62318 +
62319 + return 0;
62320 +}
62321 +
62322 +static int s3c_camif_v4l2_g_fbuf(camif_cfg_t *cfg, void *arg)
62323 +{
62324 + struct v4l2_framebuffer *fb = arg;
62325 +
62326 + *fb = cfg->v2.frmbuf;
62327 +
62328 + fb->base = cfg->v2.frmbuf.base;
62329 + fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
62330 +
62331 + fb->fmt.pixelformat = cfg->v2.frmbuf.fmt.pixelformat;
62332 + fb->fmt.width = cfg->v2.frmbuf.fmt.width;
62333 + fb->fmt.height = cfg->v2.frmbuf.fmt.height;
62334 + fb->fmt.bytesperline = cfg->v2.frmbuf.fmt.bytesperline;
62335 +
62336 + return 0;
62337 +}
62338 +
62339 +static int s3c_camif_v4l2_s_fbuf(camif_cfg_t *cfg, void *arg)
62340 +{
62341 + struct v4l2_framebuffer *fb = arg;
62342 + int i, depth;
62343 +
62344 + for (i = 0; i < NUMBER_OF_PREVIEW_FORMATS; i++)
62345 + if (fimc_preview_formats[i].pixelformat == fb->fmt.pixelformat)
62346 + break;
62347 +
62348 + if (i == NUMBER_OF_PREVIEW_FORMATS)
62349 + return -EINVAL;
62350 +
62351 + cfg->v2.frmbuf.base = fb->base;
62352 + cfg->v2.frmbuf.flags = fb->flags;
62353 + cfg->v2.frmbuf.capability = fb->capability;
62354 +
62355 + cfg->target_x = fb->fmt.width;
62356 + cfg->target_y = fb->fmt.height;
62357 +
62358 + depth = s3c_camif_convert_format(fb->fmt.pixelformat,
62359 + (int *) &cfg->dst_fmt);
62360 + s3c_camif_set_fb_info(cfg, depth, fb->fmt.pixelformat);
62361 +
62362 + return s3c_camif_control_fimc(cfg);
62363 +}
62364 +
62365 +static int s3c_camif_v4l2_g_fmt(camif_cfg_t *cfg, void *arg)
62366 +{
62367 + struct v4l2_format *f = arg;
62368 + int size = sizeof(struct v4l2_pix_format);
62369 + int ret = -1;
62370 +
62371 + switch (f->type) {
62372 + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
62373 + memset(&f->fmt.pix, 0, size);
62374 + memcpy(&f->fmt.pix, &cfg->v2.frmbuf.fmt, size);
62375 + ret = 0;
62376 + break;
62377 +
62378 + default:
62379 + break;
62380 + }
62381 +
62382 + return ret;
62383 +}
62384 +
62385 +static int s3c_camif_v4l2_s_fmt(camif_cfg_t *cfg, void *arg)
62386 +{
62387 + struct v4l2_format *f = arg;
62388 + int ret = -1;
62389 +
62390 + switch (f->type) {
62391 + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
62392 + cfg->v2.frmbuf.fmt = f->fmt.pix;
62393 + cfg->v2.status |= CAMIF_v4L2_DIRTY;
62394 + cfg->v2.status &= ~CAMIF_v4L2_DIRTY; /* dummy ? */
62395 +
62396 + s3c_camif_convert_type(cfg, 1);
62397 + s3c_camif_control_fimc(cfg);
62398 + ret = 0;
62399 + break;
62400 +
62401 + default:
62402 + break;
62403 + }
62404 +
62405 + return ret;
62406 +}
62407 +
62408 +static int s3c_camif_v4l2_enum_fmt(camif_cfg_t *cfg, void *arg)
62409 +{
62410 + struct v4l2_fmtdesc *f = arg;
62411 + int index = f->index;
62412 +
62413 + if (index >= NUMBER_OF_CODEC_FORMATS)
62414 + return -EINVAL;
62415 +
62416 + switch (f->type) {
62417 + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
62418 + break;
62419 +
62420 + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
62421 + default:
62422 + return -EINVAL;
62423 + }
62424 +
62425 + memset(f, 0, sizeof(*f));
62426 + memcpy(f, cfg->v2.fmtdesc + index, sizeof(*f));
62427 +
62428 + return 0;
62429 +}
62430 +
62431 +static int s3c_camif_v4l2_overlay(camif_cfg_t *cfg, void *arg)
62432 +{
62433 + int on = *(int *) arg;
62434 +
62435 + if (on)
62436 + return s3c_camif_start_preview(cfg);
62437 + else
62438 + return s3c_camif_stop_preview(cfg);
62439 +}
62440 +
62441 +static int s3c_camif_v4l2_g_ctrl(camif_cfg_t *cfg, void *arg)
62442 +{
62443 + return 0;
62444 +}
62445 +
62446 +static int s3c_camif_v4l2_s_ctrl(camif_cfg_t *cfg, void *arg)
62447 +{
62448 + struct v4l2_control *ctrl = arg;
62449 +
62450 + switch (ctrl->id) {
62451 + case V4L2_CID_ORIGINAL:
62452 + case V4L2_CID_ARBITRARY:
62453 + case V4L2_CID_NEGATIVE:
62454 + case V4L2_CID_EMBOSSING:
62455 + case V4L2_CID_ART_FREEZE:
62456 + case V4L2_CID_SILHOUETTE:
62457 + cfg->effect = ctrl->value;
62458 + s3c_camif_change_effect(cfg);
62459 + break;
62460 +
62461 + case V4L2_CID_HFLIP:
62462 + cfg->flip = CAMIF_FLIP_X;
62463 + s3c_camif_change_flip(cfg);
62464 + break;
62465 +
62466 + case V4L2_CID_VFLIP:
62467 + cfg->flip = CAMIF_FLIP_Y;
62468 + s3c_camif_change_flip(cfg);
62469 + break;
62470 +
62471 + case V4L2_CID_ROTATE_180:
62472 + cfg->flip = CAMIF_FLIP_MIRROR;
62473 + s3c_camif_change_flip(cfg);
62474 + break;
62475 +
62476 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
62477 + case V4L2_CID_ROTATE_90:
62478 + cfg->flip = CAMIF_ROTATE_90;
62479 + s3c_camif_change_flip(cfg);
62480 + break;
62481 +
62482 + case V4L2_CID_ROTATE_270:
62483 + cfg->flip = CAMIF_FLIP_ROTATE_270;
62484 + s3c_camif_change_flip(cfg);
62485 + break;
62486 +#endif
62487 +
62488 + case V4L2_CID_ROTATE_BYPASS:
62489 + cfg->flip = CAMIF_FLIP;
62490 + s3c_camif_change_flip(cfg);
62491 + break;
62492 +
62493 + case V4L2_CID_ZOOMIN:
62494 + if (!s3c_camif_check_zoom_range(cfg, ctrl->id))
62495 + break;
62496 + cfg->cis->win_hor_ofst += ZOOM_AT_A_TIME_IN_PIXELS;
62497 + cfg->cis->win_ver_ofst += ZOOM_AT_A_TIME_IN_PIXELS;
62498 + cfg->cis->win_hor_ofst2 += ZOOM_AT_A_TIME_IN_PIXELS;
62499 + cfg->cis->win_ver_ofst2 += ZOOM_AT_A_TIME_IN_PIXELS;
62500 +
62501 + s3c_camif_restart_preview(cfg);
62502 +
62503 + break;
62504 +
62505 + case V4L2_CID_ZOOMOUT:
62506 + if (!s3c_camif_check_zoom_range(cfg, ctrl->id))
62507 + break;
62508 + cfg->cis->win_hor_ofst -= ZOOM_AT_A_TIME_IN_PIXELS;
62509 + cfg->cis->win_ver_ofst -= ZOOM_AT_A_TIME_IN_PIXELS;
62510 + cfg->cis->win_hor_ofst2 -= ZOOM_AT_A_TIME_IN_PIXELS;
62511 + cfg->cis->win_ver_ofst2 -= ZOOM_AT_A_TIME_IN_PIXELS;
62512 +
62513 + s3c_camif_restart_preview(cfg);
62514 +
62515 + break;
62516 +
62517 + case V4L2_CID_CONTRAST:
62518 + case V4L2_CID_AUTO_WHITE_BALANCE:
62519 + s3c_camif_send_sensor_command(cfg, SENSOR_WB,
62520 + ctrl->value);
62521 + break;
62522 +
62523 + default:
62524 + printk(KERN_ERR "Invalid control id: %d\n", ctrl->id);
62525 + return -1;
62526 + }
62527 +
62528 + return 0;
62529 +}
62530 +
62531 +static int s3c_camif_v4l2_streamon(camif_cfg_t *cfg, void *arg)
62532 +{
62533 + return s3c_camif_start_capture(cfg);
62534 +}
62535 +
62536 +static int s3c_camif_v4l2_streamoff(camif_cfg_t *cfg, void *arg)
62537 +{
62538 + cfg->cis->status &= ~C_WORKING;
62539 +
62540 + s3c_camif_stop_capture(cfg);
62541 +
62542 + return 0;
62543 +}
62544 +
62545 +static int s3c_camif_v4l2_g_input(camif_cfg_t *cfg, void *arg)
62546 +{
62547 + unsigned int *index = arg;
62548 +
62549 + *index = cfg->v2.input->index;
62550 +
62551 + return 0;
62552 +}
62553 +
62554 +static int s3c_camif_v4l2_s_input(camif_cfg_t *cfg, unsigned int index)
62555 +{
62556 + int ret = -1;
62557 +
62558 + if (index >= NUMBER_OF_INPUTS)
62559 + ret = -1;
62560 + else {
62561 + cfg->v2.input = &fimc_inputs[index];
62562 +
62563 + if (cfg->v2.input->type == V4L2_INPUT_TYPE_MSDMA) {
62564 + if (cfg->dma_type & CAMIF_PREVIEW) {
62565 + cfg->input_channel = MSDMA_FROM_PREVIEW;
62566 + ret = 0;
62567 + } else if (cfg->dma_type & CAMIF_CODEC) {
62568 + cfg->input_channel = MSDMA_FROM_CODEC;
62569 + ret = 0;
62570 + }
62571 + } else {
62572 + cfg->input_channel = CAMERA_INPUT;
62573 + ret = 0;
62574 + }
62575 + }
62576 +
62577 + return ret;
62578 +}
62579 +
62580 +static int s3c_camif_v4l2_g_output(camif_cfg_t *cfg, void *arg)
62581 +{
62582 + unsigned int *index = arg;
62583 +
62584 + *index = cfg->v2.output->index;
62585 +
62586 + return 0;
62587 +}
62588 +
62589 +static int s3c_camif_v4l2_s_output(camif_cfg_t *cfg, unsigned int index)
62590 +{
62591 + if (index >= NUMBER_OF_OUTPUTS)
62592 + return -EINVAL;
62593 + else {
62594 + cfg->v2.output = (struct v4l2_output *) &fimc_outputs[index];
62595 + return 0;
62596 + }
62597 +}
62598 +
62599 +static int s3c_camif_v4l2_enum_input(camif_cfg_t *cfg, void *arg)
62600 +{
62601 + struct v4l2_input *i = arg;
62602 +
62603 + if (i->index >= NUMBER_OF_INPUTS)
62604 + return -EINVAL;
62605 +
62606 + memcpy(i, &fimc_inputs[i->index], sizeof(struct v4l2_input));
62607 +
62608 + return 0;
62609 +}
62610 +
62611 +static int s3c_camif_v4l2_enum_output(camif_cfg_t *cfg, void *arg)
62612 +{
62613 + struct v4l2_output *i = arg;
62614 +
62615 + if (i->index >= NUMBER_OF_OUTPUTS)
62616 + return -EINVAL;
62617 +
62618 + memcpy(i, &fimc_outputs[i->index], sizeof(struct v4l2_output));
62619 +
62620 + return 0;
62621 +}
62622 +
62623 +static int s3c_camif_v4l2_reqbufs(camif_cfg_t *cfg, void *arg)
62624 +{
62625 + struct v4l2_requestbuffers *req = arg;
62626 +
62627 + if (req->memory != V4L2_MEMORY_MMAP) {
62628 + printk(KERN_ERR "Only V4L2_MEMORY_MMAP capture is supported\n");
62629 + return -EINVAL;
62630 + }
62631 +
62632 + /* control user input */
62633 + if (req->count > 2)
62634 + req->count = 4;
62635 + else if (req->count > 1)
62636 + req->count = 2;
62637 + else
62638 + req->count = 1;
62639 +
62640 + return 0;
62641 +}
62642 +
62643 +static int s3c_camif_v4l2_querybuf(camif_cfg_t *cfg, void *arg)
62644 +{
62645 + struct v4l2_buffer *buf = arg;
62646 +
62647 + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
62648 + buf->memory != V4L2_MEMORY_MMAP)
62649 + return -1;
62650 +
62651 + buf->length = cfg->buffer_size;
62652 + buf->m.offset = buf->length * buf->index;
62653 +
62654 + return 0;
62655 +}
62656 +
62657 +static int s3c_camif_v4l2_qbuf(camif_cfg_t *cfg, void *arg)
62658 +{
62659 + return 0;
62660 +}
62661 +
62662 +static int s3c_camif_v4l2_dqbuf(camif_cfg_t *cfg, void *arg)
62663 +{
62664 + struct v4l2_buffer *buf = arg;
62665 +
62666 + buf->index = cfg->cur_frame_num % cfg->pp_num;
62667 +
62668 + return 0;
62669 +}
62670 +
62671 +/*
62672 + * S3C specific
62673 + */
62674 +static int s3c_camif_v4l2_s_msdma(camif_cfg_t *cfg, void *arg)
62675 +{
62676 + struct v4l2_msdma_format *f = arg;
62677 + int ret;
62678 +
62679 + switch(f->input_path) {
62680 + case V4L2_MSDMA_PREVIEW:
62681 + cfg->cis->user--;
62682 + /* CIS will be replaced with a CIS for MSDMA */
62683 +
62684 + cfg->cis = &msdma_input;
62685 + cfg->cis->user++;
62686 + cfg->input_channel = MSDMA_FROM_PREVIEW;
62687 + break;
62688 +
62689 + case V4L2_MSDMA_CODEC:
62690 + cfg->cis->user--;
62691 + /* CIS will be replaced with a CIS for MSDMA */
62692 +
62693 + cfg->cis = &msdma_input;
62694 + cfg->cis->user++;
62695 + cfg->input_channel = MSDMA_FROM_CODEC;
62696 + break;
62697 +
62698 + default:
62699 + cfg->input_channel = CAMERA_INPUT;
62700 + break;
62701 + }
62702 +
62703 + cfg->cis->source_x = f->width;
62704 + cfg->cis->source_y = f->height;
62705 +
62706 + s3c_camif_convert_format(f->pixelformat, (int *) &cfg->src_fmt);
62707 +
62708 + cfg->cis->win_hor_ofst = 0;
62709 + cfg->cis->win_ver_ofst = 0;
62710 + cfg->cis->win_hor_ofst2 = 0;
62711 + cfg->cis->win_ver_ofst2 = 0;
62712 +
62713 + ret = s3c_camif_control_fimc(cfg);
62714 +
62715 + switch(f->input_path) {
62716 + case V4L2_MSDMA_PREVIEW:
62717 + ret = s3c_camif_start_preview(cfg);
62718 + break;
62719 +
62720 + case V4L2_MSDMA_CODEC:
62721 + ret = s3c_camif_start_capture(cfg);
62722 + break;
62723 +
62724 + default:
62725 + break;
62726 +
62727 + }
62728 +
62729 + return ret;
62730 +}
62731 +
62732 +static int s3c_camif_v4l2_msdma_start(camif_cfg_t *cfg, void *arg)
62733 +{
62734 + if (cfg->input_channel == MSDMA_FROM_PREVIEW) {
62735 + cfg->msdma_status = 1;
62736 + s3c_camif_start_preview_msdma(cfg);
62737 + }
62738 +
62739 + return 0;
62740 +}
62741 +
62742 +static int s3c_camif_v4l2_msdma_stop(camif_cfg_t *cfg, void *arg)
62743 +{
62744 + struct v4l2_msdma_format *f = arg;
62745 + int ret = -1;
62746 +
62747 + cfg->cis->status &= ~C_WORKING;
62748 + cfg->msdma_status = 0;
62749 +
62750 + switch(f->input_path) {
62751 + case V4L2_MSDMA_PREVIEW:
62752 + ret = s3c_camif_stop_preview(cfg);
62753 + break;
62754 +
62755 + case V4L2_MSDMA_CODEC:
62756 + ret = s3c_camif_stop_capture(cfg);
62757 + break;
62758 +
62759 + default:
62760 + break;
62761 + }
62762 +
62763 + return ret;
62764 +}
62765 +
62766 +static int s3c_camif_v4l2_camera_start(camif_cfg_t *cfg, void *arg)
62767 +{
62768 + return 0;
62769 +}
62770 +
62771 +static int s3c_camif_v4l2_camera_stop(camif_cfg_t *cfg, void *arg)
62772 +{
62773 + return 0;
62774 +}
62775 +
62776 +static int s3c_camif_v4l2_cropcap(camif_cfg_t *cfg, void *arg)
62777 +{
62778 + struct v4l2_cropcap *cap = arg;
62779 +
62780 + if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
62781 + cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
62782 + return -EINVAL;
62783 +
62784 + /* crop limitations */
62785 + cfg->v2.crop_bounds.left = 0;
62786 + cfg->v2.crop_bounds.top = 0;
62787 + cfg->v2.crop_bounds.width = cfg->cis->source_x;
62788 + cfg->v2.crop_bounds.height = cfg->cis->source_y;
62789 +
62790 + /* crop default values */
62791 + cfg->v2.crop_defrect.left =
62792 + (cfg->cis->source_x - CROP_DEFAULT_WIDTH) / 2;
62793 + cfg->v2.crop_defrect.top =
62794 + (cfg->cis->source_y - CROP_DEFAULT_HEIGHT) / 2;
62795 + cfg->v2.crop_defrect.width = CROP_DEFAULT_WIDTH;
62796 + cfg->v2.crop_defrect.height = CROP_DEFAULT_HEIGHT;
62797 +
62798 + cap->bounds = cfg->v2.crop_bounds;
62799 + cap->defrect = cfg->v2.crop_defrect;
62800 +
62801 + return 0;
62802 +}
62803 +
62804 +static int s3c_camif_v4l2_g_crop(camif_cfg_t *cfg, void *arg)
62805 +{
62806 + struct v4l2_crop *crop = arg;
62807 +
62808 + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
62809 + crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
62810 + return -EINVAL;
62811 +
62812 + crop->c = cfg->v2.crop_current;
62813 +
62814 + return 0;
62815 +}
62816 +
62817 +static int s3c_camif_v4l2_s_crop(camif_cfg_t *cfg, void *arg)
62818 +{
62819 + struct v4l2_crop *crop = arg;
62820 +
62821 + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
62822 + crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
62823 + return -EINVAL;
62824 +
62825 + if (crop->c.height < 0)
62826 + return -EINVAL;
62827 +
62828 + if (crop->c.width < 0)
62829 + return -EINVAL;
62830 +
62831 + if ((crop->c.left + crop->c.width > cfg->cis->source_x) ||
62832 + (crop->c.top + crop->c.height > cfg->cis->source_y))
62833 + return -EINVAL;
62834 +
62835 + cfg->v2.crop_current = crop->c;
62836 +
62837 + cfg->cis->win_hor_ofst = (cfg->cis->source_x - crop->c.width) / 2;
62838 + cfg->cis->win_ver_ofst = (cfg->cis->source_y - crop->c.height) / 2;
62839 +
62840 + cfg->cis->win_hor_ofst2 = cfg->cis->win_hor_ofst;
62841 + cfg->cis->win_ver_ofst2 = cfg->cis->win_ver_ofst;
62842 +
62843 + s3c_camif_restart_preview(cfg);
62844 +
62845 + return 0;
62846 +}
62847 +
62848 +static int s3c_camif_v4l2_s_parm(camif_cfg_t *cfg, void *arg)
62849 +{
62850 + struct v4l2_streamparm *sp = arg;
62851 +
62852 + if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
62853 + return -EINVAL;
62854 +
62855 + if (sp->parm.capture.capturemode == V4L2_MODE_HIGHQUALITY) {
62856 + s3c_camif_change_mode(cfg, SENSOR_MAX);
62857 + s3c_camif_control_fimc(cfg);
62858 + } else {
62859 + s3c_camif_change_mode(cfg, SENSOR_DEFAULT);
62860 + s3c_camif_control_fimc(cfg);
62861 + }
62862 +
62863 + return 0;
62864 +}
62865 +
62866 +/*************************************************************************
62867 + * Interrupt part
62868 + ************************************************************************/
62869 +#if defined(FSM_ON_CODEC) && !defined(USE_LAST_IRQ)
62870 +int s3c_camif_do_fsm_codec(camif_cfg_t *cfg)
62871 +{
62872 + cfg->perf.frames++;
62873 +
62874 + if (cfg->fsm == CAMIF_DUMMY_INT &&
62875 + cfg->perf.frames > CAMIF_CAPTURE_SKIP_FRAMES)
62876 + cfg->fsm = CAMIF_NORMAL_INT;
62877 +
62878 + switch (cfg->fsm) {
62879 + case CAMIF_DUMMY_INT:
62880 + DPRINTK(KERN_INFO "CAMIF_DUMMY_INT: %d\n", cfg->perf.frames);
62881 + cfg->status = CAMIF_STARTED;
62882 + cfg->fsm = CAMIF_DUMMY_INT;
62883 + return INSTANT_SKIP;
62884 +
62885 + case CAMIF_NORMAL_INT:
62886 + DPRINTK(KERN_INFO "CAMIF_NORMAL_INT: %d\n", cfg->perf.frames);
62887 + cfg->status = CAMIF_INT_HAPPEN;
62888 + cfg->fsm = CAMIF_CONTINUOUS_INT;
62889 + return INSTANT_GO;
62890 +
62891 + case CAMIF_CONTINUOUS_INT:
62892 + DPRINTK(KERN_INFO "CAMIF_CONTINUOS_INT: %d\n",
62893 + cfg->perf.frames);
62894 + cfg->status = CAMIF_INT_HAPPEN;
62895 + cfg->fsm = CAMIF_CONTINUOUS_INT;
62896 + return INSTANT_GO;
62897 +
62898 + default:
62899 + printk(KERN_INFO "Unexpect INT: %d\n", cfg->fsm);
62900 + return INSTANT_SKIP;
62901 + }
62902 +}
62903 +#endif
62904 +
62905 +#if defined(FSM_ON_CODEC) && defined(USE_LAST_IRQ)
62906 +int s3c_camif_do_fsm_codec_lastirq(camif_cfg_t *cfg)
62907 +{
62908 + cfg->perf.frames++;
62909 +
62910 + if (cfg->fsm == CAMIF_DUMMY_INT &&
62911 + cfg->perf.frames > CAMIF_CAPTURE_SKIP_FRAMES - 2)
62912 + cfg->fsm = CAMIF_SET_LAST_INT;
62913 +
62914 + switch (cfg->fsm) {
62915 + case CAMIF_DUMMY_INT:
62916 + DPRINTK(KERN_INFO "CAMIF_DUMMY_INT: %d\n", cfg->perf.frames);
62917 + cfg->status = CAMIF_STARTED;
62918 + cfg->fsm = CAMIF_DUMMY_INT;
62919 + return INSTANT_SKIP;
62920 +
62921 + case CAMIF_SET_LAST_INT:
62922 + DPRINTK(KERN_INFO "CAMIF_SET_LAST_INT: %d\n", cfg->perf.frames);
62923 + s3c_camif_enable_lastirq(cfg);
62924 +
62925 +/* in 64xx, lastirq is not auto cleared. */
62926 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
62927 + s3c_camif_disable_lastirq(cfg);
62928 +#endif
62929 + cfg->status = CAMIF_INT_HAPPEN;
62930 + cfg->fsm = CAMIF_STOP_CAPTURE;
62931 + return INSTANT_SKIP;
62932 +
62933 + case CAMIF_STOP_CAPTURE:
62934 + DPRINTK(KERN_INFO "CAMIF_STOP_CAPTURE: %d\n", cfg->perf.frames);
62935 + cfg->capture_enable = CAMIF_DMA_OFF;
62936 + s3c_camif_stop_dma(cfg);
62937 + cfg->fsm = CAMIF_LAST_IRQ;
62938 + return INSTANT_SKIP;
62939 +
62940 + case CAMIF_LAST_IRQ:
62941 + DPRINTK(KERN_INFO "CAMIF_LAST_IRQ: %d\n", cfg->perf.frames);
62942 + cfg->fsm = CAMIF_SET_LAST_INT;
62943 + cfg->status = CAMIF_INT_HAPPEN;
62944 + return INSTANT_GO;
62945 +
62946 + default:
62947 + printk(KERN_INFO "Unexpect INT: %d\n", cfg->fsm);
62948 + return = INSTANT_SKIP;
62949 + }
62950 +}
62951 +#endif
62952 +
62953 +#if defined(FSM_ON_PREVIEW)
62954 +static int s3c_camif_do_lastirq_preview(camif_cfg_t *cfg)
62955 +{
62956 + cfg->perf.frames++;
62957 +
62958 + if (cfg->fsm == CAMIF_NORMAL_INT)
62959 + if (cfg->perf.frames % CHECK_FREQ == 0)
62960 + if (s3c_camif_check_global_status(cfg) > 0)
62961 + cfg->fsm = CAMIF_Xth_INT;
62962 +
62963 + switch (cfg->fsm) {
62964 + case CAMIF_1st_INT:
62965 + DPRINTK(KERN_INFO "CAMIF_1st_INT INT\n");
62966 + cfg->fsm = CAMIF_NORMAL_INT;
62967 + return INSTANT_SKIP;
62968 +
62969 + case CAMIF_NORMAL_INT:
62970 + DPRINTK(KERN_INFO "CAMIF_NORMAL_INT\n");
62971 + cfg->status = CAMIF_INT_HAPPEN;
62972 + cfg->fsm = CAMIF_NORMAL_INT;
62973 + return INSTANT_GO;
62974 +
62975 + case CAMIF_Xth_INT:
62976 + DPRINTK(KERN_INFO "CAMIF_Xth_INT\n");
62977 + s3c_camif_enable_lastirq(cfg);
62978 + cfg->status = CAMIF_INT_HAPPEN;
62979 + cfg->fsm = CAMIF_Yth_INT;
62980 + return INSTANT_GO;
62981 +
62982 + case CAMIF_Yth_INT:
62983 + DPRINTK(KERN_INFO "CAMIF_Yth_INT\n");
62984 + s3c_camif_disable_lastirq(cfg);
62985 + cfg->capture_enable = CAMIF_DMA_OFF;
62986 + cfg->status = CAMIF_INT_HAPPEN;
62987 + s3c_camif_stop_dma(cfg);
62988 + cfg->fsm = CAMIF_Zth_INT;
62989 + return INSTANT_GO;
62990 +
62991 + case CAMIF_Zth_INT:
62992 + DPRINTK(KERN_INFO "CAMIF_Zth_INT\n");
62993 + cfg->fsm = CAMIF_DUMMY_INT;
62994 + cfg->status = CAMIF_INT_HAPPEN;
62995 + s3c_camif_auto_restart(cfg);
62996 + return INSTANT_GO;
62997 +
62998 + case CAMIF_DUMMY_INT:
62999 + DPRINTK(KERN_INFO "CAMIF_DUMMY_INT\n");
63000 + cfg->status = CAMIF_STOPPED;
63001 + return INSTANT_SKIP;
63002 +
63003 + default:
63004 + printk(KERN_INFO "Unexpected INT %d\n", cfg->fsm);
63005 + return INSTANT_SKIP;
63006 + }
63007 +}
63008 +#endif
63009 +
63010 +static irqreturn_t s3c_camif_do_irq_codec(int irq, void *dev_id)
63011 +{
63012 + camif_cfg_t *cfg = (camif_cfg_t *) dev_id;
63013 +
63014 +/* @@@ SMKD ? - WA */
63015 +#if 0 && (defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410))
63016 + s3c_gpio_setpin(S3C_GPN15, 1);
63017 +#endif
63018 + s3c_camif_clear_irq(irq);
63019 + s3c_camif_get_fifo_status(cfg);
63020 + s3c_camif_get_frame_num(cfg);
63021 +
63022 +#if defined(FSM_ON_CODEC) && !defined(USE_LAST_IRQ)
63023 + if (s3c_camif_do_fsm_codec(cfg) == INSTANT_SKIP)
63024 + return IRQ_HANDLED;
63025 +#endif
63026 +
63027 +#if defined(FSM_ON_CODEC) && defined(USE_LAST_IRQ)
63028 + if (s3c_camif_do_fsm_codec_lastirq(cfg) == INSTANT_SKIP)
63029 + return IRQ_HANDLED;
63030 +#endif
63031 + wake_up_interruptible(&cfg->waitq);
63032 +
63033 + return IRQ_HANDLED;
63034 +}
63035 +
63036 +static irqreturn_t s3c_camif_do_irq_preview(int irq, void *dev_id)
63037 +{
63038 + camif_cfg_t *cfg = (camif_cfg_t *) dev_id;
63039 +
63040 + s3c_camif_clear_irq(irq);
63041 + s3c_camif_get_fifo_status(cfg);
63042 + s3c_camif_get_frame_num(cfg);
63043 + wake_up_interruptible(&cfg->waitq);
63044 +
63045 +#if defined(FSM_ON_PREVIEW)
63046 + if (s3c_camif_do_lastirq_preview(cfg) == INSTANT_SKIP)
63047 + return IRQ_HANDLED;
63048 +
63049 + wake_up_interruptible(&cfg->waitq);
63050 +#endif
63051 + cfg->status = CAMIF_INT_HAPPEN;
63052 +
63053 + return IRQ_HANDLED;
63054 +}
63055 +
63056 +static void s3c_camif_release_irq(camif_cfg_t * cfg)
63057 +{
63058 + disable_irq(cfg->irq);
63059 + free_irq(cfg->irq, cfg);
63060 +}
63061 +
63062 +static int s3c_camif_request_irq(camif_cfg_t * cfg)
63063 +{
63064 + int ret;
63065 +
63066 + if (cfg->dma_type & CAMIF_CODEC) {
63067 + ret = request_irq(cfg->irq, s3c_camif_do_irq_codec,
63068 + IRQF_SHARED, cfg->shortname, cfg);
63069 + if (ret)
63070 + printk(KERN_ERR "Request irq (CAM_C) failed\n");
63071 + else
63072 + printk(KERN_INFO "Request irq %d for codec\n",
63073 + cfg->irq);
63074 + }
63075 +
63076 + if (cfg->dma_type & CAMIF_PREVIEW) {
63077 + ret = request_irq(cfg->irq, s3c_camif_do_irq_preview,
63078 + IRQF_SHARED, cfg->shortname, cfg);
63079 + if (ret)
63080 + printk("Request_irq (CAM_P) failed\n");
63081 + else
63082 + printk(KERN_INFO "Request irq %d for preview\n",
63083 + cfg->irq);
63084 + }
63085 +
63086 + return 0;
63087 +}
63088 +
63089 +/*************************************************************************
63090 + * Standard file operations part
63091 + ************************************************************************/
63092 +long s3c_camif_ioctl(struct file *file, unsigned int cmd, unsigned long _arg)
63093 +{
63094 + camif_cfg_t *cfg = file->private_data;
63095 + void *arg = (void *) _arg; /* @@@ - WA */
63096 +
63097 + switch (cmd) {
63098 + case VIDIOC_QUERYCAP:
63099 + return s3c_camif_v4l2_querycap(cfg, arg);
63100 +
63101 + case VIDIOC_G_FBUF:
63102 + return s3c_camif_v4l2_g_fbuf(cfg, arg);
63103 +
63104 + case VIDIOC_S_FBUF:
63105 + return s3c_camif_v4l2_s_fbuf(cfg, arg);
63106 +
63107 + case VIDIOC_G_FMT:
63108 + return s3c_camif_v4l2_g_fmt(cfg, arg);
63109 +
63110 + case VIDIOC_S_FMT:
63111 + return s3c_camif_v4l2_s_fmt(cfg, arg);
63112 +
63113 + case VIDIOC_ENUM_FMT:
63114 + return s3c_camif_v4l2_enum_fmt(cfg, arg);
63115 +
63116 + case VIDIOC_OVERLAY:
63117 + return s3c_camif_v4l2_overlay(cfg, arg);
63118 +
63119 + case VIDIOC_S_CTRL:
63120 + return s3c_camif_v4l2_s_ctrl(cfg, arg);
63121 +
63122 + case VIDIOC_G_CTRL:
63123 + return s3c_camif_v4l2_g_ctrl(cfg, arg);
63124 +
63125 + case VIDIOC_STREAMON:
63126 + return s3c_camif_v4l2_streamon(cfg, arg);
63127 +
63128 + case VIDIOC_STREAMOFF:
63129 + return s3c_camif_v4l2_streamoff(cfg, arg);
63130 +
63131 + case VIDIOC_G_INPUT:
63132 + return s3c_camif_v4l2_g_input(cfg, arg);
63133 +
63134 + case VIDIOC_S_INPUT:
63135 + return s3c_camif_v4l2_s_input(cfg, *((int *) arg));
63136 +
63137 + case VIDIOC_G_OUTPUT:
63138 + return s3c_camif_v4l2_g_output(cfg, arg);
63139 +
63140 + case VIDIOC_S_OUTPUT:
63141 + return s3c_camif_v4l2_s_output(cfg, *((int *) arg));
63142 +
63143 + case VIDIOC_ENUMINPUT:
63144 + return s3c_camif_v4l2_enum_input(cfg, arg);
63145 +
63146 + case VIDIOC_ENUMOUTPUT:
63147 + return s3c_camif_v4l2_enum_output(cfg, arg);
63148 +
63149 + case VIDIOC_REQBUFS:
63150 + return s3c_camif_v4l2_reqbufs(cfg, arg);
63151 +
63152 + case VIDIOC_QUERYBUF:
63153 + return s3c_camif_v4l2_querybuf(cfg, arg);
63154 +
63155 + case VIDIOC_QBUF:
63156 + return s3c_camif_v4l2_qbuf(cfg, arg);
63157 +
63158 + case VIDIOC_DQBUF:
63159 + return s3c_camif_v4l2_dqbuf(cfg, arg);
63160 +
63161 + case VIDIOC_S_MSDMA:
63162 + return s3c_camif_v4l2_s_msdma(cfg, arg);
63163 +
63164 + case VIDIOC_MSDMA_START:
63165 + return s3c_camif_v4l2_msdma_start(cfg, arg);
63166 +
63167 + case VIDIOC_MSDMA_STOP:
63168 + return s3c_camif_v4l2_msdma_stop(cfg, arg);
63169 +
63170 + case VIDIOC_S_CAMERA_START:
63171 + return s3c_camif_v4l2_camera_start(cfg, arg);
63172 +
63173 + case VIDIOC_S_CAMERA_STOP:
63174 + return s3c_camif_v4l2_camera_stop(cfg, arg);
63175 +
63176 + case VIDIOC_CROPCAP:
63177 + return s3c_camif_v4l2_cropcap(cfg, arg);
63178 +
63179 + case VIDIOC_G_CROP:
63180 + return s3c_camif_v4l2_g_crop(cfg, arg);
63181 +
63182 + case VIDIOC_S_CROP:
63183 + return s3c_camif_v4l2_s_crop(cfg, arg);
63184 +
63185 + case VIDIOC_S_PARM:
63186 + return s3c_camif_v4l2_s_parm(cfg, arg);
63187 +
63188 + default: /* For v4l compatability */
63189 + return
63190 + v4l_compat_translate_ioctl(file, cmd, arg, s3c_camif_ioctl);
63191 + }
63192 +}
63193 +
63194 +
63195 +void om_3d7k_camera_on(void)
63196 +{
63197 + extern struct pcf50633 *om_3d7k_pcf;
63198 + int i;
63199 +
63200 + gpio_direction_output(S3C64XX_GPF(3), 0);
63201 +
63202 + /* @@@ hack - WA */
63203 + pcf50633_reg_write(om_3d7k_pcf, 0x30, 0x21);
63204 + for (i = 0; !(pcf50633_reg_read(om_3d7k_pcf, 0x42) & 0x02); i++) {
63205 + if (i == 100) {
63206 + printk(KERN_ERR "can't bring up LDO2\n");
63207 + break;
63208 + }
63209 + msleep(10);
63210 + }
63211 +
63212 + pcf50633_reg_write(om_3d7k_pcf, 0x39, 0x13);
63213 + pcf50633_reg_write(om_3d7k_pcf, 0x3a, 0x21);
63214 + for (i = 0; !(pcf50633_reg_read(om_3d7k_pcf, 0x42) & 0x40); i++) {
63215 + if (i == 100) {
63216 + printk(KERN_ERR "can't bring up HCLDO\n");
63217 + break;
63218 + }
63219 + msleep(10);
63220 + }
63221 +
63222 + msleep(100); /* > 0 ms */
63223 +
63224 + if (cam_clock)
63225 + clk_enable(cam_clock);
63226 +
63227 + msleep(1); /* > 100 cycles */
63228 + gpio_direction_output(S3C64XX_GPF(3), 1);
63229 + msleep(25); /* > 1 Mcycles */
63230 + s3c_gpio_cfgpin(S3C64XX_GPF(3), S3C64XX_GPF3_CAMIF_nRST);
63231 + msleep(25); /* just to be sure > 1 Mcycles */
63232 +
63233 + __raw_writel(__raw_readl(S3C64XX_NORMAL_CFG) |
63234 + S3C64XX_NORMALCFG_DOMAIN_I_ON, S3C64XX_NORMAL_CFG);
63235 +}
63236 +
63237 +void om_3d7k_camera_off(void)
63238 +{
63239 + extern struct pcf50633 *om_3d7k_pcf;
63240 +
63241 + gpio_direction_output(S3C64XX_GPF(3), 0);
63242 +
63243 + msleep(1); /* > 20 cycles */
63244 +
63245 + if (cam_clock)
63246 + clk_disable(cam_clock);
63247 + msleep(1); /* > 0 ms */
63248 +
63249 + /* @@@ hack - WA */
63250 + pcf50633_reg_write(om_3d7k_pcf, 0x3a, 0x20); /* 2V8, ... */
63251 + pcf50633_reg_write(om_3d7k_pcf, 0x30, 0x20); /* ... then 1V5 */
63252 +
63253 +#if 0
63254 + __raw_writel(__raw_readl(S3C64XX_NORMAL_CFG) &
63255 + ~S3C64XX_NORMALCFG_DOMAIN_I_ON, S3C64XX_NORMAL_CFG);
63256 +#endif
63257 +}
63258 +
63259 +
63260 +/* @@@ - WA */
63261 +#define s3c_camif_exclusive_open(inode, file) 0
63262 +#define s3c_camif_exclusive_release(inode, file)
63263 +
63264 +int s3c_camif_open(struct file *file)
63265 +{
63266 + int err;
63267 + camif_cfg_t *cfg =
63268 + s3c_camif_get_fimc_object(MINOR(file->f_dentry->d_inode->i_rdev));
63269 +
63270 + if (!cfg->cis) {
63271 + printk(KERN_ERR "An object for a CIS is missing\n");
63272 + printk(KERN_ERR
63273 + "Using msdma_input as a default CIS data structure\n");
63274 + cfg->cis = &msdma_input;
63275 +
63276 + /* global lock for both Codec and Preview */
63277 + sema_init(&cfg->cis->lock, 1);
63278 + cfg->cis->status |= P_NOT_WORKING;
63279 + }
63280 +
63281 + if (cfg->dma_type & CAMIF_PREVIEW) {
63282 + if (cfg->dma_type & CAMIF_PREVIEW)
63283 + cfg->cis->status &= ~P_NOT_WORKING;
63284 +
63285 + up(&cfg->cis->lock);
63286 + }
63287 +
63288 + om_3d7k_camera_on();
63289 +
63290 + err = s3c_camif_exclusive_open(inode, file);
63291 + cfg->cis->user++;
63292 + cfg->status = CAMIF_STOPPED;
63293 +
63294 + if (err < 0)
63295 + return err;
63296 +
63297 + if (file->f_flags & O_NONCAP) {
63298 + printk(KERN_ERR "Don't support non-capturing open\n");
63299 + return 0;
63300 + }
63301 +
63302 + file->private_data = cfg;
63303 +
63304 + s3c_camif_init_sensor(cfg);
63305 +
63306 + return 0;
63307 +}
63308 +
63309 +int s3c_camif_release(struct file *file)
63310 +{
63311 + camif_cfg_t *cfg =
63312 + s3c_camif_get_fimc_object(MINOR(file->f_dentry->d_inode->i_rdev));
63313 +
63314 + if (cfg->dma_type & CAMIF_PREVIEW) {
63315 + cfg->cis->status &= ~PWANT2START;
63316 + cfg->cis->status |= P_NOT_WORKING;
63317 + s3c_camif_stop_preview(cfg);
63318 + up(&cfg->cis->lock);
63319 + } else {
63320 + cfg->cis->status &= ~CWANT2START;
63321 + s3c_camif_stop_capture(cfg);
63322 + }
63323 +
63324 + s3c_camif_exclusive_release(inode, file);
63325 +
63326 + if (cfg->cis->sensor == NULL)
63327 + DPRINTK("A CIS sensor for MSDMA has been used\n");
63328 + else
63329 + cfg->cis->sensor->driver->command(cfg->cis->sensor, USER_EXIT,
63330 + NULL);
63331 +
63332 + cfg->cis->user--;
63333 + cfg->status = CAMIF_STOPPED;
63334 +
63335 + om_3d7k_camera_off();
63336 + cfg->cis->init_sensor = 0;
63337 +
63338 + return 0;
63339 +}
63340 +
63341 +ssize_t s3c_camif_read(struct file * file, char *buf, size_t count,
63342 + loff_t *pos)
63343 +{
63344 + camif_cfg_t *cfg = NULL;
63345 + size_t end;
63346 +
63347 + cfg = s3c_camif_get_fimc_object(MINOR(file->f_dentry->d_inode->i_rdev));
63348 +
63349 +#if defined(FSM_ON_PREVIEW)
63350 + if (cfg->dma_type == CAMIF_PREVIEW) {
63351 + if (wait_event_interruptible(cfg->waitq,
63352 + cfg->status == CAMIF_INT_HAPPEN))
63353 + return -ERESTARTSYS;
63354 +
63355 + cfg->status = CAMIF_STOPPED;
63356 + }
63357 +#endif
63358 +
63359 +#if defined(FSM_ON_CODEC)
63360 + if (cfg->dma_type == CAMIF_CODEC) {
63361 + if (wait_event_interruptible(cfg->waitq,
63362 + cfg->status == CAMIF_INT_HAPPEN))
63363 + return -ERESTARTSYS;
63364 +
63365 + cfg->status = CAMIF_STOPPED;
63366 + }
63367 +#endif
63368 + end = min_t(size_t, cfg->pp_totalsize / cfg->pp_num, count);
63369 +
63370 + if (copy_to_user(buf, s3c_camif_get_frame(cfg), end))
63371 + return -EFAULT;
63372 +
63373 + return end;
63374 +}
63375 +
63376 +ssize_t s3c_camif_write(struct file * f, const char *b, size_t c,
63377 + loff_t *offset)
63378 +{
63379 + camif_cfg_t *cfg;
63380 + int ret = 0;
63381 +
63382 + cfg = s3c_camif_get_fimc_object(MINOR(f->f_dentry->d_inode->i_rdev));
63383 +
63384 + switch (*b) {
63385 + case 'O':
63386 + if (cfg->dma_type & CAMIF_PREVIEW)
63387 + s3c_camif_start_preview(cfg);
63388 + else {
63389 + ret = s3c_camif_start_capture(cfg);
63390 +
63391 + if (ret < 0)
63392 + ret = 1;
63393 + }
63394 +
63395 + break;
63396 +
63397 + case 'X':
63398 + if (cfg->dma_type & CAMIF_PREVIEW) {
63399 + s3c_camif_stop_preview(cfg);
63400 + cfg->cis->status |= P_NOT_WORKING;
63401 + } else {
63402 + cfg->cis->status &= ~C_WORKING;
63403 + s3c_camif_stop_capture(cfg);
63404 + }
63405 +
63406 + break;
63407 +
63408 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
63409 + case 'P':
63410 + if (cfg->dma_type & CAMIF_PREVIEW) {
63411 + s3c_camif_start_preview(cfg);
63412 + s3c_camif_do_postprocess(cfg);
63413 + return 0;
63414 + } else
63415 + return -EFAULT;
63416 +#endif
63417 + default:
63418 + panic("s3c_camera_driver.c: s3c_camif_write() - "
63419 + "Unexpected Parameter\n");
63420 + }
63421 +
63422 + return ret;
63423 +}
63424 +
63425 +int s3c_camif_mmap(struct file* filp, struct vm_area_struct *vma)
63426 +{
63427 + camif_cfg_t *cfg = filp->private_data;
63428 +
63429 + unsigned long pageFrameNo;
63430 + unsigned long size = vma->vm_end - vma->vm_start;
63431 + unsigned long total_size;
63432 +
63433 + if (cfg->dma_type == CAMIF_PREVIEW)
63434 + total_size = RGB_MEM;
63435 + else
63436 + total_size = YUV_MEM;
63437 +
63438 + /*
63439 + * page frame number of the address for a source RGB frame to be stored
63440 + * at.
63441 + */
63442 + pageFrameNo = __phys_to_pfn(cfg->pp_phys_buf);
63443 +
63444 + if (size > total_size) {
63445 + printk(KERN_ERR "The size of RGB_MEM mapping is too big\n");
63446 + return -EINVAL;
63447 + }
63448 +
63449 + if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
63450 + printk(KERN_ERR "Writable RGB_MEM mapping must be shared\n");
63451 + return -EINVAL;
63452 + }
63453 +
63454 + if (remap_pfn_range(vma, vma->vm_start, pageFrameNo + vma->vm_pgoff,
63455 + size, vma->vm_page_prot))
63456 + return -EINVAL;
63457 +
63458 + return 0;
63459 +}
63460 +
63461 +static unsigned int s3c_camif_poll(struct file *file, poll_table *wait)
63462 +{
63463 + unsigned int mask = 0;
63464 + camif_cfg_t *cfg = file->private_data;
63465 +
63466 + poll_wait(file, &cfg->waitq, wait);
63467 +
63468 + if (cfg->status == CAMIF_INT_HAPPEN)
63469 + mask = POLLIN | POLLRDNORM;
63470 +
63471 + cfg->status = CAMIF_STOPPED;
63472 +
63473 + return mask;
63474 +}
63475 +
63476 +struct v4l2_file_operations camif_c_fops = {
63477 + .owner = THIS_MODULE,
63478 + .open = s3c_camif_open,
63479 + .release = s3c_camif_release,
63480 + .ioctl = s3c_camif_ioctl,
63481 + .read = s3c_camif_read,
63482 + .write = s3c_camif_write,
63483 + .mmap = s3c_camif_mmap,
63484 + .poll = s3c_camif_poll,
63485 +};
63486 +
63487 +struct v4l2_file_operations camif_p_fops = {
63488 + .owner = THIS_MODULE,
63489 + .open = s3c_camif_open,
63490 + .release = s3c_camif_release,
63491 + .ioctl = s3c_camif_ioctl,
63492 + .read = s3c_camif_read,
63493 + .write = s3c_camif_write,
63494 + .mmap = s3c_camif_mmap,
63495 + .poll = s3c_camif_poll,
63496 +};
63497 +
63498 +/*************************************************************************
63499 + * Templates for V4L2
63500 + ************************************************************************/
63501 +void camif_vdev_release (struct video_device *vdev) {
63502 + kfree(vdev);
63503 +}
63504 +
63505 +struct video_device codec_template = {
63506 + .name = CODEC_DEV_NAME,
63507 +#if 0
63508 + .type = VID_TYPE_OVERLAY | VID_TYPE_CAPTURE | VID_TYPE_CLIPPING | VID_TYPE_SCALES,
63509 + .type2 = V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING,
63510 + .hardware = VID_HARDWARE_SAMSUNG_FIMC3X,
63511 +#endif
63512 + .fops = &camif_c_fops,
63513 + .release = camif_vdev_release,
63514 + .minor = CODEC_MINOR,
63515 +};
63516 +
63517 +struct video_device preview_template = {
63518 + .name = PREVIEW_DEV_NAME,
63519 +#if 0
63520 + .type = VID_TYPE_OVERLAY | VID_TYPE_CAPTURE | VID_TYPE_CLIPPING | VID_TYPE_SCALES,
63521 + .type2 = V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING,
63522 + .hardware = VID_HARDWARE_SAMSUNG_FIMC3X,
63523 +#endif
63524 + .fops = &camif_p_fops,
63525 + .release = camif_vdev_release,
63526 + .minor = PREVIEW_MINOR,
63527 +};
63528 +
63529 +/*************************************************************************
63530 + * Initialize part
63531 + ************************************************************************/
63532 +void s3c_camif_init_sensor(camif_cfg_t *cfg)
63533 +{
63534 + camif_cis_t *cis = cfg->cis;
63535 + camif_cis_t *initialized_cis;
63536 +
63537 + if (!cis->sensor) {
63538 + initialized_cis = (camif_cis_t *) get_initialized_cis();
63539 +
63540 + if (initialized_cis == NULL) {
63541 + printk(KERN_ERR "An I2C client for CIS sensor isn't registered\n");
63542 + return;
63543 + }
63544 +
63545 + cis = cfg->cis = initialized_cis;
63546 + cfg->input_channel = 0;
63547 + cfg->cis->user++;
63548 + }
63549 +
63550 + if (!cis->init_sensor) {
63551 + cis->sensor->driver->command(cis->sensor, SENSOR_INIT, NULL);
63552 + cis->init_sensor = 1;
63553 +
63554 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K3BA)
63555 + cis->sensor->driver->command(cis->sensor, SENSOR_VGA, NULL);
63556 + cis->source_x = 640;
63557 + cis->source_y = 480;
63558 +#elif defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
63559 + cis->sensor->driver->command(cis->sensor, SENSOR_SVGA, NULL);
63560 + cis->source_x = 800;
63561 + cis->source_y = 600;
63562 +#endif
63563 + }
63564 +
63565 + cis->sensor->driver->command(cis->sensor, USER_ADD, NULL);
63566 +}
63567 +
63568 +static int s3c_camif_init_preview(camif_cfg_t * cfg)
63569 +{
63570 + cfg->target_x = PREVIEW_DEFAULT_WIDTH;
63571 + cfg->target_y = PREVIEW_DEFAULT_WIDTH;
63572 + cfg->pp_num = PREVIEW_DEFAULT_PPNUM;
63573 + cfg->dma_type = CAMIF_PREVIEW;
63574 + cfg->input_channel = CAMERA_INPUT;
63575 + cfg->src_fmt = CAMIF_YCBCR422;
63576 + cfg->output_channel = CAMIF_OUT_PP;
63577 + cfg->dst_fmt = CAMIF_RGB16;
63578 + cfg->flip = CAMIF_FLIP_Y;
63579 + cfg->v = &preview_template;
63580 +
63581 + /* @@@ - WA */
63582 + //init_MUTEX((struct semaphore *) &cfg->v->lock);
63583 + init_waitqueue_head(&cfg->waitq);
63584 +
63585 + cfg->status = CAMIF_STOPPED;
63586 +
63587 + /* To get the handle of CODEC */
63588 + cfg->other = s3c_camif_get_fimc_object(CODEC_MINOR);
63589 +
63590 + return cfg->status;
63591 +}
63592 +
63593 +static int s3c_camif_init_codec(camif_cfg_t * cfg)
63594 +{
63595 + cfg->target_x = CODEC_DEFAULT_WIDTH;
63596 + cfg->target_y = CODEC_DEFAULT_HEIGHT;
63597 + cfg->pp_num = CODEC_DEFAULT_PPNUM;
63598 + cfg->dma_type = CAMIF_CODEC;
63599 + cfg->src_fmt = CAMIF_YCBCR422;
63600 + cfg->input_channel = CAMERA_INPUT;
63601 + cfg->dst_fmt = CAMIF_YCBCR420;
63602 + cfg->output_channel = CAMIF_OUT_PP;
63603 + cfg->flip = CAMIF_FLIP_X;
63604 + cfg->v = &codec_template;
63605 +
63606 + /* @@@ - WA */
63607 + //init_MUTEX((struct semaphore *) &cfg->v->lock);
63608 +
63609 + init_waitqueue_head(&cfg->waitq);
63610 +
63611 + cfg->status = CAMIF_STOPPED;
63612 +
63613 + /* To get the handle of PREVIEW */
63614 + cfg->other = s3c_camif_get_fimc_object(PREVIEW_MINOR);
63615 +
63616 + return cfg->status;
63617 +}
63618 +
63619 +static int s3c_camif_probe(struct platform_device *pdev)
63620 +{
63621 + struct resource *res;
63622 + camif_cfg_t *codec, *preview;
63623 + struct clk *camif_clock;
63624 +
63625 + /* Initialize fimc objects */
63626 + codec = s3c_camif_get_fimc_object(CODEC_MINOR);
63627 + preview = s3c_camif_get_fimc_object(PREVIEW_MINOR);
63628 +
63629 + memset(codec, 0, sizeof(camif_cfg_t));
63630 + memset(preview, 0, sizeof(camif_cfg_t));
63631 +
63632 + /* Set the fimc name */
63633 + strcpy(codec->shortname, CODEC_DEV_NAME);
63634 + strcpy(preview->shortname, PREVIEW_DEV_NAME);
63635 +
63636 + /* get resource for io memory */
63637 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
63638 +
63639 + if (!res) {
63640 + printk("Failed to get io memory region resouce.\n");
63641 + return -1;
63642 + }
63643 +
63644 + /* request mem region */
63645 + res = request_mem_region(res->start, res->end - res->start + 1,
63646 + pdev->name);
63647 +
63648 + if (!res) {
63649 + printk("Failed to request io memory region.\n");
63650 + return -1;
63651 + }
63652 +
63653 + /* ioremap for register block */
63654 + codec->regs = preview->regs =
63655 + ioremap(res->start, res->end - res->start + 1);
63656 +
63657 + if (codec->regs == NULL) {
63658 + printk(KERN_ERR "Failed to remap register block\n");
63659 + return -1;
63660 + }
63661 +
63662 + /* ioremap for reserved memory */
63663 + codec->pp_phys_buf = PHYS_OFFSET + (MEM_SIZE - RESERVED_MEM);
63664 + codec->pp_virt_buf = ioremap_nocache(codec->pp_phys_buf, YUV_MEM);
63665 +
63666 + preview->pp_phys_buf =
63667 + PHYS_OFFSET + (MEM_SIZE - RESERVED_MEM) + YUV_MEM;
63668 + preview->pp_virt_buf = ioremap_nocache(preview->pp_phys_buf, RGB_MEM);
63669 +
63670 + camif_clock = clk_get(&pdev->dev, "camif");
63671 + if (IS_ERR(camif_clock)) {
63672 + dev_err(&pdev->dev,
63673 + "Failed to find camera interface clock source\n");
63674 + return PTR_ERR(cam_clock);
63675 + }
63676 + clk_enable(camif_clock);
63677 +
63678 + /* Device init */
63679 + s3c_camif_init();
63680 + s3c_camif_init_codec(codec);
63681 + s3c_camif_init_preview(preview);
63682 +
63683 + /* Set irq */
63684 + codec->irq = platform_get_irq(pdev, FIMC_CODEC_INDEX);
63685 + preview->irq = platform_get_irq(pdev, FIMC_PREVIEW_INDEX);
63686 +
63687 + s3c_camif_request_irq(codec);
63688 + s3c_camif_request_irq(preview);
63689 +
63690 + /* Register to video device */
63691 + if (video_register_device(codec->v, VFL_TYPE_GRABBER, CODEC_MINOR) !=
63692 + 0) {
63693 + printk(KERN_ERR "Couldn't register this codec driver\n");
63694 + return -1;
63695 + }
63696 +
63697 + if (video_register_device(preview->v, VFL_TYPE_GRABBER, PREVIEW_MINOR)
63698 + != 0) {
63699 + printk(KERN_ERR "Couldn't register this preview driver\n");
63700 + return -1;
63701 + }
63702 +
63703 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
63704 + cam_clock = clk_get(&pdev->dev, "camera");
63705 +#elif defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2416) || defined(CONFIG_CPU_S3C2450)
63706 + cam_clock = clk_get(&pdev->dev, "camif-upll");
63707 +#else
63708 +#error cam_clock should be defined
63709 +#endif
63710 +
63711 + if (IS_ERR(cam_clock)) {
63712 + printk("Failed to find camera clock source\n");
63713 + return PTR_ERR(cam_clock);
63714 + }
63715 +
63716 + /* Print banner */
63717 + printk(KERN_INFO "S3C FIMC v%s\n", FIMC_VER);
63718 +
63719 + return 0;
63720 +}
63721 +
63722 +static int s3c_camif_remove(struct platform_device *pdev)
63723 +{
63724 + camif_cfg_t *codec, *preview;
63725 +
63726 + codec = s3c_camif_get_fimc_object(CODEC_MINOR);
63727 + preview = s3c_camif_get_fimc_object(PREVIEW_MINOR);
63728 +
63729 + s3c_camif_release_irq(codec);
63730 + s3c_camif_release_irq(preview);
63731 +
63732 + iounmap(codec->pp_virt_buf);
63733 + codec->pp_virt_buf = 0;
63734 +
63735 + iounmap(preview->pp_virt_buf);
63736 + preview->pp_virt_buf = 0;
63737 +
63738 + video_unregister_device(codec->v);
63739 + video_unregister_device(preview->v);
63740 +
63741 + s3c_camif_set_priority(0);
63742 + clk_disable(cam_clock);
63743 +
63744 + memset(codec, 0, sizeof(camif_cfg_t));
63745 + memset(preview, 0, sizeof(camif_cfg_t));
63746 +
63747 + return 0;
63748 +}
63749 +
63750 +static struct platform_driver s3c_camif_driver =
63751 +{
63752 + .probe = s3c_camif_probe,
63753 + .remove = s3c_camif_remove,
63754 + .driver = {
63755 + .name = "s3c-camif",
63756 + .owner = THIS_MODULE,
63757 + },
63758 +};
63759 +
63760 +static int s3c_camif_register(void)
63761 +{
63762 + platform_driver_register(&s3c_camif_driver);
63763 +
63764 + return 0;
63765 +}
63766 +
63767 +static void s3c_camif_unregister(void)
63768 +{
63769 + platform_driver_unregister(&s3c_camif_driver);
63770 +}
63771 +
63772 +void s3c_camif_open_sensor(camif_cis_t *cis)
63773 +{
63774 + clk_set_rate(cam_clock, cis->camclk);
63775 + s3c_camif_reset(cis->reset_type, cis->reset_udelay);
63776 +}
63777 +
63778 +void s3c_camif_register_sensor(struct i2c_client *ptr)
63779 +{
63780 + camif_cfg_t *codec, *preview;
63781 + camif_cis_t *cis = i2c_get_clientdata(ptr);
63782 +
63783 + codec = s3c_camif_get_fimc_object(CODEC_MINOR);
63784 + preview = s3c_camif_get_fimc_object(PREVIEW_MINOR);
63785 +
63786 + codec->cis = preview->cis = cis;
63787 +
63788 + sema_init(&codec->cis->lock, 1);
63789 + sema_init(&preview->cis->lock, 1);
63790 +
63791 + preview->cis->status |= P_NOT_WORKING; /* Default Value */
63792 +
63793 + s3c_camif_set_polarity(preview);
63794 + s3c_camif_set_source_format(cis);
63795 + s3c_camif_set_priority(1);
63796 +}
63797 +
63798 +void s3c_camif_unregister_sensor(struct i2c_client *ptr)
63799 +{
63800 + camif_cis_t *cis;
63801 +
63802 + cis = i2c_get_clientdata(ptr);
63803 + cis->init_sensor = 0;
63804 +}
63805 +
63806 +module_init(s3c_camif_register);
63807 +module_exit(s3c_camif_unregister);
63808 +
63809 +EXPORT_SYMBOL(s3c_camif_register_sensor);
63810 +EXPORT_SYMBOL(s3c_camif_unregister_sensor);
63811 +
63812 +MODULE_AUTHOR("Jinsung Yang <jsgood.yang@samsung.com>");
63813 +MODULE_DESCRIPTION("S3C Camera Driver for FIMC Interface");
63814 +MODULE_LICENSE("GPL");
63815 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/media/video/s3c_camif.c linux-2.6.29-rc3.owrt.om/drivers/media/video/s3c_camif.c
63816 --- linux-2.6.29-rc3.owrt/drivers/media/video/s3c_camif.c 1970-01-01 01:00:00.000000000 +0100
63817 +++ linux-2.6.29-rc3.owrt.om/drivers/media/video/s3c_camif.c 2009-05-10 22:27:59.000000000 +0200
63818 @@ -0,0 +1,1916 @@
63819 +/* drivers/media/video/s3c_camif.c
63820 + *
63821 + * Copyright (c) 2008 Samsung Electronics
63822 + *
63823 + * Samsung S3C Camera driver
63824 + *
63825 + * This program is free software; you can redistribute it and/or modify
63826 + * it under the terms of the GNU General Public License as published by
63827 + * the Free Software Foundation; either version 2 of the License, or
63828 + * (at your option) any later version.
63829 + *
63830 + * This program is distributed in the hope that it will be useful,
63831 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
63832 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
63833 + * GNU General Public License for more details.
63834 + *
63835 + * You should have received a copy of the GNU General Public License
63836 + * along with this program; if not, write to the Free Software
63837 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
63838 + */
63839 +
63840 +#include <linux/module.h>
63841 +#include <linux/kernel.h>
63842 +#include <linux/init.h>
63843 +#include <linux/sched.h>
63844 +#include <linux/completion.h>
63845 +#include <linux/delay.h>
63846 +#include <linux/slab.h>
63847 +#include <linux/vmalloc.h>
63848 +#include <linux/wait.h>
63849 +#include <linux/videodev.h>
63850 +#include <asm/io.h>
63851 +#include <mach/hardware.h>
63852 +#include <asm/uaccess.h>
63853 +#include <mach/map.h>
63854 +#include <mach/gpio.h>
63855 +#include <mach/irqs.h>
63856 +#include <plat/gpio-cfg.h>
63857 +#include <plat/regs-camif.h>
63858 +#include <plat/regs-gpio.h>
63859 +#include <plat/gpio-bank-f.h>
63860 +
63861 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
63862 +#include <asm/arch/regs-irq.h>
63863 +#endif
63864 +
63865 +#include "s3c_camif.h"
63866 +
63867 +#define S3C_VIDW00ADD0B0 (S3C24XX_VA_LCD+0xa0)
63868 +#define S3C_VIDW01ADD0B0 (S3C24XX_VA_LCD+0xa8)
63869 +
63870 +static unsigned int irq_old_priority;
63871 +
63872 +/*************************************************************************
63873 + * Utility part
63874 + ************************************************************************/
63875 +int s3c_camif_get_frame_num(camif_cfg_t *cfg)
63876 +{
63877 + int index = 0;
63878 +
63879 + if (cfg->dma_type & CAMIF_CODEC)
63880 + index = (readl(cfg->regs + S3C_CICOSTATUS) >> 26) & 0x3;
63881 + else {
63882 + assert(cfg->dma_type & CAMIF_PREVIEW);
63883 + index = (readl(cfg->regs + S3C_CIPRSTATUS) >> 26) & 0x3;
63884 + }
63885 +
63886 + cfg->cur_frame_num = (index + 2) % 4; /* When 4 PingPong */
63887 +
63888 + return 0;
63889 +}
63890 +
63891 +unsigned char* s3c_camif_get_frame(camif_cfg_t *cfg)
63892 +{
63893 + unsigned char *ret = NULL;
63894 + int cnt = cfg->cur_frame_num;
63895 +
63896 + if (cfg->dma_type & CAMIF_PREVIEW)
63897 + ret = cfg->img_buf[cnt].virt_rgb;
63898 +
63899 + if (cfg->dma_type & CAMIF_CODEC) {
63900 + if ((cfg->dst_fmt & CAMIF_RGB16) ||
63901 + (cfg->dst_fmt & CAMIF_RGB24))
63902 + ret = cfg->img_buf[cnt].virt_rgb;
63903 + else
63904 + ret = cfg->img_buf[cnt].virt_y;
63905 + }
63906 +
63907 + return ret;
63908 +}
63909 +
63910 +int s3c_camif_get_fifo_status(camif_cfg_t *cfg)
63911 +{
63912 + unsigned int reg, val, flag;
63913 +
63914 + if (cfg->dma_type & CAMIF_CODEC) {
63915 + flag = S3C_CICOSTATUS_OVFIY_CO | S3C_CICOSTATUS_OVFICB_CO |
63916 + S3C_CICOSTATUS_OVFICR_CO;
63917 + reg = readl(cfg->regs + S3C_CICOSTATUS);
63918 +
63919 + if (reg & flag) {
63920 + /* FIFO Error Count ++ */
63921 + val = readl(cfg->regs + S3C_CIWDOFST);
63922 + val |= S3C_CIWDOFST_CLROVCOFIY |
63923 + S3C_CIWDOFST_CLROVCOFICB | S3C_CIWDOFST_CLROVCOFICR;
63924 + writel(val, cfg->regs + S3C_CIWDOFST);
63925 +
63926 + val = readl(cfg->regs + S3C_CIWDOFST);
63927 + val &= ~(S3C_CIWDOFST_CLROVCOFIY |
63928 + S3C_CIWDOFST_CLROVCOFICB |
63929 + S3C_CIWDOFST_CLROVCOFICR);
63930 + writel(val, cfg->regs + S3C_CIWDOFST);
63931 +
63932 + return 1; /* Error */
63933 + }
63934 + } else if (cfg->dma_type & CAMIF_PREVIEW) {
63935 + flag = S3C_CIPRSTATUS_OVFICB_PR | S3C_CIPRSTATUS_OVFICR_PR;
63936 + reg = readl(cfg->regs + S3C_CIPRSTATUS);
63937 +
63938 + if (reg & flag) {
63939 + /* FIFO Error Count ++ */
63940 + val = readl(cfg->regs + S3C_CIWDOFST);
63941 + val |= S3C_CIWDOFST_CLROVPRFICB |
63942 + S3C_CIWDOFST_CLROVPRFICR;
63943 + writel(val, cfg->regs + S3C_CIWDOFST);
63944 +
63945 + val = readl(cfg->regs + S3C_CIWDOFST);
63946 + val &= ~(S3C_CIWDOFST_CLROVPRFIY |
63947 + S3C_CIWDOFST_CLROVPRFICB |
63948 + S3C_CIWDOFST_CLROVPRFICR);
63949 + writel(val, cfg->regs + S3C_CIWDOFST);
63950 +
63951 + return 1; /* Error */
63952 + }
63953 + }
63954 +
63955 + return 0;
63956 +}
63957 +
63958 +void s3c_camif_set_polarity(camif_cfg_t *cfg)
63959 +{
63960 + camif_cis_t *cis = cfg->cis;
63961 + unsigned int val;
63962 + unsigned int cmd;
63963 +
63964 + cmd = readl(cfg->regs + S3C_CIGCTRL);
63965 + cmd &= ~(0x7 << 24);
63966 +
63967 + if (cis->polarity_pclk)
63968 + cmd |= S3C_CIGCTRL_INVPOLPCLK;
63969 +
63970 + if (cis->polarity_vsync)
63971 + cmd |= S3C_CIGCTRL_INVPOLVSYNC;
63972 +
63973 + if (cis->polarity_href)
63974 + cmd |= S3C_CIGCTRL_INVPOLHREF;
63975 +
63976 + val = readl(cfg->regs + S3C_CIGCTRL);
63977 + val |= cmd;
63978 + writel(val, cfg->regs + S3C_CIGCTRL);
63979 +}
63980 +
63981 +/*************************************************************************
63982 + * Memory part
63983 + ************************************************************************/
63984 +static int s3c_camif_request_memory(camif_cfg_t *cfg)
63985 +{
63986 + unsigned int t_size = 0, i = 0;
63987 + unsigned int area = 0;
63988 +
63989 + area = cfg->target_x * cfg->target_y;
63990 +
63991 + if (cfg->dma_type & CAMIF_CODEC) {
63992 + if (cfg->dst_fmt & CAMIF_YCBCR420)
63993 + t_size = area * 3 / 2; /* CAMIF_YCBCR420 */
63994 + else if (cfg->dst_fmt & CAMIF_YCBCR422 ||
63995 + cfg->dst_fmt & CAMIF_YCBCR422I)
63996 + t_size = area * 2; /* CAMIF_YCBCR422 */
63997 + else if (cfg->dst_fmt & CAMIF_RGB16)
63998 + t_size = area * 2; /* 2 bytes per pixel */
63999 + else if (cfg->dst_fmt & CAMIF_RGB24)
64000 + t_size = area * 4; /* 4 bytes per pixel */
64001 + else
64002 + printk(KERN_INFO "Invalid target format\n");
64003 + } else if (cfg->dma_type & CAMIF_PREVIEW) {
64004 +
64005 + if (cfg->dst_fmt & CAMIF_RGB16)
64006 + t_size = area * 2; /* 2 bytes per pixel */
64007 + else if (cfg->dst_fmt & CAMIF_RGB24)
64008 + t_size = area * 4; /* 4 bytes per pixel */
64009 + else
64010 + printk(KERN_ERR "Invalid target format\n");
64011 +
64012 + } else {
64013 + return 0;
64014 + }
64015 +
64016 + if (t_size % PAGE_SIZE != 0) {
64017 + i = t_size / PAGE_SIZE;
64018 + t_size = (i + 1) * PAGE_SIZE;
64019 + }
64020 +
64021 + t_size = t_size * cfg->pp_num;
64022 + cfg->pp_totalsize = t_size;
64023 +
64024 + printk(KERN_INFO "%s memory required: 0x%08X bytes\n",
64025 + cfg->dma_type & CAMIF_CODEC ? "Codec" : "Preview", t_size);
64026 +
64027 + return 0;
64028 +}
64029 +
64030 +static void s3c_camif_calc_burst_length_yuv422i(unsigned int hsize,
64031 + unsigned int *mburst, unsigned int *rburst)
64032 +{
64033 + unsigned int tmp, wanted;
64034 +
64035 + tmp = (hsize / 2) & 0xf;
64036 +
64037 + switch (tmp) {
64038 + case 0:
64039 + wanted = 16;
64040 + break;
64041 +
64042 + case 4:
64043 + wanted = 4;
64044 + break;
64045 +
64046 + case 8:
64047 + wanted = 8;
64048 + break;
64049 +
64050 + default:
64051 + wanted = 4;
64052 + break;
64053 + }
64054 +
64055 + *mburst = wanted / 2;
64056 + *rburst = wanted / 2;
64057 +}
64058 +
64059 +static void s3c_camif_calc_burst_length(unsigned int hsize,
64060 + unsigned int *mburst, unsigned int *rburst)
64061 +{
64062 + unsigned int tmp;
64063 +
64064 + tmp = (hsize / 4) & 0xf;
64065 +
64066 + switch (tmp) {
64067 + case 0:
64068 + *mburst = 16;
64069 + *rburst = 16;
64070 + break;
64071 +
64072 + case 4:
64073 + *mburst = 16;
64074 + *rburst = 4;
64075 + break;
64076 +
64077 + case 8:
64078 + *mburst = 16;
64079 + *rburst = 8;
64080 + break;
64081 +
64082 + default:
64083 + tmp = (hsize / 4) % 8;
64084 +
64085 + if (tmp == 0) {
64086 + *mburst = 8;
64087 + *rburst = 8;
64088 + } else if (tmp == 4) {
64089 + *mburst = 8;
64090 + *rburst = 4;
64091 + } else {
64092 + tmp = (hsize / 4) % 4;
64093 + *mburst = 4;
64094 + *rburst = tmp ? tmp : 4;
64095 + }
64096 +
64097 + break;
64098 + }
64099 +}
64100 +
64101 +int s3c_camif_setup_dma(camif_cfg_t *cfg)
64102 +{
64103 + int width = cfg->target_x;
64104 + unsigned int val, yburst_m, yburst_r, cburst_m, cburst_r;
64105 +
64106 + if (cfg->dma_type & CAMIF_CODEC) {
64107 + if (cfg->dst_fmt == CAMIF_RGB16 ||
64108 + cfg->dst_fmt == CAMIF_RGB24) {
64109 + if (cfg->dst_fmt == CAMIF_RGB24) {
64110 + if (width % 2 != 0)
64111 + return BURST_ERR;
64112 +
64113 + s3c_camif_calc_burst_length(width * 4,
64114 + &yburst_m, &yburst_r);
64115 + } else {
64116 + if ((width / 2) % 2 != 0)
64117 + return BURST_ERR;
64118 +
64119 + s3c_camif_calc_burst_length(width * 2,
64120 + &yburst_m, &yburst_r);
64121 + }
64122 +
64123 + val = readl(cfg->regs + S3C_CICOCTRL);
64124 + val &= ~(0xfffff << 4);
64125 +
64126 + if (cfg->dst_fmt == CAMIF_RGB24) {
64127 + val = S3C_CICOCTRL_YBURST1_CO(yburst_m / 2) |
64128 + S3C_CICOCTRL_YBURST2_CO(yburst_r / 4) |
64129 + (4 << 9) | (2 << 4);
64130 + } else {
64131 + val = S3C_CICOCTRL_YBURST1_CO(yburst_m / 2) |
64132 + S3C_CICOCTRL_YBURST2_CO(yburst_r / 2) |
64133 + (4 << 9) | (2 << 4);
64134 + }
64135 +
64136 + writel(val, cfg->regs + S3C_CICOCTRL);
64137 + } else {
64138 + /* CODEC DMA WIDHT is multiple of 16 */
64139 + if (width % 16 != 0)
64140 + return BURST_ERR;
64141 +
64142 + if (cfg->dst_fmt == CAMIF_YCBCR422I) {
64143 + s3c_camif_calc_burst_length_yuv422i(width,
64144 + &yburst_m, &yburst_r);
64145 + cburst_m = yburst_m / 2;
64146 + cburst_r = yburst_r / 2;
64147 + } else {
64148 + s3c_camif_calc_burst_length(width, &yburst_m,
64149 + &yburst_r);
64150 + s3c_camif_calc_burst_length(width / 2,
64151 + &cburst_m, &cburst_r);
64152 + }
64153 +
64154 + val = readl(cfg->regs + S3C_CICOCTRL);
64155 + val &= ~(0xfffff << 4);
64156 + val |= S3C_CICOCTRL_YBURST1_CO(yburst_m) |
64157 + S3C_CICOCTRL_CBURST1_CO(cburst_m) |
64158 + S3C_CICOCTRL_YBURST2_CO(yburst_r) |
64159 + S3C_CICOCTRL_CBURST2_CO(cburst_r);
64160 + writel(val, cfg->regs + S3C_CICOCTRL);
64161 + }
64162 + } else if (cfg->dma_type & CAMIF_PREVIEW) {
64163 + if (cfg->dst_fmt == CAMIF_RGB24) {
64164 + if (width % 2 != 0)
64165 + return BURST_ERR;
64166 +
64167 + s3c_camif_calc_burst_length(width * 4, &yburst_m,
64168 + &yburst_r);
64169 + } else {
64170 + if ((width / 2) % 2 != 0)
64171 + return BURST_ERR;
64172 +
64173 + s3c_camif_calc_burst_length(width * 2, &yburst_m,
64174 + &yburst_r);
64175 + }
64176 +
64177 + val = readl(cfg->regs + S3C_CIPRCTRL);
64178 + val &= ~(0x3ff << 14);
64179 + val |= S3C_CICOCTRL_YBURST1_CO(yburst_m) |
64180 + S3C_CICOCTRL_YBURST2_CO(yburst_r);
64181 + writel(val, cfg->regs + S3C_CIPRCTRL);
64182 + }
64183 +
64184 + return 0;
64185 +}
64186 +
64187 +/*************************************************************************
64188 + * Input path part
64189 + ************************************************************************/
64190 +/*
64191 + * 2443 MSDMA (Preview Only)
64192 + */
64193 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
64194 +int s3c_camif_input_msdma_preview(camif_cfg_t * cfg)
64195 +{
64196 + unsigned int addr_start_Y, addr_start_CB, addr_start_CR;
64197 + unsigned int addr_end_Y, addr_end_CB, addr_end_CR;
64198 + unsigned int val, val_width;
64199 + unsigned area, div;
64200 +
64201 + val = readl(cfg->regs + S3C_CIMSCTRL);
64202 + val &= ~(1 << 2);
64203 + writel(val, cfg->regs + S3C_CIMSCTRL);
64204 +
64205 + val = readl(cfg->regs + S3C_CIMSCTRL);
64206 + val |= 1 << 2;
64207 + writel(val, cfg->regs + S3C_CIMSCTRL);
64208 +
64209 + switch(cfg->src_fmt) {
64210 + case CAMIF_YCBCR420:
64211 + default:
64212 + val = readl(cfg->regs + S3C_CIMSCTRL);
64213 + val |= 0x1 << 1;
64214 + writel(val, cfg->regs + S3C_CIMSCTRL);
64215 +
64216 + div = 4;
64217 + break;
64218 +
64219 + case CAMIF_YCBCR422:
64220 + case CAMIF_YCBCR422I:
64221 + val = readl(cfg->regs + S3C_CIMSCTRL);
64222 + val = (val & ~(0x1 << 5)) | (0x1 << 5); /* Interleave_MS */
64223 + val &= ~(0x1 << 1);
64224 + val &= ~(0x3 << 3); /* YCbYCr */
64225 + writel(val, cfg->regs + S3C_CIMSCTRL);
64226 +
64227 + div = 2;
64228 + break;
64229 + }
64230 +
64231 + area = cfg->cis->source_x * cfg->cis->source_y;
64232 +
64233 + addr_start_Y = readl(cfg->regs + S3C_CIMSYSA);
64234 + addr_start_CB = addr_start_Y + area;
64235 + addr_start_CR = addr_start_CB + area / div;
64236 +
64237 + addr_end_Y = addr_start_Y + area;
64238 + addr_end_CB = addr_start_CB + area / div;
64239 + addr_end_CR = addr_start_CR + area / div;
64240 +
64241 + /* MSDMA memory */
64242 + writel(addr_start_Y, cfg->regs + S3C_CIMSYSA);
64243 + writel(addr_start_CB, cfg->regs + S3C_CIMSCBSA);
64244 + writel(addr_start_CR, cfg->regs + S3C_CIMSCRSA);
64245 +
64246 + writel(addr_end_Y, cfg->regs + S3C_CIMSYEND);
64247 + writel(addr_end_CB, cfg->regs + S3C_CIMSCBEND);
64248 + writel(addr_end_CR, cfg->regs + S3C_CIMSCREND);
64249 +
64250 + /* MSDMA memory offset - default : 0 */
64251 + writel(0, cfg->regs + S3C_CIMSYOFF);
64252 + writel(0, cfg->regs + S3C_CIMSCBOFF);
64253 + writel(0, cfg->regs + S3C_CIMSCROFF);
64254 +
64255 + /* MSDMA for codec source image width */
64256 + val_width = cfg->cis->source_x; /* MSCOWIDTH */
64257 + writel(val_width, cfg->regs + S3C_CIMSWIDTH);
64258 +
64259 + return 0;
64260 +}
64261 +
64262 +static int s3c_camif_input_msdma(camif_cfg_t *cfg)
64263 +{
64264 + if (cfg->input_channel == MSDMA_FROM_PREVIEW)
64265 + s3c_camif_input_msdma_preview(cfg);
64266 +
64267 + return 0;
64268 +}
64269 +
64270 +/*
64271 + * 6400 MSDMA (Preview & Codec)
64272 + */
64273 +#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
64274 +int s3c_camif_input_msdma_codec(camif_cfg_t * cfg)
64275 +{
64276 + u32 addr_start_Y, addr_start_CB, addr_start_CR;
64277 + u32 addr_end_Y, addr_end_CB, addr_end_CR;
64278 + u32 val, val_width;
64279 + unsigned area, div;
64280 +
64281 + /* Codec path input data selection */
64282 + val = readl(cfg->regs + S3C_MSCOCTRL);
64283 + val &= ~(1 << 3);
64284 + writel(val, cfg->regs + S3C_MSCOCTRL);
64285 +
64286 + val = readl(cfg->regs + S3C_MSCOCTRL);
64287 + val |= 1 << 3;
64288 + writel(val, cfg->regs + S3C_MSCOCTRL);
64289 +
64290 + switch(cfg->src_fmt) {
64291 + case CAMIF_YCBCR420:
64292 + default:
64293 + val = readl(cfg->regs + S3C_MSCOCTRL);
64294 + val &= ~(0x3 << 1);
64295 + writel(val, cfg->regs + S3C_MSCOCTRL);
64296 +
64297 + div = 4;
64298 + break;
64299 +
64300 + case CAMIF_YCBCR422:
64301 + case CAMIF_YCBCR422I:
64302 + val = readl(cfg->regs + S3C_MSCOCTRL);
64303 + val = (val & ~(0x3 << 1)) | (0x2 << 1);
64304 + writel(val, cfg->regs + S3C_MSCOCTRL);
64305 +
64306 + div = 2;
64307 + break;
64308 + }
64309 +
64310 + area = cfg->cis->source_x * cfg->cis->source_y;
64311 +
64312 + addr_start_Y = cfg->pp_phys_buf;
64313 + addr_start_CB = addr_start_Y + area;
64314 + addr_start_CR = addr_start_CB + area / div;
64315 +
64316 + addr_end_Y = addr_start_Y + area;
64317 + addr_end_CB = addr_start_CB + area / div;
64318 + addr_end_CR = addr_start_CR + area / div;
64319 +
64320 + /* MSDMA memory */
64321 + writel(addr_start_Y, cfg->regs + S3C_MSCOY0SA);
64322 + writel(addr_start_CB, cfg->regs + S3C_MSCOCB0SA);
64323 + writel(addr_start_CR, cfg->regs + S3C_MSCOCR0SA);
64324 +
64325 + writel(addr_end_Y, cfg->regs + S3C_MSCOY0END);
64326 + writel(addr_end_CB, cfg->regs + S3C_MSCOCB0END);
64327 + writel(addr_end_CR, cfg->regs + S3C_MSCOCR0END);
64328 +
64329 + /* MSDMA memory offset */
64330 + writel(0, cfg->regs + S3C_MSCOYOFF);
64331 + writel(0, cfg->regs + S3C_MSCOCBOFF);
64332 + writel(0, cfg->regs + S3C_MSCOCROFF);
64333 +
64334 + /* MSDMA for codec source image width */
64335 + val_width = readl(cfg->regs + S3C_MSCOWIDTH);
64336 + val_width &= ~0x0fffffff;
64337 + val_width |= 0x1 << 31; /* AutoLoadEnable */
64338 + val_width |= cfg->cis->source_y << 16; /* MSCOHEIGHT */
64339 + val_width |= cfg->cis->source_x; /* MSCOWIDTH */
64340 + writel(val_width, cfg->regs + S3C_MSCOWIDTH);
64341 +
64342 + return 0;
64343 +}
64344 +
64345 +int s3c_camif_input_msdma_preview(camif_cfg_t * cfg)
64346 +{
64347 + int ret = 0;
64348 + unsigned int addr_start_Y, addr_start_CB, addr_start_CR;
64349 + unsigned int addr_end_Y, addr_end_CB, addr_end_CR;
64350 + unsigned int val, val_width;
64351 + unsigned area, div;
64352 +
64353 + val = readl(cfg->regs + S3C_CIMSCTRL);
64354 + val &= ~(0x1 << 3);
64355 + writel(val, cfg->regs + S3C_CIMSCTRL);
64356 +
64357 + val = readl(cfg->regs + S3C_CIMSCTRL);
64358 + val |= 0x1 << 3;
64359 + writel(val, cfg->regs + S3C_CIMSCTRL);
64360 +
64361 + switch(cfg->src_fmt) {
64362 + case CAMIF_YCBCR420:
64363 + default:
64364 + val = readl(cfg->regs + S3C_CIMSCTRL);
64365 + val &= ~(0x3 << 1);
64366 + writel(val, cfg->regs + S3C_CIMSCTRL);
64367 +
64368 + div = 4;
64369 + break;
64370 +
64371 + case CAMIF_YCBCR422:
64372 + case CAMIF_YCBCR422I:
64373 + val = readl(cfg->regs + S3C_CIMSCTRL);
64374 + val = (val & ~(0x3 << 1)) | (0x2 << 1); /* YCbCr 422 Interleave */
64375 + val = (val & ~(0x3 << 4)) | (0x3 << 4); /* YCbYCr */
64376 + writel(val, cfg->regs + S3C_CIMSCTRL);
64377 +
64378 + div = 2;
64379 + break;
64380 + }
64381 +
64382 + area = cfg->cis->source_x * cfg->cis->source_y;
64383 +
64384 + addr_start_Y = readl(cfg->regs + S3C_MSPRY0SA);
64385 + addr_start_CB = addr_start_Y + area;
64386 + addr_start_CR = addr_start_CB + area / div;
64387 +
64388 + addr_end_Y = addr_start_Y + area;
64389 + addr_end_CB = addr_start_CB + area / div;
64390 + addr_end_CR = addr_start_CR + area / div;
64391 +
64392 + /* MSDMA memory */
64393 + writel(addr_start_Y, cfg->regs + S3C_MSPRY0SA);
64394 + writel(addr_start_CB, cfg->regs + S3C_MSPRCB0SA);
64395 + writel(addr_start_CR, cfg->regs + S3C_MSPRCR0SA);
64396 +
64397 + writel(addr_end_Y, cfg->regs + S3C_MSPRY0END);
64398 + writel(addr_end_CB, cfg->regs + S3C_MSPRCB0END);
64399 + writel(addr_end_CR, cfg->regs + S3C_MSPRCR0END);
64400 +
64401 + /* MSDMA memory offset */
64402 + writel(0, cfg->regs + S3C_MSPRYOFF);
64403 + writel(0, cfg->regs + S3C_MSPRCBOFF);
64404 + writel(0, cfg->regs + S3C_MSPRCROFF);
64405 +
64406 + /* MSDMA for codec source image width */
64407 + val_width = readl(cfg->regs + S3C_MSPRWIDTH);
64408 + val_width &= ~(0x1 << 31); /* AutoLoadEnable */
64409 + val_width &= ~0x0fffffff;
64410 + val_width |= cfg->cis->source_y << 16; /* MSCOHEIGHT */
64411 + val_width |= cfg->cis->source_x; /* MSCOWIDTH */
64412 + writel(val_width, cfg->regs + S3C_MSPRWIDTH);
64413 +
64414 + return ret;
64415 +}
64416 +
64417 +static int s3c_camif_input_msdma(camif_cfg_t *cfg)
64418 +{
64419 + if (cfg->input_channel == MSDMA_FROM_PREVIEW)
64420 + s3c_camif_input_msdma_preview(cfg);
64421 + else if (cfg->input_channel == MSDMA_FROM_CODEC)
64422 + s3c_camif_input_msdma_codec(cfg);
64423 +
64424 + return 0;
64425 +}
64426 +#endif
64427 +
64428 +static int s3c_camif_input_camera(camif_cfg_t *cfg)
64429 +{
64430 + unsigned int val;
64431 +
64432 + s3c_camif_set_offset(cfg->cis);
64433 +
64434 + if (cfg->dma_type & CAMIF_CODEC) {
64435 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
64436 + val = readl(cfg->regs + S3C_MSCOCTRL);
64437 + val &= ~(1 << 3);
64438 + writel(val, cfg->regs + S3C_MSCOCTRL);
64439 +#endif
64440 + } else if (cfg->dma_type & CAMIF_PREVIEW) {
64441 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450)
64442 + val = readl(cfg->regs + S3C_CIMSCTRL);
64443 + val &= ~(1 << 2);
64444 + writel(val, cfg->regs + S3C_CIMSCTRL);
64445 +#elif defined(CONFIG_CPU_S3C6400)
64446 + val = readl(cfg->regs + S3C_CIMSCTRL);
64447 + val &= ~(1 << 3);
64448 + writel(val, cfg->regs + S3C_CIMSCTRL);
64449 +#endif
64450 + } else
64451 + printk(KERN_ERR "Invalid DMA type\n");
64452 +
64453 + return 0;
64454 +}
64455 +
64456 +static int s3c_camif_setup_input_path(camif_cfg_t *cfg)
64457 +{
64458 + if (cfg->input_channel == CAMERA_INPUT)
64459 + s3c_camif_input_camera(cfg);
64460 + else
64461 + s3c_camif_input_msdma(cfg);
64462 +
64463 + return 0;
64464 +}
64465 +
64466 +/*************************************************************************
64467 + * Output path part
64468 + ************************************************************************/
64469 +static int s3c_camif_output_pp_codec_rgb(camif_cfg_t *cfg)
64470 +{
64471 + int i;
64472 + unsigned int val;
64473 + unsigned int area = cfg->target_x * cfg->target_y;
64474 +
64475 + if (cfg->dst_fmt & CAMIF_RGB24)
64476 + area = area * 4;
64477 + else {
64478 + assert (cfg->dst_fmt & CAMIF_RGB16);
64479 + area = area * 2;
64480 + }
64481 +
64482 + if ((area % PAGE_SIZE) != 0) {
64483 + i = area / PAGE_SIZE;
64484 + area = (i + 1) * PAGE_SIZE;
64485 + }
64486 +
64487 + cfg->buffer_size = area;
64488 +
64489 + if (cfg->input_channel == MSDMA_FROM_CODEC) {
64490 +{
64491 +void __iomem *S3C24XX_VA_LCD = ioremap(S3C64XX_PA_FB, 1024*1024);
64492 + val = readl(S3C_VIDW00ADD0B0);
64493 +}
64494 +
64495 + for (i = 0; i < 4; i++)
64496 + writel(val, cfg->regs + S3C_CICOYSA(i));
64497 + } else {
64498 + switch ( cfg->pp_num ) {
64499 + case 1:
64500 + for (i = 0; i < 4; i++) {
64501 + cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf;
64502 + cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf;
64503 + writel(cfg->img_buf[i].phys_rgb,
64504 + cfg->regs + S3C_CICOYSA(i));
64505 + }
64506 +
64507 + break;
64508 +
64509 + case 2:
64510 + for (i = 0; i < 4; i++) {
64511 + cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf;
64512 + cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf;
64513 + if (i & 1) {
64514 + cfg->img_buf[i].virt_rgb += area;
64515 + cfg->img_buf[i].phys_rgb += area;
64516 + }
64517 + writel(cfg->img_buf[i].phys_rgb,
64518 + cfg->regs + S3C_CICOYSA(i));
64519 + }
64520 +
64521 + break;
64522 +
64523 + case 4:
64524 + for (i = 0; i < 4; i++) {
64525 + cfg->img_buf[i].virt_rgb =
64526 + cfg->pp_virt_buf + i * area;
64527 + cfg->img_buf[i].phys_rgb =
64528 + cfg->pp_phys_buf + i * area;
64529 + writel(cfg->img_buf[i].phys_rgb,
64530 + cfg->regs + S3C_CICOYSA(i));
64531 + }
64532 +
64533 + break;
64534 +
64535 + default:
64536 + printk(KERN_ERR "Invalid pingpong number %d\n",
64537 + cfg->pp_num);
64538 + panic("s3c camif halt\n");
64539 + }
64540 + }
64541 +
64542 + return 0;
64543 +}
64544 +
64545 +static int s3c_camif_output_pp_codec(camif_cfg_t *cfg)
64546 +{
64547 + unsigned int i, cbcr_size = 0;
64548 + unsigned int area = cfg->target_x * cfg->target_y;
64549 + unsigned int one_p_size;
64550 +
64551 + area = cfg->target_x * cfg->target_y;
64552 +
64553 + if (cfg->dst_fmt & CAMIF_YCBCR420)
64554 + cbcr_size = area / 4;
64555 + else if (cfg->dst_fmt & CAMIF_YCBCR422 ||
64556 + cfg->dst_fmt & CAMIF_YCBCR422I)
64557 + cbcr_size = area / 2;
64558 + else if ((cfg->dst_fmt & CAMIF_RGB16) || (cfg->dst_fmt & CAMIF_RGB24)) {
64559 + s3c_camif_output_pp_codec_rgb(cfg);
64560 + return 0;
64561 + } else
64562 + printk(KERN_ERR "Invalid target format %d\n", cfg->dst_fmt);
64563 +
64564 + one_p_size = area + 2 * cbcr_size;
64565 +
64566 + if ((one_p_size % PAGE_SIZE) != 0) {
64567 + i = one_p_size / PAGE_SIZE;
64568 + one_p_size = (i + 1) * PAGE_SIZE;
64569 + }
64570 +
64571 + cfg->buffer_size = one_p_size;
64572 +
64573 + switch (cfg->pp_num) {
64574 + case 1 :
64575 + for (i = 0; i < 4; i++) {
64576 + cfg->img_buf[i].virt_y = cfg->pp_virt_buf;
64577 + cfg->img_buf[i].phys_y = cfg->pp_phys_buf;
64578 + cfg->img_buf[i].virt_cb = cfg->pp_virt_buf + area;
64579 + cfg->img_buf[i].phys_cb = cfg->pp_phys_buf + area;
64580 + cfg->img_buf[i].virt_cr = cfg->pp_virt_buf + area + cbcr_size;
64581 + cfg->img_buf[i].phys_cr = cfg->pp_phys_buf + area + cbcr_size;
64582 + writel(cfg->img_buf[i].phys_y, cfg->regs + S3C_CICOYSA(i));
64583 + writel(cfg->img_buf[i].phys_cb, cfg->regs + S3C_CICOCBSA(i));
64584 + writel(cfg->img_buf[i].phys_cr, cfg->regs + S3C_CICOCRSA(i));
64585 + }
64586 +
64587 + break;
64588 +
64589 + case 2:
64590 + for (i = 0; i < 4; i++) {
64591 + cfg->img_buf[i].virt_y = cfg->pp_virt_buf;
64592 + cfg->img_buf[i].phys_y = cfg->pp_phys_buf;
64593 + cfg->img_buf[i].virt_cb = cfg->pp_virt_buf + area;
64594 + cfg->img_buf[i].phys_cb = cfg->pp_phys_buf + area;
64595 + cfg->img_buf[i].virt_cr =
64596 + cfg->pp_virt_buf + area + cbcr_size;
64597 + cfg->img_buf[i].phys_cr =
64598 + cfg->pp_phys_buf + area + cbcr_size;
64599 +
64600 + if (i & 1) {
64601 + cfg->img_buf[i].virt_y += one_p_size;
64602 + cfg->img_buf[i].phys_y += one_p_size;
64603 + cfg->img_buf[i].virt_cb += one_p_size;
64604 + cfg->img_buf[i].phys_cb += one_p_size;
64605 + cfg->img_buf[i].virt_cr += one_p_size;
64606 + cfg->img_buf[i].phys_cr += one_p_size;
64607 + }
64608 +
64609 + writel(cfg->img_buf[i].phys_y,
64610 + cfg->regs + S3C_CICOYSA(i));
64611 + writel(cfg->img_buf[i].phys_cb,
64612 + cfg->regs + S3C_CICOCBSA(i));
64613 + writel(cfg->img_buf[i].phys_cr,
64614 + cfg->regs + S3C_CICOCRSA(i));
64615 + }
64616 +
64617 + break;
64618 +
64619 + case 4:
64620 + for (i = 0; i < 4; i++) {
64621 + cfg->img_buf[i].virt_y =
64622 + cfg->pp_virt_buf + i * one_p_size;
64623 + cfg->img_buf[i].phys_y =
64624 + cfg->pp_phys_buf + i * one_p_size;
64625 + cfg->img_buf[i].virt_cb =
64626 + cfg->pp_virt_buf + area + i * one_p_size;
64627 + cfg->img_buf[i].phys_cb =
64628 + cfg->pp_phys_buf + area + i * one_p_size;
64629 + cfg->img_buf[i].virt_cr = cfg->pp_virt_buf +
64630 + area + cbcr_size + i * one_p_size;
64631 + cfg->img_buf[i].phys_cr = cfg->pp_phys_buf +
64632 + area + cbcr_size + i * one_p_size;
64633 + writel(cfg->img_buf[i].phys_y,
64634 + cfg->regs + S3C_CICOYSA(i));
64635 + writel(cfg->img_buf[i].phys_cb,
64636 + cfg->regs + S3C_CICOCBSA(i));
64637 + writel(cfg->img_buf[i].phys_cr,
64638 + cfg->regs + S3C_CICOCRSA(i));
64639 + }
64640 +
64641 + break;
64642 +
64643 + default:
64644 + printk(KERN_ERR "Invalid pingpong number %d\n", cfg->pp_num);
64645 + }
64646 +
64647 + return 0;
64648 +}
64649 +
64650 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
64651 +static int s3c_camif_io_duplex_preview(camif_cfg_t *cfg)
64652 +{
64653 + unsigned int cbcr_size = 0;
64654 + unsigned int area = cfg->cis->source_x * cfg->cis->source_y;
64655 + unsigned int val;
64656 + int i;
64657 +
64658 + val = readl(S3C_VIDW01ADD0);
64659 +
64660 + if (!((cfg->dst_fmt & CAMIF_RGB16) || (cfg->dst_fmt & CAMIF_RGB24)))
64661 + printk(KERN_ERR "Invalid target format\n");
64662 +
64663 + for (i = 0; i < 4; i++)
64664 + writel(val, cfg->regs + S3C_CIPRYSA(i));
64665 +
64666 + if (cfg->src_fmt & CAMIF_YCBCR420) {
64667 + cbcr_size = area / 4;
64668 + cfg->img_buf[0].virt_cb = cfg->pp_virt_buf + area;
64669 + cfg->img_buf[0].phys_cb = cfg->pp_phys_buf + area;
64670 + cfg->img_buf[0].virt_cr = cfg->pp_virt_buf + area + cbcr_size;
64671 + cfg->img_buf[0].phys_cr = cfg->pp_phys_buf + area + cbcr_size;
64672 + } else if (cfg->src_fmt & CAMIF_YCBCR422 || cfg->dst_fmt & CAMIF_YCBCR422I) {
64673 + area = area * 2;
64674 + cfg->img_buf[0].virt_cb = 0;
64675 + cfg->img_buf[0].phys_cb = 0;
64676 + cfg->img_buf[0].virt_cr = 0;
64677 + cfg->img_buf[0].phys_cr = 0;
64678 + }
64679 +
64680 + cfg->img_buf[0].virt_y = cfg->pp_virt_buf;
64681 + cfg->img_buf[0].phys_y = cfg->pp_phys_buf;
64682 +
64683 + writel(cfg->img_buf[0].phys_y, cfg->regs + S3C_CIMSYSA);
64684 + writel(cfg->img_buf[0].phys_y + area, cfg->regs + S3C_CIMSYEND);
64685 +
64686 + writel(cfg->img_buf[0].phys_cb, cfg->regs + S3C_CIMSCBSA);
64687 + writel(cfg->img_buf[0].phys_cb + cbcr_size, cfg->regs + S3C_CIMSCBEND);
64688 +
64689 + writel(cfg->img_buf[0].phys_cr, cfg->regs + S3C_CIMSCRSA);
64690 + writel(cfg->img_buf[0].phys_cr + cbcr_size, cfg->regs + S3C_CIMSCREND);
64691 +
64692 + writel(cfg->cis->source_x, cfg->regs + S3C_CIMSWIDTH);
64693 +
64694 + return 0;
64695 +}
64696 +#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
64697 +static int s3c_camif_io_duplex_preview(camif_cfg_t *cfg)
64698 +{
64699 + unsigned int cbcr_size = 0;
64700 + unsigned int area = cfg->cis->source_x * cfg->cis->source_y;
64701 + unsigned int val;
64702 + int i;
64703 +
64704 +{
64705 +void __iomem *S3C24XX_VA_LCD = ioremap(S3C64XX_PA_FB, 1024*1024);
64706 + val = readl(S3C_VIDW01ADD0B0);
64707 +}
64708 +
64709 + if (!((cfg->dst_fmt & CAMIF_RGB16) || (cfg->dst_fmt & CAMIF_RGB24)))
64710 + printk(KERN_ERR "Invalid target format\n");
64711 +
64712 + for (i = 0; i < 4; i++)
64713 + writel(val, cfg->regs + S3C_CIPRYSA(i));
64714 +
64715 + if (cfg->src_fmt & CAMIF_YCBCR420) {
64716 + cbcr_size = area / 4;
64717 + cfg->img_buf[0].virt_cb = cfg->pp_virt_buf + area;
64718 + cfg->img_buf[0].phys_cb = cfg->pp_phys_buf + area;
64719 + cfg->img_buf[0].virt_cr = cfg->pp_virt_buf + area + cbcr_size;
64720 + cfg->img_buf[0].phys_cr = cfg->pp_phys_buf + area + cbcr_size;
64721 + } else if (cfg->src_fmt & CAMIF_YCBCR422 ||
64722 + cfg->dst_fmt & CAMIF_YCBCR422I) {
64723 + area = area * 2;
64724 + cfg->img_buf[0].virt_cb = 0;
64725 + cfg->img_buf[0].phys_cb = 0;
64726 + cfg->img_buf[0].virt_cr = 0;
64727 + cfg->img_buf[0].phys_cr = 0;
64728 + }
64729 +
64730 + cfg->img_buf[0].virt_y = cfg->pp_virt_buf;
64731 + cfg->img_buf[0].phys_y = cfg->pp_phys_buf;
64732 +
64733 + writel(cfg->img_buf[0].phys_y, cfg->regs + S3C_MSPRY0SA);
64734 + writel(cfg->img_buf[0].phys_y + area, cfg->regs + S3C_MSPRY0END);
64735 +
64736 + writel(cfg->img_buf[0].phys_cb, cfg->regs + S3C_MSPRCB0SA);
64737 + writel(cfg->img_buf[0].phys_cb + cbcr_size, cfg->regs + S3C_MSPRCB0END);
64738 +
64739 + writel(cfg->img_buf[0].phys_cr, cfg->regs + S3C_MSPRCR0SA);
64740 + writel(cfg->img_buf[0].phys_cr + cbcr_size, cfg->regs + S3C_MSPRCR0END);
64741 +
64742 + val = readl(cfg->regs + S3C_MSCOWIDTH);
64743 + val |= 0x1 << 31;
64744 + val |= cfg->cis->source_y << 16;
64745 + val |= cfg->cis->source_x;
64746 + writel(val, cfg->regs + S3C_MSPRWIDTH);
64747 +
64748 + return 0;
64749 +}
64750 +#endif
64751 +
64752 +static int s3c_camif_output_pp_preview(camif_cfg_t *cfg)
64753 +{
64754 + int i;
64755 + unsigned int cbcr_size = 0;
64756 + unsigned int area = cfg->target_x * cfg->target_y;
64757 +
64758 + if (cfg->input_channel) {
64759 + s3c_camif_io_duplex_preview(cfg);
64760 + return 0;
64761 + }
64762 +
64763 + if (cfg->dst_fmt & CAMIF_YCBCR420)
64764 + cbcr_size = area / 4;
64765 + else if (cfg->dst_fmt & CAMIF_YCBCR422 ||
64766 + cfg->dst_fmt & CAMIF_YCBCR422I)
64767 + cbcr_size = area / 2;
64768 + else if (cfg->dst_fmt & CAMIF_RGB24)
64769 + area = area * 4;
64770 + else if (cfg->dst_fmt & CAMIF_RGB16)
64771 + area = area * 2;
64772 + else
64773 + printk(KERN_ERR "Invalid target format %d\n", cfg->dst_fmt);
64774 +
64775 + if ((area % PAGE_SIZE) != 0) {
64776 + i = area / PAGE_SIZE;
64777 + area = (i + 1) * PAGE_SIZE;
64778 + }
64779 +
64780 + cfg->buffer_size = area;
64781 +
64782 + switch (cfg->pp_num) {
64783 + case 1:
64784 + for (i = 0; i < 4; i++) {
64785 + cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf;
64786 + cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf;
64787 + writel(cfg->img_buf[i].phys_rgb,
64788 + cfg->regs + S3C_CIPRYSA(i));
64789 + }
64790 +
64791 + break;
64792 +
64793 + case 2:
64794 + for (i = 0; i < 4; i++) {
64795 + cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf;
64796 + cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf;
64797 + if (i & 1) {
64798 + cfg->img_buf[i].virt_rgb += area;
64799 + cfg->img_buf[i].phys_rgb += area;
64800 + }
64801 +
64802 + writel(cfg->img_buf[i].phys_rgb,
64803 + cfg->regs + S3C_CIPRYSA(i));
64804 + }
64805 +
64806 + break;
64807 +
64808 + case 4:
64809 + for (i = 0; i < 4; i++) {
64810 + cfg->img_buf[i].virt_rgb = cfg->pp_virt_buf + i * area;
64811 + cfg->img_buf[i].phys_rgb = cfg->pp_phys_buf + i * area;
64812 + writel(cfg->img_buf[i].phys_rgb,
64813 + cfg->regs + S3C_CIPRYSA(i));
64814 + }
64815 +
64816 + break;
64817 +
64818 + default:
64819 + printk(KERN_ERR "Invalid pingpong number %d\n", cfg->pp_num);
64820 + }
64821 +
64822 + return 0;
64823 +}
64824 +
64825 +static int s3c_camif_output_pp(camif_cfg_t *cfg)
64826 +{
64827 + if (cfg->dma_type & CAMIF_CODEC)
64828 + s3c_camif_output_pp_codec(cfg);
64829 + else if (cfg->dma_type & CAMIF_PREVIEW)
64830 + s3c_camif_output_pp_preview(cfg);
64831 +
64832 + return 0;
64833 +}
64834 +
64835 +static int s3c_camif_output_lcd(camif_cfg_t *cfg)
64836 +{
64837 + /* To Be Implemented */
64838 + return 0;
64839 +}
64840 +
64841 +static int s3c_camif_setup_output_path(camif_cfg_t *cfg)
64842 +{
64843 + if (cfg->output_channel == CAMIF_OUT_FIFO)
64844 + s3c_camif_output_lcd(cfg);
64845 + else
64846 + s3c_camif_output_pp(cfg);
64847 +
64848 + return 0;
64849 +}
64850 +
64851 +/*************************************************************************
64852 + * Scaler part
64853 + ************************************************************************/
64854 +static int s3c_camif_set_target_area(camif_cfg_t *cfg)
64855 +{
64856 + unsigned int rect = cfg->target_x * cfg->target_y;
64857 +
64858 + if (cfg->dma_type & CAMIF_CODEC)
64859 + writel(rect, cfg->regs + S3C_CICOTAREA);
64860 + else if (cfg->dma_type & CAMIF_PREVIEW)
64861 + writel(rect, cfg->regs + S3C_CIPRTAREA);
64862 +
64863 + return 0;
64864 +}
64865 +
64866 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
64867 +static inline int s3c_camif_set_ratio(camif_cfg_t *cfg)
64868 +{
64869 + unsigned int cmd =
64870 + S3C_CICOSCCTRL_CSCR2Y_WIDE | S3C_CICOSCCTRL_CSCY2R_WIDE;
64871 +
64872 + if (cfg->dma_type & CAMIF_CODEC) {
64873 +
64874 + writel(S3C_CICOSCPRERATIO_SHFACTOR_CO(cfg->sc.shfactor) |
64875 + S3C_CICOSCPRERATIO_PREHORRATIO_CO(cfg->sc.prehratio) |
64876 + S3C_CICOSCPRERATIO_PREVERRATIO_CO(cfg->sc.prevratio),
64877 + cfg->regs + S3C_CICOSCPRERATIO);
64878 +
64879 + writel(S3C_CICOSCPREDST_PREDSTWIDTH_CO(cfg->sc.predst_x) |
64880 + S3C_CICOSCPREDST_PREDSTHEIGHT_CO(cfg->sc.predst_y),
64881 + cfg->regs + S3C_CICOSCPREDST);
64882 +
64883 + /* Differ from Preview */
64884 + if (cfg->sc.scalerbypass)
64885 + cmd |= S3C_CICOSCCTRL_SCALERBYPASS_CO;
64886 +
64887 + /* Differ from Codec */
64888 + if (cfg->dst_fmt & CAMIF_RGB24)
64889 + cmd |= S3C_CICOSCCTRL_OUTRGB_FMT_RGB888;
64890 + else
64891 + cmd |= S3C_CICOSCCTRL_OUTRGB_FMT_RGB565;
64892 +
64893 + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)
64894 + cmd |=
64895 + S3C_CICOSCCTRL_SCALEUP_H | S3C_CICOSCCTRL_SCALEUP_V;
64896 +
64897 + writel(cmd |
64898 + S3C_CICOSCCTRL_MAINHORRATIO_CO(cfg->sc.mainhratio) |
64899 + S3C_CICOSCCTRL_MAINVERRATIO_CO(cfg->sc.mainvratio),
64900 + cfg->regs + S3C_CICOSCCTRL);
64901 +
64902 + } else if (cfg->dma_type & CAMIF_PREVIEW) {
64903 + writel(S3C_CIPRSCPRERATIO_SHFACTOR_PR(cfg->sc.shfactor) |
64904 + S3C_CIPRSCPRERATIO_PREHORRATIO_PR(cfg->sc.prehratio) |
64905 + S3C_CIPRSCPRERATIO_PREVERRATIO_PR(cfg->sc.prevratio),
64906 + cfg->regs + S3C_CIPRSCPRERATIO);
64907 +
64908 + writel(S3C_CIPRSCPREDST_PREDSTWIDTH_PR(cfg->sc.predst_x) |
64909 + S3C_CIPRSCPREDST_PREDSTHEIGHT_PR(cfg->sc.predst_y),
64910 + cfg->regs + S3C_CIPRSCPREDST);
64911 +
64912 + if (cfg->dst_fmt & CAMIF_RGB24)
64913 + cmd |= S3C_CIPRSCCTRL_OUTRGB_FMT_PR_RGB888;
64914 + else
64915 + cmd |= S3C_CIPRSCCTRL_OUTRGB_FMT_PR_RGB565;
64916 +
64917 + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)
64918 + cmd |= (1 << 30) | (1 << 29);
64919 +
64920 + writel(cmd |
64921 + S3C_CIPRSCCTRL_MAINHORRATIO_PR(cfg->sc.mainhratio) |
64922 + S3C_CIPRSCCTRL_MAINVERRATIO_PR(cfg->sc.mainvratio),
64923 + cfg->regs + S3C_CIPRSCCTRL);
64924 +
64925 + } else
64926 + printk(KERN_ERR "Invalid DMA type\n");
64927 +
64928 + return 0;
64929 +}
64930 +#elif defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
64931 +static inline int s3c_camif_set_ratio(camif_cfg_t *cfg)
64932 +{
64933 + u32 cmd = 0;
64934 +
64935 + if (cfg->dma_type & CAMIF_CODEC) {
64936 +
64937 + writel(S3C_CICOSCPRERATIO_SHFACTOR_CO(cfg->sc.shfactor) |
64938 + S3C_CICOSCPRERATIO_PREHORRATIO_CO(cfg->sc.prehratio) |
64939 + S3C_CICOSCPRERATIO_PREVERRATIO_CO(cfg->sc.prevratio),
64940 + cfg->regs + S3C_CICOSCPRERATIO);
64941 +
64942 + writel(S3C_CICOSCPREDST_PREDSTWIDTH_CO(cfg->sc.predst_x) |
64943 + S3C_CICOSCPREDST_PREDSTHEIGHT_CO(cfg->sc.predst_y),
64944 + cfg->regs + S3C_CICOSCPREDST);
64945 +
64946 + if (cfg->sc.scalerbypass)
64947 + cmd |= S3C_CICOSCCTRL_SCALERBYPASS_CO;
64948 +
64949 + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)
64950 + cmd |=
64951 + S3C_CICOSCCTRL_SCALEUP_H | S3C_CICOSCCTRL_SCALEUP_V;
64952 +
64953 + writel(cmd |
64954 + S3C_CICOSCCTRL_MAINHORRATIO_CO(cfg->sc.mainhratio) |
64955 + S3C_CICOSCCTRL_MAINVERRATIO_CO(cfg->sc.mainvratio),
64956 + cfg->regs + S3C_CICOSCCTRL);
64957 +
64958 + } else if (cfg->dma_type & CAMIF_PREVIEW) {
64959 +
64960 + cmd |= S3C_CIPRSCCTRL_SAMPLE_PR;
64961 +
64962 + writel(S3C_CIPRSCPRERATIO_SHFACTOR_PR(cfg->sc.shfactor) |
64963 + S3C_CIPRSCPRERATIO_PREHORRATIO_PR(cfg->sc.prehratio) |
64964 + S3C_CIPRSCPRERATIO_PREVERRATIO_PR(cfg->sc.prevratio),
64965 + cfg->regs + S3C_CIPRSCPRERATIO);
64966 +
64967 + writel(S3C_CIPRSCPREDST_PREDSTWIDTH_PR(cfg->sc.predst_x) |
64968 + S3C_CIPRSCPREDST_PREDSTHEIGHT_PR(cfg->sc.predst_y),
64969 + cfg->regs + S3C_CIPRSCPREDST);
64970 +
64971 + if (cfg->dst_fmt & CAMIF_RGB24)
64972 + cmd |= S3C_CIPRSCCTRL_RGBFORMAT_24;
64973 +
64974 + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)
64975 + cmd |= (1 << 29) | (1 << 28);
64976 +
64977 + writel(cmd |
64978 + S3C_CIPRSCCTRL_MAINHORRATIO_PR(cfg->sc.mainhratio) |
64979 + S3C_CIPRSCCTRL_MAINVERRATIO_PR(cfg->sc.mainvratio),
64980 + cfg->regs + S3C_CIPRSCCTRL);
64981 +
64982 + } else
64983 + printk(KERN_ERR "Invalid DMA type\n");
64984 +
64985 + return 0;
64986 +}
64987 +#endif
64988 +
64989 +static int s3c_camif_calc_ratio(unsigned int src_width, unsigned int dst_width,
64990 + unsigned int *ratio, unsigned int *shift)
64991 +{
64992 + if (src_width >= 64 * dst_width) {
64993 + printk(KERN_ERR "Out of pre-scaler range: "
64994 + "src_width / dst_width = %d (< 64)\n",
64995 + src_width / dst_width);
64996 + return 1;
64997 + }
64998 + if (src_width >= 32 * dst_width) {
64999 + *shift = 5;
65000 + } else if (src_width >= 16 * dst_width) {
65001 + *shift = 4;
65002 + } else if (src_width >= 8 * dst_width) {
65003 + *shift = 3;
65004 + } else if (src_width >= 4 * dst_width) {
65005 + *shift = 2;
65006 + } else if (src_width >= 2 * dst_width) {
65007 + *shift = 1;
65008 + } else {
65009 + *shift = 0;
65010 + }
65011 +
65012 + *ratio = 1 << *shift;
65013 +
65014 + return 0;
65015 +}
65016 +
65017 +static int s3c_camif_setup_scaler(camif_cfg_t *cfg)
65018 +{
65019 + int tx = cfg->target_x, ty = cfg->target_y;
65020 + int sx, sy;
65021 +
65022 + if (tx <= 0 || ty <= 0) {
65023 + printk(KERN_ERR "Invalid target size\n");
65024 + return -1;
65025 + }
65026 +
65027 + sx = cfg->cis->source_x -
65028 + (cfg->cis->win_hor_ofst + cfg->cis->win_hor_ofst2);
65029 + sy = cfg->cis->source_y -
65030 + (cfg->cis->win_ver_ofst + cfg->cis->win_hor_ofst2);
65031 +
65032 + if (sx <= 0 || sy <= 0) {
65033 + printk(KERN_ERR "Invalid source size\n");
65034 + return -1;
65035 + }
65036 +
65037 + cfg->sc.modified_src_x = sx;
65038 + cfg->sc.modified_src_y = sy;
65039 +
65040 + /* Pre-scaler control register 1 */
65041 + s3c_camif_calc_ratio(sx, tx, &cfg->sc.prehratio, &cfg->sc.hfactor);
65042 + s3c_camif_calc_ratio(sy, ty, &cfg->sc.prevratio, &cfg->sc.vfactor);
65043 +
65044 + if (cfg->dma_type & CAMIF_PREVIEW) {
65045 + if (sx / cfg->sc.prehratio > 640) {
65046 + printk(KERN_INFO "Internal preview line buffer length "
65047 + "is 640 pixels\n");
65048 + printk(KERN_INFO "Decrease the resolution or adjust "
65049 + "window offset values appropriately\n");
65050 + }
65051 + }
65052 +
65053 + cfg->sc.shfactor = 10 - (cfg->sc.hfactor + cfg->sc.vfactor);
65054 +
65055 + /* Pre-scaler control register 2 */
65056 + cfg->sc.predst_x = sx / cfg->sc.prehratio;
65057 + cfg->sc.predst_y = sy / cfg->sc.prevratio;
65058 +
65059 + /* Main-scaler control register */
65060 + cfg->sc.mainhratio = (sx << 8) / (tx << cfg->sc.hfactor);
65061 + cfg->sc.mainvratio = (sy << 8) / (ty << cfg->sc.vfactor);
65062 +
65063 + cfg->sc.scaleup_h = sx <= tx;
65064 + cfg->sc.scaleup_v = sy <= ty;
65065 +
65066 + s3c_camif_set_ratio(cfg);
65067 + s3c_camif_set_target_area(cfg);
65068 +
65069 + return 0;
65070 +}
65071 +
65072 +/*************************************************************************
65073 + * Format part
65074 + ************************************************************************/
65075 +int s3c_camif_set_source_format(camif_cis_t *cis)
65076 +{
65077 + camif_cfg_t *cfg = s3c_camif_get_fimc_object(CODEC_MINOR);
65078 + unsigned int cmd = 0;
65079 +
65080 + /* Configure CISRCFMT --Source Format */
65081 + if (cis->itu_fmt & CAMIF_ITU601)
65082 + cmd = CAMIF_ITU601;
65083 + else {
65084 + assert(cis->itu_fmt & CAMIF_ITU656);
65085 + cmd = CAMIF_ITU656;
65086 + }
65087 +
65088 + cmd |= S3C_CISRCFMT_SOURCEHSIZE(cis->source_x) |
65089 + S3C_CISRCFMT_SOURCEVSIZE(cis->source_y);
65090 +
65091 + /* Order422 */
65092 + cmd |= cis->order422;
65093 + writel(cmd, cfg->regs + S3C_CISRCFMT);
65094 +
65095 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65096 + cmd = cis->order422 >> 14;
65097 + writel((readl(cfg->regs + S3C_CICOCTRL) & ~(0x3 << 0)) | cmd,
65098 + cfg->regs + S3C_CICOCTRL);
65099 +#endif
65100 +
65101 + return 0;
65102 +}
65103 +
65104 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
65105 +static int s3c_camif_set_target_format(camif_cfg_t *cfg)
65106 +{
65107 + unsigned int cmd = 0;
65108 +
65109 + if (cfg->dma_type & CAMIF_CODEC) {
65110 + cmd |= S3C_CICOTRGFMT_TARGETHSIZE_CO(cfg->target_x) |
65111 + S3C_CICOTRGFMT_TARGETVSIZE_CO(cfg->target_y);
65112 +
65113 + if (cfg->dst_fmt & CAMIF_YCBCR420)
65114 + cmd |= S3C_CICOTRGFMT_OUT422_420 |
65115 + S3C_CICOTRGFMT_IN422_422;
65116 + else if (cfg->dst_fmt & CAMIF_YCBCR422)
65117 + cmd |= (S3C_CICOTRGFMT_OUT422_422 |
65118 + S3C_CICOTRGFMT_IN422_422);
65119 + else if ((cfg->dst_fmt & CAMIF_RGB24) ||
65120 + (cfg->dst_fmt & CAMIF_RGB16))
65121 + cmd |= (S3C_CICOTRGFMT_OUT422_422 |
65122 + S3C_CICOTRGFMT_IN422_422) | (1 << 29);
65123 + else
65124 + printk(KERN_ERR "Invalid target format\n");
65125 + writel(cmd, cfg->regs + S3C_CICOTRGFMT);
65126 + } else {
65127 + assert(cfg->dma_type & CAMIF_PREVIEW);
65128 +
65129 + cmd = readl(cfg->regs + S3C_CIPRTRGFMT);
65130 + cmd &= ~(S3C_CIPRTRGFMT_TARGETHSIZE_PR(0x1fff) |
65131 + S3C_CIPRTRGFMT_TARGETVSIZE_PR(0x1fff));
65132 + cmd |= S3C_CIPRTRGFMT_TARGETHSIZE_PR(cfg->target_x) |
65133 + S3C_CIPRTRGFMT_TARGETVSIZE_PR(cfg->target_y);
65134 +
65135 + writel(cmd | (2 << 30), cfg->regs + S3C_CIPRTRGFMT);
65136 + }
65137 +
65138 + return 0;
65139 +}
65140 +#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65141 +static int s3c_camif_set_target_format(camif_cfg_t *cfg)
65142 +{
65143 + unsigned int cmd = 0;
65144 +
65145 + if (cfg->dma_type & CAMIF_CODEC) {
65146 + cmd |= S3C_CICOTRGFMT_TARGETHSIZE_CO(cfg->target_x) |
65147 + S3C_CICOTRGFMT_TARGETVSIZE_CO(cfg->target_y);
65148 +
65149 + if (cfg->dst_fmt & CAMIF_YCBCR420)
65150 + cmd |= S3C_CICOTRGFMT_OUTFORMAT_YCBCR420OUT;
65151 + else if (cfg->dst_fmt & CAMIF_YCBCR422)
65152 + cmd |= S3C_CICOTRGFMT_OUTFORMAT_YCBCR422OUT;
65153 + else if (cfg->dst_fmt & CAMIF_YCBCR422I)
65154 + cmd |= S3C_CICOTRGFMT_OUTFORMAT_YCBCR422OUTINTERLEAVE;
65155 + else if ((cfg->dst_fmt & CAMIF_RGB24) ||
65156 + (cfg->dst_fmt & CAMIF_RGB16))
65157 + cmd |= S3C_CICOTRGFMT_OUTFORMAT_RGBOUT;
65158 + else
65159 + printk(KERN_ERR "Invalid target format\n");
65160 + writel(cmd, cfg->regs + S3C_CICOTRGFMT);
65161 + } else {
65162 + assert(cfg->dma_type & CAMIF_PREVIEW);
65163 +
65164 + cmd = readl(cfg->regs + S3C_CIPRTRGFMT);
65165 + cmd &= ~(S3C_CIPRTRGFMT_TARGETHSIZE_PR(0x1fff) |
65166 + S3C_CIPRTRGFMT_TARGETVSIZE_PR(0x1fff));
65167 + cmd |= S3C_CIPRTRGFMT_TARGETHSIZE_PR(cfg->target_x) |
65168 + S3C_CIPRTRGFMT_TARGETVSIZE_PR(cfg->target_y);
65169 +
65170 + if (cfg->dst_fmt & CAMIF_YCBCR420)
65171 + cmd |= S3C_CICOTRGFMT_OUTFORMAT_YCBCR420OUT;
65172 + else if (cfg->dst_fmt & CAMIF_YCBCR422)
65173 + cmd |= S3C_CICOTRGFMT_OUTFORMAT_YCBCR422OUT;
65174 + else if (cfg->dst_fmt & CAMIF_YCBCR422I)
65175 + cmd |= S3C_CICOTRGFMT_OUTFORMAT_YCBCR422OUTINTERLEAVE;
65176 + else if ((cfg->dst_fmt & CAMIF_RGB24) ||
65177 + (cfg->dst_fmt & CAMIF_RGB16))
65178 + cmd |= S3C_CICOTRGFMT_OUTFORMAT_RGBOUT;
65179 + else
65180 + printk(KERN_ERR "Invalid target format\n");
65181 +
65182 + writel(cmd, cfg->regs + S3C_CIPRTRGFMT);
65183 + }
65184 +
65185 + return 0;
65186 +}
65187 +#endif
65188 +
65189 +/*************************************************************************
65190 + * Control part
65191 + ************************************************************************/
65192 +int s3c_camif_control_fimc(camif_cfg_t *cfg)
65193 +{
65194 + if (s3c_camif_request_memory(cfg)) {
65195 + printk(KERN_ERR "Instead of using consistent_alloc(). "
65196 + "Let me use dedicated mem for DMA\n");
65197 + return -1;
65198 + }
65199 +
65200 + s3c_camif_setup_input_path(cfg);
65201 +
65202 + if (s3c_camif_setup_scaler(cfg)) {
65203 + printk(KERN_ERR "Preview scaler fault: "
65204 + "change WinHorOfset or target size\n");
65205 + return 1;
65206 + }
65207 +
65208 + s3c_camif_set_target_format(cfg);
65209 +
65210 + if (s3c_camif_setup_dma(cfg)) {
65211 + printk(KERN_ERR "DMA burst length error\n");
65212 + return 1;
65213 + }
65214 +
65215 + s3c_camif_setup_output_path(cfg);
65216 +
65217 + return 0;
65218 +}
65219 +
65220 +int s3c_camif_start_dma(camif_cfg_t *cfg)
65221 +{
65222 + unsigned int n_cmd = readl(cfg->regs + S3C_CIIMGCPT);
65223 + unsigned int val;
65224 +
65225 + switch(cfg->capture_enable) {
65226 + case CAMIF_BOTH_DMA_ON:
65227 + s3c_camif_reset(CAMIF_RESET, 0); /* Flush Camera Core Buffer */
65228 +
65229 + /* For Codec */
65230 + val = readl(cfg->regs + S3C_CICOSCCTRL);
65231 + val |= S3C_CICOSCCTRL_COSCALERSTART;
65232 + writel(val, cfg->regs + S3C_CICOSCCTRL);
65233 +
65234 + /* For Preview */
65235 + val = readl(cfg->regs + S3C_CIPRSCCTRL);
65236 + val |= S3C_CIPRSCCTRL_START;
65237 + writel(val, cfg->regs + S3C_CIPRSCCTRL);
65238 +
65239 + n_cmd |=
65240 + S3C_CIIMGCPT_IMGCPTEN_COSC | S3C_CIIMGCPT_IMGCPTEN_PRSC;
65241 + break;
65242 +
65243 + case CAMIF_DMA_ON:
65244 + s3c_camif_reset(CAMIF_RESET, 0); /* Flush Camera Core Buffer */
65245 +
65246 + if (cfg->dma_type & CAMIF_CODEC) {
65247 + val = readl(cfg->regs + S3C_CICOSCCTRL);
65248 + val |= S3C_CICOSCCTRL_COSCALERSTART;
65249 + writel(val, cfg->regs + S3C_CICOSCCTRL);
65250 +
65251 + n_cmd |= S3C_CIIMGCPT_IMGCPTEN_COSC;
65252 +
65253 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
65254 + n_cmd |= (1 << 24);
65255 +#endif
65256 + } else {
65257 + val = readl(cfg->regs + S3C_CIPRSCCTRL);
65258 + val |= S3C_CIPRSCCTRL_START;
65259 + writel(val, cfg->regs + S3C_CIPRSCCTRL);
65260 + n_cmd |= S3C_CIIMGCPT_IMGCPTEN_PRSC;
65261 + }
65262 +
65263 + /* wait until Sync Time expires */
65264 + /* First settting, to wait VSYNC fall */
65265 + /* By VESA spec,in 640x480 @60Hz
65266 + MAX Delay Time is around 64us which "while" has.*/
65267 + while (S3C_CICOSTATUS_VSYNC &
65268 + readl(cfg->regs + S3C_CICOSTATUS));
65269 + break;
65270 +
65271 + default:
65272 + break;
65273 + }
65274 +
65275 +#if defined(CONFIG_CPU_S3C2443)
65276 + if (cfg->dma_type & CAMIF_CODEC) {
65277 + if (cfg->dst_fmt & CAMIF_RGB24)
65278 + n_cmd |= 3 << 25;
65279 + else if (cfg->dst_fmt & CAMIF_RGB16)
65280 + n_cmd |= 1 << 25;
65281 + else if (cfg->dst_fmt & CAMIF_YCBCR420)
65282 + n_cmd |= 2 << 25;
65283 + }
65284 +#endif
65285 +
65286 + val = readl(cfg->regs + S3C_CIIMGCPT);
65287 + val &= ~(0x7 << 29);
65288 + writel(val | n_cmd | S3C_CIIMGCPT_IMGCPTEN, cfg->regs + S3C_CIIMGCPT);
65289 +
65290 + return 0;
65291 +}
65292 +
65293 +int s3c_camif_stop_dma(camif_cfg_t *cfg)
65294 +{
65295 + unsigned int n_cmd = readl(cfg->regs + S3C_CIIMGCPT);
65296 + unsigned int val;
65297 +
65298 + switch(cfg->capture_enable) {
65299 + case CAMIF_BOTH_DMA_OFF:
65300 + val = readl(cfg->regs + S3C_CICOSCCTRL);
65301 + val &= ~S3C_CICOSCCTRL_COSCALERSTART;
65302 + writel(val, cfg->regs + S3C_CICOSCCTRL);
65303 +
65304 + val = readl(cfg->regs + S3C_CIPRSCCTRL);
65305 + val &= ~S3C_CIPRSCCTRL_START;
65306 + writel(val, cfg->regs + S3C_CIPRSCCTRL);
65307 +
65308 + n_cmd = 0;
65309 + break;
65310 +
65311 + case CAMIF_DMA_OFF_L_IRQ: /* fall thru */
65312 + case CAMIF_DMA_OFF:
65313 + if (cfg->dma_type & CAMIF_CODEC) {
65314 + val = readl(cfg->regs + S3C_CICOSCCTRL);
65315 + val &= ~S3C_CICOSCCTRL_COSCALERSTART;
65316 + writel(val, cfg->regs + S3C_CICOSCCTRL);
65317 + n_cmd &= ~S3C_CIIMGCPT_IMGCPTEN_COSC;
65318 +
65319 + if (!(n_cmd & S3C_CIIMGCPT_IMGCPTEN_PRSC))
65320 + n_cmd = 0;
65321 + } else {
65322 + val = readl(cfg->regs + S3C_CIPRSCCTRL);
65323 + val &= ~S3C_CIPRSCCTRL_START;
65324 + writel(val, cfg->regs + S3C_CIPRSCCTRL);
65325 +
65326 + n_cmd &= ~S3C_CIIMGCPT_IMGCPTEN_PRSC;
65327 +
65328 + if (!(n_cmd & S3C_CIIMGCPT_IMGCPTEN_COSC))
65329 + n_cmd = 0;
65330 + }
65331 +
65332 + break;
65333 +
65334 + default:
65335 + printk(KERN_ERR "Unexpected DMA control\n");
65336 + }
65337 +
65338 + writel(n_cmd, cfg->regs + S3C_CIIMGCPT);
65339 +
65340 + if (cfg->capture_enable == CAMIF_DMA_OFF_L_IRQ) { /* Last IRQ */
65341 + if (cfg->dma_type & CAMIF_CODEC) {
65342 + val = readl(cfg->regs + S3C_CICOCTRL);
65343 + val |= S3C_CICOCTRL_LASTIRQEN;
65344 + writel(val, cfg->regs + S3C_CICOCTRL);
65345 + } else {
65346 + val = readl(cfg->regs + S3C_CIPRCTRL);
65347 + val |= S3C_CIPRCTRL_LASTIRQEN_ENABLE;
65348 + writel(val, cfg->regs + S3C_CIPRCTRL);
65349 + }
65350 + }
65351 +
65352 + return 0;
65353 +}
65354 +
65355 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65356 +int s3c_camif_start_codec_msdma(camif_cfg_t *cfg)
65357 +{
65358 + int ret = 0;
65359 + u32 val;
65360 +
65361 + val = readl(cfg->regs + S3C_MSCOCTRL);
65362 + val &= ~(1 << 0);
65363 + writel(val, cfg->regs + S3C_MSCOCTRL);
65364 +
65365 + val = readl(cfg->regs + S3C_MSCOCTRL);
65366 + val |= (1 << 0);
65367 + writel(val, cfg->regs + S3C_MSCOCTRL);
65368 +
65369 + return ret;
65370 +}
65371 +#endif
65372 +
65373 +int s3c_camif_start_preview_msdma(camif_cfg_t * cfg)
65374 +{
65375 + unsigned int val;
65376 + int ret = 0;
65377 +
65378 +#if !defined(CONFIG_CPU_S3C6400) && !defined(CONFIG_CPU_S3C6410)
65379 + val = readl(cfg->regs + S3C_CIMSCTRL);
65380 + val &= ~(1 << 0);
65381 + writel(val, cfg->regs + S3C_CIMSCTRL);
65382 +#endif
65383 + val = readl(cfg->regs + S3C_CIMSCTRL);
65384 + val |= (1 << 0);
65385 + writel(val, cfg->regs + S3C_CIMSCTRL);
65386 +
65387 + while(!readl(cfg->regs + S3C_CIMSCTRL) & (1 << 6));
65388 +
65389 + return ret;
65390 +}
65391 +
65392 +void s3c_camif_change_flip(camif_cfg_t *cfg)
65393 +{
65394 + unsigned int cmd = 0;
65395 +
65396 + if (cfg->dma_type & CAMIF_CODEC) {
65397 + cmd = readl(cfg->regs + S3C_CICOTRGFMT);
65398 + cmd &= ~((1 << 14) | (1 << 15));
65399 + cmd |= cfg->flip;
65400 + writel(cmd, cfg->regs + S3C_CICOTRGFMT);
65401 + } else {
65402 + /* if ROT90_Pr == 1, dma burst length must be 4 */
65403 + if (cfg->flip == CAMIF_ROTATE_90 ||
65404 + cfg->flip == CAMIF_FLIP_ROTATE_270) {
65405 + cmd = readl(cfg->regs + S3C_CIPRCTRL);
65406 + cmd &= ~(0x3ff << 14);
65407 + cmd |= (S3C_CICOCTRL_YBURST1_CO(4) |
65408 + S3C_CICOCTRL_YBURST2_CO(4));
65409 + writel(cmd, cfg->regs + S3C_CIPRCTRL);
65410 + }
65411 +
65412 + cmd = readl(cfg->regs + S3C_CIPRTRGFMT);
65413 + cmd &= ~(0x7 << 13);
65414 + cmd |= cfg->flip;
65415 + writel(cmd, cfg->regs + S3C_CIPRTRGFMT);
65416 + }
65417 +}
65418 +
65419 +void s3c_camif_change_effect(camif_cfg_t *cfg)
65420 +{
65421 + unsigned int val = readl(cfg->regs + S3C_CIIMGEFF);
65422 +
65423 + val &= ~((1 << 28) | (1 << 27) | (1 << 26));
65424 +
65425 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65426 + val |= ((1 << 31) | (1 << 30));
65427 +#endif
65428 +
65429 + switch(cfg->effect) {
65430 + case CAMIF_SILHOUETTE:
65431 + val |= S3C_CIIMGEFF_FIN_SILHOUETTE;
65432 + break;
65433 +
65434 + case CAMIF_EMBOSSING:
65435 + val |= S3C_CIIMGEFF_FIN_EMBOSSING;
65436 + break;
65437 +
65438 + case CAMIF_ART_FREEZE:
65439 + val |= S3C_CIIMGEFF_FIN_ARTFREEZE;
65440 + break;
65441 +
65442 + case CAMIF_NEGATIVE:
65443 + val |= S3C_CIIMGEFF_FIN_NEGATIVE;
65444 + break;
65445 +
65446 + case CAMIF_ARBITRARY_CB_CR:
65447 + val |= S3C_CIIMGEFF_FIN_ARBITRARY;
65448 + break;
65449 +
65450 + case CAMIF_BYPASS:
65451 + default:
65452 + break;
65453 + }
65454 +
65455 + writel(val, cfg->regs + S3C_CIIMGEFF);
65456 +}
65457 +
65458 +int s3c_camif_do_postprocess(camif_cfg_t *cfg)
65459 +{
65460 + unsigned int val = readl(cfg->regs + S3C_CIMSCTRL);
65461 +
65462 + if (cfg->dst_fmt & CAMIF_YCBCR420)
65463 + val |= 1 << 1;
65464 + else
65465 + val &= ~(1 << 1);
65466 +
65467 + val &= ~(1 << 0);
65468 + writel(val, cfg->regs + S3C_CIMSCTRL);
65469 +
65470 + val |= 1 << 0;
65471 + writel(val, cfg->regs + S3C_CIMSCTRL);
65472 +
65473 + printk(KERN_INFO "Postprocessing started\n");
65474 +
65475 + while(!readl(cfg->regs + S3C_CIMSCTRL) & (1 << 6));
65476 +
65477 + printk(KERN_INFO "Postprocessing finished\n");
65478 +
65479 + return 0;
65480 +}
65481 +
65482 +int s3c_camif_set_offset(camif_cis_t *cis)
65483 +{
65484 + camif_cfg_t *cfg = s3c_camif_get_fimc_object(CODEC_MINOR);
65485 + unsigned int h = cis->win_hor_ofst; /* Camera input offset ONLY */
65486 + unsigned int v = cis->win_ver_ofst; /* Camera input offset ONLY */
65487 + unsigned int h2 = cis->win_hor_ofst2; /* Camera input offset ONLY */
65488 + unsigned int v2 = cis->win_ver_ofst2; /* Camera input offset ONLY */
65489 +
65490 + /*Clear Overflow */
65491 + writel(S3C_CIWDOFST_CLROVCOFIY | S3C_CIWDOFST_CLROVCOFICB |
65492 + S3C_CIWDOFST_CLROVCOFICR | S3C_CIWDOFST_CLROVPRFICB |
65493 + S3C_CIWDOFST_CLROVPRFICR, cfg->regs + S3C_CIWDOFST);
65494 +
65495 + writel(0, cfg->regs + S3C_CIWDOFST);
65496 +
65497 + if (!h && !v) {
65498 + writel(0, cfg->regs + S3C_CIWDOFST);
65499 + writel(0, cfg->regs + S3C_CIDOWSFT2);
65500 + return 0;
65501 + }
65502 +
65503 + writel(S3C_CIWDOFST_WINOFSEN | S3C_CIWDOFST_WINHOROFST(h) |
65504 + S3C_CIWDOFST_WINVEROFST(v), cfg->regs + S3C_CIWDOFST);
65505 + writel(S3C_CIDOWSFT2_WINHOROFST2(h) | S3C_CIDOWSFT2_WINVEROFST2(v),
65506 + cfg->regs + S3C_CIDOWSFT2);
65507 + writel(S3C_CIDOWSFT2_WINHOROFST2(h2) | S3C_CIDOWSFT2_WINVEROFST2(v2),
65508 + cfg->regs + S3C_CIDOWSFT2);
65509 +
65510 + return 0;
65511 +}
65512 +
65513 +void s3c_camif_set_priority(int flag)
65514 +{
65515 + unsigned int val;
65516 +
65517 + if (flag) {
65518 + irq_old_priority = readl(S3C64XX_PRIORITY);
65519 + val = irq_old_priority;
65520 + val &= ~(3 << 7);
65521 + writel(val, S3C64XX_PRIORITY);
65522 +
65523 + /* Arbiter 1, REQ2 first */
65524 + val |= (1 << 7);
65525 + writel(val, S3C64XX_PRIORITY);
65526 +
65527 + /* Disable Priority Rotate */
65528 + val &= ~(1 << 1);
65529 + writel(val, S3C64XX_PRIORITY);
65530 + } else
65531 + writel(irq_old_priority, S3C64XX_PRIORITY);
65532 +}
65533 +
65534 +/*************************************************************************
65535 + * Interrupt part
65536 + ************************************************************************/
65537 +void s3c_camif_enable_lastirq(camif_cfg_t *cfg)
65538 +{
65539 + unsigned int val;
65540 +
65541 + if (cfg->capture_enable == CAMIF_BOTH_DMA_ON ||
65542 + (cfg->dma_type & CAMIF_CODEC)) {
65543 + val = readl(cfg->regs + S3C_CICOCTRL);
65544 + val |= S3C_CICOCTRL_LASTIRQEN;
65545 + writel(val, cfg->regs + S3C_CICOCTRL);
65546 + }
65547 +
65548 + if (cfg->capture_enable == CAMIF_BOTH_DMA_ON ||
65549 + !(cfg->dma_type & CAMIF_CODEC)) {
65550 + val = readl(cfg->regs + S3C_CIPRCTRL);
65551 + val |= S3C_CIPRCTRL_LASTIRQEN_ENABLE;
65552 + writel(val, cfg->regs + S3C_CIPRCTRL);
65553 + }
65554 +}
65555 +
65556 +void s3c_camif_disable_lastirq(camif_cfg_t *cfg)
65557 +{
65558 + unsigned int val;
65559 +
65560 + if (cfg->capture_enable == CAMIF_BOTH_DMA_ON ||
65561 + (cfg->dma_type & CAMIF_CODEC)) {
65562 + val = readl(cfg->regs + S3C_CICOCTRL);
65563 + val &= ~S3C_CICOCTRL_LASTIRQEN;
65564 + writel(val, cfg->regs + S3C_CICOCTRL);
65565 + }
65566 +
65567 + if (cfg->capture_enable == CAMIF_BOTH_DMA_ON ||
65568 + !(cfg->dma_type & CAMIF_CODEC)) {
65569 + val = readl(cfg->regs + S3C_CIPRCTRL);
65570 + val &= ~S3C_CIPRCTRL_LASTIRQEN_ENABLE;
65571 + writel(val, cfg->regs + S3C_CIPRCTRL);
65572 + }
65573 +}
65574 +
65575 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65576 +void s3c_camif_clear_irq(int irq)
65577 +{
65578 + camif_cfg_t *cfg = s3c_camif_get_fimc_object(CODEC_MINOR);
65579 + unsigned int val = 0;
65580 +
65581 + if (irq == IRQ_CAMIF_C) {
65582 + val = readl(cfg->regs + S3C_CIGCTRL);
65583 + val |= (1 << 19);
65584 + } else if (irq == IRQ_CAMIF_P) {
65585 + val = readl(cfg->regs + S3C_CIGCTRL);
65586 + val |= (1 << 18);
65587 + }
65588 +
65589 + writel(val, cfg->regs + S3C_CIGCTRL);
65590 +}
65591 +#else
65592 +void s3c_camif_clear_irq(int irq)
65593 +{
65594 +}
65595 +#endif
65596 +
65597 +/*************************************************************************
65598 + * Initialize part
65599 + ************************************************************************/
65600 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
65601 +static int s3c_camif_set_gpio(void)
65602 +{
65603 + s3c2410_gpio_cfgpin(S3C2440_GPJ0, S3C2440_GPJ0_CAMDATA0);
65604 + s3c2410_gpio_cfgpin(S3C2440_GPJ1, S3C2440_GPJ1_CAMDATA1);
65605 + s3c2410_gpio_cfgpin(S3C2440_GPJ2, S3C2440_GPJ2_CAMDATA2);
65606 + s3c2410_gpio_cfgpin(S3C2440_GPJ3, S3C2440_GPJ3_CAMDATA3);
65607 + s3c2410_gpio_cfgpin(S3C2440_GPJ4, S3C2440_GPJ4_CAMDATA4);
65608 + s3c2410_gpio_cfgpin(S3C2440_GPJ5, S3C2440_GPJ5_CAMDATA5);
65609 + s3c2410_gpio_cfgpin(S3C2440_GPJ6, S3C2440_GPJ6_CAMDATA6);
65610 + s3c2410_gpio_cfgpin(S3C2440_GPJ7, S3C2440_GPJ7_CAMDATA7);
65611 + s3c2410_gpio_cfgpin(S3C2440_GPJ8, S3C2440_GPJ8_CAMPCLK);
65612 + s3c2410_gpio_cfgpin(S3C2440_GPJ9, S3C2440_GPJ9_CAMVSYNC);
65613 + s3c2410_gpio_cfgpin(S3C2440_GPJ10, S3C2440_GPJ10_CAMHREF);
65614 + s3c2410_gpio_cfgpin(S3C2440_GPJ11, S3C2440_GPJ11_CAMCLKOUT);
65615 + s3c2410_gpio_cfgpin(S3C2440_GPJ12, S3C2440_GPJ12_CAMRESET);
65616 +
65617 + writel(0x1fff, S3C2443_GPJDN);
65618 +
65619 + return 0;
65620 +}
65621 +#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65622 +static int s3c_camif_set_gpio(void)
65623 +{
65624 + s3c_gpio_cfgpin(S3C64XX_GPF(5), S3C64XX_GPF5_CAMIF_YDATA0);
65625 + s3c_gpio_cfgpin(S3C64XX_GPF(6), S3C64XX_GPF6_CAMIF_YDATA1);
65626 + s3c_gpio_cfgpin(S3C64XX_GPF(7), S3C64XX_GPF7_CAMIF_YDATA2);
65627 + s3c_gpio_cfgpin(S3C64XX_GPF(8), S3C64XX_GPF8_CAMIF_YDATA3);
65628 + s3c_gpio_cfgpin(S3C64XX_GPF(9), S3C64XX_GPF9_CAMIF_YDATA4);
65629 + s3c_gpio_cfgpin(S3C64XX_GPF(10), S3C64XX_GPF10_CAMIF_YDATA5);
65630 + s3c_gpio_cfgpin(S3C64XX_GPF(11), S3C64XX_GPF11_CAMIF_YDATA6);
65631 + s3c_gpio_cfgpin(S3C64XX_GPF(12), S3C64XX_GPF12_CAMIF_YDATA7);
65632 + s3c_gpio_cfgpin(S3C64XX_GPF(2), S3C64XX_GPF2_CAMIF_PCLK);
65633 + s3c_gpio_cfgpin(S3C64XX_GPF(4), S3C64XX_GPF4_CAMIF_VSYNC);
65634 + s3c_gpio_cfgpin(S3C64XX_GPF(1), S3C64XX_GPF1_CAMIF_HREF);
65635 + s3c_gpio_cfgpin(S3C64XX_GPF(0), S3C64XX_GPF0_CAMIF_CLK);
65636 + s3c_gpio_cfgpin(S3C64XX_GPF(3), S3C64XX_GPF3_CAMIF_nRST);
65637 +
65638 + writel(0, S3C64XX_GPFPUD);
65639 +
65640 + return 0;
65641 +}
65642 +#endif
65643 +
65644 +void s3c_camif_reset(int is, int delay)
65645 +{
65646 + camif_cfg_t *cfg = s3c_camif_get_fimc_object(CODEC_MINOR);
65647 + unsigned int val;
65648 + unsigned int tmp;
65649 +
65650 + switch (is) {
65651 + case CAMIF_RESET:
65652 + tmp = readl(cfg->regs + S3C_CISRCFMT);
65653 +
65654 + if (tmp &= (1 << 31)) {
65655 + /* ITU-R BT 601 */
65656 + val = readl(cfg->regs + S3C_CIGCTRL);
65657 + val |= S3C_CIGCTRL_SWRST;
65658 +
65659 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65660 + val |= S3C_CIGCTRL_IRQ_LEVEL;
65661 +#endif
65662 + writel(val, cfg->regs + S3C_CIGCTRL);
65663 + mdelay(1);
65664 +
65665 + val = readl(cfg->regs + S3C_CIGCTRL);
65666 + val &= ~S3C_CIGCTRL_SWRST;
65667 + writel(val, cfg->regs + S3C_CIGCTRL);
65668 + } else {
65669 + /* ITU-R BT 656 */
65670 + tmp = readl(cfg->regs + S3C_CISRCFMT);
65671 + tmp |= (1 << 31);
65672 + writel(tmp, cfg->regs + S3C_CISRCFMT);
65673 +
65674 + val = readl(cfg->regs + S3C_CIGCTRL);
65675 + val |= S3C_CIGCTRL_SWRST;
65676 +
65677 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65678 + val |= S3C_CIGCTRL_IRQ_LEVEL;
65679 +#endif
65680 + writel(val, cfg->regs + S3C_CIGCTRL);
65681 + mdelay(1);
65682 +
65683 + val = readl(cfg->regs + S3C_CIGCTRL);
65684 + val &= ~S3C_CIGCTRL_SWRST;
65685 + writel(val, cfg->regs + S3C_CIGCTRL);
65686 +
65687 + tmp = readl(cfg->regs + S3C_CISRCFMT);
65688 + tmp &= ~(1 << 31);
65689 + writel(tmp, cfg->regs + S3C_CISRCFMT);
65690 + }
65691 +
65692 + break;
65693 +
65694 + case CAMIF_EX_RESET_AH:
65695 + val = readl(cfg->regs + S3C_CIGCTRL);
65696 + val |= S3C_CIGCTRL_CAMRST;
65697 + writel(val, cfg->regs + S3C_CIGCTRL);
65698 + udelay(200);
65699 +
65700 + val = readl(cfg->regs + S3C_CIGCTRL);
65701 + val &= ~S3C_CIGCTRL_CAMRST;
65702 + writel(val, cfg->regs + S3C_CIGCTRL);
65703 + udelay(delay);
65704 +
65705 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K3AA)
65706 + val = readl(cfg->regs + S3C_CIGCTRL);
65707 + val |= S3C_CIGCTRL_CAMRST;
65708 + writel(val, cfg->regs + S3C_CIGCTRL);
65709 + udelay(200);
65710 +#endif
65711 + break;
65712 +
65713 + case CAMIF_EX_RESET_AL:
65714 + val = readl(cfg->regs + S3C_CIGCTRL);
65715 + val &= ~S3C_CIGCTRL_CAMRST;
65716 + writel(val, cfg->regs + S3C_CIGCTRL);
65717 + udelay(200);
65718 +
65719 + val = readl(cfg->regs + S3C_CIGCTRL);
65720 + val |= S3C_CIGCTRL_CAMRST;
65721 + writel(val, cfg->regs + S3C_CIGCTRL);
65722 + udelay(delay);
65723 + break;
65724 +
65725 + default:
65726 + break;
65727 + }
65728 +}
65729 +
65730 +void s3c_camif_init(void)
65731 +{
65732 + s3c_camif_reset(CAMIF_RESET, 0);
65733 + s3c_camif_set_gpio();
65734 +}
65735 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/media/video/s3c_camif.h linux-2.6.29-rc3.owrt.om/drivers/media/video/s3c_camif.h
65736 --- linux-2.6.29-rc3.owrt/drivers/media/video/s3c_camif.h 1970-01-01 01:00:00.000000000 +0100
65737 +++ linux-2.6.29-rc3.owrt.om/drivers/media/video/s3c_camif.h 2009-05-10 22:27:59.000000000 +0200
65738 @@ -0,0 +1,404 @@
65739 +/* drivers/media/video/s3c_camif.h
65740 + *
65741 + * Copyright (c) 2008 Samsung Electronics
65742 + *
65743 + * Samsung S3C Camera driver
65744 + *
65745 + * This program is free software; you can redistribute it and/or modify
65746 + * it under the terms of the GNU General Public License as published by
65747 + * the Free Software Foundation; either version 2 of the License, or
65748 + * (at your option) any later version.
65749 + *
65750 + * This program is distributed in the hope that it will be useful,
65751 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
65752 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
65753 + * GNU General Public License for more details.
65754 + *
65755 + * You should have received a copy of the GNU General Public License
65756 + * along with this program; if not, write to the Free Software
65757 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
65758 + */
65759 +
65760 +#ifndef __S3C_CAMIF_H_
65761 +#define __S3C_CAMIF_H_
65762 +
65763 +#ifdef __KERNEL__
65764 +#include <linux/videodev.h>
65765 +#include <linux/videodev2.h>
65766 +#include <asm/types.h>
65767 +#include <linux/i2c.h>
65768 +#include <linux/video_decoder.h>
65769 +#endif /* __KERNEL__ */
65770 +
65771 +#if !defined(O_NONCAP)
65772 +#define O_NONCAP O_TRUNC
65773 +#endif
65774 +
65775 +#if defined(CAMIF_DEBUG)
65776 +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
65777 +#else
65778 +#define DPRINTK(fmt, args...)
65779 +#endif
65780 +
65781 +#if defined(CAMIF_DEBUG)
65782 +#define assert(expr) \
65783 + if(!(expr)) { \
65784 + printk( "Assertion failed! %s,%s,%s,line=%d\n", \
65785 + #expr,__FILE__,__FUNCTION__,__LINE__); \
65786 + }
65787 +#else
65788 +#define assert(expr)
65789 +#endif
65790 +
65791 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65792 +#define MEM_SIZE 0x08000000
65793 +#define FIMC_VER "3.0"
65794 +#elif defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
65795 +#define MEM_SIZE 0x04000000
65796 +#define FIMC_VER "2.3"
65797 +#else
65798 +#define MEM_SIZE 0x04000000
65799 +#define FIMC_VER "2.x"
65800 +#endif
65801 +
65802 +#undef FSM_ON_PREVIEW
65803 +#define FSM_ON_CODEC
65804 +
65805 +#undef USE_LAST_IRQ /* turn on if pp count is 1 */
65806 +
65807 +#define CODEC_DEV_NAME "CAMIF_CODEC"
65808 +#define PREVIEW_DEV_NAME "CAMIF_PREVIEW"
65809 +
65810 +#define CAMIF_DEV_NUM 2
65811 +#define FIMC_CODEC_INDEX 0
65812 +#define FIMC_PREVIEW_INDEX 1
65813 +
65814 +#define BURST_ERR 1
65815 +#define RESERVED_MEM (15 * 1024 * 1024)
65816 +#define YUV_MEM (10 * 1024 * 1024)
65817 +#define RGB_MEM (RESERVED_MEM - YUV_MEM)
65818 +
65819 +#define CODEC_DEFAULT_WIDTH 640
65820 +#define CODEC_DEFAULT_HEIGHT 480
65821 +#define PREVIEW_DEFAULT_WIDTH 640
65822 +#define PREVIEW_DEFAULT_HEIGHT 480
65823 +
65824 +#define CROP_DEFAULT_WIDTH 352
65825 +#define CROP_DEFAULT_HEIGHT 272
65826 +
65827 +#define CODEC_DEFAULT_PPNUM 4
65828 +#define PREVIEW_DEFAULT_PPNUM 4
65829 +
65830 +#define CODEC_MINOR 12
65831 +#define PREVIEW_MINOR 13
65832 +
65833 +#define CHECK_FREQ 5
65834 +#define INSTANT_SKIP 0
65835 +#define INSTANT_GO 1
65836 +
65837 +#define VID_HARDWARE_SAMSUNG_FIMC3X 236
65838 +
65839 +#define ZOOM_AT_A_TIME_IN_PIXELS 32
65840 +#define ZOOM_IN_MAX 640
65841 +
65842 +/* Codec or Preview Status */
65843 +#define CAMIF_STARTED (1 << 1)
65844 +#define CAMIF_STOPPED (1 << 2)
65845 +#define CAMIF_INT_HAPPEN (1 << 3)
65846 +
65847 +/* Codec or Preview : Interrupt FSM */
65848 +#define CAMIF_1st_INT (1 << 7)
65849 +#define CAMIF_Xth_INT (1 << 8)
65850 +#define CAMIF_Yth_INT (1 << 9)
65851 +#define CAMIF_Zth_INT (1 << 10)
65852 +#define CAMIF_NORMAL_INT (1 << 11)
65853 +#define CAMIF_DUMMY_INT (1 << 12)
65854 +#define CAMIF_CONTINUOUS_INT (1 << 13)
65855 +#define CAMIF_SET_LAST_INT (1 << 14)
65856 +#define CAMIF_STOP_CAPTURE (1 << 15)
65857 +#define CAMIF_LAST_IRQ (1 << 16)
65858 +#define CAMIF_PENDING_INT 0
65859 +
65860 +#define CAMIF_CAPTURE_SKIP_FRAMES 5
65861 +
65862 +/* CAMIF RESET Definition */
65863 +#define CAMIF_RESET (1 << 0)
65864 +#define CAMIF_EX_RESET_AL (1 << 1) /* Active Low */
65865 +#define CAMIF_EX_RESET_AH (1 << 2) /* Active High */
65866 +
65867 +#define USER_EXIT (1 << 2)
65868 +#define USER_ADD (1 << 1)
65869 +#define SENSOR_INIT (1 << 0)
65870 +
65871 +#define SENSOR_MAX 255
65872 +#define SENSOR_QSVGA (1 << 12)
65873 +#define SENSOR_UXGA (1 << 11)
65874 +#define SENSOR_SVGA (1 << 10)
65875 +#define SENSOR_SXGA (1 << 4)
65876 +#define SENSOR_VGA (1 << 3)
65877 +#define SENSOR_DEFAULT 0
65878 +
65879 +#define SENSOR_WB (1 << 9)
65880 +#define SENSOR_AF (1 << 8)
65881 +#define SENSOR_MIRROR (1 << 7)
65882 +#define SENSOR_ZOOMOUT (1 << 6)
65883 +#define SENSOR_ZOOMIN (1 << 5)
65884 +
65885 +/* Global Status Definition */
65886 +#define PWANT2START (1 << 0)
65887 +#define CWANT2START (1 << 1)
65888 +#define BOTH_STARTED (PWANT2START | CWANT2START)
65889 +#define P_NOT_WORKING (1 << 4)
65890 +#define C_WORKING (1 << 5)
65891 +#define P_WORKING (1 << 6)
65892 +#define C_NOT_WORKING (1 << 7)
65893 +
65894 +#define FORMAT_FLAGS_DITHER 0x01
65895 +#define FORMAT_FLAGS_PACKED 0x02
65896 +#define FORMAT_FLAGS_PLANAR 0x04
65897 +#define FORMAT_FLAGS_RAW 0x08
65898 +#define FORMAT_FLAGS_CrCb 0x10
65899 +
65900 +enum camif_itu_fmt {
65901 + CAMIF_ITU601 = (1 << 31),
65902 + CAMIF_ITU656 = 0,
65903 +};
65904 +
65905 +/* It is possbie to use two device simultaneously */
65906 +enum camif_dma_type {
65907 + CAMIF_PREVIEW = (1 << 0),
65908 + CAMIF_CODEC = (1 << 1),
65909 +};
65910 +
65911 +enum camif_order422 {
65912 + CAMIF_YCBYCR = 0,
65913 + CAMIF_YCRYCB = (1 << 14),
65914 + CAMIF_CBYCRY = (1 << 15),
65915 + CAMIF_CRYCBY = (1 << 15) | (1 << 14),
65916 +};
65917 +
65918 +enum flip_mode {
65919 + CAMIF_FLIP = 0,
65920 + CAMIF_ROTATE_90 = (1 << 13),
65921 + CAMIF_FLIP_X = (1 << 14),
65922 + CAMIF_FLIP_Y = (1 << 15),
65923 + CAMIF_FLIP_MIRROR = (1 << 15) | (1 << 14),
65924 + CAMIF_FLIP_ROTATE_270 = (1 << 15) | (1 << 14) | (1 << 13),
65925 +};
65926 +
65927 +enum camif_fmt {
65928 + CAMIF_YCBCR420 = (1 << 0),
65929 + CAMIF_YCBCR422 = (1 << 1),
65930 + CAMIF_YCBCR422I = (1 << 2),
65931 + CAMIF_RGB16 = (1 << 3),
65932 + CAMIF_RGB24 = (1 << 4),
65933 + CAMIF_RGB32 = (1 << 5),
65934 +};
65935 +
65936 +enum camif_capturing {
65937 + CAMIF_BOTH_DMA_ON = (1 << 4),
65938 + CAMIF_DMA_ON = (1 << 3),
65939 + CAMIF_BOTH_DMA_OFF = (1 << 1),
65940 + CAMIF_DMA_OFF = (1 << 0),
65941 + CAMIF_DMA_OFF_L_IRQ = (1 << 5),
65942 +};
65943 +
65944 +enum image_effect {
65945 + CAMIF_BYPASS,
65946 + CAMIF_ARBITRARY_CB_CR,
65947 + CAMIF_NEGATIVE,
65948 + CAMIF_ART_FREEZE,
65949 + CAMIF_EMBOSSING ,
65950 + CAMIF_SILHOUETTE,
65951 +};
65952 +
65953 +enum input_channel{
65954 + CAMERA_INPUT,
65955 + MSDMA_FROM_CODEC,
65956 + MSDMA_FROM_PREVIEW,
65957 +};
65958 +
65959 +enum output_channel{
65960 + CAMIF_OUT_PP,
65961 + CAMIF_OUT_FIFO,
65962 +};
65963 +
65964 +typedef struct camif_performance
65965 +{
65966 + int frames;
65967 + int framesdropped;
65968 + __u64 bytesin;
65969 + __u64 bytesout;
65970 + __u32 reserved[4];
65971 +} camif_perf_t;
65972 +
65973 +typedef struct {
65974 + dma_addr_t phys_y;
65975 + dma_addr_t phys_cb;
65976 + dma_addr_t phys_cr;
65977 + u8 *virt_y;
65978 + u8 *virt_cb;
65979 + u8 *virt_cr;
65980 + dma_addr_t phys_rgb;
65981 + u8 *virt_rgb;
65982 +} img_buf_t;
65983 +
65984 +/* this structure convers the CIWDOFFST, prescaler, mainscaler */
65985 +typedef struct {
65986 + u32 modified_src_x; /* After windows applyed to source_x */
65987 + u32 modified_src_y;
65988 + u32 hfactor;
65989 + u32 vfactor;
65990 + u32 shfactor; /* SHfactor = 10 - ( hfactor + vfactor ) */
65991 + u32 prehratio;
65992 + u32 prevratio;
65993 + u32 predst_x;
65994 + u32 predst_y;
65995 + u32 scaleup_h;
65996 + u32 scaleup_v;
65997 + u32 mainhratio;
65998 + u32 mainvratio;
65999 + u32 scalerbypass; /* only codec */
66000 + u32 zoom_in_cnt;
66001 +} scaler_t;
66002 +
66003 +enum v4l2_status {
66004 + CAMIF_V4L2_INIT = (1 << 0),
66005 + CAMIF_v4L2_DIRTY = (1 << 1),
66006 +};
66007 +
66008 +typedef struct {
66009 + struct semaphore lock;
66010 + enum camif_itu_fmt itu_fmt;
66011 + enum camif_order422 order422;
66012 + struct i2c_client *sensor;
66013 + u32 win_hor_ofst;
66014 + u32 win_ver_ofst;
66015 + u32 win_hor_ofst2;
66016 + u32 win_ver_ofst2;
66017 + u32 camclk; /* External Image Sensor Camera Clock */
66018 + u32 source_x;
66019 + u32 source_y;
66020 + u32 polarity_pclk;
66021 + u32 polarity_vsync;
66022 + u32 polarity_href;
66023 + u32 user; /* MAX 2 (codec, preview) */
66024 + u32 irq_old_priority; /* BUS PRIORITY register */
66025 + u32 status;
66026 + u32 init_sensor; /* initializing sensor */
66027 + u32 reset_type; /* External Sensor Reset Type */
66028 + u32 reset_udelay;
66029 + u32 zoom_in_cnt;
66030 +} camif_cis_t;
66031 +
66032 +/* when App want to change v4l2 parameter,
66033 + * we instantly store it into v4l2_t v2
66034 + * and then reflect it to hardware
66035 + */
66036 +typedef struct v4l2 {
66037 + struct v4l2_fmtdesc *fmtdesc;
66038 + struct v4l2_framebuffer frmbuf; /* current frame buffer */
66039 + struct v4l2_input *input;
66040 + struct v4l2_output *output;
66041 + enum v4l2_status status;
66042 +
66043 + /* crop */
66044 + struct v4l2_rect crop_bounds;
66045 + struct v4l2_rect crop_defrect;
66046 + struct v4l2_rect crop_current;
66047 +
66048 +} v4l2_t;
66049 +
66050 +
66051 +typedef struct camif_c_t {
66052 + struct video_device *v;
66053 +
66054 + /* V4L2 param only for v4l2 driver */
66055 + v4l2_t v2;
66056 + camif_cis_t *cis; /* Common between Codec and Preview */
66057 +
66058 + /* logical parameter */
66059 + wait_queue_head_t waitq;
66060 + u32 status; /* Start/Stop */
66061 + u32 fsm; /* Start/Stop */
66062 + u32 open_count; /* duplicated */
66063 + int irq;
66064 + char shortname[16];
66065 + u32 target_x;
66066 + u32 target_y;
66067 + scaler_t sc;
66068 + enum flip_mode flip;
66069 + enum image_effect effect;
66070 + enum camif_dma_type dma_type;
66071 +
66072 + /* 4 pingpong Frame memory */
66073 + u8 *pp_virt_buf;
66074 + dma_addr_t pp_phys_buf;
66075 + u32 pp_totalsize;
66076 + u32 pp_num; /* used pingpong memory number */
66077 + img_buf_t img_buf[4];
66078 + enum camif_fmt src_fmt;
66079 + enum camif_fmt dst_fmt;
66080 + enum camif_capturing capture_enable;
66081 + camif_perf_t perf;
66082 + u32 cur_frame_num;
66083 + u32 auto_restart; /* Only For Preview */
66084 + int input_channel;
66085 + int output_channel;
66086 + int buffer_size;
66087 + void *other; /* other camif_cfg_t */
66088 + u32 msdma_status; /* 0 : stop, 1 : start */
66089 + void __iomem *regs;
66090 +} camif_cfg_t;
66091 +
66092 +/* Test Application Usage */
66093 +typedef struct {
66094 + int src_x;
66095 + int src_y;
66096 + int dst_x;
66097 + int dst_y;
66098 + int src_fmt;
66099 + int dst_fmt;
66100 + int flip;
66101 + int awb;
66102 + int effect;
66103 + int input_channel;
66104 + int output_channel;
66105 + unsigned int h_offset;
66106 + unsigned int v_offset;
66107 + unsigned int h_offset2;
66108 + unsigned int v_offset2;
66109 +} camif_param_t;
66110 +
66111 +/* Externs */
66112 +extern camif_cfg_t* s3c_camif_get_fimc_object(int);
66113 +extern int s3c_camif_start_dma(camif_cfg_t *);
66114 +extern int s3c_camif_stop_dma(camif_cfg_t *);
66115 +extern int s3c_camif_get_frame_num(camif_cfg_t *);
66116 +extern unsigned char* s3c_camif_get_frame(camif_cfg_t *);
66117 +extern int s3c_camif_control_fimc(camif_cfg_t *);
66118 +extern void s3c_camif_reset(int, int);
66119 +extern void s3c_camif_init(void);
66120 +extern int s3c_camif_get_fifo_status(camif_cfg_t *);
66121 +extern void s3c_camif_enable_lastirq(camif_cfg_t *);
66122 +extern void s3c_camif_disable_lastirq(camif_cfg_t *);
66123 +extern void s3c_camif_change_flip(camif_cfg_t *);
66124 +extern void s3c_camif_change_effect(camif_cfg_t *);
66125 +extern int s3c_camif_start_codec_msdma(camif_cfg_t *);
66126 +extern int s3c_camif_set_clock(unsigned int camclk);
66127 +extern void s3c_camif_disable_clock(void);
66128 +extern int s3c_camif_start_preview_msdma(camif_cfg_t *);
66129 +extern camif_cis_t* get_initialized_cis(void);
66130 +extern void s3c_camif_clear_irq(int);
66131 +extern int s3c_camif_set_source_format(camif_cis_t *);
66132 +extern void s3c_camif_register_sensor(struct i2c_client *);
66133 +extern void s3c_camif_unregister_sensor(struct i2c_client*);
66134 +extern int s3c_camif_setup_dma(camif_cfg_t *);
66135 +extern void s3c_camif_init_sensor(camif_cfg_t *);
66136 +extern int s3c_camif_set_offset(camif_cis_t *);
66137 +extern void s3c_camif_set_priority(int);
66138 +extern void s3c_camif_open_sensor(camif_cis_t *);
66139 +extern void s3c_camif_set_polarity(camif_cfg_t *cfg);
66140 +
66141 +#endif
66142 +
66143 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/media/video/samsung/4xa_sensor.c linux-2.6.29-rc3.owrt.om/drivers/media/video/samsung/4xa_sensor.c
66144 --- linux-2.6.29-rc3.owrt/drivers/media/video/samsung/4xa_sensor.c 1970-01-01 01:00:00.000000000 +0100
66145 +++ linux-2.6.29-rc3.owrt.om/drivers/media/video/samsung/4xa_sensor.c 2009-05-10 22:27:59.000000000 +0200
66146 @@ -0,0 +1,384 @@
66147 +/*
66148 + * Copyright (C) 2004 Samsung Electronics
66149 + * SW.LEE <hitchcar@samsung.com>
66150 + * - based on Russell King : pcf8583.c
66151 + * - added smdk24a0, smdk2440
66152 + * - added poseidon (s3c24a0+wavecom)
66153 + *
66154 + * This program is free software; you can redistribute it and/or modify
66155 + * it under the terms of the GNU General Public License version 2 as
66156 + * published by the Free Software Foundation.
66157 + *
66158 + * Driver for FIMC2.x Camera Decoder
66159 + *
66160 + */
66161 +
66162 +//#include <linux/config.h>
66163 +#include <linux/module.h>
66164 +#include <linux/kernel.h>
66165 +#include <linux/init.h>
66166 +#include <linux/i2c.h>
66167 +#include <linux/i2c-id.h>
66168 +#include <linux/slab.h>
66169 +#include <linux/string.h>
66170 +#include <linux/init.h>
66171 +#include <linux/delay.h>
66172 +
66173 +//#define CAMIF_DEBUG
66174 +
66175 +#include "../s3c_camif.h"
66176 +#include "4xa_sensor.h"
66177 +
66178 +
66179 +/*
66180 + * Samsung's original code:
66181 + * .camclk = 44000000, / * for 20 fps: 44MHz, for 12 fps (more
66182 + * stable): 26MHz * /
66183 + *
66184 + * Experimenting with the controls yielded the following:
66185 + *
66186 + * PLL_CLK gets divided according to TCMD.Div8_r (1,00h) and then by
66187 + * SEL_MAIN.Half_PCLK_Enable (5,8Fh) until it finally becomes PCLK.
66188 + *
66189 + * Div8_r = 0: 1/4, 1: 1/2 (default)
66190 + * Half_PCLK_Enable = 0: 1/1 (default), 1: 1/2
66191 + *
66192 + * Thus our 26.6 MHz MCLK becomes an 87.78 MHz PLL_CLK and eventually a PCLK
66193 + * of 43.89 MHz.
66194 + */
66195 +
66196 +#define CAMCLK 26600000 /* 26.6 MHz */
66197 +
66198 +
66199 +static struct i2c_driver sensor_driver;
66200 +
66201 +/* This is an abstract CIS sensor for MSDMA input. */
66202 +
66203 +camif_cis_t msdma_input = {
66204 + .itu_fmt = CAMIF_ITU601,
66205 + .order422 = CAMIF_CBYCRY, /* another case: YCRYCB */
66206 + .camclk = CAMCLK,
66207 + .source_x = 800,
66208 + .source_y = 600,
66209 + .win_hor_ofst = 0,
66210 + .win_ver_ofst = 0,
66211 + .win_hor_ofst2 = 0,
66212 + .win_ver_ofst2 = 0,
66213 + .polarity_pclk = 0,
66214 + .polarity_vsync = 1,
66215 + .polarity_href = 0,
66216 + .reset_type = CAMIF_EX_RESET_AL,
66217 + .reset_udelay = 5000,
66218 +};
66219 +
66220 +camif_cis_t interlace_input = {
66221 + .itu_fmt = CAMIF_ITU601,
66222 + .order422 = CAMIF_CBYCRY, /* another case: YCRYCB */
66223 + .camclk = CAMCLK,
66224 + .source_x = 800,
66225 + .source_y = 600,
66226 + .win_hor_ofst = 0,
66227 + .win_ver_ofst = 0,
66228 + .win_hor_ofst2 = 0,
66229 + .win_ver_ofst2 = 0,
66230 + .polarity_pclk = 0,
66231 + .polarity_vsync = 1,
66232 + .polarity_href = 0,
66233 + .reset_type = CAMIF_EX_RESET_AL,
66234 + .reset_udelay = 5000,
66235 +};
66236 +
66237 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
66238 +static camif_cis_t data = {
66239 + .itu_fmt = CAMIF_ITU601,
66240 + .order422 = CAMIF_YCBYCR,
66241 + .camclk = CAMCLK,
66242 + .source_x = 800,
66243 + .source_y = 600,
66244 + .win_hor_ofst = 0,
66245 + .win_ver_ofst = 0,
66246 + .win_hor_ofst2 = 0,
66247 + .win_ver_ofst2 = 0,
66248 + .polarity_pclk = 0,
66249 + .polarity_vsync = 1,
66250 + .polarity_href = 0,
66251 + .reset_type = CAMIF_EX_RESET_AL,
66252 + .reset_udelay = 5000,
66253 +};
66254 +
66255 +s5k4xa_t s5k4ba_regs_mirror[S5K4BA_REGS];
66256 +#else
66257 +#error No samsung CIS moudule here !
66258 +#endif
66259 +
66260 +camif_cis_t* get_initialized_cis(void)
66261 +{
66262 + if (data.init_sensor == 0)
66263 + return NULL;
66264 +
66265 + return &data;
66266 +}
66267 +
66268 +#define CAM_ID 0x5a
66269 +
66270 +static unsigned short ignore[] = { I2C_CLIENT_END };
66271 +static unsigned short normal_addr[] = { CAM_ID >> 1, I2C_CLIENT_END };
66272 +static const unsigned short *forces[] = { NULL };
66273 +
66274 +static struct i2c_client_address_data addr_data = {
66275 + .normal_i2c = normal_addr,
66276 + .probe = ignore,
66277 + .ignore = ignore,
66278 + .forces = forces,
66279 +};
66280 +
66281 +
66282 +static unsigned char sensor_read(struct i2c_client *client,
66283 + unsigned char subaddr)
66284 +{
66285 + unsigned char buf = subaddr;
66286 + struct i2c_msg msg = {
66287 + .addr = client->addr,
66288 + .flags = 0,
66289 + .len = 1,
66290 + .buf = &buf,
66291 + };
66292 +
66293 + if (i2c_transfer(client->adapter, &msg, 1) != 1) {
66294 + printk(" I2C write Error\n");
66295 + return -EIO;
66296 + }
66297 +
66298 + msg.flags = I2C_M_RD;
66299 + if (i2c_transfer(client->adapter, &msg, 1) != 1) {
66300 + printk(" I2C read Error\n");
66301 + return -EIO;
66302 + }
66303 +
66304 + return buf;
66305 +}
66306 +
66307 +static int
66308 +sensor_write(struct i2c_client *client,
66309 + unsigned char subaddr, unsigned char val)
66310 +{
66311 + unsigned char buf[2];
66312 + struct i2c_msg msg = {
66313 + .addr = client->addr,
66314 + .flags = 0,
66315 + .len = 2,
66316 + .buf = buf,
66317 + };
66318 +
66319 + buf[0] = subaddr;
66320 + buf[1] = val;
66321 +
66322 + return i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EIO;
66323 +}
66324 +
66325 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
66326 +void inline sensor_init(struct i2c_client *sam_client)
66327 +{
66328 + int i;
66329 +
66330 + i = ARRAY_SIZE(s5k4ba_reg);
66331 + for (i = 0; i < S5K4BA_INIT_REGS; i++)
66332 + sensor_write(sam_client,
66333 + s5k4ba_reg[i].subaddr, s5k4ba_reg[i].value);
66334 +}
66335 +#else
66336 +#error No samsung CIS moudule !
66337 +#endif
66338 +
66339 +static int
66340 +s5k4xa_attach(struct i2c_adapter *adap, int addr, int kind)
66341 +{
66342 + struct i2c_client *c;
66343 +
66344 + c = kmalloc(sizeof(*c), GFP_KERNEL);
66345 + if (!c)
66346 + return -ENOMEM;
66347 +
66348 + memset(c, 0, sizeof(struct i2c_client));
66349 +
66350 + strcpy(c->name, "S5K4XA");
66351 + c->addr = addr;
66352 + c->adapter = adap;
66353 + c->driver = &sensor_driver;
66354 + i2c_set_clientdata(c, &data);
66355 + data.sensor = c;
66356 +
66357 + s3c_camif_register_sensor(c);
66358 +
66359 + return i2c_attach_client(c);
66360 +}
66361 +
66362 +static int sensor_attach_adapter(struct i2c_adapter *adap)
66363 +{
66364 + extern void om_3d7k_camera_on(void);
66365 + extern void om_3d7k_camera_off(void);
66366 + int ret;
66367 +
66368 + s3c_camif_open_sensor(&data);
66369 +
66370 + om_3d7k_camera_on();
66371 + ret = i2c_probe(adap, &addr_data, s5k4xa_attach);
66372 + om_3d7k_camera_off();
66373 + return ret;
66374 +}
66375 +
66376 +static int sensor_detach(struct i2c_client *client)
66377 +{
66378 + i2c_detach_client(client);
66379 + s3c_camif_unregister_sensor(client);
66380 + return 0;
66381 +}
66382 +
66383 +/*
66384 + * Purpose:
66385 + * This function only for SVGA Camera : 4BA
66386 + */
66387 +
66388 +static int change_sensor_size(struct i2c_client *client, int size)
66389 +{
66390 + int i;
66391 +
66392 + switch (size) {
66393 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
66394 + case SENSOR_QSVGA:
66395 + for (i = 0; i < S5K4BA_QSVGA_REGS; i++)
66396 + sensor_write(client, s5k4ba_reg_qsvga[i].subaddr,
66397 + s5k4ba_reg_qsvga[i].value);
66398 + break;
66399 +
66400 + case SENSOR_SVGA:
66401 + for (i = 0; i < S5K4BA_SVGA_REGS; i++)
66402 + sensor_write(client, s5k4ba_reg_svga[i].subaddr,
66403 + s5k4ba_reg_svga[i].value);
66404 + break;
66405 +#else
66406 +#error No samsung CIS moudule !
66407 +#endif
66408 + default:
66409 + panic("4xa_sensor.c: unexpect value\n");
66410 + }
66411 +
66412 + return 0;
66413 +}
66414 +
66415 +static int change_sensor_wb(struct i2c_client *client, int type)
66416 +{
66417 + printk("[ *** Page 0, 4XA Sensor White Balance Mode ***]\n");
66418 +
66419 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
66420 + sensor_write(client, 0xFC, 0x0);
66421 + sensor_write(client, 0x30, type);
66422 +#endif
66423 +
66424 + switch(type){
66425 + case 0:
66426 + default:
66427 + printk(" -> AWB auto mode ]\n");
66428 + break;
66429 + case 1:
66430 + printk(" -> Indoor 3100 mode ]\n");
66431 + break;
66432 + case 2:
66433 + printk(" -> Outdoor 5100 mode ]\n");
66434 + break;
66435 + case 3:
66436 + printk(" -> Indoor 2000 mode ]\n");
66437 + break;
66438 + case 4:
66439 + printk(" -> AE/AWB halt ]\n");
66440 + break;
66441 + case 5:
66442 + printk(" -> Cloudy(6000) mode ]\n");
66443 + break;
66444 + case 6:
66445 + printk(" -> Sunny(8000) mode ]\n");
66446 + break;
66447 + }
66448 +
66449 + return 0;
66450 +}
66451 +
66452 +static int
66453 +sensor_command(struct i2c_client *client, unsigned int cmd, void *arg)
66454 +{
66455 + switch (cmd) {
66456 + case SENSOR_INIT:
66457 + sensor_init(client);
66458 + printk(KERN_INFO "External Camera initialized\n");
66459 + break;
66460 +
66461 + case USER_ADD:
66462 + break;
66463 +
66464 + case USER_EXIT:
66465 + break;
66466 +
66467 + case SENSOR_QSVGA:
66468 + change_sensor_size(client, SENSOR_QSVGA);
66469 + break;
66470 +
66471 + case SENSOR_VGA:
66472 + change_sensor_size(client, SENSOR_VGA);
66473 + break;
66474 +
66475 + case SENSOR_SVGA:
66476 + change_sensor_size(client, SENSOR_SVGA);
66477 + break;
66478 +
66479 + case SENSOR_SXGA:
66480 + change_sensor_size(client, SENSOR_SXGA);
66481 + break;
66482 +
66483 + case SENSOR_UXGA:
66484 + change_sensor_size(client, SENSOR_UXGA);
66485 + break;
66486 +/* Todo
66487 + case SENSOR_BRIGHTNESS:
66488 + change_sensor_setting();
66489 + break;
66490 +*/
66491 + case SENSOR_WB:
66492 + printk("[ *** 4XA Sensor White Balance , No mode ***]\n");
66493 + change_sensor_wb(client, (int) arg);
66494 + break;
66495 +
66496 + default:
66497 + panic("4xa_sensor.c: Unexpected Sensor Command\n");
66498 + break;
66499 + }
66500 +
66501 + return 0;
66502 +}
66503 +
66504 +static struct i2c_driver sensor_driver = {
66505 + .driver = {
66506 + .name = "s5k4xa",
66507 + },
66508 + .id = I2C_DRIVERID_S5K_4XA,
66509 + .attach_adapter = sensor_attach_adapter,
66510 + .detach_client = sensor_detach,
66511 + .command = sensor_command
66512 +};
66513 +
66514 +static __init int camif_sensor_init(void)
66515 +{
66516 + return i2c_add_driver(&sensor_driver);
66517 +}
66518 +
66519 +
66520 +static __init void camif_sensor_exit(void)
66521 +{
66522 + i2c_del_driver(&sensor_driver);
66523 +}
66524 +
66525 +module_init(camif_sensor_init)
66526 +module_exit(camif_sensor_exit)
66527 +
66528 +MODULE_AUTHOR("Jinsung, Yang <jsgood.yang@samsung.com>");
66529 +MODULE_DESCRIPTION("I2C Client Driver For FIMC V4L2 Driver");
66530 +MODULE_LICENSE("GPL");
66531 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/media/video/samsung/4xa_sensor.h linux-2.6.29-rc3.owrt.om/drivers/media/video/samsung/4xa_sensor.h
66532 --- linux-2.6.29-rc3.owrt/drivers/media/video/samsung/4xa_sensor.h 1970-01-01 01:00:00.000000000 +0100
66533 +++ linux-2.6.29-rc3.owrt.om/drivers/media/video/samsung/4xa_sensor.h 2009-05-10 22:27:59.000000000 +0200
66534 @@ -0,0 +1,2412 @@
66535 +#ifndef _SAMSUNG_SXGA_H_
66536 +#define _SAMSUNG_SXGA_H_
66537 +
66538 +/******************************************************************************
66539 + * Display resolution standards
66540 + *
66541 + * QCIF: 176 x 144
66542 + * CIF: 352 x 288
66543 + * QVGA: 320 x 240
66544 + * VGA: 640 x 480
66545 + * SVGA: 800 x 600
66546 + * XGA: 1024 x 768
66547 + * WXGA: 1280 x 800
66548 + * QVGA: 1280 x 960
66549 + * SXGA: 1280 x 1024
66550 + * SXGA+: 1400 x 1050
66551 + * WSXGA+: 1680 x 1050
66552 + * UXGA: 1600 x 1200
66553 + * WUXGA: 1920 x 1200
66554 + * QXGA: 2048 x 1536
66555 + *****************************************************************************/
66556 +
66557 +//#include "../bits.h"
66558 +
66559 +/*
66560 + * Camera information
66561 + * FPC Label : Samsung MEGA Pixel Camera : V4220 REV06
66562 + * Modified by charles -Initial function of '3AA' test routine
66563 + * Modified and tested by YongHwui.Kim <yonghwui.kim@samsung.com> for S5K3AAEX
66564 + * Camera
66565 + */
66566 +
66567 +#define CHIP_DELAY 0xFF
66568 +
66569 +typedef struct samsung_t{
66570 + unsigned char subaddr;
66571 + unsigned char value;
66572 + unsigned char page;
66573 +} s5k4xa_t;
66574 +
66575 +#ifdef CONFIG_CPU_S3C24A0A
66576 +#define TRY_HIGH_CLOCK 1
66577 +#endif
66578 +
66579 +/***************************************************
66580 + * name: S5K3AAEX EVT2 setfile
66581 + * ver: v2.61
66582 + * history:
66583 + * v0.0 start from 040908 setfile
66584 + * v1.0 arange register
66585 + * v1.01 change MCLK(25Mhz) and Frame rate(7fps)
66586 + * v2.0 adjust register setting for 3AA EVT2
66587 + * - color correction, RGB shading off, hsync start position,
66588 + * Mirror, fps
66589 + * - Color Tuning, YGRPDLY
66590 + * v2.1 change Frame rate(7.5fps) and Total gain to x4
66591 + * (because of reducing visual noise at low illumination)
66592 + * - change BPRM AGC Max and FrameAE start
66593 + * improve AE speed
66594 + * v2.2 modify AWB G gain and solve 50hz flicker detection fail in
66595 + * 25MHz 7.5fps
66596 + * v2.3 Adjust gamma, Dark Slice, white point, Hue gain,
66597 + * White Balance B control, Y gain On, Digital Clamp On
66598 + * lower AWB G gain
66599 + * v2.4 Adjust AE window weight, Y Gamma, WhitePoint, Shading and BPR
66600 + * Max Thres.
66601 + * v2.41 Adjust AE/AWB window and AWB internal window boundary to
66602 + * decrease skin color tracking
66603 + * v2.411 special version for PSCDS
66604 + * v2.412 RGB shading off
66605 + * v2.5 Lens change STW to Sekonix
66606 + * adjust White point and Y shading Coef (RGB shading off)
66607 + * v2.6 New Tuning because of Full YC off and YCbCr Coef change
66608 + * Gamma, Dark Slice, color matrix (not use), Color suppress
66609 + * R Gain and DBPR agc MIN/MAX
66610 + * v2.61 VCK inversion(data rising)
66611 + ****************************************************/
66612 +
66613 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
66614 +
66615 +/* For SVGA (800 x 600) */
66616 +#if 1 /* from han */
66617 +s5k4xa_t s5k4ba_reg[] =
66618 +{
66619 + {0xfc,0x07},
66620 + {0x66,0x01}, /* Watch Dog Time On */
66621 + {0xfc,0x00},
66622 + {0x00,0xAA}, /* For EDS Check */
66623 + {0x21,0x03}, /* peter */
66624 + {0xfc,0x01},
66625 + {0x04,0x01}, /* ARM Clock Divider */
66626 +
66627 + {0xfc,0x02},
66628 + {0x30,0x90}, /* Analog offset */
66629 + {0x37,0x0d}, /* Global Gain */
66630 + {0x2d,0x48}, /* Double Shutter */
66631 + {0x60,0x00}, /* Blank_Adrs */
66632 +
66633 + {0x45,0x1e}, /* 0e - CDS Timing for Average Sub_Sampling */
66634 + {0x47,0x2f},
66635 + {0x02,0x0e}, /* ADC Resolution */
66636 + {0x3d,0x06}, /* Frame ADLC */
66637 + {0x4d,0x08}, /* Doubler Volatage */
66638 + {0x54,0x02}, /* Double Shutter */
66639 + {0x55,0x1e}, /* Line ADLC */
66640 + {0x56,0x30},
66641 + {0x59,0x00}, /* LineADLC offset */
66642 + {0x5b,0x08}, /* R_Ref_Ctrl */
66643 + {0x44,0x63}, /* CLP_EN */
66644 + {0x4A,0x10}, /* Clamp Control */
66645 + {0x42,0x02},
66646 + {0x43,0xef},
66647 +
66648 + /*
66649 + * Table Set for Sub-Sampling
66650 + */
66651 +
66652 + {0xfc,0x03},
66653 + {0x2c,0x00}, /* crcb_sel for Sub-Sampling Table */
66654 + {0x05,0x46}, /* Output Image Size Set for Capture */
66655 + {0x07,0xb6},
66656 + {0x0e,0x04},
66657 + {0x12,0x03},
66658 +
66659 + {0xfc,0x04},
66660 + {0x32,0x04},
66661 + {0x33,0xbc},
66662 +
66663 + {0xfc,0x04},
66664 + {0xc5,0x26}, /* Output Image Size Set for Preview */
66665 + {0xc7,0x5e},
66666 + {0xce,0x04},
66667 + {0xd2,0x04},
66668 +
66669 + {0xec,0x06}, /* CrCb sel = YCBYCR(0x06) by jsgood */
66670 + {0xc0,0x06},
66671 + {0xc1,0x70},
66672 + {0xc2,0x02},
66673 + {0xc3,0x87},
66674 +
66675 + {0xfc,0x07},
66676 + {0x05,0x00},
66677 + {0x06,0x00},
66678 + {0x07,0x8b},
66679 + {0x08,0xf5},
66680 + {0x09,0x00},
66681 + {0x0a,0xb4},
66682 + {0x0b,0x00},
66683 + {0x0c,0xea},
66684 + {0x0d,0x00},
66685 + {0x0e,0x40},
66686 +
66687 + {0xfc,0x00},
66688 + {0x70,0x02},
66689 +
66690 + /* Jeongyun added still shot cbcr_sel */
66691 + {0xfc,0x03},
66692 + {0x2c,0x00},
66693 + {0x5c,0x00},
66694 + {0x8c,0x00},
66695 + {0xbc,0x00},
66696 + {0xfc,0x04},
66697 + {0x5c,0x00},
66698 +
66699 + /*
66700 + * COMMAND SET
66701 + */
66702 +
66703 + {0xfc,0x00},
66704 + {0x73,0x21}, /* Frame AE Enable peter */
66705 + {0x20,0x02}, /* Change AWB Mode */
66706 +
66707 + {0xfc,0x00},
66708 + {0x6c,0xb0}, /* AE target */
66709 + {0x6d,0x00},
66710 +
66711 + {0xfc,0x20},
66712 + {0x16,0x5a}, /* for Prevating AE Hunting */
66713 +
66714 + {0xfc,0x00},
66715 + {0x78,0x6a}, /* AGC Max */
66716 + {0xfc,0x20},
66717 + {0x16,0x60}, /* Frame AE Start */
66718 +
66719 + {0xfc,0x20},
66720 + {0x57,0x18}, /* Stable_Frame_AE */
66721 + {0x2C,0x30}, /* For Forbidden Area */
66722 + {0x2E,0x00}, /* For Forbidden Area */
66723 + {0x14,0x70},
66724 + {0x01,0x00}, /* Stepless_Off */
66725 +
66726 + {0xfc,0x07},
66727 + {0x11,0x02}, /* AWB G Gain offset */
66728 +
66729 + {0xfc,0x07},
66730 + {0x3e,0x0a}, /* AWB Cut R max */
66731 +
66732 + {0xfc,0x01},
66733 + {0xc8,0xd0}, /* AWB Y Max */
66734 + {0xfc,0x00},
66735 + {0x3e,0x20}, /* 30 - AWB Y_min */
66736 + {0x3d,0x10}, /* AWB Y_min Low */
66737 + {0xfc,0x22},
66738 + {0x8c,0x04}, /* AWB Min Y Weight AWB */
66739 + {0x8d,0x16}, /* AWB Max Y Weight */
66740 +
66741 + {0xfc,0x00},
66742 + {0x32,0x04}, /* AWB moving average 8 frame */
66743 + {0x81,0x10}, /* AWB G gain suppress Disable */
66744 + {0xbc,0xf0},
66745 +
66746 + {0x29,0x04}, /* Y level H */
66747 + {0x2a,0x00}, /* Y level L */
66748 + {0x2b,0x03}, /* color level H */
66749 + {0x2c,0xc8}, /* color level L */
66750 +
66751 + {0xfc,0x07},
66752 + {0x37,0x00}, /* Flicker Add for 32 MHz */
66753 + {0xfc,0x00},
66754 + {0x72,0xa0}, /* Flicker for 32 MHz */
66755 + {0x74,0x08}, /* flicker 60 Hz Fix */
66756 +
66757 + {0xfc,0x20},
66758 + {0x02,0x02}, /* Flicker Dgain Mode */
66759 +
66760 + {0xfc,0x00},
66761 + //{0x23,0x40}, /* Mirror Option */
66762 + {0x62,0x0a}, /* Mirror Option */
66763 +
66764 + {0xfc,0x02},
66765 + {0x4e,0x1b}, /* Enable SDA and SCL pull-up; drive 8 mA */
66766 + {0x4f,0xf0}, /* PCLK and YC: 8 mA, AF and ZM (AZ): 2 mA */
66767 +
66768 + {0xfc,0x01},
66769 + {0x0c,0x03}, /* Full YC Enable */
66770 + //{0x0c,03}, /* Full YC Enable */
66771 + //{0x02,02}, /* crcb_sel */
66772 + //{0x02,02}, /* crcb_sel peter */
66773 + //{0x01,01}, /* pclk peter */
66774 + //{0x01,01},
66775 +
66776 + /*
66777 + * COLOR MATRIX
66778 + */
66779 +
66780 + {0xfc,0x01}, /* color matrix */
66781 + {0x51,0x0A},
66782 + {0x52,0x42},
66783 + {0x53,0xF9},
66784 + {0x54,0x80},
66785 + {0x55,0x00},
66786 + {0x56,0x3D},
66787 +
66788 + {0x57,0xFE},
66789 + {0x58,0x0B},
66790 + {0x59,0x06},
66791 + {0x5A,0x9C},
66792 + {0x5B,0xFF},
66793 + {0x5C,0x59},
66794 +
66795 + {0x5D,0xFF},
66796 + {0x5E,0xD8},
66797 + {0x5F,0xFC},
66798 + {0x60,0x2E},
66799 + {0x61,0x07},
66800 + {0x62,0xFA},
66801 +
66802 + /*
66803 + * EDGE ENHANCEMENT
66804 + */
66805 +
66806 + {0xfc,0x00},
66807 + {0x89,0x03}, /* Edge Suppress On */
66808 + {0xfc,0x0b},
66809 + {0x42,0x50}, /* Edge AGC MIN */
66810 + {0x43,0x60}, /* Edge AGC MAX */
66811 + {0x45,0x18}, /* positive gain AGC MIN */
66812 + {0x49,0x0a}, /* positive gain AGC MAX */
66813 + {0x4d,0x18}, /* negative gain AGC MIN */
66814 + {0x51,0x0a}, /* negative gain AGC MAX */
66815 +
66816 + {0xfc,0x05},
66817 + {0x34,0x20}, /* APTCLP */
66818 + {0x35,0x09}, /* APTSC */
66819 + {0x36,0x0b}, /* ENHANCE */
66820 + {0x3f,0x00}, /* NON-LIN */
66821 + {0x42,0x10}, /* EGFALL */
66822 + {0x43,0x00}, /* HLFALL */
66823 + {0x45,0xa0}, /* EGREF */
66824 + {0x46,0x7a}, /* HLREF */
66825 + {0x47,0x40}, /* LLREF */
66826 + {0x48,0x0c},
66827 + {0x49,0x31}, /* CSSEL EGSEL CS_DLY */
66828 +
66829 + {0x40,0x41}, /* Y delay */
66830 +
66831 + /*
66832 + * GAMMA
66833 + */
66834 +
66835 + {0xfc,0x01},
66836 +
66837 + {0x6F,0x0A}, /* R */
66838 + {0x70,0x1A},
66839 + {0x71,0x7A},
66840 + {0x72,0xF8},
66841 + {0x73,0x00},
66842 +
66843 + {0x74,0xA0},
66844 + {0x75,0x18},
66845 + {0x76,0x65},
66846 + {0x77,0xAD},
66847 + {0x78,0x6A},
66848 +
66849 + {0x79,0xE2},
66850 + {0x7A,0x12},
66851 + {0x7B,0x3D},
66852 + {0x7C,0x5A},
66853 + {0x7D,0xBF},
66854 +
66855 + {0x7E,0x72},
66856 + {0x7F,0x88},
66857 + {0x80,0x9D},
66858 + {0x81,0xB0},
66859 + {0x82,0xFF},
66860 +
66861 + {0x83,0xC0},
66862 + {0x84,0xCF},
66863 + {0x85,0xDA},
66864 + {0x86,0xFC},
66865 +
66866 + {0x87,0x08}, /* G */
66867 + {0x88,0x12},
66868 + {0x89,0x42},
66869 + {0x8A,0xBA},
66870 + {0x8B,0x00},
66871 +
66872 + {0x8C,0x75},
66873 + {0x8D,0xED},
66874 + {0x8E,0x42},
66875 + {0x8F,0x80},
66876 + {0x90,0x5A},
66877 +
66878 + {0x91,0xB5},
66879 + {0x92,0xE5},
66880 + {0x93,0x10},
66881 + {0x94,0x35},
66882 + {0x95,0xAF},
66883 +
66884 + {0x96,0x55},
66885 + {0x97,0x70},
66886 + {0x98,0x88},
66887 + {0x99,0x9D},
66888 + {0x9A,0xFF},
66889 +
66890 + {0x9B,0xB1},
66891 + {0x9C,0xC4},
66892 + {0x9D,0xD5},
66893 + {0x9E,0xFC},
66894 +
66895 + {0x9F,0x05}, /* B */
66896 + {0xA0,0x18},
66897 + {0xA1,0x42},
66898 + {0xA2,0xd7},
66899 + {0xA3,0x00},
66900 +
66901 + {0xA4,0xB6},
66902 + {0xA5,0x3b},
66903 + {0xA6,0x88},
66904 + {0xA7,0xC8},
66905 + {0xA8,0x6A},
66906 +
66907 + {0xA9,0x00},
66908 + {0xAA,0x30},
66909 + {0xAB,0x58},
66910 + {0xAC,0x78},
66911 + {0xAD,0xFF},
66912 +
66913 + {0xAE,0x90},
66914 + {0xAF,0xA5},
66915 + {0xB0,0xB6},
66916 + {0xB1,0xC5},
66917 + {0xB2,0xFF},
66918 +
66919 + {0xB3,0xD0},
66920 + {0xB4,0xD6},
66921 + {0xB5,0xDA},
66922 + {0xB6,0xFC},
66923 +
66924 + /*
66925 + * HUE CONTROL
66926 + */
66927 +
66928 + {0xfc,0x00},
66929 + {0x48,0x34}, /* 2000K */
66930 + {0x49,0x34},
66931 + {0x4a,0xf4},
66932 + {0x4b,0x00},
66933 + {0x4c,0x44},
66934 + {0x4d,0x3c},
66935 + {0x4e,0xf0},
66936 + {0x4f,0x0c},
66937 +
66938 + {0x50,0x34}, /* 3000K */
66939 + {0x51,0x34},
66940 + {0x52,0xf4},
66941 + {0x53,0x00},
66942 + {0x54,0x44},
66943 + {0x55,0x3c},
66944 + {0x56,0xf0},
66945 + {0x57,0x0c},
66946 +
66947 + {0x58,0x34}, /* 5100K */
66948 + {0x59,0x30},
66949 + {0x5a,0x00},
66950 + {0x5b,0x04},
66951 + {0x5c,0x40},
66952 + {0x5d,0x2c},
66953 + {0x5e,0xfc},
66954 + {0x5f,0x04},
66955 +
66956 + /*
66957 + * UPPRE0x0x FUNCTION
66958 + */
66959 +
66960 + {0xfc,0x00},
66961 + {0x7e,0xf4},
66962 +
66963 + /*
66964 + * BPR
66965 + */
66966 +
66967 + {0xfc,0x01},
66968 + {0x3d,0x10},
66969 +
66970 + {0xfc,0x0b},
66971 + {0x0b,0x00}, /* ISP BPR On start */
66972 + {0x0c,0x20}, /* Th13 AGC Min */
66973 + {0x0d,0x40}, /* Th13 AGC Max */
66974 + {0x0e,0x00}, /* Th1 Max H for AGCMIN */
66975 + {0x0f,0x20}, /* Th1 Max L for AGCMIN */
66976 + {0x10,0x00}, /* Th1 Min H for AGCMAX */
66977 + {0x11,0x10}, /* Th1 Min L for AGCMAX */
66978 + {0x12,0x00}, /* Th3 Max H for AGCMIN */
66979 + {0x13,0x00}, /* Th3 Max L for AGCMIN */
66980 + {0x14,0xff}, /* Th3 Min H for AGCMAX */
66981 + {0x15,0xff}, /* Th3 Min L for AGCMAX */
66982 + {0x16,0x20}, /* Th57 AGC Min */
66983 + {0x17,0x40}, /* Th57 AGC Max */
66984 + {0x18,0x00}, /* Th5 Max H for AGCMIN */
66985 + {0x19,0x00}, /* Th5 Max L for AGCMIN */
66986 + {0x1a,0x00}, /* Th5 Min H for AGCMAX */
66987 + {0x1b,0x20}, /* Th5 Min L for AGCMAX */
66988 + {0x1c,0x00}, /* Th7 Max H for AGCMIN */
66989 + {0x1d,0x00}, /* Th7 Max L for AGCMIN */
66990 + {0x1e,0x00}, /* Th7 Min H for AGCMAX */
66991 + {0x1f,0x20}, /* Th7 Min L for AGCMAX */
66992 +
66993 + /*
66994 + * GR/GB CORRECTION
66995 + */
66996 +
66997 + {0xfc,0x01},
66998 + {0x45,0x0c},
66999 +
67000 + {0xfc,0x0b},
67001 + {0x21,0x00}, /* start AGC */
67002 + {0x22,0x18}, /* AGCMIN */
67003 + {0x23,0x58}, /* AGCMAX */
67004 + {0x24,0x0d}, /* G Th AGCMIN */
67005 + {0x25,0x30}, /* G Th AGCMAX */
67006 + {0x26,0x0d}, /* RB Th AGCMIN */
67007 + {0x27,0x30}, /* RB Th AGCMAX */
67008 +
67009 + /*
67010 + * NR
67011 + */
67012 +
67013 + {0xfc,0x01},
67014 + {0x4C,0x01}, /* NR Enable */
67015 + {0x49,0x15}, /* Sig_Th Mult */
67016 + {0x4B,0x0A}, /* Pre_Th Mult */
67017 +
67018 + {0xfc,0x0b},
67019 + {0x28,0x00}, /* NR start AGC */
67020 + {0x29,0x00}, /* SIG Th AGCMIN H */
67021 + {0x2a,0x14}, /* SIG Th AGCMIN L */
67022 + {0x2b,0x00}, /* SIG Th AGCMAX H */
67023 + {0x2c,0x14}, /* SIG Th AGCMAX L */
67024 + {0x2d,0x00}, /* PRE Th AGCMIN H */
67025 + {0x2e,0x90}, /* PRE Th AGCMIN L */
67026 + {0x2f,0x01}, /* PRE Th AGCMAX H */
67027 + {0x30,0x00}, /* PRE Th AGCMAX L */
67028 + {0x31,0x00}, /* POST Th AGCMIN H */
67029 + {0x32,0xa0}, /* POST Th AGCMIN L */
67030 + {0x33,0x01}, /* POST Th AGCMAX H */
67031 + {0x34,0x10}, /* POST Th AGCMAX L */
67032 +
67033 + /*
67034 + * 1D-Y/C-SIGMA-LPF
67035 + */
67036 +
67037 + {0xfc,0x01},
67038 + {0x05,0xc0},
67039 +
67040 + {0xfc,0x0b},
67041 + {0x35,0x00}, /* YLPF start AGC */
67042 + {0x36,0x40}, /* YLPF01 AGCMIN */
67043 + {0x37,0x60}, /* YLPF01 AGCMAX */
67044 + {0x38,0x00}, /* YLPF SIG01 Th AGCMINH */
67045 + {0x39,0x18}, /* YLPF SIG01 Th AGCMINL */
67046 + {0x3a,0x00}, /* YLPF SIG01 Th AGCMAXH */
67047 + {0x3b,0x40}, /* YLPF SIG01 Th AGCMAXH */
67048 + {0x3c,0x50}, /* YLPF02 AGCMIN */
67049 + {0x3d,0x60}, /* YLPF02 AGCMAX */
67050 + {0x3e,0x00}, /* YLPF SIG02 Th AGCMINH */
67051 + {0x3f,0x30}, /* YLPF SIG02 Th AGCMINL */
67052 + {0x40,0x00}, /* YLPF SIG02 Th AGCMAXH */
67053 + {0x41,0x40}, /* YLPF SIG02 Th AGCMAXH */
67054 + {0xd4,0x40}, /* CLPF AGCMIN */
67055 + {0xd5,0x60}, /* CLPF AGCMAX */
67056 + {0xd6,0xb0}, /* CLPF SIG01 Th AGCMIN */
67057 + {0xd7,0xf0}, /* CLPF SIG01 Th AGCMAX */
67058 + {0xd8,0xb0}, /* CLPF SIG02 Th AGCMIN */
67059 + {0xd9,0xf0}, /* CLPF SIG02 Th AGCMAX */
67060 +
67061 + /*
67062 + * COLOR SUPPRESS
67063 + */
67064 +
67065 + {0xfc,0x0b},
67066 + {0x08,0x58}, /* Color suppress AGC MIN */
67067 + {0x09,0x03}, /* Color suppress MIN H */
67068 + {0x0a,0x80}, /* Color suppress MIN L */
67069 +
67070 + /*
67071 + * SHADING
67072 + */
67073 +
67074 + {0xfc,0x09},
67075 + //Shading file for 3BAFX
67076 + //s90000// shading off
67077 + // DSP9_SH_WIDTH_H
67078 + {0x01,0x06},
67079 + {0x02,0x40},
67080 + // DSP9_SH_HEIGHT_H
67081 + {0x03,0x04},
67082 + {0x04,0xB0},
67083 + // DSP9_SH_XCH_R
67084 + {0x05,0x03},
67085 + {0x06,0x1A},
67086 + {0x07,0x02},
67087 + {0x08,0x4E},
67088 + // DSP9_SH_XCH_G
67089 + {0x09,0x03},
67090 + {0x0A,0x27},
67091 + {0x0B,0x02},
67092 + {0x0C,0x11},
67093 + // DSP9_SH_XCH_B
67094 + {0x0D,0x03},
67095 + {0x0E,0x15},
67096 + {0x0F,0x01},
67097 + {0x10,0xE3},
67098 + // DSP9_SH_Del_eH_R
67099 + {0x1D,0x85},
67100 + {0x1E,0x55},
67101 + {0x1F,0x77},
67102 + {0x20,0x9E},
67103 + {0x23,0x7F},
67104 + {0x24,0xE6},
67105 + {0x21,0x7F},
67106 + {0x22,0xE6},
67107 + // DSP9_SH_Del_eH_G
67108 + {0x25,0x82},
67109 + {0x26,0x9A},
67110 + {0x27,0x78},
67111 + {0x28,0xC0},
67112 + {0x2B,0x76},
67113 + {0x2C,0x07},
67114 + {0x29,0x86},
67115 + {0x2A,0x09},
67116 + // DSP9_SH_Del_eH_B
67117 + {0x2D,0x85},
67118 + {0x2E,0x55},
67119 + {0x2F,0x75},
67120 + {0x30,0x6D},
67121 + {0x33,0x74},
67122 + {0x34,0xA2},
67123 + {0x31,0x84},
67124 + {0x32,0xA2},
67125 + // DSP9_SH_VAL_R0H
67126 + {0x35,0x01},
67127 + {0x36,0x01},
67128 + {0x37,0x01},
67129 + {0x38,0x14},
67130 + {0x39,0x01},
67131 + {0x3A,0x45},
67132 + {0x3B,0x01},
67133 + {0x3C,0x8A},
67134 + {0x3D,0x01},
67135 + {0x3E,0xA3},
67136 + {0x3F,0x01},
67137 + {0x40,0xB9},
67138 + {0x41,0x01},
67139 + {0x42,0xD9},
67140 + {0x43,0x01},
67141 + {0x44,0xF6},
67142 + // DSP9_SH_VAL_G0H
67143 + {0x45,0x01},
67144 + {0x46,0x00},
67145 + {0x47,0x01},
67146 + {0x48,0x0E},
67147 + {0x49,0x01},
67148 + {0x4A,0x34},
67149 + {0x4B,0x01},
67150 + {0x4C,0x68},
67151 + {0x4D,0x01},
67152 + {0x4E,0x76},
67153 + {0x4F,0x01},
67154 + {0x50,0x94},
67155 + {0x51,0x01},
67156 + {0x52,0xAB},
67157 + {0x53,0x01},
67158 + {0x54,0xC3},
67159 + // DSP9_SH_VAL_B0H
67160 + {0x55,0x01},
67161 + {0x56,0x00},
67162 + {0x57,0x01},
67163 + {0x58,0x0C},
67164 + {0x59,0x01},
67165 + {0x5A,0x2B},
67166 + {0x5B,0x01},
67167 + {0x5C,0x5D},
67168 + {0x5D,0x01},
67169 + {0x5E,0x70},
67170 + {0x5F,0x01},
67171 + {0x60,0x8A},
67172 + {0x61,0x01},
67173 + {0x62,0xA1},
67174 + {0x63,0x01},
67175 + {0x64,0xB3},
67176 + // DSP9_SH_M_R2_R1H
67177 + {0x65,0x00},
67178 + {0x66,0x98},
67179 + {0x67,0x2C},
67180 + {0x68,0x02},
67181 + {0x69,0x60},
67182 + {0x6A,0xB0},
67183 + {0x6B,0x05},
67184 + {0x6C,0x59},
67185 + {0x6D,0x8C},
67186 + {0x6E,0x07},
67187 + {0x6F,0x48},
67188 + {0x70,0x1B},
67189 + {0x71,0x09},
67190 + {0x72,0x82},
67191 + {0x73,0xC0},
67192 + {0x74,0x0C},
67193 + {0x75,0x09},
67194 + {0x76,0x7B},
67195 + {0x77,0x0E},
67196 + {0x78,0xDC},
67197 + {0x79,0x4D},
67198 + // DSP9_SH_M_R2_G1H
67199 + {0x7A,0x00},
67200 + {0x7B,0xAD},
67201 + {0x7C,0x76},
67202 + {0x7D,0x02},
67203 + {0x7E,0xB5},
67204 + {0x7F,0xD7},
67205 + {0x80,0x06},
67206 + {0x81,0x19},
67207 + {0x82,0x23},
67208 + {0x83,0x08},
67209 + {0x84,0x4C},
67210 + {0x85,0xE2},
67211 + {0x86,0x0A},
67212 + {0x87,0xD7},
67213 + {0x88,0x5C},
67214 + {0x89,0x0D},
67215 + {0x8A,0xB8},
67216 + {0x8B,0x90},
67217 + {0x8C,0x10},
67218 + {0x8D,0xF0},
67219 + {0x8E,0x7F},
67220 + // DSP9_SH_M_R2_B1H
67221 + {0x8F,0x00},
67222 + {0x90,0xC1},
67223 + {0x91,0xD0},
67224 + {0x92,0x03},
67225 + {0x93,0x07},
67226 + {0x94,0x3F},
67227 + {0x95,0x06},
67228 + {0x96,0xD0},
67229 + {0x97,0x4F},
67230 + {0x98,0x09},
67231 + {0x99,0x46},
67232 + {0x9A,0x32},
67233 + {0x9B,0x0C},
67234 + {0x9C,0x1C},
67235 + {0x9D,0xFE},
67236 + {0x9E,0x0F},
67237 + {0x9F,0x54},
67238 + {0xA0,0xB1},
67239 + {0xA1,0x12},
67240 + {0xA2,0xED},
67241 + {0xA3,0x4C},
67242 + // DSP9_SH_SUB_RR0H
67243 + {0xA4,0x6B},
67244 + {0xA5,0xAA},
67245 + {0xA6,0x23},
67246 + {0xA7,0xE3},
67247 + {0xA8,0x15},
67248 + {0xA9,0x88},
67249 + {0xAA,0x21},
67250 + {0xAB,0x20},
67251 + {0xAC,0x1C},
67252 + {0xAD,0xB6},
67253 + {0xAE,0x19},
67254 + {0xAF,0x55},
67255 + {0xB0,0x16},
67256 + {0xB1,0xAA},
67257 + // DSP9_SH_SUB_RG0H
67258 + {0xB2,0x5E},
67259 + {0xB3,0x74},
67260 + {0xB4,0x1F},
67261 + {0xB5,0x7C},
67262 + {0xB6,0x12},
67263 + {0xB7,0xE4},
67264 + {0xB8,0x1D},
67265 + {0xB9,0x10},
67266 + {0xBA,0x19},
67267 + {0xBB,0x30},
67268 + {0xBC,0x16},
67269 + {0xBD,0x39},
67270 + {0xBE,0x13},
67271 + {0xBF,0xE2},
67272 + // DSP9_SH_SUB_RB0H
67273 + {0xC0,0x54},
67274 + {0xC1,0x89},
67275 + {0xC2,0x1C},
67276 + {0xC3,0x2D},
67277 + {0xC4,0x10},
67278 + {0xC5,0xE8},
67279 + {0xC6,0x1A},
67280 + {0xC7,0x02},
67281 + {0xC8,0x16},
67282 + {0xC9,0x8A},
67283 + {0xCA,0x13},
67284 + {0xCB,0xE4},
67285 + {0xCC,0x11},
67286 + {0xCD,0xCC},
67287 +
67288 + {0x00,0x02}, // Shading on
67289 +
67290 + //==========================================================
67291 + // X-SHADING
67292 + //==========================================================
67293 + {0xfc,0x1B},
67294 + {0x80,0x01},
67295 + {0x81,0x00},
67296 + {0x82,0x4C},
67297 + {0x83,0x00},
67298 + {0x84,0x86},
67299 + {0x85,0x03},
67300 + {0x86,0x5E},
67301 + {0x87,0x00},
67302 + {0x88,0x07},
67303 + {0x89,0xA4},
67304 + {0x90,0x00},
67305 + {0x91,0x12},
67306 + {0x92,0x00},
67307 + {0x93,0x12},
67308 + {0x94,0x00},
67309 + {0x95,0x12},
67310 + {0x96,0x00},
67311 + {0x97,0x12},
67312 + {0x98,0x00},
67313 + {0x99,0x12},
67314 + {0x9A,0x00},
67315 + {0x9B,0x12},
67316 + {0x9C,0x00},
67317 + {0x9D,0x12},
67318 + {0x9E,0x00},
67319 + {0x9F,0x12},
67320 + {0xA0,0x00},
67321 + {0xA1,0x12},
67322 + {0xA2,0x00},
67323 + {0xA3,0x12},
67324 + {0xA4,0x00},
67325 + {0xA5,0x12},
67326 + {0xA6,0x00},
67327 + {0xA7,0x12},
67328 + {0xA8,0x00},
67329 + {0xA9,0x12},
67330 + {0xAA,0x00},
67331 + {0xAB,0x12},
67332 + {0xAC,0x00},
67333 + {0xAD,0x12},
67334 + {0xAE,0x00},
67335 + {0xAF,0x12},
67336 + {0xB0,0x00},
67337 + {0xB1,0x12},
67338 + {0xB2,0x00},
67339 + {0xB3,0x12},
67340 + {0xB4,0x00},
67341 + {0xB5,0x12},
67342 + {0xB6,0x00},
67343 + {0xB7,0x15},
67344 + {0xB8,0x00},
67345 + {0xB9,0x12},
67346 + {0xBA,0x00},
67347 + {0xBB,0x12},
67348 + {0xBC,0x00},
67349 + {0xBD,0x12},
67350 + {0xBE,0x00},
67351 + {0xBF,0x12},
67352 + {0xC0,0x00},
67353 + {0xC1,0x12},
67354 + {0xC2,0x00},
67355 + {0xC3,0x12},
67356 + {0xC4,0x00},
67357 + {0xC5,0x12},
67358 + {0xC6,0x00},
67359 + {0xC7,0x12},
67360 + {0xC8,0x00},
67361 + {0xC9,0x12},
67362 + {0xCA,0x00},
67363 + {0xCB,0x12},
67364 + {0xCC,0x00},
67365 + {0xCD,0x12},
67366 + {0xCE,0x00},
67367 + {0xCF,0x12},
67368 + {0xD0,0x00},
67369 + {0xD1,0x12},
67370 + {0xD2,0x00},
67371 + {0xD3,0x12},
67372 + {0xD4,0x00},
67373 + {0xD5,0x12},
67374 + // x-shading temp. correlation factor
67375 + {0xfc,0x0b},
67376 + {0xda,0x00}, // t0(3100K)
67377 + {0xdb,0xac},
67378 + {0xdc,0x01}, // tc(5100K)
67379 + {0xdd,0x30}, // default eeh
67380 +
67381 + {0xfc,0x00},
67382 + {0x81,0x10}, // xshading tem
67383 +
67384 + {0xfc,0x1b},
67385 + {0x80,0x01}, // X-Shading On
67386 +
67387 + //==========================================================
67388 + // AE WINDOW WEIGHT
67389 + //==========================================================
67390 + {0xfc,0x00},
67391 + {0x03,0x4b}, // AE Suppress On
67392 +
67393 + {0xfc,0x06},
67394 + {0x01,0x35}, // UXGA AE Window
67395 + {0x03,0xc2},
67396 + {0x05,0x48},
67397 + {0x07,0xb8},
67398 + {0x31,0x2a}, // Subsampling AE Window
67399 + {0x33,0x61},
67400 + {0x35,0x28},
67401 + {0x37,0x5c},
67402 + {0x39,0x28},
67403 + {0x3B,0x5A},
67404 + {0x3D,0x10}, // 1c
67405 + {0x3F,0x44},
67406 +
67407 + {0xfc,0x20},
67408 + {0x60,0x11},
67409 + {0x61,0x11},
67410 + {0x62,0x11},
67411 + {0x63,0x11},
67412 + {0x64,0x11},
67413 + {0x65,0x22},
67414 + {0x66,0x22},
67415 + {0x67,0x11},
67416 + {0x68,0x11},
67417 + {0x69,0x33},
67418 + {0x6a,0x33},
67419 + {0x6b,0x11},
67420 + {0x6c,0x12},
67421 + {0x6d,0x55},
67422 + {0x6e,0x55},
67423 + {0x6f,0x21},
67424 + {0x70,0x13},
67425 + {0x71,0x55},
67426 + {0x72,0x55},
67427 + {0x73,0x31},
67428 + {0x74,0x33},
67429 + {0x75,0x33},
67430 + {0x76,0x33},
67431 + {0x77,0x33},
67432 +
67433 + //==========================================================
67434 + // SAIT AWB
67435 + //==========================================================
67436 + //=================================
67437 + // White Point
67438 + //=================================
67439 + {0xfc,0x22}, // White Point (For Hue Control & MWB)
67440 + {0x01,0xD0}, // D65
67441 + {0x03,0x9B},
67442 + {0x05,0xC0}, // 5000K
67443 + {0x07,0xB8},
67444 + {0x09,0xA7}, // CWF
67445 + {0x0b,0xDC},
67446 + {0x0d,0x98}, // 3000K
67447 + {0x0f,0xE0},
67448 + {0x11,0x85}, // A
67449 + {0x12,0x00},
67450 + {0x13,0xF6},
67451 + {0x15,0x80}, // 2000K
67452 + {0x16,0x01},
67453 + {0x17,0x00},
67454 +
67455 + //=================================
67456 + // Basic Setting
67457 + //=================================
67458 + {0xfc,0x22},
67459 + {0xA0,0x01},
67460 + {0xA1,0x3F},
67461 + {0xA2,0x0E},
67462 + {0xA3,0x65},
67463 + {0xA4,0x07},
67464 + {0xA5,0xF4},
67465 + {0xA6,0x11},
67466 + {0xA7,0xC8},
67467 + {0xA9,0x02},
67468 + {0xAA,0x43},
67469 + {0xAB,0x26},
67470 + {0xAC,0x1F},
67471 + {0xAD,0x02},
67472 + {0xAE,0x2C},
67473 + {0xAF,0x19},
67474 + {0xB0,0x0F},
67475 +
67476 + {0x94,0x3C},
67477 + {0x95,0xCC},
67478 + {0x96,0x5C},
67479 + {0x97,0x4D},
67480 + {0xD0,0xA8},
67481 + {0xD1,0x29},
67482 + {0xD2,0x39},
67483 + {0xD3,0x22},
67484 + {0xD4,0x30},
67485 + {0xDB,0x29},
67486 + {0xDC,0x7E},
67487 + {0xDD,0x22},
67488 +
67489 + {0xE7,0x00},
67490 + {0xE8,0xca},
67491 + {0xE9,0x00},
67492 + {0xEA,0x62},
67493 + {0xEB,0x00},
67494 + {0xEC,0x00},
67495 + {0xEE,0x97},
67496 +
67497 + //=================================
67498 + // Pixel Filter Setting
67499 + //=================================
67500 + {0xFC,0x07},
67501 + {0x95,0x8F},
67502 +
67503 + {0xfc,0x01},
67504 + {0xD3,0x4B},
67505 + {0xD4,0x00},
67506 + {0xD5,0x38},
67507 + {0xD6,0x00},
67508 + {0xD7,0x60},
67509 + {0xD8,0x00},
67510 + {0xD9,0x4E},
67511 + {0xDA,0x00},
67512 + {0xDB,0x27},
67513 + {0xDC,0x15},
67514 + {0xDD,0x23},
67515 + {0xDE,0xAD},
67516 + {0xDF,0x24},
67517 + {0xE0,0x01},
67518 + {0xE1,0x17},
67519 + {0xE2,0x4A},
67520 + {0xE3,0x36},
67521 + {0xE4,0x40},
67522 + {0xE5,0x40},
67523 + {0xE6,0x40},
67524 + {0xE7,0x40},
67525 + {0xE8,0x30},
67526 + {0xE9,0x3D},
67527 + {0xEA,0x17},
67528 + {0xEB,0x01},
67529 +
67530 + //=================================
67531 + // Polygon AWB Region Tune
67532 + //=================================
67533 + {0xfc,0x22},
67534 + {0x18,0x00}, // 1
67535 + {0x19,0x5a},
67536 + {0x1a,0xf8},
67537 + {0x1b,0x00}, // 2
67538 + {0x1c,0x59},
67539 + {0x1d,0xCC},
67540 + {0x1e,0x00}, // 3
67541 + {0x1f,0x74},
67542 + {0x20,0xB3},
67543 + {0x21,0x00}, // 4
67544 + {0x22,0x86},
67545 + {0x23,0xA2},
67546 + {0x24,0x00}, // 5
67547 + {0x25,0x94},
67548 + {0x26,0x89},
67549 + {0x27,0x00}, // 6
67550 + {0x28,0xA6},
67551 + {0x29,0x76},
67552 + {0x2A,0x00}, // 7
67553 + {0x2B,0xd0},
67554 + {0x2C,0x5e},
67555 + {0x2D,0x00}, // 8
67556 + {0x2E,0xfa},
67557 + {0x2F,0x47},
67558 + {0x30,0x00}, // 9
67559 + {0x31,0xfD},
67560 + {0x32,0x5D},
67561 + {0x33,0x00}, // 10
67562 + {0x34,0xBB},
67563 + {0x35,0x7c},
67564 + {0x36,0x00}, // 11
67565 + {0x37,0xAD},
67566 + {0x38,0x88},
67567 + {0x39,0x00}, // 12
67568 + {0x3A,0x9A},
67569 + {0x3B,0xA3},
67570 + {0x3C,0x00}, // 13
67571 + {0x3D,0x7C},
67572 + {0x3E,0xDD},
67573 + {0x3F,0x00}, // 14
67574 + {0x40,0x00},
67575 + {0x41,0x00},
67576 +
67577 + //=================================
67578 + // Moving Equation Weight
67579 + //=================================
67580 + {0xfc,0x22},
67581 + {0x98,0x07},
67582 +
67583 + //=================================
67584 + // EIT Threshold
67585 + //=================================
67586 + {0xfc,0x22},
67587 + {0xb1,0x00}, // {0xunny
67588 + {0xb2,0x03},
67589 + {0xb3,0x00},
67590 + {0xb4,0xc1},
67591 +
67592 + {0xb5,0x00}, // Cloudy
67593 + {0xb6,0x05},
67594 + {0xb7,0xc9},
67595 + {0xb9,0x81},
67596 +
67597 + {0xd7,0x00}, // Shade
67598 + {0xd8,0x35},
67599 + {0xd9,0x20},
67600 + {0xda,0x81},
67601 +
67602 + //=================================
67603 + // Gain Offset
67604 + //=================================
67605 + {0xfc,0x00},
67606 + {0x79,0xF9},
67607 + {0x7A,0x02}, // Global AWB gain off{0xet
67608 +
67609 + {0xfc,0x22},
67610 + {0x58,0xf6}, // D65 R Off{0xet
67611 + {0x59,0xff}, // D65 B Off{0xet
67612 + {0x5A,0xfa}, // 5000K R Off{0xet
67613 + {0x5B,0xFe}, // 5000K B Off{0xet
67614 + {0x5C,0xfb}, // CWF R Off{0xet
67615 + {0x5D,0xFe}, // CWF B Off{0xet
67616 + {0x5E,0xfb}, // 3000K R Off{0xet
67617 + {0x5F,0xFb}, // 3000K B Off{0xet
67618 + {0x60,0xfb}, // A R Off0xet
67619 + {0x61,0xfb}, // A B Off0xet
67620 + {0x62,0xfb}, // 2000K R Off0xet
67621 + {0x63,0xfb}, // 2000K B Off0xet
67622 +
67623 + {0xde,0x00}, // LARGE OBJECT BUG FIX
67624 + {0xf0,0x6a}, // RB Ratio
67625 + //=================================
67626 + // Green Stablity Enhance
67627 + //=================================
67628 + {0xfc,0x22},
67629 + {0xb9,0x00},
67630 + {0xba,0x00},
67631 + {0xbb,0x00},
67632 + {0xbc,0x00},
67633 + {0xe5,0x01},
67634 + {0xe6,0xff},
67635 +
67636 + {0xbd,0x90},
67637 +
67638 + //==========================================================
67639 + // Special Effect
67640 + //==========================================================
67641 + {0xfc,0x07}, // Special Effect
67642 + {0x30,0xc0},
67643 + {0x31,0x20},
67644 + {0x32,0x40},
67645 + {0x33,0xc0},
67646 + {0x34,0x00},
67647 + {0x35,0xb0},
67648 +
67649 + {0xfc,0x00},
67650 + {0x73,0x21}, // Frame AE Enable, peter
67651 +
67652 + {0xfc,0x04},
67653 + {0xc0,0x06},
67654 + {0xc1,0x70},
67655 + {0xFF,0xFF} // REGISTER END
67656 +};
67657 +#else
67658 +s5k4xa_t s5k4ba_reg[] =
67659 +{
67660 +//==========================================================
67661 +// CAMERA INITIAL (Analog & Clock Setting)
67662 +//==========================================================
67663 + {0xfc, 0x07},
67664 + {0x66, 0x01},// WDT
67665 + {0xfc, 0x00},
67666 + {0x00, 0xaa},// For EDS Check
67667 + {0x21, 0x03},// peter0223 added
67668 +
67669 + {0xfc, 0x01},
67670 + {0x04, 0x01},// ARM Clock Divider
67671 +
67672 + {0xfc, 0x02},// Analog setting
67673 + {0x55, 0x1e},// LineADLC on(s551a), off(s550a)
67674 + {0x56, 0x10},// BPR 16code
67675 + {0x30, 0x82},// Analog offset (capture =?h)
67676 + {0x37, 0x25},// Global Gain (default:31)
67677 +
67678 + {0x57, 0x80},// // LineADLC Roffset
67679 + {0x58, 0x80},//89 //90 // LineADLC Goffset
67680 + {0x59, 0x80},//90 // LineADLC offset don't care
67681 +
67682 + {0x44, 0x64},//clamp en[6]=1 on
67683 + {0x4a, 0x30},//clamp level 0011h [7]~[4]
67684 +
67685 + {0x2d, 0x48},// double shutter (default:00)
67686 + {0x4d, 0x08},// Voltage doubler (default:04)
67687 + {0x4e, 0x00},// IO current 8mA set
67688 + {0x4f, 0x8a},// IO current 48mA set
67689 +
67690 + {0x66, 0x41},// 1st comp current 2uA
67691 + {0x43, 0xef},// ec_comp
67692 + {0x62, 0x60},// LD control , CFPN_EN off
67693 +
67694 +//==========================================================
67695 +// Table Set for Sub-Sampling
67696 +//==========================================================
67697 + {0xfc, 0x03},
67698 + {0x01, 0x60},
67699 + //{0x2e, 0x00},
67700 + {0x2e, 0x03},//DHL
67701 + {0x05, 0x46},// Output Image Size Set for Capture
67702 + {0x07, 0xb6},
67703 + {0x0e, 0x04},
67704 + {0x12, 0x03},
67705 +
67706 + {0xfc, 0x04},
67707 + {0xc5, 0x26},// Output Image Size Set for Preview
67708 + {0xc7, 0x5e},
67709 + {0xce, 0x04},
67710 + {0xd2, 0x04},
67711 + //{0xee, 0x00},//DHL
67712 + {0xee, 0x01},
67713 + {0xc0, 0x06},
67714 + {0xc1, 0x60},//frame_H
67715 + {0xc2, 0x02},
67716 + {0xc3, 0x8d},//frame_V
67717 +
67718 + {0xfc, 0x07},
67719 + {0x05, 0x00},
67720 + {0x06, 0x00},
67721 + {0x07, 0x8b},
67722 + {0x08, 0xf5},
67723 + {0x09, 0x00},
67724 + {0x0a, 0xb4},
67725 + {0x0b, 0x00},
67726 + {0x0c, 0xea},
67727 + {0x0d, 0x00},
67728 + {0x0e, 0x40},
67729 +
67730 +#if 1
67731 +//==========================================================
67732 +// COMMAND SET
67733 +//==========================================================
67734 + {0xfc, 0x00},
67735 + {0x70, 0x02},
67736 +
67737 + {0xfc, 0x00},
67738 + {0x73, 0x11},//21 Frmae AE Enable, peter0223
67739 + {0x20, 0x02},// Change AWB Mode
67740 +
67741 + {0xfc, 0x00},
67742 + {0x78, 0x6a},// AGC Max
67743 +
67744 + {0xfc, 0x00},
67745 + {0x6c, 0xa0},// AE target
67746 + {0x6d, 0x00},
67747 +
67748 + {0xfc, 0x20},
67749 + {0x16, 0x5a},// AGC frame AE start _for Prevating AE Hunting
67750 + {0x57, 0x18},// Stable_Frame_AE
67751 +
67752 + {0xfc, 0x00},
67753 + {0x83, 0x06},//low condition shutter off // Double shutter off
67754 +
67755 + {0xfc, 0x0b},
67756 + {0x5c, 0x69},//70 //AGC value to start shutter on/off suppress
67757 + {0x5d, 0x65},//60 //AGC value to start double shutter on/off suppress
67758 +
67759 + {0xfc, 0x20},
67760 + {0x25, 0x00},// CINTR Min
67761 + {0x2a, 0x01},// forbidden
67762 + {0x2b, 0x02},// For Forbidden Area
67763 + {0x2c, 0x0a},
67764 + {0x2d, 0x00},// For Forbidden Area
67765 + {0x2e, 0x00},
67766 + {0x2f, 0x05},// forbidden
67767 + {0x14, 0x78},//70
67768 + {0x01, 0x00},// Stepless_Off
67769 +
67770 + {0xfc, 0x00},
67771 + {0x29, 0x04},// Y level
67772 + {0x2a, 0x00},
67773 + {0x2b, 0x03},// C level
67774 + {0x2c, 0x80},//60
67775 +
67776 + {0xfc, 0x07},
67777 + {0x37, 0x00},// Flicker
67778 +
67779 + {0xfc, 0x00},
67780 + {0x72, 0xa0},// Flicker for 32MHz
67781 + {0x74, 0x08},// flicker 60Hz fix
67782 + {0xfc, 0x20},
67783 + {0x02, 0x12},//02 Flicker Dgain Mode
67784 + {0xfc, 0x00},
67785 + {0x62, 0x02},// Hue Control Enable
67786 +
67787 + {0xfc, 0x01},
67788 + //{0x0c, 0x02},// Full YC Enable
67789 + {0x0C, 0x03},//Donghoon
67790 +
67791 +
67792 +//==========================================================
67793 +// COLOR MATRIX
67794 +//==========================================================
67795 + {0xfc, 0x01}, //DL gain 60
67796 + {0x51, 0x08}, //06 //08 07
67797 + {0x52, 0xe8}, //df //9B E7
67798 + {0x53, 0xfc}, //fd //FC FB
67799 + {0x54, 0x33}, //09 //07 B9
67800 + {0x55, 0xfe}, //00 //FF 00
67801 + {0x56, 0xe6}, //17 //5E 5F
67802 + {0x57, 0xfe}, //fe //FD FD
67803 + {0x58, 0x3d}, //4f //0E 46
67804 + {0x59, 0x08}, //06 //07 05
67805 + {0x5a, 0x21}, //9b //EE E6
67806 + {0x5b, 0xfd}, //ff //FF 00
67807 + {0x5c, 0xa3}, //17 //05 D3
67808 + {0x5d, 0xff}, //ff //FF FF
67809 + {0x5e, 0xbc}, //81 //7A 53
67810 + {0x5f, 0xfc}, //fd //FC FB
67811 + {0x60, 0x96}, //5b //23 B1
67812 + {0x61, 0x07}, //07 //08 08
67813 + {0x62, 0xaf}, //24 //64 FD
67814 +
67815 +//==========================================================
67816 +// EDGE ENHANCEMENT
67817 +//==========================================================
67818 + {0xfc, 0x05},
67819 + {0x12, 0x3d},
67820 + {0x13, 0x3b},
67821 + {0x14, 0x38},
67822 + {0x15, 0x3b},
67823 + {0x16, 0x3d},
67824 +
67825 + {0x17, 0x3b},
67826 + {0x18, 0x05},
67827 + {0x19, 0x09},
67828 + {0x1a, 0x05},
67829 + {0x1b, 0x3b},
67830 +
67831 + {0x1c, 0x38},
67832 + {0x1d, 0x09},
67833 + {0x1e, 0x1c},
67834 + {0x1f, 0x09},
67835 + {0x20, 0x38},
67836 +
67837 + {0x21, 0x3b},
67838 + {0x22, 0x05},
67839 + {0x23, 0x09},
67840 + {0x24, 0x05},
67841 + {0x25, 0x3b},
67842 +
67843 + {0x26, 0x3d},
67844 + {0x27, 0x3b},
67845 + {0x28, 0x38},
67846 + {0x29, 0x3b},
67847 + {0x2a, 0x3d},
67848 +
67849 + {0xfc, 0x00},
67850 + {0x89, 0x00},// Edge Suppress On
67851 + {0xfc, 0x0b},
67852 + {0x42, 0x50},// Edge AGC MIN
67853 + {0x43, 0x60},// Edge AGC MAX
67854 + {0x45, 0x18},// positive gain AGC MIN
67855 + {0x49, 0x06},// positive gain AGC MAX
67856 + {0x4d, 0x18},// negative gain AGC MIN
67857 + {0x51, 0x06},// negative gain AGC MAX
67858 +
67859 + {0xfc, 0x05},
67860 + {0x34, 0x28},// APTCLP
67861 + {0x35, 0x03},// APTSC
67862 + {0x36, 0x0b},// ENHANCE
67863 + {0x3f, 0x00},// NON-LIN
67864 + {0x42, 0x10},// EGFALL
67865 + {0x43, 0x00},// HLFALL
67866 + {0x45, 0xa0},// EGREF
67867 + {0x46, 0x7a},// HLREF
67868 + {0x47, 0x40},// LLREF
67869 + {0x48, 0x0c},
67870 + {0x49, 0x31},// CSSEL EGSEL CS_DLY
67871 +
67872 + {0x40, 0x41},// Y delay
67873 +
67874 + // New Wide Luma Edge
67875 + {0xfc, 0x1d},
67876 + {0x86, 0x00},
67877 + {0x87, 0x60},
67878 + {0x88, 0x01},
67879 + {0x89, 0x20},
67880 + {0x8a, 0x00},
67881 + {0x8b, 0x00},
67882 + {0x8c, 0x00},
67883 + {0x8d, 0x00},
67884 + {0x8e, 0x00},
67885 + {0x8f, 0x20},
67886 + {0x90, 0x00},
67887 + {0x91, 0x00},
67888 + {0x92, 0x00},
67889 + {0x93, 0x0a},
67890 + {0x94, 0x00},
67891 + {0x95, 0x00},
67892 + {0x96, 0x00},
67893 + {0x97, 0x20},
67894 + {0x98, 0x00},
67895 + {0x99, 0x00},
67896 + {0x9a, 0xff},
67897 + {0x9b, 0xea},
67898 + {0x9c, 0xaa},
67899 + {0x9d, 0xab},
67900 + {0x9e, 0xff},
67901 + {0x9f, 0xf1},
67902 + {0xa0, 0x55},
67903 + {0xa1, 0x56},
67904 + {0xa2, 0x07},
67905 +
67906 + {0x85, 0x01},
67907 +
67908 +/*
67909 + * GAMMA
67910 + */
67911 +
67912 + {0xfc, 0x1d},
67913 + {0x00, 0x0b},
67914 + {0x01, 0x18},
67915 + {0x02, 0x3d},
67916 + {0x03, 0x9c},
67917 + {0x04, 0x00},
67918 + {0x05, 0x0c},
67919 + {0x06, 0x76},
67920 + {0x07, 0xc2},
67921 + {0x08, 0x00},
67922 + {0x09, 0x56},
67923 + {0x0a, 0x34},
67924 + {0x0b, 0x60},
67925 + {0x0c, 0x85},
67926 + {0x0d, 0xa7},
67927 + {0x0e, 0xaa},
67928 + {0x0f, 0xc6},
67929 + {0x10, 0xe2},
67930 + {0x11, 0xfc},
67931 + {0x12, 0x13},
67932 + {0x13, 0xab},
67933 + {0x14, 0x29},
67934 + {0x15, 0x3c},
67935 + {0x16, 0x4b},
67936 + {0x17, 0x5a},
67937 + {0x18, 0xff},
67938 + {0x19, 0x69},
67939 + {0x1a, 0x78},
67940 + {0x1b, 0x84},
67941 + {0x1c, 0x91},
67942 + {0x1d, 0xff},
67943 + {0x1e, 0x9c},
67944 + {0x1f, 0xa7},
67945 + {0x20, 0xb2},
67946 + {0x21, 0xbd},
67947 + {0x22, 0xff},
67948 + {0x23, 0xc7},
67949 + {0x24, 0xd2},
67950 + {0x25, 0xdb},
67951 + {0x26, 0xe4},
67952 + {0x27, 0xff},
67953 + {0x28, 0xec},
67954 + {0x29, 0xf5},
67955 + {0x2a, 0xf0},
67956 + {0x2b, 0x0b},
67957 + {0x2c, 0x18},
67958 + {0x2d, 0x3d},
67959 + {0x2e, 0x9c},
67960 + {0x2f, 0x00},
67961 + {0x30, 0x0c},
67962 + {0x31, 0x76},
67963 + {0x32, 0xc2},
67964 + {0x33, 0x00},
67965 + {0x34, 0x56},
67966 + {0x35, 0x34},
67967 + {0x36, 0x60},
67968 + {0x37, 0x85},
67969 + {0x38, 0xa7},
67970 + {0x39, 0xaa},
67971 + {0x3a, 0xc6},
67972 + {0x3b, 0xe2},
67973 + {0x3c, 0xfc},
67974 + {0x3d, 0x13},
67975 + {0x3e, 0xab},
67976 + {0x3f, 0x29},
67977 + {0x40, 0x3c},
67978 + {0x41, 0x4b},
67979 + {0x42, 0x5a},
67980 + {0x43, 0xff},
67981 + {0x44, 0x69},
67982 + {0x45, 0x78},
67983 + {0x46, 0x84},
67984 + {0x47, 0x91},
67985 + {0x48, 0xff},
67986 + {0x49, 0x9c},
67987 + {0x4a, 0xa7},
67988 + {0x4b, 0xb2},
67989 + {0x4c, 0xbd},
67990 + {0x4d, 0xff},
67991 + {0x4e, 0xc7},
67992 + {0x4f, 0xd2},
67993 + {0x50, 0xdb},
67994 + {0x51, 0xe4},
67995 + {0x52, 0xff},
67996 + {0x53, 0xec},
67997 + {0x54, 0xf5},
67998 + {0x55, 0xf0},
67999 + {0x56, 0x0b},
68000 + {0x57, 0x18},
68001 + {0x58, 0x3d},
68002 + {0x59, 0x9c},
68003 + {0x5a, 0x00},
68004 + {0x5b, 0x0c},
68005 + {0x5c, 0x76},
68006 + {0x5d, 0xc2},
68007 + {0x5e, 0x00},
68008 + {0x5f, 0x56},
68009 + {0x60, 0x34},
68010 + {0x61, 0x60},
68011 + {0x62, 0x85},
68012 + {0x63, 0xa7},
68013 + {0x64, 0xaa},
68014 + {0x65, 0xc6},
68015 + {0x66, 0xe2},
68016 + {0x67, 0xfc},
68017 + {0x68, 0x13},
68018 + {0x69, 0xab},
68019 + {0x6a, 0x29},
68020 + {0x6b, 0x3c},
68021 + {0x6c, 0x4b},
68022 + {0x6d, 0x5a},
68023 + {0x6e, 0xff},
68024 + {0x6f, 0x69},
68025 + {0x70, 0x78},
68026 + {0x71, 0x84},
68027 + {0x72, 0x91},
68028 + {0x73, 0xff},
68029 + {0x74, 0x9c},
68030 + {0x75, 0xa7},
68031 + {0x76, 0xb2},
68032 + {0x77, 0xbd},
68033 + {0x78, 0xff},
68034 + {0x79, 0xc7},
68035 + {0x7a, 0xd2},
68036 + {0x7b, 0xdb},
68037 + {0x7c, 0xe4},
68038 + {0x7d, 0xff},
68039 + {0x7e, 0xec},
68040 + {0x7f, 0xf5},
68041 + {0x80, 0xf0},
68042 +
68043 +/*
68044 + * HUE CONTROL
68045 + */
68046 +
68047 + {0xfc, 0x00},
68048 + {0x48, 0x40}, /* 2000K */
68049 + {0x49, 0x30},
68050 + {0x4a, 0x00},
68051 + {0x4b, 0x00},
68052 + {0x4c, 0x30},
68053 + {0x4d, 0x38},
68054 + {0x4e, 0x00},
68055 + {0x4f, 0x00},
68056 +
68057 + {0x50, 0x40}, /* 3000K */
68058 + {0x51, 0x30},
68059 + {0x52, 0x00},
68060 + {0x53, 0x00},
68061 + {0x54, 0x30},
68062 + {0x55, 0x38},
68063 + {0x56, 0x00},
68064 + {0x57, 0x00},
68065 +
68066 + {0x58, 0x3c}, /* 40 - 5100K */
68067 + {0x59, 0x30}, /* 4a, 40 */
68068 + {0x5a, 0x00}, /* 0c, 00 */
68069 + {0x5b, 0x00}, /* 00 */
68070 + {0x5c, 0x30}, /* 4a */
68071 + {0x5d, 0x38}, /* 40 */
68072 + {0x5e, 0x00}, /* f6, 15 */
68073 + {0x5f, 0xfc}, /* 00 */
68074 +
68075 +/*
68076 + * SUPPRESS FUNCTION
68077 + */
68078 +
68079 + {0xfc, 0x00},
68080 + {0x7e, 0xf4},
68081 +
68082 +/*
68083 + * BPR
68084 + */
68085 +
68086 + {0xfc, 0x0b},
68087 + {0x3d, 0x10},
68088 +
68089 + {0xfc, 0x0b},
68090 + {0x0b, 0x00},
68091 + {0x0c, 0x40},
68092 + {0x0d, 0x5a},
68093 + {0x0e, 0x00},
68094 + {0x0f, 0x20},
68095 + {0x10, 0x00},
68096 + {0x11, 0x10},
68097 + {0x12, 0x00},
68098 + {0x13, 0x7f},
68099 + {0x14, 0x03},
68100 + {0x15, 0xff},
68101 + {0x16, 0x48},
68102 + {0x17, 0x60},
68103 + {0x18, 0x00},
68104 + {0x19, 0x00},
68105 + {0x1a, 0x00},
68106 + {0x1b, 0x20},
68107 + {0x1c, 0x00},
68108 + {0x1d, 0x00},
68109 + {0x1e, 0x00},
68110 + {0x1f, 0x20},
68111 +
68112 +/*
68113 + * GR/GB CORRECTION
68114 + */
68115 +
68116 + {0xfc, 0x01},
68117 + {0x45, 0x0c},
68118 + {0xfc, 0x0b},
68119 + {0x21, 0x00},
68120 + {0x22, 0x40},
68121 + {0x23, 0x60},
68122 + {0x24, 0x0d},
68123 + {0x25, 0x20},
68124 + {0x26, 0x0d},
68125 + {0x27, 0x20},
68126 +
68127 +/*
68128 + * NR
68129 + */
68130 +
68131 + {0xfc, 0x01},
68132 + {0x4c, 0x01},
68133 + {0x49, 0x15},
68134 + {0x4b, 0x0a},
68135 +
68136 + {0xfc, 0x0b},
68137 + {0x28, 0x00},
68138 + {0x29, 0x00},
68139 + {0x2a, 0x14},
68140 + {0x2b, 0x00},
68141 + {0x2c, 0x14},
68142 + {0x2d, 0x00},
68143 + {0x2e, 0xD0},
68144 + {0x2f, 0x02},
68145 + {0x30, 0x00},
68146 + {0x31, 0x00},
68147 + {0x32, 0xa0},
68148 + {0x33, 0x00},
68149 + {0x34, 0xe0},
68150 +
68151 +/*
68152 + * 1D-Y/C-SIGMA-LPF
68153 + */
68154 +
68155 + {0xfc, 0x01},
68156 + {0x05, 0xC0},
68157 +
68158 + {0xfc, 0x0b},
68159 + {0x35, 0x00},
68160 + {0x36, 0x40},
68161 + {0x37, 0x60},
68162 + {0x38, 0x00},
68163 + {0x39, 0x18},
68164 + {0x3a, 0x00},
68165 + {0x3b, 0x40},
68166 + {0x3c, 0x50},
68167 + {0x3d, 0x60},
68168 + {0x3e, 0x00},
68169 + {0x3f, 0x30},
68170 + {0x40, 0x00},
68171 + {0x41, 0x40},
68172 + {0xd4, 0x40},
68173 + {0xd5, 0x60},
68174 + {0xd6, 0xb0},
68175 + {0xd7, 0xf0},
68176 + {0xd8, 0xb0},
68177 + {0xd9, 0xf0},
68178 +
68179 +/*
68180 + * COLOR SUPPRESS
68181 + */
68182 +
68183 + {0xfc, 0x0b},
68184 + {0x08, 0x58},
68185 + {0x09, 0x03},
68186 + {0x0a, 0x00},
68187 +
68188 +/*
68189 + * SHADING
68190 + */
68191 +
68192 + {0xfc, 0x09},
68193 +
68194 + {0x01, 0x06},
68195 + {0x02, 0x40},
68196 +
68197 + {0x03, 0x04},
68198 + {0x04, 0xB0},
68199 +
68200 + {0x05, 0x03},
68201 + {0x06, 0x20},
68202 + {0x07, 0x02},
68203 + {0x08, 0x91},
68204 +
68205 + {0x09, 0x03},
68206 + {0x0A, 0x25},
68207 + {0x0B, 0x02},
68208 + {0x0C, 0x64},
68209 +
68210 + {0x0D, 0x03},
68211 + {0x0E, 0x0F},
68212 + {0x0F, 0x02},
68213 + {0x10, 0x4E},
68214 +
68215 + {0x1D, 0x80},
68216 + {0x1E, 0x00},
68217 + {0x1F, 0x80},
68218 + {0x20, 0x00},
68219 + {0x23, 0x85},
68220 + {0x24, 0x52},
68221 + {0x21, 0x79},
68222 + {0x22, 0xE6},
68223 +
68224 + {0x25, 0x80},
68225 + {0x26, 0x00},
68226 + {0x27, 0x80},
68227 + {0x28, 0x00},
68228 + {0x2B, 0x81},
68229 + {0x2C, 0x48},
68230 + {0x29, 0x81},
68231 + {0x2A, 0x48},
68232 +
68233 + {0x2D, 0x80},
68234 + {0x2E, 0x00},
68235 + {0x2F, 0x80},
68236 + {0x30, 0x00},
68237 + {0x33, 0x7C},
68238 + {0x34, 0x45},
68239 + {0x31, 0x7D},
68240 + {0x32, 0x7D},
68241 +
68242 + {0x35, 0x01},
68243 + {0x36, 0x00},
68244 + {0x37, 0x01},
68245 + {0x38, 0x11},
68246 + {0x39, 0x01},
68247 + {0x3A, 0x4E},
68248 + {0x3B, 0x01},
68249 + {0x3C, 0xAB},
68250 + {0x3D, 0x01},
68251 + {0x3E, 0xDC},
68252 + {0x3F, 0x02},
68253 + {0x40, 0x1A},
68254 + {0x41, 0x02},
68255 + {0x42, 0x6A},
68256 + {0x43, 0x02},
68257 + {0x44, 0xD3},
68258 +
68259 + {0x45, 0x01},
68260 + {0x46, 0x00},
68261 + {0x47, 0x01},
68262 + {0x48, 0x0E},
68263 + {0x49, 0x01},
68264 + {0x4A, 0x40},
68265 + {0x4B, 0x01},
68266 + {0x4C, 0x8A},
68267 + {0x4D, 0x01},
68268 + {0x4E, 0xB5},
68269 + {0x4F, 0x01},
68270 + {0x50, 0xE8},
68271 + {0x51, 0x02},
68272 + {0x52, 0x27},
68273 + {0x53, 0x02},
68274 + {0x54, 0x84},
68275 +
68276 + {0x55, 0x01},
68277 + {0x56, 0x00},
68278 + {0x57, 0x01},
68279 + {0x58, 0x0C},
68280 + {0x59, 0x01},
68281 + {0x5A, 0x37},
68282 + {0x5B, 0x01},
68283 + {0x5C, 0x74},
68284 + {0x5D, 0x01},
68285 + {0x5E, 0x96},
68286 + {0x5F, 0x01},
68287 + {0x60, 0xC9},
68288 + {0x61, 0x02},
68289 + {0x62, 0x04},
68290 + {0x63, 0x02},
68291 + {0x64, 0x4B},
68292 +
68293 + {0x65, 0x00},
68294 + {0x66, 0x9A},
68295 + {0x67, 0x2D},
68296 + {0x68, 0x02},
68297 + {0x69, 0x68},
68298 + {0x6A, 0xB6},
68299 + {0x6B, 0x05},
68300 + {0x6C, 0x6B},
68301 + {0x6D, 0x99},
68302 + {0x6E, 0x07},
68303 + {0x6F, 0x60},
68304 + {0x70, 0xAD},
68305 + {0x71, 0x09},
68306 + {0x72, 0xA2},
68307 + {0x73, 0xD7},
68308 + {0x74, 0x0C},
68309 + {0x75, 0x32},
68310 + {0x76, 0x19},
68311 + {0x77, 0x0F},
68312 + {0x78, 0x0E},
68313 + {0x79, 0x70},
68314 +
68315 + {0x7A, 0x00},
68316 + {0x7B, 0x9C},
68317 + {0x7C, 0x9F},
68318 + {0x7D, 0x02},
68319 + {0x7E, 0x72},
68320 + {0x7F, 0x7A},
68321 + {0x80, 0x05},
68322 + {0x81, 0x81},
68323 + {0x82, 0x94},
68324 + {0x83, 0x07},
68325 + {0x84, 0x7E},
68326 + {0x85, 0x97},
68327 + {0x86, 0x09},
68328 + {0x87, 0xC9},
68329 + {0x88, 0xEA},
68330 + {0x89, 0x0C},
68331 + {0x8A, 0x63},
68332 + {0x8B, 0x8C},
68333 + {0x8C, 0x0F},
68334 + {0x8D, 0x4B},
68335 + {0x8E, 0x7E},
68336 +
68337 + {0x8F, 0x00},
68338 + {0x90, 0x9E},
68339 + {0x91, 0xBD},
68340 + {0x92, 0x02},
68341 + {0x93, 0x7A},
68342 + {0x94, 0xF5},
68343 + {0x95, 0x05},
68344 + {0x96, 0x94},
68345 + {0x97, 0xA8},
68346 + {0x98, 0x07},
68347 + {0x99, 0x98},
68348 + {0x9A, 0x8F},
68349 + {0x9B, 0x09},
68350 + {0x9C, 0xEB},
68351 + {0x9D, 0xD5},
68352 + {0x9E, 0x0C},
68353 + {0x9F, 0x8E},
68354 + {0xA0, 0x7A},
68355 + {0xA1, 0x0F},
68356 + {0xA2, 0x80},
68357 + {0xA3, 0x7D},
68358 +
68359 + {0xA4, 0x6A},
68360 + {0xA5, 0x44},
68361 + {0xA6, 0x23},
68362 + {0xA7, 0x6C},
68363 + {0xA8, 0x15},
68364 + {0xA9, 0x40},
68365 + {0xAA, 0x20},
68366 + {0xAB, 0xB2},
68367 + {0xAC, 0x1C},
68368 + {0xAD, 0x56},
68369 + {0xAE, 0x19},
68370 + {0xAF, 0x01},
68371 + {0xB0, 0x16},
68372 + {0xB1, 0x5F},
68373 +
68374 + {0xB2, 0x68},
68375 + {0xB3, 0x9C},
68376 + {0xB4, 0x22},
68377 + {0xB5, 0xDE},
68378 + {0xB6, 0x14},
68379 + {0xB7, 0xEC},
68380 + {0xB8, 0x20},
68381 + {0xB9, 0x30},
68382 + {0xBA, 0x1B},
68383 + {0xBB, 0xE5},
68384 + {0xBC, 0x18},
68385 + {0xBD, 0x9D},
68386 + {0xBE, 0x16},
68387 + {0xBF, 0x05},
68388 +
68389 + {0xC0, 0x67},
68390 + {0xC1, 0x36},
68391 + {0xC2, 0x22},
68392 + {0xC3, 0x67},
68393 + {0xC4, 0x14},
68394 + {0xC5, 0xA4},
68395 + {0xC6, 0x1F},
68396 + {0xC7, 0xC2},
68397 + {0xC8, 0x1B},
68398 + {0xC9, 0x86},
68399 + {0xCA, 0x18},
68400 + {0xCB, 0x49},
68401 + {0xCC, 0x15},
68402 + {0xCD, 0xBA},
68403 +
68404 + {0x00, 0x02}, /* shading on */
68405 +
68406 +/*
68407 + * X-SHADING
68408 + */
68409 +
68410 + {0xfc, 0x1B},
68411 + {0x80, 0x01},
68412 + {0x81, 0x00},
68413 + {0x82, 0x4C},
68414 + {0x83, 0x00},
68415 + {0x84, 0x86},
68416 + {0x85, 0x03},
68417 + {0x86, 0x5E},
68418 + {0x87, 0x00},
68419 + {0x88, 0x07},
68420 + {0x89, 0xA4},
68421 + {0x90, 0x00},
68422 + {0x91, 0x88},
68423 + {0x92, 0x00},
68424 + {0x93, 0xC1},
68425 + {0x94, 0x00},
68426 + {0x95, 0xF7},
68427 + {0x96, 0x01},
68428 + {0x97, 0x21},
68429 + {0x98, 0x01},
68430 + {0x99, 0x37},
68431 + {0x9A, 0x01},
68432 + {0x9B, 0x0C},
68433 + {0x9C, 0x00},
68434 + {0x9D, 0xCE},
68435 + {0x9E, 0x00},
68436 + {0x9F, 0x3B},
68437 + {0xA0, 0x00},
68438 + {0xA1, 0x5B},
68439 + {0xA2, 0x00},
68440 + {0xA3, 0x7A},
68441 + {0xA4, 0x00},
68442 + {0xA5, 0x92},
68443 + {0xA6, 0x00},
68444 + {0xA7, 0x91},
68445 + {0xA8, 0x00},
68446 + {0xA9, 0x81},
68447 + {0xAA, 0x00},
68448 + {0xAB, 0x60},
68449 + {0xAC, 0x07},
68450 + {0xAD, 0xCB},
68451 + {0xAE, 0x07},
68452 + {0xAF, 0xC5},
68453 + {0xB0, 0x07},
68454 + {0xB1, 0xBB},
68455 + {0xB2, 0x07},
68456 + {0xB3, 0xAA},
68457 + {0xB4, 0x07},
68458 + {0xB5, 0xA9},
68459 + {0xB6, 0x07},
68460 + {0xB7, 0xB2},
68461 + {0xB8, 0x07},
68462 + {0xB9, 0xBF},
68463 + {0xBA, 0x07},
68464 + {0xBB, 0x5E},
68465 + {0xBC, 0x07},
68466 + {0xBD, 0x3C},
68467 + {0xBE, 0x06},
68468 + {0xBF, 0xF9},
68469 + {0xC0, 0x06},
68470 + {0xC1, 0xBD},
68471 + {0xC2, 0x06},
68472 + {0xC3, 0xB8},
68473 + {0xC4, 0x06},
68474 + {0xC5, 0xE2},
68475 + {0xC6, 0x07},
68476 + {0xC7, 0x1A},
68477 + {0xC8, 0x07},
68478 + {0xC9, 0x15},
68479 + {0xCA, 0x06},
68480 + {0xCB, 0xDE},
68481 + {0xCC, 0x06},
68482 + {0xCD, 0x9C},
68483 + {0xCE, 0x06},
68484 + {0xCF, 0x6F},
68485 + {0xD0, 0x06},
68486 + {0xD1, 0x5E},
68487 + {0xD2, 0x06},
68488 + {0xD3, 0x84},
68489 + {0xD4, 0x06},
68490 + {0xD5, 0xCA},
68491 +
68492 + {0xfc, 0x0b},
68493 + {0xda, 0x00},
68494 + {0xdb, 0x9c},
68495 + {0xdc, 0x00},
68496 + {0xdd, 0xd1},
68497 +
68498 + {0xfc, 0x1b},
68499 + {0x80, 0x01},
68500 +
68501 +/*
68502 + * AE WINDOW WEIGHT
68503 + */
68504 +
68505 + {0xfc, 0x00},
68506 + {0x03, 0x4b},
68507 + {0xfc, 0x06},
68508 + {0x01, 0x35},
68509 + {0x03, 0xc2},
68510 + {0x05, 0x48},
68511 + {0x07, 0xb8},
68512 + {0x31, 0x2a},
68513 + {0x33, 0x61},
68514 + {0x35, 0x28},
68515 + {0x37, 0x5c},
68516 +
68517 + {0xfc, 0x20},
68518 + {0x60, 0x11},
68519 + {0x61, 0x11},
68520 + {0x62, 0x11},
68521 + {0x63, 0x11},
68522 + {0x64, 0x11},
68523 + {0x65, 0x22},
68524 + {0x66, 0x22},
68525 + {0x67, 0x11},
68526 + {0x68, 0x11},
68527 + {0x69, 0x33},
68528 + {0x6a, 0x33},
68529 + {0x6b, 0x11},
68530 + {0x6c, 0x12},
68531 + {0x6d, 0x55},
68532 + {0x6e, 0x55},
68533 + {0x6f, 0x21},
68534 + {0x70, 0x13},
68535 + {0x71, 0x55},
68536 + {0x72, 0x55},
68537 + {0x73, 0x31},
68538 + {0x74, 0x33},
68539 + {0x75, 0x33},
68540 + {0x76, 0x33},
68541 + {0x77, 0x33},
68542 +
68543 +/*
68544 + * SAIT AWB
68545 + */
68546 +
68547 + {0xfc, 0x00},
68548 + {0x7b, 0x00},
68549 +
68550 + {0xfc, 0x07},
68551 + {0x3c, 0x10},
68552 + {0x3d, 0x10},
68553 + {0x3e, 0x10},
68554 + {0x3f, 0x10},
68555 +
68556 + {0xfc, 0x01},
68557 + {0xc8, 0xe0},
68558 + {0xfc, 0x00},
68559 + {0x3e, 0x10},
68560 +
68561 + {0xfc, 0x00},
68562 + {0x3e, 0x10},
68563 + {0x3d, 0x04},
68564 + {0x32, 0x02},
68565 + {0x81, 0x10},
68566 + {0xbc, 0xf0},
68567 + {0xfc, 0x22},
68568 + {0x8c, 0x04},
68569 + {0x8d, 0x06},
68570 +
68571 + {0xfc, 0x07},
68572 + {0x97, 0x00},
68573 +
68574 +/*
68575 + * White Point
68576 + */
68577 +
68578 + {0xfc, 0x22},
68579 + {0x01, 0xD8},
68580 + {0x03, 0xA1},
68581 + {0x05, 0xCA},
68582 + {0x07, 0xC8},
68583 + {0x09, 0xB3},
68584 + {0x0b, 0xE2},
68585 + {0x0d, 0xA0},
68586 + {0x0f, 0xF0},
68587 + {0x11, 0x94},
68588 + {0x12, 0x00},
68589 + {0x13, 0xFD},
68590 + {0x15, 0x88},
68591 + {0x16, 0x01},
68592 + {0x17, 0x10},
68593 +
68594 +/*
68595 + * Basic Setting
68596 + */
68597 +
68598 + {0xfc, 0x22},
68599 + {0xA8, 0xFF},
68600 +
68601 + {0xA0, 0x01},
68602 + {0xA1, 0x38},
68603 + {0xA2, 0x0E},
68604 + {0xA3, 0x6D},
68605 + {0xA4, 0x07},
68606 + {0xA5, 0xF5},
68607 + {0xA6, 0x11},
68608 + {0xA7, 0xBE},
68609 + {0xA9, 0x02},
68610 + {0xAA, 0xD2},
68611 + {0xAB, 0x00},
68612 + {0xAC, 0x00},
68613 + {0xAD, 0x02},
68614 + {0xAE, 0x3F},
68615 + {0xAF, 0x19},
68616 + {0xB0, 0x91},
68617 + {0x94, 0x3D},
68618 + {0x95, 0x00},
68619 + {0x96, 0x58},
68620 + {0x97, 0x80},
68621 + {0xD0, 0xA2},
68622 + {0xD1, 0x2E},
68623 + {0xD2, 0x4D},
68624 + {0xD3, 0x28},
68625 + {0xD4, 0x90},
68626 + {0xDB, 0x2E},
68627 + {0xDC, 0x7A},
68628 + {0xDD, 0x28},
68629 + {0xE7, 0x00},
68630 + {0xE8, 0xc7},
68631 + {0xE9, 0x00},
68632 + {0xEA, 0x62},
68633 + {0xEB, 0xD2},
68634 + {0xEC, 0xD9},
68635 + {0xEE, 0xA6},
68636 +
68637 + {0xfc, 0x00},
68638 + {0x8a, 0x02},
68639 +
68640 +/*
68641 + * Pixel Filter Setting
68642 + */
68643 +
68644 + {0xFC, 0x07},
68645 + {0x95, 0xCF},
68646 +
68647 + {0xfc, 0x01},
68648 + {0xd3, 0x4f},
68649 + {0xd4, 0x00},
68650 + {0xd5, 0x3c},
68651 + {0xd6, 0x80},
68652 + {0xd7, 0x61},
68653 + {0xd8, 0x00},
68654 + {0xd9, 0x49},
68655 + {0xda, 0x00},
68656 + {0xdb, 0x24},
68657 + {0xdc, 0x4b},
68658 + {0xdd, 0x23},
68659 + {0xde, 0xf2},
68660 + {0xdf, 0x20},
68661 + {0xe0, 0x73},
68662 + {0xe1, 0x18},
68663 + {0xe2, 0x69},
68664 + {0xe3, 0x31},
68665 + {0xe4, 0x40},
68666 + {0xe5, 0x34},
68667 + {0xe6, 0x40},
68668 + {0xe7, 0x40},
68669 + {0xe8, 0x32},
68670 + {0xe9, 0x40},
68671 + {0xea, 0x1c},
68672 + {0xeb, 0x00},
68673 +
68674 +/*
68675 + * Polygon AWB Region Tune
68676 + */
68677 +
68678 + /* AWB3 - Polygon Region */
68679 + {0xfc, 0x22},
68680 + {0x18, 0x00},
68681 + {0x19, 0x4b},
68682 + {0x1a, 0xfd},
68683 + {0x1b, 0x00},
68684 + {0x1c, 0x41},
68685 + {0x1d, 0xd9},
68686 + {0x1e, 0x00},
68687 + {0x1f, 0x66},
68688 + {0x20, 0xa9},
68689 + {0x21, 0x00},
68690 + {0x22, 0x8b},
68691 + {0x23, 0x82},
68692 + {0x24, 0x00},
68693 + {0x25, 0xa4},
68694 + {0x26, 0x6c},
68695 + {0x27, 0x00},
68696 + {0x28, 0xbd},
68697 + {0x29, 0x5d},
68698 + {0x2a, 0x00},
68699 + {0x2b, 0xdc},
68700 + {0x2c, 0x4d},
68701 + {0x2d, 0x00},
68702 + {0x2e, 0xdc},
68703 + {0x2f, 0x63},
68704 + {0x30, 0x00},
68705 + {0x31, 0xc1},
68706 + {0x32, 0x72},
68707 + {0x33, 0x00},
68708 + {0x34, 0xab},
68709 + {0x35, 0x84},
68710 + {0x36, 0x00},
68711 + {0x37, 0x99},
68712 + {0x38, 0xa0},
68713 + {0x39, 0x00},
68714 + {0x3a, 0x81},
68715 + {0x3b, 0xe9},
68716 + {0x3c, 0x00},
68717 + {0x3d, 0x00},
68718 + {0x3e, 0x00},
68719 + {0x3f, 0x00},
68720 + {0x40, 0x00},
68721 + {0x41, 0x00},
68722 +
68723 +/*
68724 + * Moving Equation Weight
68725 + */
68726 +
68727 + {0xfc, 0x22},
68728 + {0x98, 0x07},
68729 +
68730 +/*
68731 + * EIT Threshold
68732 + */
68733 +
68734 + {0xfc, 0x22},
68735 + {0xb1, 0x00},
68736 + {0xb2, 0x02},
68737 + {0xb3, 0x00},
68738 + {0xb4, 0xC1},
68739 +
68740 + {0xb5, 0x00},
68741 + {0xb6, 0x02},
68742 + {0xb7, 0x00},
68743 + {0xb9, 0xc2},
68744 +
68745 + {0xd7, 0x00},
68746 + {0xd8, 0x35},
68747 + {0xd9, 0x20},
68748 + {0xda, 0x81},
68749 +
68750 +/*
68751 + * Gain Offset
68752 + */
68753 +
68754 + {0xfc, 0x00},
68755 + {0x79, 0xf8},
68756 + {0x7a, 0x08},
68757 +
68758 + {0xfc, 0x07},
68759 + {0x11, 0x01},
68760 +
68761 + {0xfc, 0x22},
68762 + {0x58, 0xf8},
68763 + {0x59, 0x00},
68764 + {0x5A, 0xfc},
68765 + {0x5B, 0x00},
68766 + {0x5C, 0x00},
68767 + {0x5D, 0x00},
68768 + {0x5E, 0x00},
68769 + {0x5F, 0x00},
68770 + {0x60, 0x00},
68771 + {0x61, 0xf8},
68772 + {0x62, 0x00},
68773 + {0x63, 0xf0},
68774 +
68775 + {0xde, 0x00},
68776 + {0xf0, 0x6a},
68777 +
68778 +/*
68779 + * Green Stablity Enhance
68780 + */
68781 +
68782 + {0xfc, 0x22},
68783 + {0xb9, 0x00},
68784 + {0xba, 0x00},
68785 + {0xbb, 0x00},
68786 + {0xbc, 0x00},
68787 + {0xe5, 0x01},
68788 + {0xe6, 0xff},
68789 + {0xbd, 0x8c},
68790 +
68791 +/*
68792 + * Special Effect
68793 + */
68794 +
68795 + {0xfc, 0x07},
68796 + {0x30, 0xc0},
68797 + {0x31, 0x20},
68798 + {0x32, 0x40},
68799 + {0x33, 0xc0},
68800 + {0x34, 0x00},
68801 + {0x35, 0xb0},
68802 +#endif
68803 +
68804 +/*
68805 + * ETC
68806 + */
68807 +
68808 + {0xfc, 0x01},
68809 + {0x01, 0x01},
68810 + {0x00, 0x90},
68811 + {0xfc, 0x02},
68812 + {0x03, 0x20},
68813 +
68814 + {0xfc, 0x20},
68815 + {0x0f, 0x00},
68816 +
68817 + {0xfc, 0x00},
68818 + {0x02, 0x09},
68819 +
68820 + {0xfc, 0x01},
68821 + //{0x02, 0x00},
68822 + {0x02, 0x02},//Donghoon
68823 +};
68824 +#endif
68825 +#else
68826 +#error No samsung CIS moudule !
68827 +#endif
68828 +
68829 +
68830 +/* For VGA ( 640 x 480) on 4BA module */
68831 +
68832 +s5k4xa_t s5k4ba_reg_vga[] =
68833 +{
68834 + // To do.
68835 +};
68836 +
68837 +/* For SVGA ( 800 x 600) on 4BA module */
68838 +
68839 +s5k4xa_t s5k4ba_reg_svga[] =
68840 +{
68841 + {0xfc,0x02},
68842 + {0x2d,0x48},
68843 + {0x44,0x63},
68844 +
68845 + {0xfc,0x03},
68846 + {0x02,0x04},
68847 + {0xfc,0x20},
68848 + {0x14,0x70},
68849 +
68850 + {0xfc,0x00},
68851 + {0x03,0x4b}, /* AE/AWB On */
68852 + {0x7e,0xf4}, /* Suppress On */
68853 + {0x89,0x03}, /* Edge Suppress On */
68854 +
68855 + {0xfc,0x02},
68856 + {0x02,0x0e}, /* sensor BPRoff */
68857 +
68858 + {0xfc,0x20},
68859 + {0x16,0x60}, /* Frame AE Start */
68860 +
68861 + {0xfc,0x02},
68862 + {0x30,0x90}, /* Analog offset */
68863 + {0x37,0x0d}, /* Global Gain */
68864 + {0x60,0x00}, /* Blank_Adrs */
68865 + {0x45,0x0e}, /* CDS Timing for Average Sub_Sampling */
68866 + {0x47,0x2f},
68867 +
68868 + {0xfc,0x01},
68869 + {0x9F,0x05}, /* B */
68870 + {0xA0,0x18},
68871 + {0xA1,0x42},
68872 + {0xA2,0xd7},
68873 + {0xA3,0x00},
68874 +
68875 + {0xA4,0xB6},
68876 + {0xA5,0x3b},
68877 + {0xA6,0x88},
68878 + {0xA7,0xC8},
68879 + {0xA8,0x6A},
68880 +
68881 + {0xfc,0x05},
68882 + {0x34,0x20}, /* APTCLP */
68883 + {0x35,0x08}, /* 9 - APTSC */
68884 +
68885 + {0xfc,0x00}, /* flash 0821 */
68886 + {0x32,0x04}, /* AWB moving average 8 frame */
68887 +
68888 + {0xfc,0x01},
68889 + {0x01,0x01}, /* Pclk inversion */
68890 +
68891 + {0xfc,0x00},
68892 + {0x02,0x09}, /* 800 x 600 */
68893 +
68894 +
68895 + {0xFF,0xFF} /* REGISTER END */
68896 +};
68897 +
68898 +/* For SXGA (1280 x 1024 = 1.3M) on 4BA module */
68899 +
68900 +s5k4xa_t s5k4ba_reg_sxga[] =
68901 +{
68902 + // To do.
68903 +};
68904 +
68905 +
68906 +/* For UXGA (1600 x 1200 = 2M) on 4BA module */
68907 +
68908 +s5k4xa_t s5k4ba_reg_uxga[] =
68909 +{
68910 + // To do.
68911 +};
68912 +
68913 +
68914 +/* For SQVGA on 4BA module */
68915 +
68916 +s5k4xa_t s5k4ba_reg_qsvga[] =
68917 +{
68918 + /* Pclk inversion */
68919 + {0xfc,0x01},
68920 + {0x01,0x01},
68921 +
68922 + /* To setting CbCr selection on Table 14h */
68923 + {0xfc, 0x14},
68924 + {0x5c, 0x00},
68925 +
68926 + /* To load table_11 H4V4 */
68927 + {0xfc, 0x00},
68928 + {0x02, 0x0B}
68929 +};
68930 +
68931 +#define S5K4BA_INIT_REGS ARRAY_SIZE(s5k4ba_reg)
68932 +#define S5K4BA_UXGA_REGS ARRAY_SIZE(s5k4ba_reg_uxga)
68933 +#define S5K4BA_SVGA_REGS ARRAY_SIZE(s5k4ba_reg_svga)
68934 +#define S5K4BA_VGA_REGS ARRAY_SIZE(s5k4ba_reg_vga)
68935 +#define S5K4BA_QSVGA_REGS ARRAY_SIZE(s5k4ba_reg_qsvga)
68936 +
68937 +
68938 +#define S5K4BA_RISC_REGS 0xEB
68939 +#define S5K4BA_ISP_REGS 0xFB /* S5C7323X */
68940 +#define S5K4BA_CIS_REGS 0x2F /* S5K437LA03 */
68941 +
68942 +
68943 +#define S5K4BA_REGS (0x1000)
68944 +
68945 +
68946 +#endif
68947 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/media/video/samsung/Makefile linux-2.6.29-rc3.owrt.om/drivers/media/video/samsung/Makefile
68948 --- linux-2.6.29-rc3.owrt/drivers/media/video/samsung/Makefile 1970-01-01 01:00:00.000000000 +0100
68949 +++ linux-2.6.29-rc3.owrt.om/drivers/media/video/samsung/Makefile 2009-05-10 22:27:59.000000000 +0200
68950 @@ -0,0 +1,4 @@
68951 +#
68952 +# Samsung CIS camera module
68953 +#
68954 +obj-$(CONFIG_VIDEO_SAMSUNG_S5K4BA) += 4xa_sensor.o
68955 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/media/video/videodev2_s3c.h linux-2.6.29-rc3.owrt.om/drivers/media/video/videodev2_s3c.h
68956 --- linux-2.6.29-rc3.owrt/drivers/media/video/videodev2_s3c.h 1970-01-01 01:00:00.000000000 +0100
68957 +++ linux-2.6.29-rc3.owrt.om/drivers/media/video/videodev2_s3c.h 2009-05-10 22:28:00.000000000 +0200
68958 @@ -0,0 +1,210 @@
68959 +#ifndef __VIDEODEV2_S3C_H_
68960 +#define __VIDEODEV2_S3C_H_
68961 +
68962 +#include <linux/videodev2.h>
68963 +
68964 +#define V4L2_INPUT_TYPE_MSDMA 3
68965 +#define V4L2_INPUT_TYPE_INTERLACE 4
68966 +
68967 +/****************************************************************
68968 +* struct v4l2_control
68969 +* Control IDs defined by S3C
68970 +*****************************************************************/
68971 +/* Image Effect */
68972 +#define V4L2_CID_ORIGINAL (V4L2_CID_PRIVATE_BASE + 0)
68973 +#define V4L2_CID_ARBITRARY (V4L2_CID_PRIVATE_BASE + 1)
68974 +#define V4L2_CID_NEGATIVE (V4L2_CID_PRIVATE_BASE + 2)
68975 +#define V4L2_CID_ART_FREEZE (V4L2_CID_PRIVATE_BASE + 3)
68976 +#define V4L2_CID_EMBOSSING (V4L2_CID_PRIVATE_BASE + 4)
68977 +#define V4L2_CID_SILHOUETTE (V4L2_CID_PRIVATE_BASE + 5)
68978 +
68979 +/* Image Rotate */
68980 +#define V4L2_CID_ROTATE_90 (V4L2_CID_PRIVATE_BASE + 6)
68981 +#define V4L2_CID_ROTATE_180 (V4L2_CID_PRIVATE_BASE + 7)
68982 +#define V4L2_CID_ROTATE_270 (V4L2_CID_PRIVATE_BASE + 8)
68983 +#define V4L2_CID_ROTATE_BYPASS (V4L2_CID_PRIVATE_BASE + 9)
68984 +
68985 +/* Zoom-in, Zoom-out */
68986 +#define V4L2_CID_ZOOMIN (V4L2_CID_PRIVATE_BASE + 10)
68987 +#define V4L2_CID_ZOOMOUT (V4L2_CID_PRIVATE_BASE + 11)
68988 +
68989 +/****************************************************************
68990 +* I O C T L C O D E S F O R V I D E O D E V I C E S
68991 +* It's only for S3C
68992 +*****************************************************************/
68993 +#define VIDIOC_S_CAMERA_START _IO ('V', BASE_VIDIOC_PRIVATE + 0)
68994 +#define VIDIOC_S_CAMERA_STOP _IO ('V', BASE_VIDIOC_PRIVATE + 1)
68995 +#define VIDIOC_MSDMA_START _IOW ('V', BASE_VIDIOC_PRIVATE + 2, struct v4l2_msdma_format)
68996 +#define VIDIOC_MSDMA_STOP _IOW ('V', BASE_VIDIOC_PRIVATE + 3, struct v4l2_msdma_format)
68997 +#define VIDIOC_S_MSDMA _IOW ('V', BASE_VIDIOC_PRIVATE + 4, struct v4l2_msdma_format)
68998 +#define VIDIOC_S_INTERLACE_MODE _IOW ('V', BASE_VIDIOC_PRIVATE + 5, struct v4l2_interlace_format)
68999 +
69000 +/*
69001 + * INTERLACE MODE
69002 + */
69003 +#define S3C_VIDEO_DECODER_PAL 1 /* can decode PAL signal */
69004 +#define S3C_VIDEO_DECODER_NTSC 2 /* can decode NTSC */
69005 +#define S3C_VIDEO_DECODER_SECAM 4 /* can decode SECAM */
69006 +#define S3C_VIDEO_DECODER_AUTO 8 /* can autosense norm */
69007 +#define S3C_VIDEO_DECODER_CCIR 16 /* CCIR-601 pixel rate (720 pixels per line) instead of square pixel rate */
69008 +
69009 +#define S3C_DECODER_INIT _IOW ('V', BASE_VIDIOC_PRIVATE + 14, struct s3c_video_decoder_init) /* init internal registers at once */
69010 +#define S3C_DECODER_GET_CAPABILITIES _IOR ('V', BASE_VIDIOC_PRIVATE + 6, struct s3c_video_decoder_capability)
69011 +#define S3C_DECODER_GET_STATUS _IOR ('V', BASE_VIDIOC_PRIVATE + 7, int)
69012 +#define S3C_DECODER_SET_NORM _IOW ('V', BASE_VIDIOC_PRIVATE + 8, int)
69013 +#define S3C_DECODER_SET_INPUT _IOW ('V', BASE_VIDIOC_PRIVATE + 9, int) /* 0 <= input < #inputs */
69014 +#define S3C_DECODER_SET_OUTPUT _IOW ('V', BASE_VIDIOC_PRIVATE + 10, int) /* 0 <= output < #outputs */
69015 +#define S3C_DECODER_ENABLE_OUTPUT _IOW ('V', BASE_VIDIOC_PRIVATE + 11, int) /* boolean output enable control */
69016 +#define S3C_DECODER_SET_PICTURE _IOW ('V', BASE_VIDIOC_PRIVATE + 12, struct video_picture)
69017 +#define S3C_DECODER_SET_GPIO _IOW ('V', BASE_VIDIOC_PRIVATE + 13, int) /* switch general purpose pin */
69018 +#define S3C_DECODER_SET_VBI_BYPASS _IOW ('V', BASE_VIDIOC_PRIVATE + 15, int) /* switch vbi bypass */
69019 +#define S3C_DECODER_DUMP _IO ('V', BASE_VIDIOC_PRIVATE + 16) /* debug hook */
69020 +
69021 +enum v4l2_msdma_input {
69022 + V4L2_MSDMA_CODEC = 1,
69023 + V4L2_MSDMA_PREVIEW = 2,
69024 +};
69025 +
69026 +struct v4l2_msdma_format
69027 +{
69028 + __u32 width; /* MSDMA INPUT : Source X size */
69029 + __u32 height; /* MSDMA INPUT : Source Y size */
69030 + __u32 pixelformat;
69031 + enum v4l2_msdma_input input_path;
69032 +};
69033 +
69034 +struct v4l2_interlace_format
69035 +{
69036 + __u32 width; /* INTERLACE INPUT : Source X size */
69037 + __u32 height; /* INTERLACE INPUT : Source Y size */
69038 +};
69039 +
69040 +struct s3c_video_decoder_init {
69041 + unsigned char len;
69042 + const unsigned char *data;
69043 +};
69044 +
69045 +struct s3c_video_decoder_capability { /* this name is too long */
69046 + __u32 flags;
69047 + int inputs; /* number of inputs */
69048 + int outputs; /* number of outputs */
69049 +};
69050 +
69051 +static struct v4l2_input fimc_inputs[] = {
69052 + {
69053 + .index = 0,
69054 + .name = "S3C FIMC External Camera Input",
69055 + .type = V4L2_INPUT_TYPE_CAMERA,
69056 + .audioset = 1,
69057 + .tuner = 0,
69058 + .std = V4L2_STD_PAL_BG | V4L2_STD_NTSC_M,
69059 + .status = 0,
69060 + },
69061 + {
69062 + .index = 1,
69063 + .name = "Memory Input (MSDMA)",
69064 + .type = V4L2_INPUT_TYPE_MSDMA,
69065 + .audioset = 2,
69066 + .tuner = 0,
69067 + .std = V4L2_STD_PAL_BG | V4L2_STD_NTSC_M,
69068 + .status = 0,
69069 + }
69070 +};
69071 +
69072 +static struct v4l2_output fimc_outputs[] = {
69073 + {
69074 + .index = 0,
69075 + .name = "Pingpong Memory Output",
69076 + .type = 0,
69077 + .audioset = 0,
69078 + .modulator = 0,
69079 + .std = 0,
69080 + },
69081 + {
69082 + .index = 1,
69083 + .name = "LCD FIFO Output",
69084 + .type = 0,
69085 + .audioset = 0,
69086 + .modulator = 0,
69087 + .std = 0,
69088 + }
69089 +};
69090 +
69091 +const struct v4l2_fmtdesc fimc_codec_formats[] = {
69092 + {
69093 + .index = 0,
69094 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
69095 + .flags = FORMAT_FLAGS_PACKED,
69096 + .description = "16 bpp RGB, le",
69097 + .pixelformat = V4L2_PIX_FMT_RGB565,
69098 + },
69099 + {
69100 + .index = 1,
69101 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
69102 + .flags = FORMAT_FLAGS_PACKED,
69103 + .description = "32 bpp RGB, le",
69104 + .pixelformat = V4L2_PIX_FMT_BGR32,
69105 + },
69106 + {
69107 + .index = 2,
69108 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
69109 + .flags = FORMAT_FLAGS_PLANAR,
69110 + .description = "4:2:2, planar, Y-Cb-Cr",
69111 + .pixelformat = V4L2_PIX_FMT_YUV422P,
69112 +
69113 + },
69114 + {
69115 + .index = 3,
69116 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
69117 + .flags = FORMAT_FLAGS_PLANAR,
69118 + .description = "4:2:0, planar, Y-Cb-Cr",
69119 + .pixelformat = V4L2_PIX_FMT_YUV420,
69120 + }
69121 +};
69122 +
69123 +const struct v4l2_fmtdesc fimc_preview_formats[] = {
69124 + {
69125 + .index = 0,
69126 + .type = V4L2_BUF_TYPE_VIDEO_OVERLAY,
69127 + .flags = FORMAT_FLAGS_PACKED,
69128 + .description = "16 bpp RGB, le",
69129 + .pixelformat = V4L2_PIX_FMT_RGB565,
69130 + },
69131 + {
69132 + .index = 1,
69133 + .type = V4L2_BUF_TYPE_VIDEO_OVERLAY,
69134 + .flags = FORMAT_FLAGS_PACKED,
69135 + .description = "24 bpp RGB, le",
69136 + .pixelformat = V4L2_PIX_FMT_RGB24,
69137 + },
69138 + {
69139 + .index = 2,
69140 + .type = V4L2_BUF_TYPE_VIDEO_OVERLAY,
69141 + .flags = FORMAT_FLAGS_PACKED,
69142 + .description = "32 bpp RGB, le",
69143 + .pixelformat = V4L2_PIX_FMT_BGR32,
69144 + },
69145 + {
69146 + .index = 3,
69147 + .type = V4L2_BUF_TYPE_VIDEO_OVERLAY,
69148 + .flags = FORMAT_FLAGS_PLANAR,
69149 + .description = "4:2:2, planar, Y-Cb-Cr",
69150 + .pixelformat = V4L2_PIX_FMT_YUV422P,
69151 +
69152 + },
69153 + {
69154 + .index = 4,
69155 + .type = V4L2_BUF_TYPE_VIDEO_OVERLAY,
69156 + .flags = FORMAT_FLAGS_PLANAR,
69157 + .description = "4:2:0, planar, Y-Cb-Cr",
69158 + .pixelformat = V4L2_PIX_FMT_YUV420,
69159 + }
69160 +};
69161 +
69162 +#define NUMBER_OF_PREVIEW_FORMATS ARRAY_SIZE(fimc_preview_formats)
69163 +#define NUMBER_OF_CODEC_FORMATS ARRAY_SIZE(fimc_codec_formats)
69164 +#define NUMBER_OF_INPUTS ARRAY_SIZE(fimc_inputs)
69165 +#define NUMBER_OF_OUTPUTS ARRAY_SIZE(fimc_outputs)
69166 +
69167 +#endif
69168 +
69169 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-core.c linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-core.c
69170 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-core.c 1970-01-01 01:00:00.000000000 +0100
69171 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-core.c 2009-05-10 22:28:00.000000000 +0200
69172 @@ -0,0 +1,1457 @@
69173 +/* Smedia Glamo 336x/337x driver
69174 + *
69175 + * (C) 2007 by Openmoko, Inc.
69176 + * Author: Harald Welte <laforge@openmoko.org>
69177 + * All rights reserved.
69178 + *
69179 + * This program is free software; you can redistribute it and/or
69180 + * modify it under the terms of the GNU General Public License as
69181 + * published by the Free Software Foundation; either version 2 of
69182 + * the License, or (at your option) any later version.
69183 + *
69184 + * This program is distributed in the hope that it will be useful,
69185 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
69186 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
69187 + * GNU General Public License for more details.
69188 + *
69189 + * You should have received a copy of the GNU General Public License
69190 + * along with this program; if not, write to the Free Software
69191 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
69192 + * MA 02111-1307 USA
69193 + */
69194 +
69195 +#include <linux/module.h>
69196 +#include <linux/kernel.h>
69197 +#include <linux/errno.h>
69198 +#include <linux/string.h>
69199 +#include <linux/mm.h>
69200 +#include <linux/tty.h>
69201 +#include <linux/slab.h>
69202 +#include <linux/delay.h>
69203 +#include <linux/fb.h>
69204 +#include <linux/init.h>
69205 +#include <linux/irq.h>
69206 +#include <linux/interrupt.h>
69207 +#include <linux/workqueue.h>
69208 +#include <linux/wait.h>
69209 +#include <linux/platform_device.h>
69210 +#include <linux/kernel_stat.h>
69211 +#include <linux/spinlock.h>
69212 +#include <linux/glamofb.h>
69213 +#include <linux/mmc/mmc.h>
69214 +#include <linux/mmc/host.h>
69215 +
69216 +#include <asm/io.h>
69217 +#include <asm/uaccess.h>
69218 +#include <asm/div64.h>
69219 +
69220 +//#include <mach/regs-irq.h>
69221 +
69222 +#ifdef CONFIG_PM
69223 +#include <linux/pm.h>
69224 +#endif
69225 +
69226 +#include "glamo-regs.h"
69227 +#include "glamo-core.h"
69228 +
69229 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
69230 +
69231 +#define GLAMO_MEM_REFRESH_COUNT 0x100
69232 +
69233 +
69234 +/*
69235 + * Glamo internal settings
69236 + *
69237 + * We run the memory interface from the faster PLLB on 2.6.28 kernels and
69238 + * above. Couple of GTA02 users report trouble with memory bus when they
69239 + * upgraded from 2.6.24. So this parameter allows reversion to 2.6.24
69240 + * scheme if their Glamo chip needs it.
69241 + *
69242 + * you can override the faster default on kernel commandline using
69243 + *
69244 + * glamo3362.slow_memory=1
69245 + *
69246 + * for example
69247 + */
69248 +
69249 +static int slow_memory = 0;
69250 +module_param(slow_memory, int, 0644);
69251 +
69252 +struct reg_range {
69253 + int start;
69254 + int count;
69255 + char *name;
69256 + char dump;
69257 +};
69258 +struct reg_range reg_range[] = {
69259 + { 0x0000, 0x76, "General", 1 },
69260 + { 0x0200, 0x16, "Host Bus", 1 },
69261 + { 0x0300, 0x38, "Memory", 1 },
69262 +/* { 0x0400, 0x100, "Sensor", 0 }, */
69263 +/* { 0x0500, 0x300, "ISP", 0 }, */
69264 +/* { 0x0800, 0x400, "JPEG", 0 }, */
69265 +/* { 0x0c00, 0xcc, "MPEG", 0 }, */
69266 + { 0x1100, 0xb2, "LCD 1", 1 },
69267 + { 0x1200, 0x64, "LCD 2", 1 },
69268 + { 0x1400, 0x40, "MMC", 1 },
69269 +/* { 0x1500, 0x080, "MPU 0", 0 },
69270 + { 0x1580, 0x080, "MPU 1", 0 },
69271 + { 0x1600, 0x080, "Cmd Queue", 0 },
69272 + { 0x1680, 0x080, "RISC CPU", 0 },
69273 + { 0x1700, 0x400, "2D Unit", 0 },
69274 + { 0x1b00, 0x900, "3D Unit", 0 }, */
69275 +};
69276 +
69277 +static struct glamo_core *glamo_handle;
69278 +
69279 +static inline void __reg_write(struct glamo_core *glamo,
69280 + u_int16_t reg, u_int16_t val)
69281 +{
69282 + writew(val, glamo->base + reg);
69283 +}
69284 +
69285 +static inline u_int16_t __reg_read(struct glamo_core *glamo,
69286 + u_int16_t reg)
69287 +{
69288 + return readw(glamo->base + reg);
69289 +}
69290 +
69291 +static void __reg_set_bit_mask(struct glamo_core *glamo,
69292 + u_int16_t reg, u_int16_t mask,
69293 + u_int16_t val)
69294 +{
69295 + u_int16_t tmp;
69296 +
69297 + val &= mask;
69298 +
69299 + tmp = __reg_read(glamo, reg);
69300 + tmp &= ~mask;
69301 + tmp |= val;
69302 + __reg_write(glamo, reg, tmp);
69303 +}
69304 +
69305 +static void reg_set_bit_mask(struct glamo_core *glamo,
69306 + u_int16_t reg, u_int16_t mask,
69307 + u_int16_t val)
69308 +{
69309 + spin_lock(&glamo->lock);
69310 + __reg_set_bit_mask(glamo, reg, mask, val);
69311 + spin_unlock(&glamo->lock);
69312 +}
69313 +
69314 +static inline void __reg_set_bit(struct glamo_core *glamo,
69315 + u_int16_t reg, u_int16_t bit)
69316 +{
69317 + __reg_set_bit_mask(glamo, reg, bit, 0xffff);
69318 +}
69319 +
69320 +static inline void __reg_clear_bit(struct glamo_core *glamo,
69321 + u_int16_t reg, u_int16_t bit)
69322 +{
69323 + __reg_set_bit_mask(glamo, reg, bit, 0);
69324 +}
69325 +
69326 +static inline void glamo_vmem_write(struct glamo_core *glamo, u_int32_t addr,
69327 + u_int16_t *src, int len)
69328 +{
69329 + if (addr & 0x0001 || (unsigned long)src & 0x0001 || len & 0x0001) {
69330 + dev_err(&glamo->pdev->dev, "unaligned write(0x%08x, 0x%p, "
69331 + "0x%x)!!\n", addr, src, len);
69332 + }
69333 +
69334 +}
69335 +
69336 +static inline void glamo_vmem_read(struct glamo_core *glamo, u_int16_t *buf,
69337 + u_int32_t addr, int len)
69338 +{
69339 + if (addr & 0x0001 || (unsigned long) buf & 0x0001 || len & 0x0001) {
69340 + dev_err(&glamo->pdev->dev, "unaligned read(0x%p, 0x08%x, "
69341 + "0x%x)!!\n", buf, addr, len);
69342 + }
69343 +
69344 +
69345 +}
69346 +
69347 +/***********************************************************************
69348 + * resources of sibling devices
69349 + ***********************************************************************/
69350 +
69351 +#if 0
69352 +static struct resource glamo_core_resources[] = {
69353 + {
69354 + .start = GLAMO_REGOFS_GENERIC,
69355 + .end = GLAMO_REGOFS_GENERIC + 0x400,
69356 + .flags = IORESOURCE_MEM,
69357 + }, {
69358 + .start = 0,
69359 + .end = 0,
69360 + .flags = IORESOURCE_IRQ,
69361 + },
69362 +};
69363 +
69364 +static struct platform_device glamo_core_dev = {
69365 + .name = "glamo-core",
69366 + .resource = &glamo_core_resources,
69367 + .num_resources = ARRAY_SIZE(glamo_core_resources),
69368 +};
69369 +#endif
69370 +
69371 +static struct resource glamo_jpeg_resources[] = {
69372 + {
69373 + .start = GLAMO_REGOFS_JPEG,
69374 + .end = GLAMO_REGOFS_MPEG - 1,
69375 + .flags = IORESOURCE_MEM,
69376 + }, {
69377 + .start = IRQ_GLAMO_JPEG,
69378 + .end = IRQ_GLAMO_JPEG,
69379 + .flags = IORESOURCE_IRQ,
69380 + },
69381 +};
69382 +
69383 +static struct platform_device glamo_jpeg_dev = {
69384 + .name = "glamo-jpeg",
69385 + .resource = glamo_jpeg_resources,
69386 + .num_resources = ARRAY_SIZE(glamo_jpeg_resources),
69387 +};
69388 +
69389 +static struct resource glamo_mpeg_resources[] = {
69390 + {
69391 + .start = GLAMO_REGOFS_MPEG,
69392 + .end = GLAMO_REGOFS_LCD - 1,
69393 + .flags = IORESOURCE_MEM,
69394 + }, {
69395 + .start = IRQ_GLAMO_MPEG,
69396 + .end = IRQ_GLAMO_MPEG,
69397 + .flags = IORESOURCE_IRQ,
69398 + },
69399 +};
69400 +
69401 +static struct platform_device glamo_mpeg_dev = {
69402 + .name = "glamo-mpeg",
69403 + .resource = glamo_mpeg_resources,
69404 + .num_resources = ARRAY_SIZE(glamo_mpeg_resources),
69405 +};
69406 +
69407 +static struct resource glamo_2d_resources[] = {
69408 + {
69409 + .start = GLAMO_REGOFS_2D,
69410 + .end = GLAMO_REGOFS_3D - 1,
69411 + .flags = IORESOURCE_MEM,
69412 + }, {
69413 + .start = IRQ_GLAMO_2D,
69414 + .end = IRQ_GLAMO_2D,
69415 + .flags = IORESOURCE_IRQ,
69416 + },
69417 +};
69418 +
69419 +static struct platform_device glamo_2d_dev = {
69420 + .name = "glamo-2d",
69421 + .resource = glamo_2d_resources,
69422 + .num_resources = ARRAY_SIZE(glamo_2d_resources),
69423 +};
69424 +
69425 +static struct resource glamo_3d_resources[] = {
69426 + {
69427 + .start = GLAMO_REGOFS_3D,
69428 + .end = GLAMO_REGOFS_END - 1,
69429 + .flags = IORESOURCE_MEM,
69430 + },
69431 +};
69432 +
69433 +static struct platform_device glamo_3d_dev = {
69434 + .name = "glamo-3d",
69435 + .resource = glamo_3d_resources,
69436 + .num_resources = ARRAY_SIZE(glamo_3d_resources),
69437 +};
69438 +
69439 +static struct platform_device glamo_spigpio_dev = {
69440 + .name = "glamo-spi-gpio",
69441 +};
69442 +
69443 +static struct resource glamo_fb_resources[] = {
69444 + /* FIXME: those need to be incremented by parent base */
69445 + {
69446 + .name = "glamo-fb-regs",
69447 + .start = GLAMO_REGOFS_LCD,
69448 + .end = GLAMO_REGOFS_MMC - 1,
69449 + .flags = IORESOURCE_MEM,
69450 + }, {
69451 + .name = "glamo-fb-mem",
69452 + .start = GLAMO_OFFSET_FB,
69453 + .end = GLAMO_OFFSET_FB + GLAMO_FB_SIZE - 1,
69454 + .flags = IORESOURCE_MEM,
69455 + },
69456 +};
69457 +
69458 +static struct platform_device glamo_fb_dev = {
69459 + .name = "glamo-fb",
69460 + .resource = glamo_fb_resources,
69461 + .num_resources = ARRAY_SIZE(glamo_fb_resources),
69462 +};
69463 +
69464 +static struct resource glamo_mmc_resources[] = {
69465 + {
69466 + /* FIXME: those need to be incremented by parent base */
69467 + .start = GLAMO_REGOFS_MMC,
69468 + .end = GLAMO_REGOFS_MPROC0 - 1,
69469 + .flags = IORESOURCE_MEM
69470 + }, {
69471 + .start = IRQ_GLAMO_MMC,
69472 + .end = IRQ_GLAMO_MMC,
69473 + .flags = IORESOURCE_IRQ,
69474 + }, { /* our data buffer for MMC transfers */
69475 + .start = GLAMO_OFFSET_FB + GLAMO_FB_SIZE,
69476 + .end = GLAMO_OFFSET_FB + GLAMO_FB_SIZE +
69477 + GLAMO_MMC_BUFFER_SIZE - 1,
69478 + .flags = IORESOURCE_MEM
69479 + },
69480 +};
69481 +
69482 +struct glamo_mci_pdata glamo_mci_def_pdata = {
69483 + .gpio_detect = 0,
69484 + .glamo_can_set_mci_power = NULL, /* filled in from MFD platform data */
69485 + .ocr_avail = MMC_VDD_20_21 |
69486 + MMC_VDD_21_22 |
69487 + MMC_VDD_22_23 |
69488 + MMC_VDD_23_24 |
69489 + MMC_VDD_24_25 |
69490 + MMC_VDD_25_26 |
69491 + MMC_VDD_26_27 |
69492 + MMC_VDD_27_28 |
69493 + MMC_VDD_28_29 |
69494 + MMC_VDD_29_30 |
69495 + MMC_VDD_30_31 |
69496 + MMC_VDD_32_33,
69497 + .glamo_irq_is_wired = NULL, /* filled in from MFD platform data */
69498 + .mci_suspending = NULL, /* filled in from MFD platform data */
69499 + .mci_all_dependencies_resumed = NULL, /* filled in from MFD platform data */
69500 +};
69501 +EXPORT_SYMBOL_GPL(glamo_mci_def_pdata);
69502 +
69503 +
69504 +
69505 +static void mangle_mem_resources(struct resource *res, int num_res,
69506 + struct resource *parent)
69507 +{
69508 + int i;
69509 +
69510 + for (i = 0; i < num_res; i++) {
69511 + if (res[i].flags != IORESOURCE_MEM)
69512 + continue;
69513 + res[i].start += parent->start;
69514 + res[i].end += parent->start;
69515 + res[i].parent = parent;
69516 + }
69517 +}
69518 +
69519 +/***********************************************************************
69520 + * IRQ demultiplexer
69521 + ***********************************************************************/
69522 +#define irq2glamo(x) (x - IRQ_GLAMO(0))
69523 +
69524 +static void glamo_ack_irq(unsigned int irq)
69525 +{
69526 + /* clear interrupt source */
69527 + __reg_write(glamo_handle, GLAMO_REG_IRQ_CLEAR,
69528 + 1 << irq2glamo(irq));
69529 +}
69530 +
69531 +static void glamo_mask_irq(unsigned int irq)
69532 +{
69533 + u_int16_t tmp;
69534 +
69535 + /* clear bit in enable register */
69536 + tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE);
69537 + tmp &= ~(1 << irq2glamo(irq));
69538 + __reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp);
69539 +}
69540 +
69541 +static void glamo_unmask_irq(unsigned int irq)
69542 +{
69543 + u_int16_t tmp;
69544 +
69545 + /* set bit in enable register */
69546 + tmp = __reg_read(glamo_handle, GLAMO_REG_IRQ_ENABLE);
69547 + tmp |= (1 << irq2glamo(irq));
69548 + __reg_write(glamo_handle, GLAMO_REG_IRQ_ENABLE, tmp);
69549 +}
69550 +
69551 +static struct irq_chip glamo_irq_chip = {
69552 + .ack = glamo_ack_irq,
69553 + .mask = glamo_mask_irq,
69554 + .unmask = glamo_unmask_irq,
69555 +};
69556 +
69557 +static void glamo_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
69558 +{
69559 + const unsigned int cpu = smp_processor_id();
69560 +
69561 + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
69562 +
69563 + if (unlikely(desc->status & IRQ_INPROGRESS)) {
69564 + desc->status |= (IRQ_PENDING | IRQ_MASKED);
69565 + desc->chip->mask(irq);
69566 + desc->chip->ack(irq);
69567 + return;
69568 + }
69569 +
69570 + kstat_cpu(cpu).irqs[irq]++;
69571 + desc->chip->ack(irq);
69572 + desc->status |= IRQ_INPROGRESS;
69573 +
69574 + do {
69575 + u_int16_t irqstatus;
69576 + int i;
69577 +
69578 + if (unlikely((desc->status &
69579 + (IRQ_PENDING | IRQ_MASKED | IRQ_DISABLED)) ==
69580 + (IRQ_PENDING | IRQ_MASKED))) {
69581 + /* dealing with pending IRQ, unmasking */
69582 + desc->chip->unmask(irq);
69583 + desc->status &= ~IRQ_MASKED;
69584 + }
69585 +
69586 + desc->status &= ~IRQ_PENDING;
69587 +
69588 + /* read IRQ status register */
69589 + irqstatus = __reg_read(glamo_handle, GLAMO_REG_IRQ_STATUS);
69590 + for (i = 0; i < 9; i++)
69591 + if (irqstatus & (1 << i))
69592 + desc_handle_irq(IRQ_GLAMO(i),
69593 + irq_desc+IRQ_GLAMO(i));
69594 +
69595 + } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
69596 +
69597 + desc->status &= ~IRQ_INPROGRESS;
69598 +}
69599 +
69600 +
69601 +static ssize_t regs_write(struct device *dev, struct device_attribute *attr,
69602 + const char *buf, size_t count)
69603 +{
69604 + unsigned long reg = simple_strtoul(buf, NULL, 10);
69605 + struct glamo_core *glamo = dev_get_drvdata(dev);
69606 +
69607 + while (*buf && (*buf != ' '))
69608 + buf++;
69609 + if (*buf != ' ')
69610 + return -EINVAL;
69611 + while (*buf && (*buf == ' '))
69612 + buf++;
69613 + if (!*buf)
69614 + return -EINVAL;
69615 +
69616 + printk(KERN_INFO"reg 0x%02lX <-- 0x%04lX\n",
69617 + reg, simple_strtoul(buf, NULL, 10));
69618 +
69619 + __reg_write(glamo, reg, simple_strtoul(buf, NULL, 10));
69620 +
69621 + return count;
69622 +}
69623 +
69624 +static ssize_t regs_read(struct device *dev, struct device_attribute *attr,
69625 + char *buf)
69626 +{
69627 + struct glamo_core *glamo = dev_get_drvdata(dev);
69628 + int n, n1 = 0, r;
69629 + char * end = buf;
69630 +
69631 + spin_lock(&glamo->lock);
69632 +
69633 + for (r = 0; r < ARRAY_SIZE(reg_range); r++) {
69634 + if (!reg_range[r].dump)
69635 + continue;
69636 + n1 = 0;
69637 + end += sprintf(end, "\n%s\n", reg_range[r].name);
69638 + for (n = reg_range[r].start;
69639 + n < reg_range[r].start + reg_range[r].count; n += 2) {
69640 + if (((n1++) & 7) == 0)
69641 + end += sprintf(end, "\n%04X: ", n);
69642 + end += sprintf(end, "%04x ", __reg_read(glamo, n));
69643 + }
69644 + end += sprintf(end, "\n");
69645 + if (!attr) {
69646 + printk("%s", buf);
69647 + end = buf;
69648 + }
69649 + }
69650 + spin_unlock(&glamo->lock);
69651 +
69652 + return end - buf;
69653 +}
69654 +
69655 +static DEVICE_ATTR(regs, 0644, regs_read, regs_write);
69656 +static struct attribute *glamo_sysfs_entries[] = {
69657 + &dev_attr_regs.attr,
69658 + NULL
69659 +};
69660 +static struct attribute_group glamo_attr_group = {
69661 + .name = NULL,
69662 + .attrs = glamo_sysfs_entries,
69663 +};
69664 +
69665 +
69666 +
69667 +/***********************************************************************
69668 + * 'engine' support
69669 + ***********************************************************************/
69670 +
69671 +int __glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine)
69672 +{
69673 + switch (engine) {
69674 + case GLAMO_ENGINE_LCD:
69675 + __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
69676 + GLAMO_HOSTBUS2_MMIO_EN_LCD,
69677 + GLAMO_HOSTBUS2_MMIO_EN_LCD);
69678 + __reg_write(glamo, GLAMO_REG_CLOCK_LCD,
69679 + GLAMO_CLOCK_LCD_EN_M5CLK |
69680 + GLAMO_CLOCK_LCD_EN_DHCLK |
69681 + GLAMO_CLOCK_LCD_EN_DMCLK |
69682 + GLAMO_CLOCK_LCD_EN_DCLK |
69683 + GLAMO_CLOCK_LCD_DG_M5CLK |
69684 + GLAMO_CLOCK_LCD_DG_DMCLK);
69685 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1,
69686 + GLAMO_CLOCK_GEN51_EN_DIV_DHCLK |
69687 + GLAMO_CLOCK_GEN51_EN_DIV_DMCLK |
69688 + GLAMO_CLOCK_GEN51_EN_DIV_DCLK, 0xffff);
69689 + break;
69690 + case GLAMO_ENGINE_MMC:
69691 + __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
69692 + GLAMO_HOSTBUS2_MMIO_EN_MMC,
69693 + GLAMO_HOSTBUS2_MMIO_EN_MMC);
69694 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MMC,
69695 + GLAMO_CLOCK_MMC_EN_M9CLK |
69696 + GLAMO_CLOCK_MMC_EN_TCLK |
69697 + GLAMO_CLOCK_MMC_DG_M9CLK |
69698 + GLAMO_CLOCK_MMC_DG_TCLK, 0xffff);
69699 + /* enable the TCLK divider clk input */
69700 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1,
69701 + GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
69702 + GLAMO_CLOCK_GEN51_EN_DIV_TCLK);
69703 + break;
69704 + case GLAMO_ENGINE_2D:
69705 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D,
69706 + GLAMO_CLOCK_2D_EN_M7CLK |
69707 + GLAMO_CLOCK_2D_EN_GCLK |
69708 + GLAMO_CLOCK_2D_DG_M7CLK |
69709 + GLAMO_CLOCK_2D_DG_GCLK, 0xffff);
69710 + __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
69711 + GLAMO_HOSTBUS2_MMIO_EN_2D,
69712 + GLAMO_HOSTBUS2_MMIO_EN_2D);
69713 + break;
69714 + case GLAMO_ENGINE_CMDQ:
69715 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_2D,
69716 + GLAMO_CLOCK_2D_EN_M6CLK, 0xffff);
69717 + __reg_set_bit_mask(glamo, GLAMO_REG_HOSTBUS(2),
69718 + GLAMO_HOSTBUS2_MMIO_EN_CQ,
69719 + GLAMO_HOSTBUS2_MMIO_EN_CQ);
69720 + break;
69721 + /* FIXME: Implementation */
69722 + default:
69723 + break;
69724 + }
69725 +
69726 + glamo->engine_enabled_bitfield |= 1 << engine;
69727 +
69728 + return 0;
69729 +}
69730 +
69731 +int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine)
69732 +{
69733 + int ret;
69734 +
69735 + spin_lock(&glamo->lock);
69736 +
69737 + ret = __glamo_engine_enable(glamo, engine);
69738 +
69739 + spin_unlock(&glamo->lock);
69740 +
69741 + return ret;
69742 +}
69743 +EXPORT_SYMBOL_GPL(glamo_engine_enable);
69744 +
69745 +int __glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine)
69746 +{
69747 + switch (engine) {
69748 + case GLAMO_ENGINE_LCD:
69749 + /* remove pixel clock to LCM */
69750 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD,
69751 + GLAMO_CLOCK_LCD_EN_DCLK, 0);
69752 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD,
69753 + GLAMO_CLOCK_LCD_EN_DHCLK |
69754 + GLAMO_CLOCK_LCD_EN_DMCLK, 0);
69755 + /* kill memory clock */
69756 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_LCD,
69757 + GLAMO_CLOCK_LCD_EN_M5CLK, 0);
69758 + /* stop dividing the clocks */
69759 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1,
69760 + GLAMO_CLOCK_GEN51_EN_DIV_DHCLK |
69761 + GLAMO_CLOCK_GEN51_EN_DIV_DMCLK |
69762 + GLAMO_CLOCK_GEN51_EN_DIV_DCLK, 0);
69763 + break;
69764 +
69765 + case GLAMO_ENGINE_MMC:
69766 +// __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_MMC,
69767 +// GLAMO_CLOCK_MMC_EN_M9CLK |
69768 +// GLAMO_CLOCK_MMC_EN_TCLK |
69769 +// GLAMO_CLOCK_MMC_DG_M9CLK |
69770 +// GLAMO_CLOCK_MMC_DG_TCLK, 0);
69771 + /* disable the TCLK divider clk input */
69772 +// __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1,
69773 +// GLAMO_CLOCK_GEN51_EN_DIV_TCLK, 0);
69774 +
69775 + default:
69776 + break;
69777 + }
69778 +
69779 + glamo->engine_enabled_bitfield &= ~(1 << engine);
69780 +
69781 + return 0;
69782 +}
69783 +int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine)
69784 +{
69785 + int ret;
69786 +
69787 + spin_lock(&glamo->lock);
69788 +
69789 + ret = __glamo_engine_disable(glamo, engine);
69790 +
69791 + spin_unlock(&glamo->lock);
69792 +
69793 + return ret;
69794 +}
69795 +EXPORT_SYMBOL_GPL(glamo_engine_disable);
69796 +
69797 +static const u_int16_t engine_clock_regs[__NUM_GLAMO_ENGINES] = {
69798 + [GLAMO_ENGINE_LCD] = GLAMO_REG_CLOCK_LCD,
69799 + [GLAMO_ENGINE_MMC] = GLAMO_REG_CLOCK_MMC,
69800 + [GLAMO_ENGINE_ISP] = GLAMO_REG_CLOCK_ISP,
69801 + [GLAMO_ENGINE_JPEG] = GLAMO_REG_CLOCK_JPEG,
69802 + [GLAMO_ENGINE_3D] = GLAMO_REG_CLOCK_3D,
69803 + [GLAMO_ENGINE_2D] = GLAMO_REG_CLOCK_2D,
69804 + [GLAMO_ENGINE_MPEG_ENC] = GLAMO_REG_CLOCK_MPEG,
69805 + [GLAMO_ENGINE_MPEG_DEC] = GLAMO_REG_CLOCK_MPEG,
69806 +};
69807 +
69808 +void glamo_engine_clkreg_set(struct glamo_core *glamo,
69809 + enum glamo_engine engine,
69810 + u_int16_t mask, u_int16_t val)
69811 +{
69812 + reg_set_bit_mask(glamo, engine_clock_regs[engine], mask, val);
69813 +}
69814 +EXPORT_SYMBOL_GPL(glamo_engine_clkreg_set);
69815 +
69816 +u_int16_t glamo_engine_clkreg_get(struct glamo_core *glamo,
69817 + enum glamo_engine engine)
69818 +{
69819 + u_int16_t val;
69820 +
69821 + spin_lock(&glamo->lock);
69822 + val = __reg_read(glamo, engine_clock_regs[engine]);
69823 + spin_unlock(&glamo->lock);
69824 +
69825 + return val;
69826 +}
69827 +EXPORT_SYMBOL_GPL(glamo_engine_clkreg_get);
69828 +
69829 +struct glamo_script reset_regs[] = {
69830 + [GLAMO_ENGINE_LCD] = {
69831 + GLAMO_REG_CLOCK_LCD, GLAMO_CLOCK_LCD_RESET
69832 + },
69833 +#if 0
69834 + [GLAMO_ENGINE_HOST] = {
69835 + GLAMO_REG_CLOCK_HOST, GLAMO_CLOCK_HOST_RESET
69836 + },
69837 + [GLAMO_ENGINE_MEM] = {
69838 + GLAMO_REG_CLOCK_MEM, GLAMO_CLOCK_MEM_RESET
69839 + },
69840 +#endif
69841 + [GLAMO_ENGINE_MMC] = {
69842 + GLAMO_REG_CLOCK_MMC, GLAMO_CLOCK_MMC_RESET
69843 + },
69844 + [GLAMO_ENGINE_2D] = {
69845 + GLAMO_REG_CLOCK_2D, GLAMO_CLOCK_2D_RESET
69846 + },
69847 + [GLAMO_ENGINE_JPEG] = {
69848 + GLAMO_REG_CLOCK_JPEG, GLAMO_CLOCK_JPEG_RESET
69849 + },
69850 +};
69851 +
69852 +void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine)
69853 +{
69854 + struct glamo_script *rst;
69855 +
69856 + if (engine >= ARRAY_SIZE(reset_regs)) {
69857 + dev_warn(&glamo->pdev->dev, "unknown engine %u ", engine);
69858 + return;
69859 + }
69860 +
69861 + rst = &reset_regs[engine];
69862 +
69863 + spin_lock(&glamo->lock);
69864 + __reg_set_bit(glamo, rst->reg, rst->val);
69865 + __reg_clear_bit(glamo, rst->reg, rst->val);
69866 + spin_unlock(&glamo->lock);
69867 +}
69868 +EXPORT_SYMBOL_GPL(glamo_engine_reset);
69869 +
69870 +void glamo_lcm_reset(int level)
69871 +{
69872 + if (!glamo_handle)
69873 + return;
69874 +
69875 + glamo_gpio_setpin(glamo_handle, GLAMO_GPIO4, level);
69876 + glamo_gpio_cfgpin(glamo_handle, GLAMO_GPIO4_OUTPUT);
69877 +
69878 +}
69879 +EXPORT_SYMBOL_GPL(glamo_lcm_reset);
69880 +
69881 +enum glamo_pll {
69882 + GLAMO_PLL1,
69883 + GLAMO_PLL2,
69884 +};
69885 +
69886 +static int glamo_pll_rate(struct glamo_core *glamo,
69887 + enum glamo_pll pll)
69888 +{
69889 + u_int16_t reg;
69890 + unsigned int div = 512;
69891 + /* FIXME: move osci into platform_data */
69892 + unsigned int osci = 32768;
69893 +
69894 + if (osci == 32768)
69895 + div = 1;
69896 +
69897 + switch (pll) {
69898 + case GLAMO_PLL1:
69899 + reg = __reg_read(glamo, GLAMO_REG_PLL_GEN1);
69900 + break;
69901 + case GLAMO_PLL2:
69902 + reg = __reg_read(glamo, GLAMO_REG_PLL_GEN3);
69903 + break;
69904 + default:
69905 + return -EINVAL;
69906 + }
69907 + return (osci/div)*reg;
69908 +}
69909 +
69910 +int glamo_engine_reclock(struct glamo_core *glamo,
69911 + enum glamo_engine engine,
69912 + int ps)
69913 +{
69914 + int pll, khz;
69915 + u_int16_t reg, mask, val = 0;
69916 +
69917 + if (!ps)
69918 + return 0;
69919 +
69920 + switch (engine) {
69921 + case GLAMO_ENGINE_LCD:
69922 + pll = GLAMO_PLL1;
69923 + reg = GLAMO_REG_CLOCK_GEN7;
69924 + mask = 0xff;
69925 + break;
69926 + default:
69927 + dev_warn(&glamo->pdev->dev,
69928 + "reclock of engine 0x%x not supported\n", engine);
69929 + return -EINVAL;
69930 + break;
69931 + }
69932 +
69933 + pll = glamo_pll_rate(glamo, pll);
69934 + khz = 1000000000UL / ps;
69935 +
69936 + if (khz)
69937 + val = (pll / khz) / 1000;
69938 +
69939 + dev_dbg(&glamo->pdev->dev,
69940 + "PLL %d, kHZ %d, div %d\n", pll, khz, val);
69941 +
69942 + if (val) {
69943 + val--;
69944 + reg_set_bit_mask(glamo, reg, mask, val);
69945 + mdelay(5); /* wait some time to stabilize */
69946 +
69947 + return 0;
69948 + } else {
69949 + return -EINVAL;
69950 + }
69951 +}
69952 +EXPORT_SYMBOL_GPL(glamo_engine_reclock);
69953 +
69954 +/***********************************************************************
69955 + * script support
69956 + ***********************************************************************/
69957 +
69958 +int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script,
69959 + int len, int may_sleep)
69960 +{
69961 + int i;
69962 +
69963 + for (i = 0; i < len; i++) {
69964 + struct glamo_script *line = &script[i];
69965 +
69966 + switch (line->reg) {
69967 + case 0xffff:
69968 + return 0;
69969 + case 0xfffe:
69970 + if (may_sleep)
69971 + msleep(line->val);
69972 + else
69973 + mdelay(line->val * 4);
69974 + break;
69975 + case 0xfffd:
69976 + /* spin until PLLs lock */
69977 + while ((__reg_read(glamo, GLAMO_REG_PLL_GEN5) & 3) != 3)
69978 + ;
69979 + break;
69980 +
69981 + /*
69982 + * couple of people reported artefacts with 2.6.28 changes, this
69983 + * allows reversion to 2.6.24 settings
69984 + */
69985 +
69986 + case 0x200:
69987 + switch (slow_memory) {
69988 + /* choice 1 is the most conservative */
69989 + case 1: /* 3 waits on Async BB R & W, Use PLL 1 for mem bus */
69990 + __reg_write(glamo, script[i].reg, 0xef0);
69991 + break;
69992 + case 2: /* 2 waits on Async BB R & W, Use PLL 1 for mem bus */
69993 + __reg_write(glamo, script[i].reg, 0xea0);
69994 + break;
69995 + case 3: /* 1 waits on Async BB R & W, Use PLL 1 for mem bus */
69996 + __reg_write(glamo, script[i].reg, 0xe50);
69997 + break;
69998 + case 4: /* 0 waits on Async BB R & W, Use PLL 1 for mem bus */
69999 + __reg_write(glamo, script[i].reg, 0xe00);
70000 + break;
70001 +
70002 + /* using PLL2 for memory bus increases CPU bandwidth significantly */
70003 + case 5: /* 3 waits on Async BB R & W, Use PLL 2 for mem bus */
70004 + __reg_write(glamo, script[i].reg, 0xef3);
70005 + break;
70006 + case 6: /* 2 waits on Async BB R & W, Use PLL 2 for mem bus */
70007 + __reg_write(glamo, script[i].reg, 0xea3);
70008 + break;
70009 + case 7: /* 1 waits on Async BB R & W, Use PLL 2 for mem bus */
70010 + __reg_write(glamo, script[i].reg, 0xe53);
70011 + break;
70012 + /* default of 0 or >7 is fastest */
70013 + default: /* 0 waits on Async BB R & W, Use PLL 2 for mem bus */
70014 + __reg_write(glamo, script[i].reg, 0xe03);
70015 + break;
70016 + }
70017 + break;
70018 +
70019 + default:
70020 + __reg_write(glamo, script[i].reg, script[i].val);
70021 + break;
70022 + }
70023 + }
70024 +
70025 + return 0;
70026 +}
70027 +EXPORT_SYMBOL(glamo_run_script);
70028 +
70029 +static struct glamo_script glamo_init_script[] = {
70030 + { GLAMO_REG_CLOCK_HOST, 0x1000 },
70031 + { 0xfffe, 2 },
70032 + { GLAMO_REG_CLOCK_MEMORY, 0x1000 },
70033 + { GLAMO_REG_CLOCK_MEMORY, 0x2000 },
70034 + { GLAMO_REG_CLOCK_LCD, 0x1000 },
70035 + { GLAMO_REG_CLOCK_MMC, 0x1000 },
70036 + { GLAMO_REG_CLOCK_ISP, 0x1000 },
70037 + { GLAMO_REG_CLOCK_ISP, 0x3000 },
70038 + { GLAMO_REG_CLOCK_JPEG, 0x1000 },
70039 + { GLAMO_REG_CLOCK_3D, 0x1000 },
70040 + { GLAMO_REG_CLOCK_3D, 0x3000 },
70041 + { GLAMO_REG_CLOCK_2D, 0x1000 },
70042 + { GLAMO_REG_CLOCK_2D, 0x3000 },
70043 + { GLAMO_REG_CLOCK_RISC1, 0x1000 },
70044 + { GLAMO_REG_CLOCK_MPEG, 0x3000 },
70045 + { GLAMO_REG_CLOCK_MPEG, 0x3000 },
70046 + { GLAMO_REG_CLOCK_MPROC, 0x1000 /*0x100f*/ },
70047 + { 0xfffe, 2 },
70048 + { GLAMO_REG_CLOCK_HOST, 0x0000 },
70049 + { GLAMO_REG_CLOCK_MEMORY, 0x0000 },
70050 + { GLAMO_REG_CLOCK_LCD, 0x0000 },
70051 + { GLAMO_REG_CLOCK_MMC, 0x0000 },
70052 +#if 0
70053 +/* unused engines must be left in reset to stop MMC block read "blackouts" */
70054 + { GLAMO_REG_CLOCK_ISP, 0x0000 },
70055 + { GLAMO_REG_CLOCK_ISP, 0x0000 },
70056 + { GLAMO_REG_CLOCK_JPEG, 0x0000 },
70057 + { GLAMO_REG_CLOCK_3D, 0x0000 },
70058 + { GLAMO_REG_CLOCK_3D, 0x0000 },
70059 + { GLAMO_REG_CLOCK_2D, 0x0000 },
70060 + { GLAMO_REG_CLOCK_2D, 0x0000 },
70061 + { GLAMO_REG_CLOCK_RISC1, 0x0000 },
70062 + { GLAMO_REG_CLOCK_MPEG, 0x0000 },
70063 + { GLAMO_REG_CLOCK_MPEG, 0x0000 },
70064 +#endif
70065 + { GLAMO_REG_PLL_GEN1, 0x05db }, /* 48MHz */
70066 + { GLAMO_REG_PLL_GEN3, 0x0aba }, /* 90MHz */
70067 + { 0xfffd, 0 },
70068 + /*
70069 + * b9 of this register MUST be zero to get any interrupts on INT#
70070 + * the other set bits enable all the engine interrupt sources
70071 + */
70072 + { GLAMO_REG_IRQ_ENABLE, 0x01ff },
70073 + { GLAMO_REG_CLOCK_GEN6, 0x2000 },
70074 + { GLAMO_REG_CLOCK_GEN7, 0x0101 },
70075 + { GLAMO_REG_CLOCK_GEN8, 0x0100 },
70076 + { GLAMO_REG_CLOCK_HOST, 0x000d },
70077 + /*
70078 + * b7..b4 = 0 = no wait states on read or write
70079 + * b0 = 1 select PLL2 for Host interface, b1 = enable it
70080 + */
70081 + { 0x200, 0x0e03 /* this is replaced by script parser */ },
70082 + { 0x202, 0x07ff },
70083 + { 0x212, 0x0000 },
70084 + { 0x214, 0x4000 },
70085 + { 0x216, 0xf00e },
70086 +
70087 + /* S-Media recommended "set tiling mode to 512 mode for memory access
70088 + * more efficiency when 640x480" */
70089 + { GLAMO_REG_MEM_TYPE, 0x0c74 }, /* 8MB, 16 word pg wr+rd */
70090 + { GLAMO_REG_MEM_GEN, 0xafaf }, /* 63 grants min + max */
70091 +
70092 + { GLAMO_REGOFS_HOSTBUS + 2, 0xffff }, /* enable on MMIO*/
70093 +
70094 + { GLAMO_REG_MEM_TIMING1, 0x0108 },
70095 + { GLAMO_REG_MEM_TIMING2, 0x0010 }, /* Taa = 3 MCLK */
70096 + { GLAMO_REG_MEM_TIMING3, 0x0000 },
70097 + { GLAMO_REG_MEM_TIMING4, 0x0000 }, /* CE1# delay fall/rise */
70098 + { GLAMO_REG_MEM_TIMING5, 0x0000 }, /* UB# LB# */
70099 + { GLAMO_REG_MEM_TIMING6, 0x0000 }, /* OE# */
70100 + { GLAMO_REG_MEM_TIMING7, 0x0000 }, /* WE# */
70101 + { GLAMO_REG_MEM_TIMING8, 0x1002 }, /* MCLK delay, was 0x1000 */
70102 + { GLAMO_REG_MEM_TIMING9, 0x6006 },
70103 + { GLAMO_REG_MEM_TIMING10, 0x00ff },
70104 + { GLAMO_REG_MEM_TIMING11, 0x0001 },
70105 + { GLAMO_REG_MEM_POWER1, 0x0020 },
70106 + { GLAMO_REG_MEM_POWER2, 0x0000 },
70107 + { GLAMO_REG_MEM_DRAM1, 0x0000 },
70108 + { 0xfffe, 1 },
70109 + { GLAMO_REG_MEM_DRAM1, 0xc100 },
70110 + { 0xfffe, 1 },
70111 + { GLAMO_REG_MEM_DRAM1, 0xe100 },
70112 + { GLAMO_REG_MEM_DRAM2, 0x01d6 },
70113 + { GLAMO_REG_CLOCK_MEMORY, 0x000b },
70114 + { GLAMO_REG_GPIO_GEN1, 0x000f },
70115 + { GLAMO_REG_GPIO_GEN2, 0x111e },
70116 + { GLAMO_REG_GPIO_GEN3, 0xccc3 },
70117 + { GLAMO_REG_GPIO_GEN4, 0x111e },
70118 + { GLAMO_REG_GPIO_GEN5, 0x000f },
70119 +};
70120 +#if 0
70121 +static struct glamo_script glamo_resume_script[] = {
70122 +
70123 + { GLAMO_REG_PLL_GEN1, 0x05db }, /* 48MHz */
70124 + { GLAMO_REG_PLL_GEN3, 0x0aba }, /* 90MHz */
70125 + { GLAMO_REG_DFT_GEN6, 1 },
70126 + { 0xfffe, 100 },
70127 + { 0xfffd, 0 },
70128 + { 0x200, 0x0e03 },
70129 +
70130 + /*
70131 + * b9 of this register MUST be zero to get any interrupts on INT#
70132 + * the other set bits enable all the engine interrupt sources
70133 + */
70134 + { GLAMO_REG_IRQ_ENABLE, 0x01ff },
70135 + { GLAMO_REG_CLOCK_HOST, 0x0018 },
70136 + { GLAMO_REG_CLOCK_GEN5_1, 0x18b1 },
70137 +
70138 + { GLAMO_REG_MEM_DRAM1, 0x0000 },
70139 + { 0xfffe, 1 },
70140 + { GLAMO_REG_MEM_DRAM1, 0xc100 },
70141 + { 0xfffe, 1 },
70142 + { GLAMO_REG_MEM_DRAM1, 0xe100 },
70143 + { GLAMO_REG_MEM_DRAM2, 0x01d6 },
70144 + { GLAMO_REG_CLOCK_MEMORY, 0x000b },
70145 +};
70146 +#endif
70147 +
70148 +enum glamo_power {
70149 + GLAMO_POWER_ON,
70150 + GLAMO_POWER_SUSPEND,
70151 +};
70152 +
70153 +static void glamo_power(struct glamo_core *glamo,
70154 + enum glamo_power new_state)
70155 +{
70156 + int n;
70157 + unsigned long flags;
70158 +
70159 + spin_lock_irqsave(&glamo->lock, flags);
70160 +
70161 + dev_info(&glamo->pdev->dev, "***** glamo_power -> %d\n", new_state);
70162 +
70163 + /*
70164 +Power management
70165 +static const REG_VALUE_MASK_TYPE reg_powerOn[] =
70166 +{
70167 + { REG_GEN_DFT6, REG_BIT_ALL, REG_DATA(1u << 0) },
70168 + { REG_GEN_PLL3, 0u, REG_DATA(1u << 13) },
70169 + { REG_GEN_MEM_CLK, REG_BIT_ALL, REG_BIT_EN_MOCACLK },
70170 + { REG_MEM_DRAM2, 0u, REG_BIT_EN_DEEP_POWER_DOWN },
70171 + { REG_MEM_DRAM1, 0u, REG_BIT_SELF_REFRESH }
70172 +};
70173 +
70174 +static const REG_VALUE_MASK_TYPE reg_powerStandby[] =
70175 +{
70176 + { REG_MEM_DRAM1, REG_BIT_ALL, REG_BIT_SELF_REFRESH },
70177 + { REG_GEN_MEM_CLK, 0u, REG_BIT_EN_MOCACLK },
70178 + { REG_GEN_PLL3, REG_BIT_ALL, REG_DATA(1u << 13) },
70179 + { REG_GEN_DFT5, REG_BIT_ALL, REG_DATA(1u << 0) }
70180 +};
70181 +
70182 +static const REG_VALUE_MASK_TYPE reg_powerSuspend[] =
70183 +{
70184 + { REG_MEM_DRAM2, REG_BIT_ALL, REG_BIT_EN_DEEP_POWER_DOWN },
70185 + { REG_GEN_MEM_CLK, 0u, REG_BIT_EN_MOCACLK },
70186 + { REG_GEN_PLL3, REG_BIT_ALL, REG_DATA(1u << 13) },
70187 + { REG_GEN_DFT5, REG_BIT_ALL, REG_DATA(1u << 0) }
70188 +};
70189 +*/
70190 +
70191 + switch (new_state) {
70192 + case GLAMO_POWER_ON:
70193 +
70194 + /*
70195 + * glamo state on resume is nondeterministic in some
70196 + * fundamental way, it has also been observed that the
70197 + * Glamo reset pin can get asserted by, eg, touching it with
70198 + * a scope probe. So the only answer is to roll with it and
70199 + * force an external reset on the Glamo during resume.
70200 + */
70201 +
70202 + (glamo->pdata->glamo_external_reset)(0);
70203 + udelay(10);
70204 + (glamo->pdata->glamo_external_reset)(1);
70205 + mdelay(5);
70206 +
70207 + glamo_run_script(glamo, glamo_init_script,
70208 + ARRAY_SIZE(glamo_init_script), 0);
70209 +
70210 + break;
70211 +
70212 + case GLAMO_POWER_SUSPEND:
70213 +
70214 + /* nuke interrupts */
70215 + __reg_write(glamo, GLAMO_REG_IRQ_ENABLE, 0x200);
70216 +
70217 + /* stash a copy of which engines were running */
70218 + glamo->engine_enabled_bitfield_suspend =
70219 + glamo->engine_enabled_bitfield;
70220 +
70221 + /* take down each engine before we kill mem and pll */
70222 + for (n = 0; n < __NUM_GLAMO_ENGINES; n++)
70223 + if (glamo->engine_enabled_bitfield & (1 << n))
70224 + __glamo_engine_disable(glamo, n);
70225 +
70226 + /* enable self-refresh */
70227 +
70228 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1,
70229 + GLAMO_MEM_DRAM1_EN_DRAM_REFRESH |
70230 + GLAMO_MEM_DRAM1_EN_GATE_CKE |
70231 + GLAMO_MEM_DRAM1_SELF_REFRESH |
70232 + GLAMO_MEM_REFRESH_COUNT);
70233 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1,
70234 + GLAMO_MEM_DRAM1_EN_MODEREG_SET |
70235 + GLAMO_MEM_DRAM1_EN_DRAM_REFRESH |
70236 + GLAMO_MEM_DRAM1_EN_GATE_CKE |
70237 + GLAMO_MEM_DRAM1_SELF_REFRESH |
70238 + GLAMO_MEM_REFRESH_COUNT);
70239 +
70240 + /* force RAM into deep powerdown */
70241 +
70242 + __reg_write(glamo, GLAMO_REG_MEM_DRAM2,
70243 + GLAMO_MEM_DRAM2_DEEP_PWRDOWN |
70244 + (7 << 6) | /* tRC */
70245 + (1 << 4) | /* tRP */
70246 + (1 << 2) | /* tRCD */
70247 + 2); /* CAS latency */
70248 +
70249 + /* disable clocks to memory */
70250 + __reg_write(glamo, GLAMO_REG_CLOCK_MEMORY, 0);
70251 +
70252 + /* all dividers from OSCI */
70253 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1, 0x400, 0x400);
70254 +
70255 + /* PLL2 into bypass */
70256 + __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 1 << 12, 1 << 12);
70257 +
70258 + __reg_write(glamo, 0x200, 0x0e00);
70259 +
70260 +
70261 + /* kill PLLS 1 then 2 */
70262 + __reg_write(glamo, GLAMO_REG_DFT_GEN5, 0x0001);
70263 + __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 1 << 13, 1 << 13);
70264 +
70265 + break;
70266 + }
70267 +
70268 + spin_unlock_irqrestore(&glamo->lock, flags);
70269 +}
70270 +
70271 +#if 0
70272 +#define MEMDETECT_RETRY 6
70273 +static unsigned int detect_memsize(struct glamo_core *glamo)
70274 +{
70275 + int i;
70276 +
70277 + /*static const u_int16_t pattern[] = {
70278 + 0x1111, 0x8a8a, 0x2222, 0x7a7a,
70279 + 0x3333, 0x6a6a, 0x4444, 0x5a5a,
70280 + 0x5555, 0x4a4a, 0x6666, 0x3a3a,
70281 + 0x7777, 0x2a2a, 0x8888, 0x1a1a
70282 + }; */
70283 +
70284 + for (i = 0; i < MEMDETECT_RETRY; i++) {
70285 + switch (glamo->type) {
70286 + case 3600:
70287 + __reg_write(glamo, GLAMO_REG_MEM_TYPE, 0x0072);
70288 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xc100);
70289 + break;
70290 + case 3650:
70291 + switch (glamo->revision) {
70292 + case GLAMO_CORE_REV_A0:
70293 + if (i & 1)
70294 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
70295 + 0x097a);
70296 + else
70297 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
70298 + 0x0173);
70299 +
70300 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0x0000);
70301 + msleep(1);
70302 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xc100);
70303 + break;
70304 + default:
70305 + if (i & 1)
70306 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
70307 + 0x0972);
70308 + else
70309 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
70310 + 0x0872);
70311 +
70312 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0x0000);
70313 + msleep(1);
70314 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xe100);
70315 + break;
70316 + }
70317 + break;
70318 + case 3700:
70319 + /* FIXME */
70320 + default:
70321 + break;
70322 + }
70323 +
70324 +#if 0
70325 + /* FIXME: finish implementation */
70326 + for (j = 0; j < 8; j++) {
70327 + __
70328 +#endif
70329 + }
70330 +
70331 + return 0;
70332 +}
70333 +#endif
70334 +
70335 +/* Find out if we can support this version of the Glamo chip */
70336 +static int glamo_supported(struct glamo_core *glamo)
70337 +{
70338 + u_int16_t dev_id, rev_id; /*, memsize; */
70339 +
70340 + dev_id = __reg_read(glamo, GLAMO_REG_DEVICE_ID);
70341 + rev_id = __reg_read(glamo, GLAMO_REG_REVISION_ID);
70342 +
70343 + switch (dev_id) {
70344 + case 0x3650:
70345 + switch (rev_id) {
70346 + case GLAMO_CORE_REV_A2:
70347 + break;
70348 + case GLAMO_CORE_REV_A0:
70349 + case GLAMO_CORE_REV_A1:
70350 + case GLAMO_CORE_REV_A3:
70351 + dev_warn(&glamo->pdev->dev, "untested core revision "
70352 + "%04x, your mileage may vary\n", rev_id);
70353 + break;
70354 + default:
70355 + dev_warn(&glamo->pdev->dev, "unknown glamo revision "
70356 + "%04x, your mileage may vary\n", rev_id);
70357 + /* maybe should abort ? */
70358 + }
70359 + break;
70360 + case 0x3600:
70361 + case 0x3700:
70362 + default:
70363 + dev_err(&glamo->pdev->dev, "unsupported Glamo device %04x\n",
70364 + dev_id);
70365 + return 0;
70366 + }
70367 +
70368 + dev_dbg(&glamo->pdev->dev, "Detected Glamo core %04x Revision %04x "
70369 + "(%uHz CPU / %uHz Memory)\n", dev_id, rev_id,
70370 + glamo_pll_rate(glamo, GLAMO_PLL1),
70371 + glamo_pll_rate(glamo, GLAMO_PLL2));
70372 +
70373 + return 1;
70374 +}
70375 +
70376 +static int __init glamo_probe(struct platform_device *pdev)
70377 +{
70378 + int rc = 0, irq;
70379 + struct glamo_core *glamo;
70380 + struct platform_device *glamo_mmc_dev;
70381 +
70382 + if (glamo_handle) {
70383 + dev_err(&pdev->dev,
70384 + "This driver supports only one instance\n");
70385 + return -EBUSY;
70386 + }
70387 +
70388 + glamo = kmalloc(GFP_KERNEL, sizeof(*glamo));
70389 + if (!glamo)
70390 + return -ENOMEM;
70391 +
70392 + spin_lock_init(&glamo->lock);
70393 + glamo_handle = glamo;
70394 + glamo->pdev = pdev;
70395 + glamo->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
70396 + glamo->irq = platform_get_irq(pdev, 0);
70397 + glamo->pdata = pdev->dev.platform_data;
70398 + if (!glamo->mem || !glamo->pdata) {
70399 + dev_err(&pdev->dev, "platform device with no MEM/PDATA ?\n");
70400 + rc = -ENOENT;
70401 + goto bail_free;
70402 + }
70403 +
70404 + /* register a number of sibling devices whoise IOMEM resources
70405 + * are siblings of pdev's IOMEM resource */
70406 +#if 0
70407 + glamo_core_dev.dev.parent = &pdev.dev;
70408 + mangle_mem_resources(glamo_core_dev.resources,
70409 + glamo_core_dev.num_resources, glamo->mem);
70410 + glamo_core_dev.resources[1].start = glamo->irq;
70411 + glamo_core_dev.resources[1].end = glamo->irq;
70412 + platform_device_register(&glamo_core_dev);
70413 +#endif
70414 + /* only remap the generic, hostbus and memory controller registers */
70415 + glamo->base = ioremap(glamo->mem->start, 0x4000 /*GLAMO_REGOFS_VIDCAP*/);
70416 + if (!glamo->base) {
70417 + dev_err(&pdev->dev, "failed to ioremap() memory region\n");
70418 + goto bail_free;
70419 + }
70420 +
70421 + platform_set_drvdata(pdev, glamo);
70422 +
70423 + (glamo->pdata->glamo_external_reset)(0);
70424 + udelay(10);
70425 + (glamo->pdata->glamo_external_reset)(1);
70426 + mdelay(10);
70427 +
70428 + /*
70429 + * finally set the mfd interrupts up
70430 + * can't do them earlier or sibling probes blow up
70431 + */
70432 +
70433 + for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
70434 + set_irq_chip(irq, &glamo_irq_chip);
70435 + set_irq_handler(irq, handle_level_irq);
70436 + set_irq_flags(irq, IRQF_VALID);
70437 + }
70438 +
70439 + if (glamo->pdata->glamo_irq_is_wired &&
70440 + !glamo->pdata->glamo_irq_is_wired()) {
70441 + set_irq_chained_handler(glamo->irq, glamo_irq_demux_handler);
70442 + set_irq_type(glamo->irq, IRQ_TYPE_EDGE_FALLING);
70443 + dev_info(&pdev->dev, "Glamo interrupt registered\n");
70444 + glamo->irq_works = 1;
70445 + } else {
70446 + dev_err(&pdev->dev, "Glamo interrupt not used\n");
70447 + glamo->irq_works = 0;
70448 + }
70449 +
70450 +
70451 + /* confirm it isn't insane version */
70452 + if (!glamo_supported(glamo)) {
70453 + dev_err(&pdev->dev, "This Glamo is not supported\n");
70454 + goto bail_irq;
70455 + }
70456 +
70457 + /* sysfs */
70458 + rc = sysfs_create_group(&pdev->dev.kobj, &glamo_attr_group);
70459 + if (rc < 0) {
70460 + dev_err(&pdev->dev, "cannot create sysfs group\n");
70461 + goto bail_irq;
70462 + }
70463 +
70464 + /* init the chip with canned register set */
70465 +
70466 + dev_dbg(&glamo->pdev->dev, "running init script\n");
70467 + glamo_run_script(glamo, glamo_init_script,
70468 + ARRAY_SIZE(glamo_init_script), 1);
70469 +
70470 + dev_info(&glamo->pdev->dev, "Glamo core PLL1: %uHz, PLL2: %uHz\n",
70471 + glamo_pll_rate(glamo, GLAMO_PLL1),
70472 + glamo_pll_rate(glamo, GLAMO_PLL2));
70473 +
70474 + /* bring MCI specific stuff over from our MFD platform data */
70475 + glamo_mci_def_pdata.glamo_can_set_mci_power =
70476 + glamo->pdata->glamo_can_set_mci_power;
70477 + glamo_mci_def_pdata.glamo_mci_use_slow =
70478 + glamo->pdata->glamo_mci_use_slow;
70479 + glamo_mci_def_pdata.glamo_irq_is_wired =
70480 + glamo->pdata->glamo_irq_is_wired;
70481 +
70482 + /* start creating the siblings */
70483 +
70484 + glamo_2d_dev.dev.parent = &pdev->dev;
70485 + mangle_mem_resources(glamo_2d_dev.resource,
70486 + glamo_2d_dev.num_resources, glamo->mem);
70487 + platform_device_register(&glamo_2d_dev);
70488 +
70489 + glamo_3d_dev.dev.parent = &pdev->dev;
70490 + mangle_mem_resources(glamo_3d_dev.resource,
70491 + glamo_3d_dev.num_resources, glamo->mem);
70492 + platform_device_register(&glamo_3d_dev);
70493 +
70494 + glamo_jpeg_dev.dev.parent = &pdev->dev;
70495 + mangle_mem_resources(glamo_jpeg_dev.resource,
70496 + glamo_jpeg_dev.num_resources, glamo->mem);
70497 + platform_device_register(&glamo_jpeg_dev);
70498 +
70499 + glamo_mpeg_dev.dev.parent = &pdev->dev;
70500 + mangle_mem_resources(glamo_mpeg_dev.resource,
70501 + glamo_mpeg_dev.num_resources, glamo->mem);
70502 + platform_device_register(&glamo_mpeg_dev);
70503 +
70504 + glamo->pdata->glamo = glamo;
70505 + glamo_fb_dev.dev.parent = &pdev->dev;
70506 + glamo_fb_dev.dev.platform_data = glamo->pdata;
70507 + mangle_mem_resources(glamo_fb_dev.resource,
70508 + glamo_fb_dev.num_resources, glamo->mem);
70509 + platform_device_register(&glamo_fb_dev);
70510 +
70511 + glamo->pdata->spigpio_info->glamo = glamo;
70512 + glamo_spigpio_dev.dev.parent = &pdev->dev;
70513 + glamo_spigpio_dev.dev.platform_data = glamo->pdata->spigpio_info;
70514 + platform_device_register(&glamo_spigpio_dev);
70515 +
70516 + glamo_mmc_dev = glamo->pdata->mmc_dev;
70517 + glamo_mmc_dev->name = "glamo-mci";
70518 + glamo_mmc_dev->dev.parent = &pdev->dev;
70519 + glamo_mmc_dev->resource = glamo_mmc_resources;
70520 + glamo_mmc_dev->num_resources = ARRAY_SIZE(glamo_mmc_resources);
70521 +
70522 + /* we need it later to give to the engine enable and disable */
70523 + glamo_mci_def_pdata.pglamo = glamo;
70524 + mangle_mem_resources(glamo_mmc_dev->resource,
70525 + glamo_mmc_dev->num_resources, glamo->mem);
70526 + platform_device_register(glamo_mmc_dev);
70527 +
70528 + /* only request the generic, hostbus and memory controller MMIO */
70529 + glamo->mem = request_mem_region(glamo->mem->start,
70530 + GLAMO_REGOFS_VIDCAP, "glamo-core");
70531 + if (!glamo->mem) {
70532 + dev_err(&pdev->dev, "failed to request memory region\n");
70533 + goto bail_irq;
70534 + }
70535 +
70536 + return 0;
70537 +
70538 +bail_irq:
70539 + disable_irq(glamo->irq);
70540 + set_irq_chained_handler(glamo->irq, NULL);
70541 +
70542 + for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
70543 + set_irq_flags(irq, 0);
70544 + set_irq_chip(irq, NULL);
70545 + }
70546 +
70547 + iounmap(glamo->base);
70548 +bail_free:
70549 + platform_set_drvdata(pdev, NULL);
70550 + glamo_handle = NULL;
70551 + kfree(glamo);
70552 +
70553 + return rc;
70554 +}
70555 +
70556 +static int glamo_remove(struct platform_device *pdev)
70557 +{
70558 + struct glamo_core *glamo = platform_get_drvdata(pdev);
70559 + int irq;
70560 +
70561 + disable_irq(glamo->irq);
70562 + set_irq_chained_handler(glamo->irq, NULL);
70563 +
70564 + for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
70565 + set_irq_flags(irq, 0);
70566 + set_irq_chip(irq, NULL);
70567 + }
70568 +
70569 + platform_set_drvdata(pdev, NULL);
70570 + platform_device_unregister(&glamo_fb_dev);
70571 + platform_device_unregister(glamo->pdata->mmc_dev);
70572 + iounmap(glamo->base);
70573 + release_mem_region(glamo->mem->start, GLAMO_REGOFS_VIDCAP);
70574 + glamo_handle = NULL;
70575 + kfree(glamo);
70576 +
70577 + return 0;
70578 +}
70579 +
70580 +#ifdef CONFIG_PM
70581 +
70582 +static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
70583 +{
70584 + glamo_handle->suspending = 1;
70585 + glamo_power(glamo_handle, GLAMO_POWER_SUSPEND);
70586 +
70587 + return 0;
70588 +}
70589 +
70590 +static int glamo_resume(struct platform_device *pdev)
70591 +{
70592 + glamo_power(glamo_handle, GLAMO_POWER_ON);
70593 + glamo_handle->suspending = 0;
70594 +
70595 + return 0;
70596 +}
70597 +
70598 +#else
70599 +#define glamo_suspend NULL
70600 +#define glamo_resume NULL
70601 +#endif
70602 +
70603 +static struct platform_driver glamo_driver = {
70604 + .probe = glamo_probe,
70605 + .remove = glamo_remove,
70606 + .suspend = glamo_suspend,
70607 + .resume = glamo_resume,
70608 + .driver = {
70609 + .name = "glamo3362",
70610 + .owner = THIS_MODULE,
70611 + },
70612 +};
70613 +
70614 +static int __devinit glamo_init(void)
70615 +{
70616 + return platform_driver_register(&glamo_driver);
70617 +}
70618 +
70619 +static void __exit glamo_cleanup(void)
70620 +{
70621 + platform_driver_unregister(&glamo_driver);
70622 +}
70623 +
70624 +module_init(glamo_init);
70625 +module_exit(glamo_cleanup);
70626 +
70627 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
70628 +MODULE_DESCRIPTION("Smedia Glamo 336x/337x core/resource driver");
70629 +MODULE_LICENSE("GPL");
70630 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-core.h linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-core.h
70631 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-core.h 1970-01-01 01:00:00.000000000 +0100
70632 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-core.h 2009-05-10 22:28:00.000000000 +0200
70633 @@ -0,0 +1,92 @@
70634 +#ifndef __GLAMO_CORE_H
70635 +#define __GLAMO_CORE_H
70636 +
70637 +#include <asm/system.h>
70638 +
70639 +/* for the time being, we put the on-screen framebuffer into the lowest
70640 + * VRAM space. This should make the code easily compatible with the various
70641 + * 2MB/4MB/8MB variants of the Smedia chips */
70642 +#define GLAMO_OFFSET_VRAM 0x800000
70643 +#define GLAMO_OFFSET_FB (GLAMO_OFFSET_VRAM)
70644 +
70645 +/* we only allocate the minimum possible size for the framebuffer to make
70646 + * sure we have sufficient memory for other functions of the chip */
70647 +//#define GLAMO_FB_SIZE (640*480*4) /* == 0x12c000 */
70648 +#define GLAMO_INTERNAL_RAM_SIZE 0x800000
70649 +#define GLAMO_MMC_BUFFER_SIZE (64 * 1024)
70650 +#define GLAMO_FB_SIZE (GLAMO_INTERNAL_RAM_SIZE - GLAMO_MMC_BUFFER_SIZE)
70651 +
70652 +struct glamo_core {
70653 + int irq;
70654 + int irq_works; /* 0 means PCB does not support Glamo IRQ */
70655 + struct resource *mem;
70656 + struct resource *mem_core;
70657 + void __iomem *base;
70658 + struct platform_device *pdev;
70659 + struct glamofb_platform_data *pdata;
70660 + u_int16_t type;
70661 + u_int16_t revision;
70662 + spinlock_t lock;
70663 + u32 engine_enabled_bitfield;
70664 + u32 engine_enabled_bitfield_suspend;
70665 + int suspending;
70666 +};
70667 +
70668 +struct glamo_script {
70669 + u_int16_t reg;
70670 + u_int16_t val;
70671 +};
70672 +
70673 +int glamo_run_script(struct glamo_core *glamo,
70674 + struct glamo_script *script, int len, int may_sleep);
70675 +
70676 +enum glamo_engine {
70677 + GLAMO_ENGINE_CAPTURE,
70678 + GLAMO_ENGINE_ISP,
70679 + GLAMO_ENGINE_JPEG,
70680 + GLAMO_ENGINE_MPEG_ENC,
70681 + GLAMO_ENGINE_MPEG_DEC,
70682 + GLAMO_ENGINE_LCD,
70683 + GLAMO_ENGINE_CMDQ,
70684 + GLAMO_ENGINE_2D,
70685 + GLAMO_ENGINE_3D,
70686 + GLAMO_ENGINE_MMC,
70687 + GLAMO_ENGINE_MICROP0,
70688 + GLAMO_ENGINE_RISC,
70689 + GLAMO_ENGINE_MICROP1_MPEG_ENC,
70690 + GLAMO_ENGINE_MICROP1_MPEG_DEC,
70691 +#if 0
70692 + GLAMO_ENGINE_H264_DEC,
70693 + GLAMO_ENGINE_RISC1,
70694 + GLAMO_ENGINE_SPI,
70695 +#endif
70696 + __NUM_GLAMO_ENGINES
70697 +};
70698 +
70699 +struct glamo_mci_pdata {
70700 + struct glamo_core * pglamo;
70701 + unsigned int gpio_detect;
70702 + unsigned int gpio_wprotect;
70703 + unsigned long ocr_avail;
70704 + int (*glamo_can_set_mci_power)(void);
70705 + /* glamo-mci asking if it should use the slow clock to card */
70706 + int (*glamo_mci_use_slow)(void);
70707 + int (*glamo_irq_is_wired)(void);
70708 + void (*mci_suspending)(struct platform_device *dev);
70709 + int (*mci_all_dependencies_resumed)(struct platform_device *dev);
70710 +
70711 +};
70712 +
70713 +int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine);
70714 +int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine);
70715 +void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine);
70716 +int glamo_engine_reclock(struct glamo_core *glamo,
70717 + enum glamo_engine engine, int ps);
70718 +
70719 +void glamo_engine_clkreg_set(struct glamo_core *glamo,
70720 + enum glamo_engine engine,
70721 + u_int16_t mask, u_int16_t val);
70722 +
70723 +u_int16_t glamo_engine_clkreg_get(struct glamo_core *glamo,
70724 + enum glamo_engine engine);
70725 +#endif /* __GLAMO_CORE_H */
70726 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-fb.c linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-fb.c
70727 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-fb.c 1970-01-01 01:00:00.000000000 +0100
70728 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-fb.c 2009-05-10 22:28:00.000000000 +0200
70729 @@ -0,0 +1,1193 @@
70730 +/* Smedia Glamo 336x/337x driver
70731 + *
70732 + * (C) 2007-2008 by Openmoko, Inc.
70733 + * Author: Harald Welte <laforge@openmoko.org>
70734 + * All rights reserved.
70735 + *
70736 + * This program is free software; you can redistribute it and/or
70737 + * modify it under the terms of the GNU General Public License as
70738 + * published by the Free Software Foundation; either version 2 of
70739 + * the License, or (at your option) any later version.
70740 + *
70741 + * This program is distributed in the hope that it will be useful,
70742 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
70743 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
70744 + * GNU General Public License for more details.
70745 + *
70746 + * You should have received a copy of the GNU General Public License
70747 + * along with this program; if not, write to the Free Software
70748 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
70749 + * MA 02111-1307 USA
70750 + */
70751 +
70752 +#include <linux/module.h>
70753 +#include <linux/kernel.h>
70754 +#include <linux/errno.h>
70755 +#include <linux/string.h>
70756 +#include <linux/mm.h>
70757 +#include <linux/slab.h>
70758 +#include <linux/delay.h>
70759 +#include <linux/fb.h>
70760 +#include <linux/init.h>
70761 +#include <linux/vmalloc.h>
70762 +#include <linux/dma-mapping.h>
70763 +#include <linux/interrupt.h>
70764 +#include <linux/workqueue.h>
70765 +#include <linux/wait.h>
70766 +#include <linux/platform_device.h>
70767 +#include <linux/clk.h>
70768 +#include <linux/spinlock.h>
70769 +#include <linux/io.h>
70770 +#include <linux/uaccess.h>
70771 +
70772 +#include <asm/div64.h>
70773 +
70774 +#ifdef CONFIG_PM
70775 +#include <linux/pm.h>
70776 +#endif
70777 +
70778 +#include <linux/glamofb.h>
70779 +
70780 +#include "glamo-regs.h"
70781 +#include "glamo-core.h"
70782 +
70783 +#ifndef DEBUG
70784 +#define GLAMO_LOG(...)
70785 +#else
70786 +#define GLAMO_LOG(...) \
70787 +do { \
70788 + printk(KERN_DEBUG "in %s:%s:%d", __FILE__, __func__, __LINE__); \
70789 + printk(KERN_DEBUG __VA_ARGS__); \
70790 +} while (0);
70791 +#endif
70792 +
70793 +
70794 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
70795 +
70796 +struct glamofb_handle {
70797 + struct fb_info *fb;
70798 + struct device *dev;
70799 + struct resource *reg;
70800 + struct resource *fb_res;
70801 + char __iomem *base;
70802 + struct glamofb_platform_data *mach_info;
70803 + char __iomem *cursor_addr;
70804 + int cursor_on;
70805 + u_int32_t pseudo_pal[16];
70806 + spinlock_t lock_cmd;
70807 + int angle; /* Current rotation angle */
70808 + int blank_mode;
70809 +};
70810 +
70811 +/* 'sibling' spi device for lcm init */
70812 +static struct platform_device glamo_spi_dev = {
70813 + .name = "glamo-lcm-spi",
70814 +};
70815 +
70816 +
70817 +static int reg_read(struct glamofb_handle *glamo,
70818 + u_int16_t reg)
70819 +{
70820 + int i = 0;
70821 +
70822 + for (i = 0; i != 2; i++)
70823 + nop();
70824 +
70825 + return readw(glamo->base + reg);
70826 +}
70827 +
70828 +static void reg_write(struct glamofb_handle *glamo,
70829 + u_int16_t reg, u_int16_t val)
70830 +{
70831 + int i = 0;
70832 +
70833 + for (i = 0; i != 2; i++)
70834 + nop();
70835 +
70836 + writew(val, glamo->base + reg);
70837 +}
70838 +
70839 +static struct glamo_script glamo_regs[] = {
70840 + { GLAMO_REG_LCD_MODE1, 0x0020 },
70841 + /* no display rotation, no hardware cursor, no dither, no gamma,
70842 + * no retrace flip, vsync low-active, hsync low active,
70843 + * no TVCLK, no partial display, hw dest color from fb,
70844 + * no partial display mode, LCD1, software flip, */
70845 + { GLAMO_REG_LCD_MODE2, 0x9020 },
70846 + /* video flip, no ptr, no ptr, dhclk off,
70847 + * normal mode, no cpuif,
70848 + * res, serial msb first, single fb, no fr ctrl,
70849 + * cpu if bits all zero, no crc
70850 + * 0000 0000 0010 0000 */
70851 + { GLAMO_REG_LCD_MODE3, 0x0b40 },
70852 + /* src data rgb565, res, 18bit rgb666
70853 + * 000 01 011 0100 0000 */
70854 + { GLAMO_REG_LCD_POLARITY, 0x440c },
70855 + /* DE high active, no cpu/lcd if, cs0 force low, a0 low active,
70856 + * np cpu if, 9bit serial data, sclk rising edge latch data
70857 + * 01 00 0 100 0 000 01 0 0 */
70858 + /* The following values assume 640*480@16bpp */
70859 + { GLAMO_REG_LCD_A_BASE1, 0x0000 }, /* display A base address 15:0 */
70860 + { GLAMO_REG_LCD_A_BASE2, 0x0000 }, /* display A base address 22:16 */
70861 + { GLAMO_REG_LCD_B_BASE1, 0x6000 }, /* display B base address 15:0 */
70862 + { GLAMO_REG_LCD_B_BASE2, 0x0009 }, /* display B base address 22:16 */
70863 + { GLAMO_REG_LCD_CURSOR_BASE1, 0xC000 }, /* cursor base address 15:0 */
70864 + { GLAMO_REG_LCD_CURSOR_BASE2, 0x0012 }, /* cursor base address 22:16 */
70865 + { GLAMO_REG_LCD_COMMAND2, 0x0000 }, /* display page A */
70866 +};
70867 +
70868 +static int glamofb_run_script(struct glamofb_handle *glamo,
70869 + struct glamo_script *script, int len)
70870 +{
70871 + int i;
70872 +
70873 + if (glamo->mach_info->glamo->suspending) {
70874 + dev_err(&glamo->mach_info->glamo->pdev->dev,
70875 + "IGNORING glamofb_run_script while "
70876 + "suspended\n");
70877 + return -EBUSY;
70878 + }
70879 +
70880 + for (i = 0; i < len; i++) {
70881 + struct glamo_script *line = &script[i];
70882 +
70883 + if (line->reg == 0xffff)
70884 + return 0;
70885 + else if (line->reg == 0xfffe)
70886 + msleep(line->val);
70887 + else
70888 + reg_write(glamo, script[i].reg, script[i].val);
70889 + }
70890 +
70891 + return 0;
70892 +}
70893 +
70894 +static int glamofb_check_var(struct fb_var_screeninfo *var,
70895 + struct fb_info *info)
70896 +{
70897 + struct glamofb_handle *glamo = info->par;
70898 +
70899 + if (glamo->mach_info->glamo->suspending) {
70900 + dev_err(&glamo->mach_info->glamo->pdev->dev,
70901 + "IGNORING glamofb_check_var while "
70902 + "suspended\n");
70903 + return -EBUSY;
70904 + }
70905 +
70906 + if (var->yres > glamo->mach_info->yres.max)
70907 + var->yres = glamo->mach_info->yres.max;
70908 + else if (var->yres < glamo->mach_info->yres.min)
70909 + var->yres = glamo->mach_info->yres.min;
70910 +
70911 + if (var->xres > glamo->mach_info->xres.max)
70912 + var->xres = glamo->mach_info->xres.max;
70913 + else if (var->xres < glamo->mach_info->xres.min)
70914 + var->xres = glamo->mach_info->xres.min;
70915 +
70916 + if (var->bits_per_pixel > glamo->mach_info->bpp.max)
70917 + var->bits_per_pixel = glamo->mach_info->bpp.max;
70918 + else if (var->bits_per_pixel < glamo->mach_info->bpp.min)
70919 + var->bits_per_pixel = glamo->mach_info->bpp.min;
70920 +
70921 + /* FIXME: set rgb positions */
70922 + switch (var->bits_per_pixel) {
70923 + case 16:
70924 + switch (reg_read(glamo, GLAMO_REG_LCD_MODE3) & 0xc000) {
70925 + case GLAMO_LCD_SRC_RGB565:
70926 + var->red.offset = 11;
70927 + var->green.offset = 5;
70928 + var->blue.offset = 0;
70929 + var->red.length = 5;
70930 + var->green.length = 6;
70931 + var->blue.length = 5;
70932 + var->transp.length = 0;
70933 + break;
70934 + case GLAMO_LCD_SRC_ARGB1555:
70935 + var->transp.offset = 15;
70936 + var->red.offset = 10;
70937 + var->green.offset = 5;
70938 + var->blue.offset = 0;
70939 + var->transp.length = 1;
70940 + var->red.length = 5;
70941 + var->green.length = 5;
70942 + var->blue.length = 5;
70943 + break;
70944 + case GLAMO_LCD_SRC_ARGB4444:
70945 + var->transp.offset = 12;
70946 + var->red.offset = 8;
70947 + var->green.offset = 4;
70948 + var->blue.offset = 0;
70949 + var->transp.length = 4;
70950 + var->red.length = 4;
70951 + var->green.length = 4;
70952 + var->blue.length = 4;
70953 + break;
70954 + }
70955 + break;
70956 + case 24:
70957 + case 32:
70958 + default:
70959 + /* The Smedia Glamo doesn't support anything but 16bit color */
70960 + printk(KERN_ERR
70961 + "Smedia driver does not [yet?] support 24/32bpp\n");
70962 + return -EINVAL;
70963 + }
70964 +
70965 + return 0;
70966 +}
70967 +
70968 +static void reg_set_bit_mask(struct glamofb_handle *glamo,
70969 + u_int16_t reg, u_int16_t mask,
70970 + u_int16_t val)
70971 +{
70972 + u_int16_t tmp;
70973 +
70974 + val &= mask;
70975 +
70976 + tmp = reg_read(glamo, reg);
70977 + tmp &= ~mask;
70978 + tmp |= val;
70979 + reg_write(glamo, reg, tmp);
70980 +}
70981 +
70982 +#define GLAMO_LCD_WIDTH_MASK 0x03FF
70983 +#define GLAMO_LCD_HEIGHT_MASK 0x03FF
70984 +#define GLAMO_LCD_PITCH_MASK 0x07FE
70985 +#define GLAMO_LCD_HV_TOTAL_MASK 0x03FF
70986 +#define GLAMO_LCD_HV_RETR_START_MASK 0x03FF
70987 +#define GLAMO_LCD_HV_RETR_END_MASK 0x03FF
70988 +#define GLAMO_LCD_HV_RETR_DISP_START_MASK 0x03FF
70989 +#define GLAMO_LCD_HV_RETR_DISP_END_MASK 0x03FF
70990 +
70991 +enum orientation {ORIENTATION_PORTRAIT, ORIENTATION_LANDSCAPE};
70992 +
70993 +/* the caller has to enxure lock_cmd is held and we are in cmd mode */
70994 +static void __rotate_lcd(struct glamofb_handle *glamo, __u32 rotation)
70995 +{
70996 + int glamo_rot;
70997 +
70998 + if (glamo->mach_info->glamo->suspending) {
70999 + dev_err(&glamo->mach_info->glamo->pdev->dev,
71000 + "IGNORING rotate_lcd while "
71001 + "suspended\n");
71002 + return;
71003 + }
71004 +
71005 + switch (rotation) {
71006 + case FB_ROTATE_UR:
71007 + glamo_rot = GLAMO_LCD_ROT_MODE_0;
71008 + glamo->angle = 0;
71009 + break;
71010 + case FB_ROTATE_CW:
71011 + glamo_rot = GLAMO_LCD_ROT_MODE_90;
71012 + glamo->angle = 90;
71013 + break;
71014 + case FB_ROTATE_UD:
71015 + glamo_rot = GLAMO_LCD_ROT_MODE_180;
71016 + glamo->angle = 180;
71017 + break;
71018 + case FB_ROTATE_CCW:
71019 + glamo_rot = GLAMO_LCD_ROT_MODE_270;
71020 + glamo->angle = 270;
71021 + break;
71022 + default:
71023 + glamo->angle = 0;
71024 + glamo_rot = GLAMO_LCD_ROT_MODE_0;
71025 + break;
71026 + }
71027 +
71028 + reg_set_bit_mask(glamo,
71029 + GLAMO_REG_LCD_WIDTH,
71030 + GLAMO_LCD_ROT_MODE_MASK,
71031 + glamo_rot);
71032 + reg_set_bit_mask(glamo,
71033 + GLAMO_REG_LCD_MODE1,
71034 + GLAMO_LCD_MODE1_ROTATE_EN,
71035 + (glamo_rot != GLAMO_LCD_ROT_MODE_0) ?
71036 + GLAMO_LCD_MODE1_ROTATE_EN : 0);
71037 +}
71038 +
71039 +static enum orientation get_orientation(struct fb_var_screeninfo *var)
71040 +{
71041 + if (var->xres <= var->yres)
71042 + return ORIENTATION_PORTRAIT;
71043 +
71044 + return ORIENTATION_LANDSCAPE;
71045 +}
71046 +
71047 +static int will_orientation_change(struct fb_var_screeninfo *var)
71048 +{
71049 + enum orientation orient = get_orientation(var);
71050 +
71051 + switch (orient) {
71052 + case ORIENTATION_LANDSCAPE:
71053 + if (var->rotate == FB_ROTATE_UR || var->rotate == FB_ROTATE_UD)
71054 + return 1;
71055 + break;
71056 + case ORIENTATION_PORTRAIT:
71057 + if (var->rotate == FB_ROTATE_CW || var->rotate == FB_ROTATE_CCW)
71058 + return 1;
71059 + break;
71060 + }
71061 + return 0;
71062 +}
71063 +
71064 +#ifdef CONFIG_MFD_GLAMO_FB_XGLAMO_WORKAROUND
71065 +
71066 +/*
71067 + * See https://docs.openmoko.org/trac/ticket/2255
71068 + * We have a hack for some Xglamo bugs in kernel code.
71069 + * If someone fixes xglamo we can remove this hack.
71070 + * We might make xglamo_hack_enabled 0 by default in the future.
71071 + */
71072 +
71073 +static unsigned xglamo_hack_enabled = 1;
71074 +
71075 +static ssize_t xglamo_hack_read(struct device *dev,
71076 + struct device_attribute *attr, char *buf)
71077 +{
71078 + return sprintf(buf, "%d\n", xglamo_hack_enabled);
71079 +}
71080 +
71081 +static ssize_t xglamo_hack_write(struct device *dev,
71082 + struct device_attribute *attr, const char *buf,
71083 + size_t count)
71084 +{
71085 + unsigned long val;
71086 +
71087 + if (!strict_strtoul(buf, 10, &val))
71088 + xglamo_hack_enabled = !!val;
71089 +
71090 + return count;
71091 +}
71092 +
71093 +static DEVICE_ATTR(xglamo_hack, S_IWUSR | S_IRUGO, xglamo_hack_read,
71094 + xglamo_hack_write);
71095 +
71096 +static struct attribute *glamo_fb_sysfs_entries[] = {
71097 + &dev_attr_xglamo_hack.attr,
71098 + NULL
71099 +};
71100 +
71101 +static struct attribute_group glamo_fb_attr_group = {
71102 + .name = NULL,
71103 + .attrs = glamo_fb_sysfs_entries,
71104 +};
71105 +
71106 +/* This function implements the actual Xglamo hack. */
71107 +
71108 +static void glamofb_update_lcd_controller_hack(struct glamofb_handle *glamo,
71109 + struct fb_var_screeninfo *var,
71110 + int *xres, int *yres, int *pitch)
71111 +{
71112 + int width, height;
71113 +
71114 + if (glamo->angle == 90 || glamo->angle == 270) {
71115 + /*
71116 + * But if we are going back to portrait mode from here,
71117 + * we get inverted values from Xglamo
71118 + */
71119 + if (!(var->rotate == FB_ROTATE_UR ||
71120 + var->rotate == FB_ROTATE_UD)) {
71121 + width = var->yres;
71122 + height = var->xres;
71123 + } else {
71124 + width = var->xres;
71125 + height = var->yres;
71126 + }
71127 +
71128 + } else {
71129 + width = var->xres;
71130 + height = var->yres;
71131 + }
71132 +
71133 + /* Portrait ? */
71134 + if (var->rotate == FB_ROTATE_UR || var->rotate == FB_ROTATE_UD) {
71135 + /* We don't need to set xres and yres in this particular case
71136 + * because Xglamo does it for us */
71137 + if (!(glamo->angle == 90 || glamo->angle == 270)) {
71138 + var->xres = width;
71139 + var->yres = height;
71140 + }
71141 +
71142 + var->xres_virtual = width;
71143 + var->yres_virtual = height * 2;
71144 + *pitch = width * var->bits_per_pixel / 8;
71145 + } else {
71146 + var->xres = height;
71147 + var->yres = width;
71148 + var->xres_virtual = height * 2;
71149 + var->yres_virtual = width;
71150 + *pitch = height * var->bits_per_pixel / 8;
71151 + }
71152 +
71153 + *xres = width;
71154 + *yres = height;
71155 +}
71156 +#else
71157 +#define xglamo_hack_enabled 0
71158 +static void glamofb_update_lcd_controller_hack(struct glamofb_handle *glamo,
71159 + struct fb_var_screeninfo *var,
71160 + int *xres, int *yres, int *pitch)
71161 +{
71162 +}
71163 +#endif
71164 +
71165 +static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
71166 + struct fb_var_screeninfo *var)
71167 +{
71168 + int sync, bp, disp, fp, total, xres, yres, pitch;
71169 + int uninitialized_var(orientation_changing);
71170 + unsigned long flags;
71171 +
71172 + if (!glamo || !var)
71173 + return;
71174 +
71175 + if (glamo->mach_info->glamo->suspending) {
71176 + dev_err(&glamo->mach_info->glamo->pdev->dev,
71177 + "IGNORING glamofb_update_lcd_controller while "
71178 + "suspended\n");
71179 + return;
71180 + }
71181 +
71182 + dev_dbg(&glamo->mach_info->glamo->pdev->dev,
71183 + "glamofb_update_lcd_controller spin_lock_irqsave\n");
71184 + spin_lock_irqsave(&glamo->lock_cmd, flags);
71185 +
71186 + if (glamofb_cmd_mode(glamo, 1))
71187 + goto out_unlock;
71188 +
71189 + if (var->pixclock)
71190 + glamo_engine_reclock(glamo->mach_info->glamo,
71191 + GLAMO_ENGINE_LCD,
71192 + var->pixclock);
71193 +
71194 + if (xglamo_hack_enabled) {
71195 + glamofb_update_lcd_controller_hack(glamo, var, &xres, &yres,
71196 + &pitch);
71197 + } else {
71198 + xres = var->xres;
71199 + yres = var->yres;
71200 +
71201 + orientation_changing = will_orientation_change(var);
71202 + /* Adjust the pitch according to new orientation to come. */
71203 + if (orientation_changing)
71204 + pitch = var->yres * var->bits_per_pixel / 8;
71205 + else
71206 + pitch = var->xres * var->bits_per_pixel / 8;
71207 + }
71208 +
71209 + reg_set_bit_mask(glamo,
71210 + GLAMO_REG_LCD_WIDTH,
71211 + GLAMO_LCD_WIDTH_MASK,
71212 + xres);
71213 + reg_set_bit_mask(glamo,
71214 + GLAMO_REG_LCD_HEIGHT,
71215 + GLAMO_LCD_HEIGHT_MASK,
71216 + yres);
71217 + reg_set_bit_mask(glamo,
71218 + GLAMO_REG_LCD_PITCH,
71219 + GLAMO_LCD_PITCH_MASK,
71220 + pitch);
71221 +
71222 + /* honour the rotation request */
71223 + __rotate_lcd(glamo, var->rotate);
71224 +
71225 + if (!xglamo_hack_enabled) {
71226 + /* update the reported geometry of the framebuffer. */
71227 + if (orientation_changing) {
71228 + var->xres_virtual = yres;
71229 + var->xres = yres;
71230 + var->xres_virtual *= 2;
71231 + var->yres_virtual = xres;
71232 + var->yres = xres;
71233 + } else {
71234 + var->xres_virtual = xres;
71235 + var->yres_virtual = yres;
71236 + var->yres_virtual *= 2;
71237 + }
71238 + }
71239 +
71240 + /* update scannout timings */
71241 + sync = 0;
71242 + bp = sync + var->hsync_len;
71243 + disp = bp + var->left_margin;
71244 + fp = disp + xres;
71245 + total = fp + var->right_margin;
71246 +
71247 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_TOTAL,
71248 + GLAMO_LCD_HV_TOTAL_MASK, total);
71249 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_START,
71250 + GLAMO_LCD_HV_RETR_START_MASK, sync);
71251 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_RETR_END,
71252 + GLAMO_LCD_HV_RETR_END_MASK, bp);
71253 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_START,
71254 + GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
71255 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_HORIZ_DISP_END,
71256 + GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
71257 +
71258 + sync = 0;
71259 + bp = sync + var->vsync_len;
71260 + disp = bp + var->upper_margin;
71261 + fp = disp + yres;
71262 + total = fp + var->lower_margin;
71263 +
71264 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_TOTAL,
71265 + GLAMO_LCD_HV_TOTAL_MASK, total);
71266 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_START,
71267 + GLAMO_LCD_HV_RETR_START_MASK, sync);
71268 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_RETR_END,
71269 + GLAMO_LCD_HV_RETR_END_MASK, bp);
71270 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_START,
71271 + GLAMO_LCD_HV_RETR_DISP_START_MASK, disp);
71272 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_VERT_DISP_END,
71273 + GLAMO_LCD_HV_RETR_DISP_END_MASK, fp);
71274 +
71275 + glamofb_cmd_mode(glamo, 0);
71276 +
71277 +out_unlock:
71278 + dev_dbg(&glamo->mach_info->glamo->pdev->dev,
71279 + "glamofb_update_lcd_controller spin_unlock_irqrestore\n");
71280 + spin_unlock_irqrestore(&glamo->lock_cmd, flags);
71281 +}
71282 +
71283 +static int glamofb_pan_display(struct fb_var_screeninfo *var,
71284 + struct fb_info *info)
71285 +{
71286 + struct glamofb_handle *glamo = info->par;
71287 + u_int16_t page = var->yoffset / glamo->mach_info->yres.defval;
71288 + reg_write(glamo, GLAMO_REG_LCD_COMMAND2, page);
71289 +
71290 + return 0;
71291 +}
71292 +
71293 +static int glamofb_set_par(struct fb_info *info)
71294 +{
71295 + struct glamofb_handle *glamo = info->par;
71296 + struct fb_var_screeninfo *var = &info->var;
71297 +
71298 + if (glamo->mach_info->glamo->suspending) {
71299 + dev_err(&glamo->mach_info->glamo->pdev->dev,
71300 + "IGNORING glamofb_set_par while "
71301 + "suspended\n");
71302 + return -EBUSY;
71303 + }
71304 +
71305 + switch (var->bits_per_pixel) {
71306 + case 16:
71307 + info->fix.visual = FB_VISUAL_TRUECOLOR;
71308 + break;
71309 + default:
71310 + printk("Smedia driver doesn't support != 16bpp\n");
71311 + return -EINVAL;
71312 + }
71313 +
71314 + info->fix.line_length = (var->xres * var->bits_per_pixel) / 8;
71315 +
71316 + glamofb_update_lcd_controller(glamo, var);
71317 +
71318 + return 0;
71319 +}
71320 +
71321 +
71322 +static void notify_blank(struct fb_info *info, int blank_mode)
71323 +{
71324 + struct fb_event event;
71325 +
71326 + event.info = info;
71327 + event.data = &blank_mode;
71328 + fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
71329 +}
71330 +
71331 +
71332 +static int glamofb_blank(int blank_mode, struct fb_info *info)
71333 +{
71334 + struct glamofb_handle *gfb = info->par;
71335 + struct glamo_core *gcore = gfb->mach_info->glamo;
71336 +
71337 + dev_dbg(gfb->dev, "glamofb_blank(%u)\n", blank_mode);
71338 +
71339 + switch (blank_mode) {
71340 + case FB_BLANK_VSYNC_SUSPEND:
71341 + case FB_BLANK_HSYNC_SUSPEND:
71342 + /* FIXME: add pdata hook/flag to indicate whether
71343 + * we should already switch off pixel clock here */
71344 + break;
71345 + case FB_BLANK_POWERDOWN:
71346 + /* Simulating FB_BLANK_NORMAL allow turning off backlight */
71347 + if (gfb->blank_mode != FB_BLANK_NORMAL)
71348 + notify_blank(info, FB_BLANK_NORMAL);
71349 +
71350 + /* LCM need notification before pixel clock is stopped */
71351 + notify_blank(info, blank_mode);
71352 +
71353 + /* disable the pixel clock */
71354 + glamo_engine_clkreg_set(gcore, GLAMO_ENGINE_LCD,
71355 + GLAMO_CLOCK_LCD_EN_DCLK, 0);
71356 + gfb->blank_mode = blank_mode;
71357 + break;
71358 + case FB_BLANK_UNBLANK:
71359 + case FB_BLANK_NORMAL:
71360 + /* enable the pixel clock if off */
71361 + if (gfb->blank_mode == FB_BLANK_POWERDOWN)
71362 + glamo_engine_clkreg_set(gcore,
71363 + GLAMO_ENGINE_LCD,
71364 + GLAMO_CLOCK_LCD_EN_DCLK,
71365 + GLAMO_CLOCK_LCD_EN_DCLK);
71366 +
71367 + notify_blank(info, blank_mode);
71368 + gfb->blank_mode = blank_mode;
71369 + break;
71370 + }
71371 +
71372 + /* FIXME: once we have proper clock management in glamo-core,
71373 + * we can determine if other units need MCLK1 or the PLL, and
71374 + * disable it if not used. */
71375 + return 0;
71376 +}
71377 +
71378 +static inline unsigned int chan_to_field(unsigned int chan,
71379 + struct fb_bitfield *bf)
71380 +{
71381 + chan &= 0xffff;
71382 + chan >>= 16 - bf->length;
71383 + return chan << bf->offset;
71384 +}
71385 +
71386 +static int glamofb_setcolreg(unsigned regno,
71387 + unsigned red, unsigned green, unsigned blue,
71388 + unsigned transp, struct fb_info *info)
71389 +{
71390 + struct glamofb_handle *glamo = info->par;
71391 + unsigned int val;
71392 +
71393 + if (glamo->mach_info->glamo->suspending) {
71394 + dev_err(&glamo->mach_info->glamo->pdev->dev,
71395 + "IGNORING glamofb_set_par while "
71396 + "suspended\n");
71397 + return -EBUSY;
71398 + }
71399 +
71400 + switch (glamo->fb->fix.visual) {
71401 + case FB_VISUAL_TRUECOLOR:
71402 + case FB_VISUAL_DIRECTCOLOR:
71403 + /* true-colour, use pseuo-palette */
71404 +
71405 + if (regno < 16) {
71406 + u32 *pal = glamo->fb->pseudo_palette;
71407 +
71408 + val = chan_to_field(red, &glamo->fb->var.red);
71409 + val |= chan_to_field(green, &glamo->fb->var.green);
71410 + val |= chan_to_field(blue, &glamo->fb->var.blue);
71411 +
71412 + pal[regno] = val;
71413 + };
71414 + break;
71415 + default:
71416 + return 1; /* unknown type */
71417 + }
71418 +
71419 + return 0;
71420 +}
71421 +
71422 +#ifdef CONFIG_MFD_GLAMO_HWACCEL
71423 +static inline void glamofb_vsync_wait(struct glamofb_handle *glamo,
71424 + int line, int size, int range)
71425 +{
71426 + int count[2];
71427 +
71428 + do {
71429 + count[0] = reg_read(glamo, GLAMO_REG_LCD_STATUS2) & 0x3ff;
71430 + count[1] = reg_read(glamo, GLAMO_REG_LCD_STATUS2) & 0x3ff;
71431 + } while (count[0] != count[1] ||
71432 + (line < count[0] + range &&
71433 + size > count[0] - range) ||
71434 + count[0] < range * 2);
71435 +}
71436 +
71437 +/*
71438 + * Enable/disable the hardware cursor mode altogether
71439 + * (for blinking and such, use glamofb_cursor()).
71440 + */
71441 +static void glamofb_cursor_onoff(struct glamofb_handle *glamo, int on)
71442 +{
71443 + int y, size;
71444 +
71445 + if (glamo->cursor_on) {
71446 + y = reg_read(glamo, GLAMO_REG_LCD_CURSOR_Y_POS);
71447 + size = reg_read(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE);
71448 +
71449 + glamofb_vsync_wait(glamo, y, size, 30);
71450 + }
71451 +
71452 + reg_set_bit_mask(glamo, GLAMO_REG_LCD_MODE1,
71453 + GLAMO_LCD_MODE1_CURSOR_EN,
71454 + on ? GLAMO_LCD_MODE1_CURSOR_EN : 0);
71455 + glamo->cursor_on = on;
71456 +
71457 + /* Hide the cursor by default */
71458 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE, 0);
71459 +}
71460 +
71461 +static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
71462 +{
71463 + struct glamofb_handle *glamo = info->par;
71464 + unsigned long flags;
71465 +
71466 + spin_lock_irqsave(&glamo->lock_cmd, flags);
71467 +
71468 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE,
71469 + cursor->enable ? cursor->image.width : 0);
71470 +
71471 + if (cursor->set & FB_CUR_SETPOS) {
71472 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_POS,
71473 + cursor->image.dx);
71474 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_POS,
71475 + cursor->image.dy);
71476 + }
71477 +
71478 + if (cursor->set & FB_CUR_SETCMAP) {
71479 + uint16_t fg = glamo->pseudo_pal[cursor->image.fg_color];
71480 + uint16_t bg = glamo->pseudo_pal[cursor->image.bg_color];
71481 +
71482 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_FG_COLOR, fg);
71483 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_BG_COLOR, bg);
71484 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_DST_COLOR, fg);
71485 + }
71486 +
71487 + if (cursor->set & FB_CUR_SETHOT)
71488 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_PRESET,
71489 + (cursor->hot.x << 8) | cursor->hot.y);
71490 +
71491 + if ((cursor->set & FB_CUR_SETSIZE) ||
71492 + (cursor->set & (FB_CUR_SETIMAGE | FB_CUR_SETSHAPE))) {
71493 + int x, y, pitch, op;
71494 + const uint8_t *pcol = cursor->image.data;
71495 + const uint8_t *pmsk = cursor->mask;
71496 + uint8_t __iomem *dst = glamo->cursor_addr;
71497 + uint8_t dcol = 0;
71498 + uint8_t dmsk = 0;
71499 + uint8_t byte = 0;
71500 +
71501 + if (cursor->image.depth > 1) {
71502 + spin_unlock_irqrestore(&glamo->lock_cmd, flags);
71503 + return -EINVAL;
71504 + }
71505 +
71506 + pitch = ((cursor->image.width + 7) >> 2) & ~1;
71507 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_PITCH,
71508 + pitch);
71509 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE,
71510 + cursor->image.height);
71511 +
71512 + for (y = 0; y < cursor->image.height; y++) {
71513 + byte = 0;
71514 + for (x = 0; x < cursor->image.width; x++) {
71515 + if ((x % 8) == 0) {
71516 + dcol = *pcol++;
71517 + dmsk = *pmsk++;
71518 + } else {
71519 + dcol >>= 1;
71520 + dmsk >>= 1;
71521 + }
71522 +
71523 + if (cursor->rop == ROP_COPY)
71524 + op = (dmsk & 1) ?
71525 + (dcol & 1) ? 1 : 3 : 0;
71526 + else
71527 + op = ((dmsk & 1) << 1) |
71528 + ((dcol & 1) << 0);
71529 + byte |= op << ((x & 3) << 1);
71530 +
71531 + if (x % 4 == 3) {
71532 + writeb(byte, dst + x / 4);
71533 + byte = 0;
71534 + }
71535 + }
71536 + if (x % 4) {
71537 + writeb(byte, dst + x / 4);
71538 + byte = 0;
71539 + }
71540 +
71541 + dst += pitch;
71542 + }
71543 + }
71544 +
71545 + spin_unlock_irqrestore(&glamo->lock_cmd, flags);
71546 +
71547 + return 0;
71548 +}
71549 +#endif
71550 +
71551 +static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb)
71552 +{
71553 + /* DGCMdQempty -- 1 == command queue is empty */
71554 + return reg_read(gfb, GLAMO_REG_LCD_STATUS1) & (1 << 15);
71555 +}
71556 +
71557 +/* call holding gfb->lock_cmd when locking, until you unlock */
71558 +int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
71559 +{
71560 + int timeout = 2000000;
71561 +
71562 + if (gfb->mach_info->glamo->suspending) {
71563 + dev_err(&gfb->mach_info->glamo->pdev->dev,
71564 + "IGNORING glamofb_cmd_mode while "
71565 + "suspended\n");
71566 + return -EBUSY;
71567 + }
71568 +
71569 + dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on);
71570 + if (on) {
71571 + dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
71572 + __func__);
71573 + while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
71574 + /* yield() */;
71575 + if (timeout < 0) {
71576 + printk(KERN_ERR"*************"
71577 + "glamofb cmd_queue never got empty"
71578 + "*************\n");
71579 + return -EIO;
71580 + }
71581 + dev_dbg(gfb->dev, "empty!\n");
71582 +
71583 + /* display the entire frame then switch to command */
71584 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
71585 + GLAMO_LCD_CMD_TYPE_DISP |
71586 + GLAMO_LCD_CMD_DATA_FIRE_VSYNC);
71587 +
71588 + /* wait until lcd idle */
71589 + dev_dbg(gfb->dev, "waiting for lcd idle: ");
71590 + timeout = 2000000;
71591 + while ((!reg_read(gfb, GLAMO_REG_LCD_STATUS2) & (1 << 12)) &&
71592 + (timeout--))
71593 + /* yield() */;
71594 + if (timeout < 0) {
71595 + printk(KERN_ERR"*************"
71596 + "glamofb lcd never idle"
71597 + "*************\n");
71598 + return -EIO;
71599 + }
71600 +
71601 + mdelay(100);
71602 +
71603 + dev_dbg(gfb->dev, "cmd mode entered\n");
71604 +
71605 + } else {
71606 + /* RGB interface needs vsync/hsync */
71607 + if (reg_read(gfb, GLAMO_REG_LCD_MODE3) & GLAMO_LCD_MODE3_RGB)
71608 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
71609 + GLAMO_LCD_CMD_TYPE_DISP |
71610 + GLAMO_LCD_CMD_DATA_DISP_SYNC);
71611 +
71612 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
71613 + GLAMO_LCD_CMD_TYPE_DISP |
71614 + GLAMO_LCD_CMD_DATA_DISP_FIRE);
71615 + }
71616 +
71617 + return 0;
71618 +}
71619 +EXPORT_SYMBOL_GPL(glamofb_cmd_mode);
71620 +
71621 +
71622 +int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
71623 +{
71624 + int timeout = 200000;
71625 +
71626 + if (gfb->mach_info->glamo->suspending) {
71627 + dev_err(&gfb->mach_info->glamo->pdev->dev,
71628 + "IGNORING glamofb_cmd_write while "
71629 + "suspended\n");
71630 + return -EBUSY;
71631 + }
71632 +
71633 + dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", __func__);
71634 + while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
71635 + yield();
71636 + if (timeout < 0) {
71637 + printk(KERN_ERR"*************"
71638 + "glamofb cmd_queue never got empty"
71639 + "*************\n");
71640 + return 1;
71641 + }
71642 + dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val);
71643 +
71644 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val);
71645 +
71646 + return 0;
71647 +}
71648 +EXPORT_SYMBOL_GPL(glamofb_cmd_write);
71649 +
71650 +static struct fb_ops glamofb_ops = {
71651 + .owner = THIS_MODULE,
71652 + .fb_check_var = glamofb_check_var,
71653 + .fb_pan_display = glamofb_pan_display,
71654 + .fb_set_par = glamofb_set_par,
71655 + .fb_blank = glamofb_blank,
71656 + .fb_setcolreg = glamofb_setcolreg,
71657 +#ifdef CONFIG_MFD_GLAMO_HWACCEL
71658 + .fb_cursor = glamofb_cursor,
71659 +#endif
71660 + .fb_fillrect = cfb_fillrect,
71661 + .fb_copyarea = cfb_copyarea,
71662 + .fb_imageblit = cfb_imageblit,
71663 +};
71664 +
71665 +static int glamofb_init_regs(struct glamofb_handle *glamo)
71666 +{
71667 + struct fb_info *info = glamo->fb;
71668 +
71669 + glamofb_check_var(&info->var, info);
71670 + glamofb_run_script(glamo, glamo_regs, ARRAY_SIZE(glamo_regs));
71671 + glamofb_set_par(info);
71672 +
71673 + return 0;
71674 +}
71675 +
71676 +static int __init glamofb_probe(struct platform_device *pdev)
71677 +{
71678 + int rc = -EIO;
71679 + struct fb_info *fbinfo;
71680 + struct glamofb_handle *glamofb;
71681 + struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
71682 +
71683 + printk(KERN_INFO "SMEDIA Glamo frame buffer driver (C) 2007 "
71684 + "Openmoko, Inc.\n");
71685 +
71686 + fbinfo = framebuffer_alloc(sizeof(struct glamofb_handle), &pdev->dev);
71687 + if (!fbinfo)
71688 + return -ENOMEM;
71689 +
71690 + glamofb = fbinfo->par;
71691 + glamofb->fb = fbinfo;
71692 + glamofb->dev = &pdev->dev;
71693 +
71694 + glamofb->angle = 0;
71695 + glamofb->blank_mode = FB_BLANK_POWERDOWN;
71696 +
71697 + strcpy(fbinfo->fix.id, "SMedia Glamo");
71698 +
71699 + glamofb->reg = platform_get_resource_byname(pdev, IORESOURCE_MEM,
71700 + "glamo-fb-regs");
71701 + if (!glamofb->reg) {
71702 + dev_err(&pdev->dev, "platform device with no registers?\n");
71703 + rc = -ENOENT;
71704 + goto out_free;
71705 + }
71706 +
71707 + glamofb->fb_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
71708 + "glamo-fb-mem");
71709 + if (!glamofb->fb_res) {
71710 + dev_err(&pdev->dev, "platform device with no memory ?\n");
71711 + rc = -ENOENT;
71712 + goto out_free;
71713 + }
71714 +
71715 + glamofb->reg = request_mem_region(glamofb->reg->start,
71716 + RESSIZE(glamofb->reg), pdev->name);
71717 + if (!glamofb->reg) {
71718 + dev_err(&pdev->dev, "failed to request mmio region\n");
71719 + goto out_free;
71720 + }
71721 +
71722 + glamofb->fb_res = request_mem_region(glamofb->fb_res->start,
71723 + mach_info->fb_mem_size,
71724 + pdev->name);
71725 + if (!glamofb->fb_res) {
71726 + dev_err(&pdev->dev, "failed to request vram region\n");
71727 + goto out_release_reg;
71728 + }
71729 +
71730 + /* we want to remap only the registers required for this core
71731 + * driver. */
71732 + glamofb->base = ioremap(glamofb->reg->start, RESSIZE(glamofb->reg));
71733 + if (!glamofb->base) {
71734 + dev_err(&pdev->dev, "failed to ioremap() mmio memory\n");
71735 + goto out_release_fb;
71736 + }
71737 + fbinfo->fix.smem_start = (unsigned long) glamofb->fb_res->start;
71738 + fbinfo->fix.smem_len = mach_info->fb_mem_size;
71739 +
71740 + fbinfo->screen_base = ioremap(glamofb->fb_res->start,
71741 + RESSIZE(glamofb->fb_res));
71742 + if (!fbinfo->screen_base) {
71743 + dev_err(&pdev->dev, "failed to ioremap() vram memory\n");
71744 + goto out_release_fb;
71745 + }
71746 + glamofb->cursor_addr = fbinfo->screen_base + 0x12C000;
71747 +
71748 + platform_set_drvdata(pdev, glamofb);
71749 +
71750 + glamofb->mach_info = pdev->dev.platform_data;
71751 +
71752 + fbinfo->fix.visual = FB_VISUAL_TRUECOLOR;
71753 + fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
71754 + fbinfo->fix.type_aux = 0;
71755 + fbinfo->fix.xpanstep = 0;
71756 + fbinfo->fix.ypanstep = mach_info->yres.defval;
71757 + fbinfo->fix.ywrapstep = 0;
71758 + fbinfo->fix.accel = FB_ACCEL_GLAMO;
71759 +
71760 + fbinfo->var.nonstd = 0;
71761 + fbinfo->var.activate = FB_ACTIVATE_NOW;
71762 + fbinfo->var.height = mach_info->height;
71763 + fbinfo->var.width = mach_info->width;
71764 + fbinfo->var.accel_flags = 0; /* FIXME */
71765 + fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
71766 +
71767 + fbinfo->fbops = &glamofb_ops;
71768 + fbinfo->flags = FBINFO_FLAG_DEFAULT;
71769 + fbinfo->pseudo_palette = &glamofb->pseudo_pal;
71770 +
71771 + fbinfo->var.xres = mach_info->xres.defval;
71772 + fbinfo->var.xres_virtual = mach_info->xres.defval;
71773 + fbinfo->var.yres = mach_info->yres.defval;
71774 + fbinfo->var.yres_virtual = mach_info->yres.defval * 2;
71775 + fbinfo->var.bits_per_pixel = mach_info->bpp.defval;
71776 +
71777 + fbinfo->var.pixclock = mach_info->pixclock;
71778 + fbinfo->var.left_margin = mach_info->left_margin;
71779 + fbinfo->var.right_margin = mach_info->right_margin;
71780 + fbinfo->var.upper_margin = mach_info->upper_margin;
71781 + fbinfo->var.lower_margin = mach_info->lower_margin;
71782 + fbinfo->var.hsync_len = mach_info->hsync_len;
71783 + fbinfo->var.vsync_len = mach_info->vsync_len;
71784 +
71785 + memset(fbinfo->screen_base, 0,
71786 + mach_info->xres.max *
71787 + mach_info->yres.max *
71788 + mach_info->bpp.max / 8);
71789 +
71790 + glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
71791 + glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
71792 +
71793 + dev_info(&pdev->dev, "spin_lock_init\n");
71794 + spin_lock_init(&glamofb->lock_cmd);
71795 + glamofb_init_regs(glamofb);
71796 +#ifdef CONFIG_MFD_GLAMO_HWACCEL
71797 + glamofb_cursor_onoff(glamofb, 1);
71798 +#endif
71799 +
71800 +#ifdef CONFIG_MFD_GLAMO_FB_XGLAMO_WORKAROUND
71801 + /* sysfs */
71802 + rc = sysfs_create_group(&pdev->dev.kobj, &glamo_fb_attr_group);
71803 + if (rc < 0) {
71804 + dev_err(&pdev->dev, "cannot create sysfs group\n");
71805 + goto out_unmap_fb;
71806 + }
71807 +#endif
71808 +
71809 + rc = register_framebuffer(fbinfo);
71810 + if (rc < 0) {
71811 + dev_err(&pdev->dev, "failed to register framebuffer\n");
71812 + goto out_unmap_fb;
71813 + }
71814 +
71815 + if (mach_info->spi_info) {
71816 + /* register the sibling spi device */
71817 + mach_info->spi_info->glamofb_handle = glamofb;
71818 + glamo_spi_dev.dev.parent = &pdev->dev;
71819 + glamo_spi_dev.dev.platform_data = mach_info->spi_info;
71820 + platform_device_register(&glamo_spi_dev);
71821 + }
71822 +
71823 + printk(KERN_INFO "fb%d: %s frame buffer device\n",
71824 + fbinfo->node, fbinfo->fix.id);
71825 +
71826 + return 0;
71827 +
71828 +out_unmap_fb:
71829 + iounmap(fbinfo->screen_base);
71830 + iounmap(glamofb->base);
71831 +out_release_fb:
71832 + release_mem_region(glamofb->fb_res->start, RESSIZE(glamofb->fb_res));
71833 +out_release_reg:
71834 + release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
71835 +out_free:
71836 + framebuffer_release(fbinfo);
71837 + return rc;
71838 +}
71839 +
71840 +static int glamofb_remove(struct platform_device *pdev)
71841 +{
71842 + struct glamofb_handle *glamofb = platform_get_drvdata(pdev);
71843 +
71844 + platform_set_drvdata(pdev, NULL);
71845 + iounmap(glamofb->base);
71846 + release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
71847 + kfree(glamofb);
71848 +
71849 + return 0;
71850 +}
71851 +
71852 +#ifdef CONFIG_PM
71853 +
71854 +static int glamofb_suspend(struct platform_device *pdev, pm_message_t state)
71855 +{
71856 + struct glamofb_handle *gfb = platform_get_drvdata(pdev);
71857 +
71858 + /* we need to stop anything touching our framebuffer */
71859 + fb_set_suspend(gfb->fb, 1);
71860 +
71861 + /* seriously -- nobody is allowed to touch glamo memory when we
71862 + * are suspended or we lock on nWAIT
71863 + */
71864 + /* iounmap(gfb->fb->screen_base); */
71865 +
71866 + return 0;
71867 +}
71868 +
71869 +static int glamofb_resume(struct platform_device *pdev)
71870 +{
71871 + struct glamofb_handle *gfb = platform_get_drvdata(pdev);
71872 + struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
71873 +
71874 + /* OK let's allow framebuffer ops again */
71875 + /* gfb->fb->screen_base = ioremap(gfb->fb_res->start,
71876 + RESSIZE(gfb->fb_res)); */
71877 + glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
71878 + glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
71879 +
71880 + printk(KERN_ERR"spin_lock_init\n");
71881 + spin_lock_init(&gfb->lock_cmd);
71882 + glamofb_init_regs(gfb);
71883 +#ifdef CONFIG_MFD_GLAMO_HWACCEL
71884 + glamofb_cursor_onoff(gfb, 1);
71885 +#endif
71886 +
71887 + fb_set_suspend(gfb->fb, 0);
71888 +
71889 + return 0;
71890 +}
71891 +#else
71892 +#define glamofb_suspend NULL
71893 +#define glamofb_resume NULL
71894 +#endif
71895 +
71896 +static struct platform_driver glamofb_driver = {
71897 + .probe = glamofb_probe,
71898 + .remove = glamofb_remove,
71899 + .suspend = glamofb_suspend,
71900 + .resume = glamofb_resume,
71901 + .driver = {
71902 + .name = "glamo-fb",
71903 + .owner = THIS_MODULE,
71904 + },
71905 +};
71906 +
71907 +static int __devinit glamofb_init(void)
71908 +{
71909 + return platform_driver_register(&glamofb_driver);
71910 +}
71911 +
71912 +static void __exit glamofb_cleanup(void)
71913 +{
71914 + platform_driver_unregister(&glamofb_driver);
71915 +}
71916 +
71917 +module_init(glamofb_init);
71918 +module_exit(glamofb_cleanup);
71919 +
71920 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
71921 +MODULE_DESCRIPTION("Smedia Glamo 336x/337x framebuffer driver");
71922 +MODULE_LICENSE("GPL");
71923 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-gpio.c linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-gpio.c
71924 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-gpio.c 1970-01-01 01:00:00.000000000 +0100
71925 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-gpio.c 2009-05-10 22:28:00.000000000 +0200
71926 @@ -0,0 +1,62 @@
71927 +
71928 +#include <linux/kernel.h>
71929 +#include <linux/module.h>
71930 +#include <linux/spinlock.h>
71931 +#include <linux/io.h>
71932 +
71933 +#include <linux/glamo-gpio.h>
71934 +
71935 +#include "glamo-core.h"
71936 +#include "glamo-regs.h"
71937 +
71938 +void glamo_gpio_setpin(struct glamo_core *glamo, unsigned int pin,
71939 + unsigned int value)
71940 +{
71941 + unsigned int reg = REG_OF_GPIO(pin);
71942 + u_int16_t tmp;
71943 +
71944 + spin_lock(&glamo->lock);
71945 + tmp = readw(glamo->base + reg);
71946 + if (value)
71947 + tmp |= OUTPUT_BIT(pin);
71948 + else
71949 + tmp &= ~OUTPUT_BIT(pin);
71950 + writew(tmp, glamo->base + reg);
71951 + spin_unlock(&glamo->lock);
71952 +}
71953 +EXPORT_SYMBOL(glamo_gpio_setpin);
71954 +
71955 +int glamo_gpio_getpin(struct glamo_core *glamo, unsigned int pin)
71956 +{
71957 + return readw(REG_OF_GPIO(pin)) & INPUT_BIT(pin) ? 1 : 0;
71958 +}
71959 +EXPORT_SYMBOL(glamo_gpio_getpin);
71960 +
71961 +void glamo_gpio_cfgpin(struct glamo_core *glamo, unsigned int pinfunc)
71962 +{
71963 + unsigned int reg = REG_OF_GPIO(pinfunc);
71964 + u_int16_t tmp;
71965 +
71966 + spin_lock(&glamo->lock);
71967 + tmp = readw(glamo->base + reg);
71968 +
71969 + if ((pinfunc & 0x00f0) == GLAMO_GPIO_F_FUNC) {
71970 + /* pin is a function pin: clear gpio bit */
71971 + tmp &= ~FUNC_BIT(pinfunc);
71972 + } else {
71973 + /* pin is gpio: set gpio bit */
71974 + tmp |= FUNC_BIT(pinfunc);
71975 +
71976 + if (pinfunc & GLAMO_GPIO_F_IN) {
71977 + /* gpio input: set bit to disable output mode */
71978 + tmp |= GPIO_OUT_BIT(pinfunc);
71979 + } else if (pinfunc & GLAMO_GPIO_F_OUT) {
71980 + /* gpio output: clear bit to enable output mode */
71981 + tmp &= ~GPIO_OUT_BIT(pinfunc);
71982 + }
71983 + }
71984 + writew(tmp, glamo->base + reg);
71985 + spin_unlock(&glamo->lock);
71986 +}
71987 +EXPORT_SYMBOL(glamo_gpio_cfgpin);
71988 +
71989 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-lcm-spi.c linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-lcm-spi.c
71990 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-lcm-spi.c 1970-01-01 01:00:00.000000000 +0100
71991 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-lcm-spi.c 2009-05-10 22:28:00.000000000 +0200
71992 @@ -0,0 +1,240 @@
71993 +/*
71994 + * Copyright (C) 2007 Openmoko, Inc.
71995 + * Author: Harald Welte <laforge@openmoko.org>
71996 + *
71997 + * Smedia Glamo GPIO based SPI driver
71998 + *
71999 + * This program is free software; you can redistribute it and/or modify
72000 + * it under the terms of the GNU General Public License version 2 as
72001 + * published by the Free Software Foundation.
72002 + *
72003 + * This driver currently only implements a minimum subset of the hardware
72004 + * features, esp. those features that are required to drive the jbt6k74
72005 + * LCM controller asic in the TD028TTEC1 LCM.
72006 + *
72007 +*/
72008 +
72009 +#define DEBUG
72010 +
72011 +#include <linux/kernel.h>
72012 +#include <linux/init.h>
72013 +#include <linux/delay.h>
72014 +#include <linux/device.h>
72015 +#include <linux/spinlock.h>
72016 +#include <linux/workqueue.h>
72017 +#include <linux/platform_device.h>
72018 +
72019 +#include <linux/spi/spi.h>
72020 +#include <linux/spi/spi_bitbang.h>
72021 +#include <linux/spi/glamo.h>
72022 +
72023 +#include <linux/glamofb.h>
72024 +
72025 +#include <mach/hardware.h>
72026 +
72027 +#include "glamo-core.h"
72028 +#include "glamo-regs.h"
72029 +
72030 +struct glamo_spi {
72031 + struct spi_bitbang bitbang;
72032 + struct spi_master *master;
72033 + struct glamo_spi_info *info;
72034 + struct device *dev;
72035 +};
72036 +
72037 +static inline struct glamo_spi *to_gs(struct spi_device *spi)
72038 +{
72039 + return spi->controller_data;
72040 +}
72041 +
72042 +static int glamo_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
72043 +{
72044 + unsigned int bpw;
72045 +
72046 + bpw = t ? t->bits_per_word : spi->bits_per_word;
72047 +
72048 + if (bpw != 9 && bpw != 8) {
72049 + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
72050 + return -EINVAL;
72051 + }
72052 +
72053 + return 0;
72054 +}
72055 +
72056 +static void glamo_spi_chipsel(struct spi_device *spi, int value)
72057 +{
72058 +#if 0
72059 + struct glamo_spi *gs = to_gs(spi);
72060 +
72061 + dev_dbg(&spi->dev, "chipsel %d: spi=%p, gs=%p, info=%p, handle=%p\n",
72062 + value, spi, gs, gs->info, gs->info->glamofb_handle);
72063 +
72064 + glamofb_cmd_mode(gs->info->glamofb_handle, value);
72065 +#endif
72066 +}
72067 +
72068 +static int glamo_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
72069 +{
72070 + struct glamo_spi *gs = to_gs(spi);
72071 + const u_int16_t *ui16 = (const u_int16_t *) t->tx_buf;
72072 + u_int16_t nine_bits;
72073 + int i;
72074 +
72075 + dev_dbg(&spi->dev, "txrx: tx %p, rx %p, bpw %d, len %d\n",
72076 + t->tx_buf, t->rx_buf, t->bits_per_word, t->len);
72077 +
72078 + if (spi->bits_per_word == 9)
72079 + nine_bits = (1 << 9);
72080 + else
72081 + nine_bits = 0;
72082 +
72083 + if (t->len > 3 * sizeof(u_int16_t)) {
72084 + dev_err(&spi->dev, "this driver doesn't support "
72085 + "%u sized xfers\n", t->len);
72086 + return -EINVAL;
72087 + }
72088 +
72089 + for (i = 0; i < t->len/sizeof(u_int16_t); i++) {
72090 + /* actually transfer the data */
72091 +#if 1
72092 + glamofb_cmd_write(gs->info->glamofb_handle,
72093 + GLAMO_LCD_CMD_TYPE_SERIAL | nine_bits |
72094 + (1 << 10) | (1 << 11) | (ui16[i] & 0x1ff));
72095 +#endif
72096 + /* FIXME: fire ?!? */
72097 + if (i == 0 && (ui16[i] & 0x1ff) == 0x29) {
72098 + dev_dbg(&spi->dev, "leaving command mode\n");
72099 + glamofb_cmd_mode(gs->info->glamofb_handle, 0);
72100 + }
72101 + }
72102 +
72103 + return t->len;
72104 +}
72105 +
72106 +static int glamo_spi_setup(struct spi_device *spi)
72107 +{
72108 + int ret;
72109 +
72110 + if (!spi->bits_per_word)
72111 + spi->bits_per_word = 9;
72112 +
72113 + /* FIXME: hardware can do this */
72114 + if (spi->mode & SPI_LSB_FIRST)
72115 + return -EINVAL;
72116 +
72117 + ret = glamo_spi_setupxfer(spi, NULL);
72118 + if (ret < 0) {
72119 + dev_err(&spi->dev, "setupxfer returned %d\n", ret);
72120 + return ret;
72121 + }
72122 +
72123 + dev_dbg(&spi->dev, "%s: mode %d, %u bpw\n",
72124 + __FUNCTION__, spi->mode, spi->bits_per_word);
72125 +
72126 + return 0;
72127 +}
72128 +
72129 +static int glamo_spi_probe(struct platform_device *pdev)
72130 +{
72131 + struct spi_master *master;
72132 + struct glamo_spi *sp;
72133 + int ret;
72134 + int i;
72135 +
72136 + master = spi_alloc_master(&pdev->dev, sizeof(struct glamo_spi));
72137 + if (master == NULL) {
72138 + dev_err(&pdev->dev, "failed to allocate spi master\n");
72139 + ret = -ENOMEM;
72140 + goto err;
72141 + }
72142 +
72143 + sp = spi_master_get_devdata(master);
72144 + memset(sp, 0, sizeof(struct glamo_spi));
72145 +
72146 + sp->master = spi_master_get(master);
72147 + sp->info = pdev->dev.platform_data;
72148 + if (!sp->info) {
72149 + dev_err(&pdev->dev, "can't operate without platform data\n");
72150 + ret = -EIO;
72151 + goto err_no_pdev;
72152 + }
72153 + dev_dbg(&pdev->dev, "sp->info(pdata) = %p\n", sp->info);
72154 +
72155 + sp->dev = &pdev->dev;
72156 +
72157 + platform_set_drvdata(pdev, sp);
72158 +
72159 + sp->bitbang.master = sp->master;
72160 + sp->bitbang.setup_transfer = glamo_spi_setupxfer;
72161 + sp->bitbang.chipselect = glamo_spi_chipsel;
72162 + sp->bitbang.txrx_bufs = glamo_spi_txrx;
72163 + sp->bitbang.master->setup = glamo_spi_setup;
72164 +
72165 + ret = spi_bitbang_start(&sp->bitbang);
72166 + if (ret)
72167 + goto err_no_bitbang;
72168 +
72169 + /* register the chips to go with the board */
72170 +
72171 + glamofb_cmd_mode(sp->info->glamofb_handle, 1);
72172 +
72173 + for (i = 0; i < sp->info->board_size; i++) {
72174 + dev_info(&pdev->dev, "registering %p: %s\n",
72175 + &sp->info->board_info[i],
72176 + sp->info->board_info[i].modalias);
72177 +
72178 + sp->info->board_info[i].controller_data = sp;
72179 + spi_new_device(master, sp->info->board_info + i);
72180 + }
72181 +
72182 + return 0;
72183 +
72184 +err_no_bitbang:
72185 + platform_set_drvdata(pdev, NULL);
72186 +err_no_pdev:
72187 + spi_master_put(sp->bitbang.master);
72188 +err:
72189 + return ret;
72190 +
72191 +}
72192 +
72193 +static int glamo_spi_remove(struct platform_device *pdev)
72194 +{
72195 + struct glamo_spi *sp = platform_get_drvdata(pdev);
72196 +
72197 + spi_bitbang_stop(&sp->bitbang);
72198 + spi_master_put(sp->bitbang.master);
72199 +
72200 + return 0;
72201 +}
72202 +
72203 +#define glamo_spi_suspend NULL
72204 +#define glamo_spi_resume NULL
72205 +
72206 +static struct platform_driver glamo_spi_drv = {
72207 + .probe = glamo_spi_probe,
72208 + .remove = glamo_spi_remove,
72209 + .suspend = glamo_spi_suspend,
72210 + .resume = glamo_spi_resume,
72211 + .driver = {
72212 + .name = "glamo-lcm-spi",
72213 + .owner = THIS_MODULE,
72214 + },
72215 +};
72216 +
72217 +static int __init glamo_spi_init(void)
72218 +{
72219 + return platform_driver_register(&glamo_spi_drv);
72220 +}
72221 +
72222 +static void __exit glamo_spi_exit(void)
72223 +{
72224 + platform_driver_unregister(&glamo_spi_drv);
72225 +}
72226 +
72227 +module_init(glamo_spi_init);
72228 +module_exit(glamo_spi_exit);
72229 +
72230 +MODULE_DESCRIPTION("Smedia Glamo 336x/337x LCM serial command SPI Driver");
72231 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>")
72232 +MODULE_LICENSE("GPL");
72233 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-mci.c linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-mci.c
72234 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-mci.c 1970-01-01 01:00:00.000000000 +0100
72235 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-mci.c 2009-05-10 22:28:00.000000000 +0200
72236 @@ -0,0 +1,1168 @@
72237 +/*
72238 + * linux/drivers/mmc/host/glamo-mmc.c - Glamo MMC driver
72239 + *
72240 + * Copyright (C) 2007 Openmoko, Inc, Andy Green <andy@openmoko.com>
72241 + * Based on S3C MMC driver that was:
72242 + * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
72243 + *
72244 + * This program is free software; you can redistribute it and/or modify
72245 + * it under the terms of the GNU General Public License version 2 as
72246 + * published by the Free Software Foundation.
72247 + */
72248 +
72249 +#include <linux/module.h>
72250 +#include <linux/dma-mapping.h>
72251 +#include <linux/clk.h>
72252 +#include <linux/mmc/mmc.h>
72253 +#include <linux/mmc/host.h>
72254 +#include <linux/platform_device.h>
72255 +#include <linux/irq.h>
72256 +#include <linux/pcf50633.h>
72257 +#include <linux/delay.h>
72258 +#include <linux/interrupt.h>
72259 +#include <linux/spinlock.h>
72260 +#include <linux/workqueue.h>
72261 +
72262 +#include <asm/dma.h>
72263 +#include <asm/dma-mapping.h>
72264 +#include <asm/io.h>
72265 +
72266 +#include "glamo-mci.h"
72267 +#include "glamo-core.h"
72268 +#include "glamo-regs.h"
72269 +
72270 +/* from glamo-core.c */
72271 +extern struct glamo_mci_pdata glamo_mci_def_pdata;
72272 +
72273 +static spinlock_t clock_lock;
72274 +
72275 +#define DRIVER_NAME "glamo-mci"
72276 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start) + 1)
72277 +
72278 +static void glamo_mci_send_request(struct mmc_host *mmc);
72279 +
72280 +/*
72281 + * Max SD clock rate
72282 + *
72283 + * held at /(3 + 1) due to concerns of 100R recommended series resistor
72284 + * allows 16MHz @ 4-bit --> 8MBytes/sec raw
72285 + *
72286 + * you can override this on kernel commandline using
72287 + *
72288 + * glamo_mci.sd_max_clk=10000000
72289 + *
72290 + * for example
72291 + */
72292 +
72293 +static int sd_max_clk = 50000000 / 3;
72294 +module_param(sd_max_clk, int, 0644);
72295 +
72296 +/*
72297 + * Slow SD clock rate
72298 + *
72299 + * you can override this on kernel commandline using
72300 + *
72301 + * glamo_mci.sd_slow_ratio=8
72302 + *
72303 + * for example
72304 + *
72305 + * platform callback is used to decide effective clock rate, if not
72306 + * defined then max is used, if defined and returns nonzero, rate is
72307 + * divided by this factor
72308 + */
72309 +
72310 +static int sd_slow_ratio = 8;
72311 +module_param(sd_slow_ratio, int, 0644);
72312 +
72313 +/*
72314 + * Post-power SD clock rate
72315 + *
72316 + * you can override this on kernel commandline using
72317 + *
72318 + * glamo_mci.sd_post_power_clock=1000000
72319 + *
72320 + * for example
72321 + *
72322 + * After changing power to card, clock is held at this rate until first bulk
72323 + * transfer completes
72324 + */
72325 +
72326 +static int sd_post_power_clock = 1000000;
72327 +module_param(sd_post_power_clock, int, 0644);
72328 +
72329 +
72330 +/*
72331 + * SD Signal drive strength
72332 + *
72333 + * you can override this on kernel commandline using
72334 + *
72335 + * glamo_mci.sd_drive=0
72336 + *
72337 + * for example
72338 + */
72339 +
72340 +static int sd_drive;
72341 +module_param(sd_drive, int, 0644);
72342 +
72343 +/*
72344 + * SD allow SD clock to run while idle
72345 + *
72346 + * you can override this on kernel commandline using
72347 + *
72348 + * glamo_mci.sd_idleclk=0
72349 + *
72350 + * for example
72351 + */
72352 +
72353 +static int sd_idleclk = 0; /* disallow idle clock by default */
72354 +module_param(sd_idleclk, int, 0644);
72355 +
72356 +/* used to stash real idleclk state in suspend: we force it to run in there */
72357 +static int suspend_sd_idleclk;
72358 +
72359 +
72360 +unsigned char CRC7(u8 * pu8, int cnt)
72361 +{
72362 + u8 crc = 0;
72363 +
72364 + while (cnt--) {
72365 + int n;
72366 + u8 d = *pu8++;
72367 + for (n = 0; n < 8; n++) {
72368 + crc <<= 1;
72369 + if ((d & 0x80) ^ (crc & 0x80))
72370 + crc ^= 0x09;
72371 + d <<= 1;
72372 + }
72373 + }
72374 + return (crc << 1) | 1;
72375 +}
72376 +
72377 +static int get_data_buffer(struct glamo_mci_host *host,
72378 + volatile u32 *words, volatile u16 **pointer)
72379 +{
72380 + struct scatterlist *sg;
72381 +
72382 + *words = 0;
72383 + *pointer = NULL;
72384 +
72385 + if (host->pio_active == XFER_NONE)
72386 + return -EINVAL;
72387 +
72388 + if ((!host->mrq) || (!host->mrq->data))
72389 + return -EINVAL;
72390 +
72391 + if (host->pio_sgptr >= host->mrq->data->sg_len) {
72392 + dev_dbg(&host->pdev->dev, "no more buffers (%i/%i)\n",
72393 + host->pio_sgptr, host->mrq->data->sg_len);
72394 + return -EBUSY;
72395 + }
72396 + sg = &host->mrq->data->sg[host->pio_sgptr];
72397 +
72398 + *words = sg->length >> 1; /* we are working with a 16-bit data bus */
72399 + *pointer = page_address(sg_page(sg)) + sg->offset;
72400 +
72401 + BUG_ON(((long)(*pointer)) & 1);
72402 +
72403 + host->pio_sgptr++;
72404 +
72405 + /* dev_info(&host->pdev->dev, "new buffer (%i/%i)\n",
72406 + host->pio_sgptr, host->mrq->data->sg_len); */
72407 + return 0;
72408 +}
72409 +
72410 +static void do_pio_read(struct glamo_mci_host *host)
72411 +{
72412 + int res;
72413 + u16 __iomem *from_ptr = host->base_data + (RESSIZE(host->mem_data) /
72414 + sizeof(u16) / 2);
72415 +#ifdef DEBUG
72416 + u16 * block;
72417 +#endif
72418 +
72419 + while (1) {
72420 + res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);
72421 + if (res) {
72422 + host->pio_active = XFER_NONE;
72423 + host->complete_what = COMPLETION_FINALIZE;
72424 +
72425 + dev_dbg(&host->pdev->dev, "pio_read(): "
72426 + "complete (no more data).\n");
72427 + return;
72428 + }
72429 +
72430 + dev_dbg(&host->pdev->dev, "pio_read(): host->pio_words: %d\n",
72431 + host->pio_words);
72432 +
72433 + host->pio_count += host->pio_words << 1;
72434 +
72435 +#ifdef DEBUG
72436 + block = (u16 *)host->pio_ptr;
72437 + res = host->pio_words << 1;
72438 +#endif
72439 +#if 0
72440 + /* u16-centric memcpy */
72441 + while (host->pio_words--)
72442 + *host->pio_ptr++ = *from_ptr++;
72443 +#else
72444 + /* memcpy can be faster? */
72445 + memcpy((void *)host->pio_ptr, from_ptr, host->pio_words << 1);
72446 + host->pio_ptr += host->pio_words;
72447 +#endif
72448 +
72449 +#ifdef DEBUG
72450 + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1,
72451 + (void *)block, res, 1);
72452 +#endif
72453 + }
72454 +}
72455 +
72456 +static int do_pio_write(struct glamo_mci_host *host)
72457 +{
72458 + int res = 0;
72459 + volatile u16 __iomem *to_ptr = host->base_data;
72460 + int err = 0;
72461 +
72462 + dev_dbg(&host->pdev->dev, "pio_write():\n");
72463 + while (!res) {
72464 + res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);
72465 + if (res)
72466 + continue;
72467 +
72468 + dev_dbg(&host->pdev->dev, "pio_write():new source: [%i]@[%p]\n",
72469 + host->pio_words, host->pio_ptr);
72470 +
72471 + host->pio_count += host->pio_words << 1;
72472 + while (host->pio_words--)
72473 + writew(*host->pio_ptr++, to_ptr++);
72474 + }
72475 +
72476 + dev_dbg(&host->pdev->dev, "pio_write(): complete\n");
72477 + host->pio_active = XFER_NONE;
72478 + return err;
72479 +}
72480 +
72481 +static void __glamo_mci_fix_card_div(struct glamo_mci_host *host, int div)
72482 +{
72483 + unsigned long flags;
72484 +
72485 + spin_lock_irqsave(&clock_lock, flags);
72486 +
72487 + if (div < 0) {
72488 + /* stop clock - remove clock from divider input */
72489 + writew(readw(glamo_mci_def_pdata.pglamo->base +
72490 + GLAMO_REG_CLOCK_GEN5_1) & (~GLAMO_CLOCK_GEN51_EN_DIV_TCLK),
72491 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
72492 +
72493 + goto done;
72494 + } else {
72495 + /* set the nearest prescaler factor
72496 + *
72497 + * register shared with SCLK divisor -- no chance of race because
72498 + * we don't use sensor interface
72499 + */
72500 + writew((readw(glamo_mci_def_pdata.pglamo->base +
72501 + GLAMO_REG_CLOCK_GEN8) & 0xff00) | div,
72502 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN8);
72503 + /* enable clock to divider input */
72504 + writew(readw(glamo_mci_def_pdata.pglamo->base +
72505 + GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
72506 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
72507 + }
72508 +
72509 + if (host->force_slow_during_powerup)
72510 + div = host->clk_rate / sd_post_power_clock;
72511 + else
72512 + if (host->pdata->glamo_mci_use_slow)
72513 + if ((host->pdata->glamo_mci_use_slow)())
72514 + div = div * sd_slow_ratio;
72515 +
72516 + if (div > 255)
72517 + div = 255;
72518 +
72519 + /*
72520 + * set the nearest prescaler factor
72521 + *
72522 + * register shared with SCLK divisor -- no chance of race because
72523 + * we don't use sensor interface
72524 + */
72525 + writew((readw(glamo_mci_def_pdata.pglamo->base +
72526 + GLAMO_REG_CLOCK_GEN8) & 0xff00) | div,
72527 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN8);
72528 + /* enable clock to divider input */
72529 + writew(readw(glamo_mci_def_pdata.pglamo->base +
72530 + GLAMO_REG_CLOCK_GEN5_1) | GLAMO_CLOCK_GEN51_EN_DIV_TCLK,
72531 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_GEN5_1);
72532 +
72533 +done:
72534 + spin_unlock_irqrestore(&clock_lock, flags);
72535 +}
72536 +
72537 +static int __glamo_mci_set_card_clock(struct glamo_mci_host *host, int freq,
72538 + int *division)
72539 +{
72540 + int div = 0;
72541 + int real_rate = 0;
72542 +
72543 + if (freq) {
72544 + /* Set clock */
72545 + for (div = 0; div < 256; div++) {
72546 + real_rate = host->clk_rate / (div + 1);
72547 + if (real_rate <= freq)
72548 + break;
72549 + }
72550 + if (div > 255)
72551 + div = 255;
72552 +
72553 + if (division)
72554 + *division = div;
72555 +
72556 + __glamo_mci_fix_card_div(host, div);
72557 +
72558 + } else {
72559 + /* stop clock */
72560 + if (division)
72561 + *division = 0xff;
72562 +
72563 + if (!sd_idleclk && !host->force_slow_during_powerup)
72564 + /* clock off */
72565 + __glamo_mci_fix_card_div(host, -1);
72566 + }
72567 +
72568 + return real_rate;
72569 +}
72570 +
72571 +
72572 +static void glamo_mci_irq_worker(struct work_struct *work)
72573 +{
72574 + struct glamo_mci_host *host =
72575 + container_of(work, struct glamo_mci_host, irq_work);
72576 + struct mmc_command *cmd = host->mrq->cmd;
72577 +
72578 + if (host->pio_active == XFER_READ)
72579 + do_pio_read(host);
72580 +
72581 + host->mrq->data->bytes_xfered = host->pio_count;
72582 + dev_dbg(&host->pdev->dev, "count=%d\n", host->pio_count);
72583 +
72584 + /* issue STOP if we have been given one to use */
72585 + if (host->mrq->stop) {
72586 + host->cmd_is_stop = 1;
72587 + glamo_mci_send_request(host->mmc);
72588 + host->cmd_is_stop = 0;
72589 + }
72590 +
72591 + if (!sd_idleclk && !host->force_slow_during_powerup)
72592 + /* clock off */
72593 + __glamo_mci_fix_card_div(host, -1);
72594 +
72595 + host->complete_what = COMPLETION_NONE;
72596 + host->mrq = NULL;
72597 + mmc_request_done(host->mmc, cmd->mrq);
72598 +}
72599 +
72600 +static void glamo_mci_irq_host(struct glamo_mci_host *host)
72601 +{
72602 + u16 status;
72603 + struct mmc_command *cmd;
72604 + unsigned long iflags;
72605 +
72606 + if (host->suspending) { /* bad news, dangerous time */
72607 + dev_err(&host->pdev->dev, "****glamo_mci_irq before resumed\n");
72608 + return;
72609 + }
72610 +
72611 + if (!host->mrq)
72612 + return;
72613 + cmd = host->mrq->cmd;
72614 + if (!cmd)
72615 + return;
72616 +
72617 + spin_lock_irqsave(&host->complete_lock, iflags);
72618 +
72619 + status = readw(host->base + GLAMO_REG_MMC_RB_STAT1);
72620 + dev_dbg(&host->pdev->dev, "status = 0x%04x\n", status);
72621 +
72622 + /* ack this interrupt source */
72623 + writew(GLAMO_IRQ_MMC,
72624 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_IRQ_CLEAR);
72625 +
72626 + /* we ignore a data timeout report if we are also told the data came */
72627 + if (status & GLAMO_STAT1_MMC_RB_DRDY)
72628 + status &= ~GLAMO_STAT1_MMC_DTOUT;
72629 +
72630 + if (status & (GLAMO_STAT1_MMC_RTOUT |
72631 + GLAMO_STAT1_MMC_DTOUT))
72632 + cmd->error = -ETIMEDOUT;
72633 + if (status & (GLAMO_STAT1_MMC_BWERR |
72634 + GLAMO_STAT1_MMC_BRERR))
72635 + cmd->error = -EILSEQ;
72636 + if (cmd->error) {
72637 + dev_info(&host->pdev->dev, "Error after cmd: 0x%x\n", status);
72638 + goto done;
72639 + }
72640 +
72641 + /*
72642 + * disable the initial slow start after first bulk transfer
72643 + */
72644 + if (host->force_slow_during_powerup)
72645 + host->force_slow_during_powerup--;
72646 +
72647 + /*
72648 + * we perform the memcpy out of Glamo memory outside of IRQ context
72649 + * so we don't block other interrupts
72650 + */
72651 + schedule_work(&host->irq_work);
72652 +
72653 + goto leave;
72654 +
72655 +done:
72656 + host->complete_what = COMPLETION_NONE;
72657 + host->mrq = NULL;
72658 + mmc_request_done(host->mmc, cmd->mrq);
72659 +leave:
72660 + spin_unlock_irqrestore(&host->complete_lock, iflags);
72661 +}
72662 +
72663 +static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc)
72664 +{
72665 + struct glamo_mci_host *host = (struct glamo_mci_host *)
72666 + desc->handler_data;
72667 +
72668 + if (host)
72669 + glamo_mci_irq_host(host);
72670 +
72671 +}
72672 +
72673 +static int glamo_mci_send_command(struct glamo_mci_host *host,
72674 + struct mmc_command *cmd)
72675 +{
72676 + u8 u8a[6];
72677 + u16 fire = 0;
72678 +
72679 + /* if we can't do it, reject as busy */
72680 + if (!readw(host->base + GLAMO_REG_MMC_RB_STAT1) &
72681 + GLAMO_STAT1_MMC_IDLE) {
72682 + host->mrq = NULL;
72683 + cmd->error = -EBUSY;
72684 + mmc_request_done(host->mmc, host->mrq);
72685 + return -EBUSY;
72686 + }
72687 +
72688 + /* create an array in wire order for CRC computation */
72689 + u8a[0] = 0x40 | (cmd->opcode & 0x3f);
72690 + u8a[1] = (u8)(cmd->arg >> 24);
72691 + u8a[2] = (u8)(cmd->arg >> 16);
72692 + u8a[3] = (u8)(cmd->arg >> 8);
72693 + u8a[4] = (u8)cmd->arg;
72694 + u8a[5] = CRC7(&u8a[0], 5); /* CRC7 on first 5 bytes of packet */
72695 +
72696 + /* issue the wire-order array including CRC in register order */
72697 + writew((u8a[4] << 8) | u8a[5], host->base + GLAMO_REG_MMC_CMD_REG1);
72698 + writew((u8a[2] << 8) | u8a[3], host->base + GLAMO_REG_MMC_CMD_REG2);
72699 + writew((u8a[0] << 8) | u8a[1], host->base + GLAMO_REG_MMC_CMD_REG3);
72700 +
72701 + /* command index toggle */
72702 + fire |= (host->ccnt & 1) << 12;
72703 +
72704 + /* set type of command */
72705 + switch (mmc_cmd_type(cmd)) {
72706 + case MMC_CMD_BC:
72707 + fire |= GLAMO_FIRE_MMC_CMDT_BNR;
72708 + break;
72709 + case MMC_CMD_BCR:
72710 + fire |= GLAMO_FIRE_MMC_CMDT_BR;
72711 + break;
72712 + case MMC_CMD_AC:
72713 + fire |= GLAMO_FIRE_MMC_CMDT_AND;
72714 + break;
72715 + case MMC_CMD_ADTC:
72716 + fire |= GLAMO_FIRE_MMC_CMDT_AD;
72717 + break;
72718 + }
72719 + /*
72720 + * if it expects a response, set the type expected
72721 + *
72722 + * R1, Length : 48bit, Normal response
72723 + * R1b, Length : 48bit, same R1, but added card busy status
72724 + * R2, Length : 136bit (really 128 bits with CRC snipped)
72725 + * R3, Length : 48bit (OCR register value)
72726 + * R4, Length : 48bit, SDIO_OP_CONDITION, Reverse SDIO Card
72727 + * R5, Length : 48bit, IO_RW_DIRECTION, Reverse SDIO Card
72728 + * R6, Length : 48bit (RCA register)
72729 + * R7, Length : 48bit (interface condition, VHS(voltage supplied),
72730 + * check pattern, CRC7)
72731 + */
72732 + switch (mmc_resp_type(cmd)) {
72733 + case MMC_RSP_R6: /* same index as R7 and R1 */
72734 + fire |= GLAMO_FIRE_MMC_RSPT_R1;
72735 + break;
72736 + case MMC_RSP_R1B:
72737 + fire |= GLAMO_FIRE_MMC_RSPT_R1b;
72738 + break;
72739 + case MMC_RSP_R2:
72740 + fire |= GLAMO_FIRE_MMC_RSPT_R2;
72741 + break;
72742 + case MMC_RSP_R3:
72743 + fire |= GLAMO_FIRE_MMC_RSPT_R3;
72744 + break;
72745 + /* R4 and R5 supported by chip not defined in linux/mmc/core.h (sdio) */
72746 + }
72747 + /*
72748 + * From the command index, set up the command class in the host ctrllr
72749 + *
72750 + * missing guys present on chip but couldn't figure out how to use yet:
72751 + * 0x0 "stream read"
72752 + * 0x9 "cancel running command"
72753 + */
72754 + switch (cmd->opcode) {
72755 + case MMC_READ_SINGLE_BLOCK:
72756 + fire |= GLAMO_FIRE_MMC_CC_SBR; /* single block read */
72757 + break;
72758 + case MMC_SWITCH: /* 64 byte payload */
72759 + case 0x33: /* observed issued by MCI */
72760 + case MMC_READ_MULTIPLE_BLOCK:
72761 + /* we will get an interrupt off this */
72762 + if (!cmd->mrq->stop)
72763 + /* multiblock no stop */
72764 + fire |= GLAMO_FIRE_MMC_CC_MBRNS;
72765 + else
72766 + /* multiblock with stop */
72767 + fire |= GLAMO_FIRE_MMC_CC_MBRS;
72768 + break;
72769 + case MMC_WRITE_BLOCK:
72770 + fire |= GLAMO_FIRE_MMC_CC_SBW; /* single block write */
72771 + break;
72772 + case MMC_WRITE_MULTIPLE_BLOCK:
72773 + if (cmd->mrq->stop)
72774 + /* multiblock with stop */
72775 + fire |= GLAMO_FIRE_MMC_CC_MBWS;
72776 + else
72777 +// /* multiblock NO stop-- 'RESERVED'? */
72778 + fire |= GLAMO_FIRE_MMC_CC_MBWNS;
72779 + break;
72780 + case MMC_STOP_TRANSMISSION:
72781 + fire |= GLAMO_FIRE_MMC_CC_STOP; /* STOP */
72782 + break;
72783 + default:
72784 + fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */
72785 + break;
72786 + }
72787 +
72788 + /* always largest timeout */
72789 + writew(0xfff, host->base + GLAMO_REG_MMC_TIMEOUT);
72790 +
72791 + /* Generate interrupt on txfer */
72792 + writew((readw(host->base + GLAMO_REG_MMC_BASIC) & 0x3e) |
72793 + 0x0800 | GLAMO_BASIC_MMC_NO_CLK_RD_WAIT |
72794 + GLAMO_BASIC_MMC_EN_COMPL_INT | (sd_drive << 6),
72795 + host->base + GLAMO_REG_MMC_BASIC);
72796 +
72797 + /* send the command out on the wire */
72798 + /* dev_info(&host->pdev->dev, "Using FIRE %04X\n", fire); */
72799 + writew(fire, host->base + GLAMO_REG_MMC_CMD_FIRE);
72800 + cmd->error = 0;
72801 + return 0;
72802 +}
72803 +
72804 +static int glamo_mci_prepare_pio(struct glamo_mci_host *host,
72805 + struct mmc_data *data)
72806 +{
72807 + /*
72808 + * the S-Media-internal RAM offset for our MMC buffer
72809 + * Read is halfway up the buffer and write is at the start
72810 + */
72811 + if (data->flags & MMC_DATA_READ) {
72812 + writew((u16)(GLAMO_FB_SIZE + (RESSIZE(host->mem_data) / 2)),
72813 + host->base + GLAMO_REG_MMC_WDATADS1);
72814 + writew((u16)((GLAMO_FB_SIZE +
72815 + (RESSIZE(host->mem_data) / 2)) >> 16),
72816 + host->base + GLAMO_REG_MMC_WDATADS2);
72817 + } else {
72818 + writew((u16)GLAMO_FB_SIZE, host->base +
72819 + GLAMO_REG_MMC_RDATADS1);
72820 + writew((u16)(GLAMO_FB_SIZE >> 16), host->base +
72821 + GLAMO_REG_MMC_RDATADS2);
72822 + }
72823 +
72824 + /* set up the block info */
72825 + writew(data->blksz, host->base + GLAMO_REG_MMC_DATBLKLEN);
72826 + writew(data->blocks, host->base + GLAMO_REG_MMC_DATBLKCNT);
72827 + dev_dbg(&host->pdev->dev, "(blksz=%d, count=%d)\n",
72828 + data->blksz, data->blocks);
72829 + host->pio_sgptr = 0;
72830 + host->pio_words = 0;
72831 + host->pio_count = 0;
72832 + host->pio_active = 0;
72833 + /* if write, prep the write into the shared RAM before the command */
72834 + if (data->flags & MMC_DATA_WRITE) {
72835 + host->pio_active = XFER_WRITE;
72836 + return do_pio_write(host);
72837 + }
72838 + host->pio_active = XFER_READ;
72839 + return 0;
72840 +}
72841 +
72842 +static void glamo_mci_send_request(struct mmc_host *mmc)
72843 +{
72844 + struct glamo_mci_host *host = mmc_priv(mmc);
72845 + struct mmc_request *mrq = host->mrq;
72846 + struct mmc_command *cmd = host->cmd_is_stop ? mrq->stop : mrq->cmd;
72847 + u16 * pu16 = (u16 *)&cmd->resp[0];
72848 + u16 * reg_resp = (u16 *)(host->base + GLAMO_REG_MMC_CMD_RSP1);
72849 + u16 status;
72850 + int n;
72851 + int timeout = 1000000;
72852 + int insanity_timeout = 1000000;
72853 +
72854 + if (host->suspending) {
72855 + dev_err(&host->pdev->dev, "IGNORING glamo_mci_send_request while "
72856 + "suspended\n");
72857 + cmd->error = -EIO;
72858 + if (cmd->data)
72859 + cmd->data->error = -EIO;
72860 + mmc_request_done(mmc, mrq);
72861 + return;
72862 + }
72863 +
72864 + host->ccnt++;
72865 + /*
72866 + * somehow 2.6.24 MCI manages to issue MMC_WRITE_BLOCK *without* the
72867 + * MMC_DATA_WRITE flag, WTF? Work around the madness.
72868 + */
72869 + if (cmd->opcode == MMC_WRITE_BLOCK)
72870 + if (mrq->data)
72871 + mrq->data->flags |= MMC_DATA_WRITE;
72872 +
72873 + /* this guy has data to read/write? */
72874 + if ((!host->cmd_is_stop) && cmd->data) {
72875 + int res;
72876 + host->dcnt++;
72877 + res = glamo_mci_prepare_pio(host, cmd->data);
72878 + if (res) {
72879 + cmd->error = -EIO;
72880 + cmd->data->error = -EIO;
72881 + mmc_request_done(mmc, mrq);
72882 + return;
72883 + }
72884 + }
72885 +
72886 + dev_dbg(&host->pdev->dev,"cmd 0x%x, "
72887 + "arg 0x%x data=%p mrq->stop=%p flags 0x%x\n",
72888 + cmd->opcode, cmd->arg, cmd->data, cmd->mrq->stop,
72889 + cmd->flags);
72890 +
72891 + /* resume requested clock rate
72892 + * scale it down by sd_slow_ratio if platform requests it
72893 + */
72894 + __glamo_mci_fix_card_div(host, host->clk_div);
72895 +
72896 + if (glamo_mci_send_command(host, cmd))
72897 + goto bail;
72898 +
72899 + /* we are deselecting card? because it isn't going to ack then... */
72900 + if ((cmd->opcode == 7) && (cmd->arg == 0))
72901 + goto done;
72902 +
72903 + /*
72904 + * we must spin until response is ready or timed out
72905 + * -- we don't get interrupts unless there is a bulk rx
72906 + */
72907 + do
72908 + status = readw(host->base + GLAMO_REG_MMC_RB_STAT1);
72909 + while (((((status >> 15) & 1) != (host->ccnt & 1)) ||
72910 + (!(status & (GLAMO_STAT1_MMC_RB_RRDY |
72911 + GLAMO_STAT1_MMC_RTOUT |
72912 + GLAMO_STAT1_MMC_DTOUT |
72913 + GLAMO_STAT1_MMC_BWERR |
72914 + GLAMO_STAT1_MMC_BRERR)))) && (insanity_timeout--));
72915 +
72916 + if (insanity_timeout < 0)
72917 + dev_info(&host->pdev->dev, "command timeout, continuing\n");
72918 +
72919 + if (status & (GLAMO_STAT1_MMC_RTOUT |
72920 + GLAMO_STAT1_MMC_DTOUT))
72921 + cmd->error = -ETIMEDOUT;
72922 + if (status & (GLAMO_STAT1_MMC_BWERR |
72923 + GLAMO_STAT1_MMC_BRERR))
72924 + cmd->error = -EILSEQ;
72925 +
72926 + if (host->cmd_is_stop)
72927 + goto bail;
72928 +
72929 + if (cmd->error) {
72930 + dev_info(&host->pdev->dev, "Error after cmd: 0x%x\n", status);
72931 + goto done;
72932 + }
72933 + /*
72934 + * mangle the response registers in two different exciting
72935 + * undocumented ways discovered by trial and error
72936 + */
72937 + if (mmc_resp_type(cmd) == MMC_RSP_R2)
72938 + /* grab the response */
72939 + for (n = 0; n < 8; n++) /* super mangle power 1 */
72940 + pu16[n ^ 6] = readw(&reg_resp[n]);
72941 + else
72942 + for (n = 0; n < 3; n++) /* super mangle power 2 */
72943 + pu16[n] = (readw(&reg_resp[n]) >> 8) |
72944 + (readw(&reg_resp[n + 1]) << 8);
72945 + /*
72946 + * if we don't have bulk data to take care of, we're done
72947 + */
72948 + if (!cmd->data)
72949 + goto done;
72950 + if (!(cmd->data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)))
72951 + goto done;
72952 +
72953 + /*
72954 + * Otherwise can can use the interrupt as async completion --
72955 + * if there is read data coming, or we wait for write data to complete,
72956 + * exit without mmc_request_done() as the payload interrupt
72957 + * will service it
72958 + */
72959 + dev_dbg(&host->pdev->dev, "Waiting for payload data\n");
72960 + /*
72961 + * if the glamo INT# line isn't wired (*cough* it can happen)
72962 + * I'm afraid we have to spin on the IRQ status bit and "be
72963 + * our own INT# line"
72964 + */
72965 + if (!glamo_mci_def_pdata.pglamo->irq_works) {
72966 + /*
72967 + * we have faith we will get an "interrupt"...
72968 + * but something insane like suspend problems can mean
72969 + * we spin here forever, so we timeout after a LONG time
72970 + */
72971 + while ((!(readw(glamo_mci_def_pdata.pglamo->base +
72972 + GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC)) &&
72973 + (timeout--))
72974 + ;
72975 +
72976 + if (timeout < 0) {
72977 + if (cmd->data->error)
72978 + cmd->data->error = -ETIMEDOUT;
72979 + dev_err(&host->pdev->dev, "Payload timeout\n");
72980 + goto bail;
72981 + }
72982 +
72983 + /* yay we are an interrupt controller! -- call the ISR
72984 + * it will stop clock to card
72985 + */
72986 + glamo_mci_irq_host(host);
72987 + }
72988 + return;
72989 +
72990 +done:
72991 + host->complete_what = COMPLETION_NONE;
72992 + host->mrq = NULL;
72993 + mmc_request_done(host->mmc, cmd->mrq);
72994 +bail:
72995 + if (!sd_idleclk && !host->force_slow_during_powerup)
72996 + /* stop the clock to card */
72997 + __glamo_mci_fix_card_div(host, -1);
72998 +}
72999 +
73000 +static void glamo_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
73001 +{
73002 + struct glamo_mci_host *host = mmc_priv(mmc);
73003 +
73004 + host->cmd_is_stop = 0;
73005 + host->mrq = mrq;
73006 + glamo_mci_send_request(mmc);
73007 +}
73008 +
73009 +#if 1
73010 +static void glamo_mci_reset(struct glamo_mci_host *host)
73011 +{
73012 + if (host->suspending) {
73013 + dev_err(&host->pdev->dev, "IGNORING glamo_mci_reset while "
73014 + "suspended\n");
73015 + return;
73016 + }
73017 + dev_dbg(&host->pdev->dev, "******* glamo_mci_reset\n");
73018 + /* reset MMC controller */
73019 + writew(GLAMO_CLOCK_MMC_RESET | GLAMO_CLOCK_MMC_DG_TCLK |
73020 + GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |
73021 + GLAMO_CLOCK_MMC_EN_M9CLK,
73022 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_MMC);
73023 + udelay(10);
73024 + /* and disable reset */
73025 + writew(GLAMO_CLOCK_MMC_DG_TCLK |
73026 + GLAMO_CLOCK_MMC_EN_TCLK | GLAMO_CLOCK_MMC_DG_M9CLK |
73027 + GLAMO_CLOCK_MMC_EN_M9CLK,
73028 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_CLOCK_MMC);
73029 +}
73030 +#endif
73031 +static inline int glamo_mci_get_mv(int vdd)
73032 +{
73033 + int mv = 1650;
73034 +
73035 + if (vdd > 7)
73036 + mv += 350 + 100 * (vdd - 8);
73037 +
73038 + return mv;
73039 +}
73040 +
73041 +static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
73042 +{
73043 + struct glamo_mci_host *host = mmc_priv(mmc);
73044 + struct regulator *regulator;
73045 + int n = 0;
73046 + int div;
73047 + int powering = 0;
73048 + int mv;
73049 +
73050 + if (host->suspending) {
73051 + dev_err(&host->pdev->dev, "IGNORING glamo_mci_set_ios while "
73052 + "suspended\n");
73053 + return;
73054 + }
73055 +
73056 + regulator = host->regulator;
73057 +
73058 + /* Set power */
73059 + switch(ios->power_mode) {
73060 + case MMC_POWER_UP:
73061 + if (host->pdata->glamo_can_set_mci_power()) {
73062 + mv = glamo_mci_get_mv(ios->vdd);
73063 + regulator_set_voltage(regulator, mv * 1000, mv * 1000);
73064 + regulator_enable(regulator);
73065 + }
73066 + break;
73067 + case MMC_POWER_ON:
73068 + /*
73069 + * we should use very slow clock until first bulk
73070 + * transfer completes OK
73071 + */
73072 + host->force_slow_during_powerup = 1;
73073 +
73074 + if (host->vdd_current != ios->vdd) {
73075 + if (host->pdata->glamo_can_set_mci_power()) {
73076 + mv = glamo_mci_get_mv(ios->vdd);
73077 + regulator_set_voltage(regulator, mv * 1000, mv * 1000);
73078 + printk(KERN_INFO "SD power -> %dmV\n", mv);
73079 + }
73080 + host->vdd_current = ios->vdd;
73081 + }
73082 + if (host->power_mode_current == MMC_POWER_OFF) {
73083 + glamo_engine_enable(glamo_mci_def_pdata.pglamo,
73084 + GLAMO_ENGINE_MMC);
73085 + powering = 1;
73086 + }
73087 + break;
73088 +
73089 + case MMC_POWER_OFF:
73090 + default:
73091 + if (host->power_mode_current == MMC_POWER_OFF)
73092 + break;
73093 + /* never want clocking with dead card */
73094 + __glamo_mci_fix_card_div(host, -1);
73095 +
73096 + glamo_engine_disable(glamo_mci_def_pdata.pglamo,
73097 + GLAMO_ENGINE_MMC);
73098 + regulator_disable(regulator);
73099 + host->vdd_current = -1;
73100 + break;
73101 + }
73102 + host->power_mode_current = ios->power_mode;
73103 +
73104 + host->real_rate = __glamo_mci_set_card_clock(host, ios->clock, &div);
73105 + host->clk_div = div;
73106 +
73107 + /* after power-up, we are meant to give it >= 74 clocks so it can
73108 + * initialize itself. Doubt any modern cards need it but anyway...
73109 + */
73110 + if (powering)
73111 + mdelay(1);
73112 +
73113 + if (!sd_idleclk && !host->force_slow_during_powerup)
73114 + /* stop the clock to card, because we are idle until transfer */
73115 + __glamo_mci_fix_card_div(host, -1);
73116 +
73117 + if ((ios->power_mode == MMC_POWER_ON) ||
73118 + (ios->power_mode == MMC_POWER_UP)) {
73119 + dev_info(&host->pdev->dev,
73120 + "powered (vdd = %d) clk: %lukHz div=%d (req: %ukHz). "
73121 + "Bus width=%d\n",(int)ios->vdd,
73122 + host->real_rate / 1000, (int)host->clk_div,
73123 + ios->clock / 1000, (int)ios->bus_width);
73124 + } else
73125 + dev_info(&host->pdev->dev, "glamo_mci_set_ios: power down.\n");
73126 +
73127 + /* set bus width */
73128 + host->bus_width = ios->bus_width;
73129 + if (host->bus_width == MMC_BUS_WIDTH_4)
73130 + n = GLAMO_BASIC_MMC_EN_4BIT_DATA;
73131 + writew((readw(host->base + GLAMO_REG_MMC_BASIC) &
73132 + (~(GLAMO_BASIC_MMC_EN_4BIT_DATA |
73133 + GLAMO_BASIC_MMC_EN_DR_STR0 |
73134 + GLAMO_BASIC_MMC_EN_DR_STR1))) | n |
73135 + sd_drive << 6, host->base + GLAMO_REG_MMC_BASIC);
73136 +}
73137 +
73138 +
73139 +/*
73140 + * no physical write protect supported by us
73141 + */
73142 +static int glamo_mci_get_ro(struct mmc_host *mmc)
73143 +{
73144 + return 0;
73145 +}
73146 +
73147 +static struct mmc_host_ops glamo_mci_ops = {
73148 + .request = glamo_mci_request,
73149 + .set_ios = glamo_mci_set_ios,
73150 + .get_ro = glamo_mci_get_ro,
73151 +};
73152 +
73153 +static int glamo_mci_probe(struct platform_device *pdev)
73154 +{
73155 + struct mmc_host *mmc;
73156 + struct glamo_mci_host *host;
73157 + int ret;
73158 +
73159 + dev_info(&pdev->dev, "glamo_mci driver (C)2007 Openmoko, Inc\n");
73160 +
73161 + mmc = mmc_alloc_host(sizeof(struct glamo_mci_host), &pdev->dev);
73162 + if (!mmc) {
73163 + ret = -ENOMEM;
73164 + goto probe_out;
73165 + }
73166 +
73167 + host = mmc_priv(mmc);
73168 + host->mmc = mmc;
73169 + host->pdev = pdev;
73170 + host->pdata = &glamo_mci_def_pdata;
73171 + host->power_mode_current = MMC_POWER_OFF;
73172 +
73173 + host->complete_what = COMPLETION_NONE;
73174 + host->pio_active = XFER_NONE;
73175 +
73176 + spin_lock_init(&host->complete_lock);
73177 + INIT_WORK(&host->irq_work, glamo_mci_irq_worker);
73178 +
73179 + host->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
73180 + if (!host->mem) {
73181 + dev_err(&pdev->dev,
73182 + "failed to get io memory region resouce.\n");
73183 +
73184 + ret = -ENOENT;
73185 + goto probe_free_host;
73186 + }
73187 +
73188 + host->mem = request_mem_region(host->mem->start,
73189 + RESSIZE(host->mem), pdev->name);
73190 +
73191 + if (!host->mem) {
73192 + dev_err(&pdev->dev, "failed to request io memory region.\n");
73193 + ret = -ENOENT;
73194 + goto probe_free_host;
73195 + }
73196 +
73197 + host->base = ioremap(host->mem->start, RESSIZE(host->mem));
73198 + if (!host->base) {
73199 + dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
73200 + ret = -EINVAL;
73201 + goto probe_free_mem_region;
73202 + }
73203 +
73204 + host->regulator = regulator_get(&pdev->dev, "SD_3V3");
73205 + if (!host->regulator) {
73206 + dev_err(&pdev->dev, "Cannot proceed without regulator.\n");
73207 + return -ENODEV;
73208 + }
73209 +
73210 + /* set the handler for our bit of the shared chip irq register */
73211 + set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_MMC), glamo_mci_irq);
73212 + /* stash host as our handler's private data */
73213 + set_irq_data(IRQ_GLAMO(GLAMO_IRQIDX_MMC), host);
73214 +
73215 + /* Get ahold of our data buffer we use for data in and out on MMC */
73216 + host->mem_data = platform_get_resource(pdev, IORESOURCE_MEM, 1);
73217 + if (!host->mem_data) {
73218 + dev_err(&pdev->dev,
73219 + "failed to get io memory region resource.\n");
73220 + ret = -ENOENT;
73221 + goto probe_iounmap;
73222 + }
73223 +
73224 + host->mem_data = request_mem_region(host->mem_data->start,
73225 + RESSIZE(host->mem_data), pdev->name);
73226 +
73227 + if (!host->mem_data) {
73228 + dev_err(&pdev->dev, "failed to request io memory region.\n");
73229 + ret = -ENOENT;
73230 + goto probe_iounmap;
73231 + }
73232 + host->base_data = ioremap(host->mem_data->start,
73233 + RESSIZE(host->mem_data));
73234 + host->data_max_size = RESSIZE(host->mem_data);
73235 +
73236 + if (host->base_data == 0) {
73237 + dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
73238 + ret = -EINVAL;
73239 + goto probe_free_mem_region_data;
73240 + }
73241 +
73242 + host->vdd_current = 0;
73243 + host->clk_rate = 50000000; /* really it's 49152000 */
73244 + host->clk_div = 16;
73245 +
73246 + /* explain our host controller capabilities */
73247 + mmc->ops = &glamo_mci_ops;
73248 + mmc->ocr_avail = host->pdata->ocr_avail;
73249 + mmc->caps = MMC_CAP_4_BIT_DATA |
73250 + MMC_CAP_MMC_HIGHSPEED |
73251 + MMC_CAP_SD_HIGHSPEED;
73252 + mmc->f_min = host->clk_rate / 256;
73253 + mmc->f_max = sd_max_clk;
73254 +
73255 + mmc->max_blk_count = (1 << 16) - 1; /* GLAMO_REG_MMC_RB_BLKCNT */
73256 + mmc->max_blk_size = (1 << 12) - 1; /* GLAMO_REG_MMC_RB_BLKLEN */
73257 + mmc->max_req_size = RESSIZE(host->mem_data) / 2;
73258 + mmc->max_seg_size = mmc->max_req_size;
73259 + mmc->max_phys_segs = 1; /* hw doesn't talk about segs??? */
73260 + mmc->max_hw_segs = 1;
73261 +
73262 + dev_info(&host->pdev->dev, "probe: mapped mci_base:%p irq:%u.\n",
73263 + host->base, host->irq);
73264 +
73265 + platform_set_drvdata(pdev, mmc);
73266 +
73267 + glamo_engine_enable(glamo_mci_def_pdata.pglamo, GLAMO_ENGINE_MMC);
73268 + glamo_mci_reset(host);
73269 +
73270 + if ((ret = mmc_add_host(mmc))) {
73271 + dev_err(&pdev->dev, "failed to add mmc host.\n");
73272 + goto probe_free_mem_region_data;
73273 + }
73274 +
73275 + dev_info(&pdev->dev,"initialisation done.\n");
73276 + return 0;
73277 +
73278 + probe_free_mem_region_data:
73279 + release_mem_region(host->mem_data->start, RESSIZE(host->mem_data));
73280 +
73281 + probe_iounmap:
73282 + iounmap(host->base);
73283 +
73284 + probe_free_mem_region:
73285 + release_mem_region(host->mem->start, RESSIZE(host->mem));
73286 +
73287 + probe_free_host:
73288 + mmc_free_host(mmc);
73289 + probe_out:
73290 + return ret;
73291 +}
73292 +
73293 +static int glamo_mci_remove(struct platform_device *pdev)
73294 +{
73295 + struct mmc_host *mmc = platform_get_drvdata(pdev);
73296 + struct glamo_mci_host *host = mmc_priv(mmc);
73297 + struct regulator *regulator;
73298 +
73299 + mmc_remove_host(mmc);
73300 + /* stop using our handler, revert it to default */
73301 + set_irq_handler(IRQ_GLAMO(GLAMO_IRQIDX_MMC), handle_level_irq);
73302 + iounmap(host->base);
73303 + iounmap(host->base_data);
73304 + release_mem_region(host->mem->start, RESSIZE(host->mem));
73305 + release_mem_region(host->mem_data->start, RESSIZE(host->mem_data));
73306 +
73307 + regulator = host->regulator;
73308 + regulator_put(regulator);
73309 +
73310 + mmc_free_host(mmc);
73311 +
73312 + glamo_engine_disable(glamo_mci_def_pdata.pglamo, GLAMO_ENGINE_MMC);
73313 + return 0;
73314 +}
73315 +
73316 +
73317 +#ifdef CONFIG_PM
73318 +
73319 +static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)
73320 +{
73321 + struct mmc_host *mmc = platform_get_drvdata(dev);
73322 + struct glamo_mci_host *host = mmc_priv(mmc);
73323 + int ret;
73324 +
73325 + cancel_work_sync(&host->irq_work);
73326 +
73327 + /*
73328 + * possible workaround for SD corruption during suspend - resume
73329 + * make sure the clock was running during suspend and consequently
73330 + * resume
73331 + */
73332 + __glamo_mci_fix_card_div(host, host->clk_div);
73333 +
73334 + /* we are going to do more commands to override this in
73335 + * mmc_suspend_host(), so we need to change sd_idleclk for the
73336 + * duration as well
73337 + */
73338 + suspend_sd_idleclk = sd_idleclk;
73339 + sd_idleclk = 1;
73340 +
73341 + ret = mmc_suspend_host(mmc, state);
73342 +
73343 + host->suspending++;
73344 + /* so that when we resume, we use any modified max rate */
73345 + mmc->f_max = sd_max_clk;
73346 +
73347 + return ret;
73348 +}
73349 +
73350 +int glamo_mci_resume(struct platform_device *dev)
73351 +{
73352 + struct mmc_host *mmc = platform_get_drvdata(dev);
73353 + struct glamo_mci_host *host = mmc_priv(mmc);
73354 + int ret;
73355 +
73356 + sd_idleclk = 1;
73357 +
73358 + glamo_engine_enable(host->pdata->pglamo, GLAMO_ENGINE_MMC);
73359 + glamo_mci_reset(host);
73360 +
73361 + host->suspending--;
73362 +
73363 + ret = mmc_resume_host(mmc);
73364 +
73365 + /* put sd_idleclk back to pre-suspend state */
73366 + sd_idleclk = suspend_sd_idleclk;
73367 +
73368 + return ret;
73369 +}
73370 +EXPORT_SYMBOL_GPL(glamo_mci_resume);
73371 +
73372 +#else /* CONFIG_PM */
73373 +#define glamo_mci_suspend NULL
73374 +#define glamo_mci_resume NULL
73375 +#endif /* CONFIG_PM */
73376 +
73377 +
73378 +static struct platform_driver glamo_mci_driver =
73379 +{
73380 + .driver.name = "glamo-mci",
73381 + .probe = glamo_mci_probe,
73382 + .remove = glamo_mci_remove,
73383 + .suspend = glamo_mci_suspend,
73384 + .resume = glamo_mci_resume,
73385 +};
73386 +
73387 +static int __init glamo_mci_init(void)
73388 +{
73389 + spin_lock_init(&clock_lock);
73390 + platform_driver_register(&glamo_mci_driver);
73391 + return 0;
73392 +}
73393 +
73394 +static void __exit glamo_mci_exit(void)
73395 +{
73396 + platform_driver_unregister(&glamo_mci_driver);
73397 +}
73398 +
73399 +module_init(glamo_mci_init);
73400 +module_exit(glamo_mci_exit);
73401 +
73402 +MODULE_DESCRIPTION("Glamo MMC/SD Card Interface driver");
73403 +MODULE_LICENSE("GPL");
73404 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
73405 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-mci.h linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-mci.h
73406 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-mci.h 1970-01-01 01:00:00.000000000 +0100
73407 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-mci.h 2009-05-10 22:28:00.000000000 +0200
73408 @@ -0,0 +1,84 @@
73409 +/*
73410 + * linux/drivers/mmc/host/glamo-mmc.h - GLAMO MCI driver
73411 + *
73412 + * Copyright (C) 2007-2008 Openmoko, Inc, Andy Green <andy@openmoko.com>
73413 + * based on S3C MMC driver -->
73414 + * Copyright (C) 2004-2006 Thomas Kleffel, All Rights Reserved.
73415 + *
73416 + * This program is free software; you can redistribute it and/or modify
73417 + * it under the terms of the GNU General Public License version 2 as
73418 + * published by the Free Software Foundation.
73419 + */
73420 +
73421 +#include <linux/regulator/consumer.h>
73422 +
73423 +enum glamo_mci_waitfor {
73424 + COMPLETION_NONE,
73425 + COMPLETION_FINALIZE,
73426 + COMPLETION_CMDSENT,
73427 + COMPLETION_RSPFIN,
73428 + COMPLETION_XFERFINISH,
73429 + COMPLETION_XFERFINISH_RSPFIN,
73430 +};
73431 +
73432 +struct glamo_mci_host {
73433 + struct platform_device *pdev;
73434 + struct glamo_mci_pdata *pdata;
73435 + struct mmc_host *mmc;
73436 + struct resource *mem;
73437 + struct resource *mem_data;
73438 + struct clk *clk;
73439 + void __iomem *base;
73440 + u16 __iomem *base_data;
73441 + int irq;
73442 + int irq_cd;
73443 + int dma;
73444 + int data_max_size;
73445 +
73446 + int suspending;
73447 +
73448 + int power_mode_current;
73449 + unsigned int vdd_current;
73450 +
73451 + unsigned long clk_rate;
73452 + unsigned long clk_div;
73453 + unsigned long real_rate;
73454 + u8 prescaler;
73455 +
73456 + int force_slow_during_powerup;
73457 +
73458 + unsigned sdiimsk;
73459 + int dodma;
73460 +
73461 + volatile int dmatogo;
73462 +
73463 + struct mmc_request *mrq;
73464 + int cmd_is_stop;
73465 + struct work_struct irq_work;
73466 +
73467 + spinlock_t complete_lock;
73468 + volatile enum glamo_mci_waitfor
73469 + complete_what;
73470 +
73471 + volatile int dma_complete;
73472 +
73473 + volatile u32 pio_sgptr;
73474 + volatile u32 pio_words;
73475 + volatile u32 pio_count;
73476 + volatile u16 *pio_ptr;
73477 +#define XFER_NONE 0
73478 +#define XFER_READ 1
73479 +#define XFER_WRITE 2
73480 + volatile u32 pio_active;
73481 +
73482 + int bus_width;
73483 +
73484 + char dbgmsg_cmd[301];
73485 + char dbgmsg_dat[301];
73486 + volatile char *status;
73487 +
73488 + unsigned int ccnt, dcnt;
73489 + struct tasklet_struct pio_tasklet;
73490 +
73491 + struct regulator *regulator;
73492 +};
73493 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-regs.h linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-regs.h
73494 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-regs.h 1970-01-01 01:00:00.000000000 +0100
73495 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-regs.h 2009-05-10 22:28:00.000000000 +0200
73496 @@ -0,0 +1,632 @@
73497 +#ifndef _GLAMO_REGS_H
73498 +#define _GLAMO_REGS_H
73499 +
73500 +/* Smedia Glamo 336x/337x driver
73501 + *
73502 + * (C) 2007 by Openmoko, Inc.
73503 + * Author: Harald Welte <laforge@openmoko.org>
73504 + * All rights reserved.
73505 + *
73506 + * This program is free software; you can redistribute it and/or
73507 + * modify it under the terms of the GNU General Public License as
73508 + * published by the Free Software Foundation; either version 2 of
73509 + * the License, or (at your option) any later version.
73510 + *
73511 + * This program is distributed in the hope that it will be useful,
73512 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
73513 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
73514 + * GNU General Public License for more details.
73515 + *
73516 + * You should have received a copy of the GNU General Public License
73517 + * along with this program; if not, write to the Free Software
73518 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
73519 + * MA 02111-1307 USA
73520 + */
73521 +
73522 +enum glamo_regster_offsets {
73523 + GLAMO_REGOFS_GENERIC = 0x0000,
73524 + GLAMO_REGOFS_HOSTBUS = 0x0200,
73525 + GLAMO_REGOFS_MEMORY = 0x0300,
73526 + GLAMO_REGOFS_VIDCAP = 0x0400,
73527 + GLAMO_REGOFS_ISP = 0x0500,
73528 + GLAMO_REGOFS_JPEG = 0x0800,
73529 + GLAMO_REGOFS_MPEG = 0x0c00,
73530 + GLAMO_REGOFS_LCD = 0x1100,
73531 + GLAMO_REGOFS_MMC = 0x1400,
73532 + GLAMO_REGOFS_MPROC0 = 0x1500,
73533 + GLAMO_REGOFS_MPROC1 = 0x1580,
73534 + GLAMO_REGOFS_CMDQUEUE = 0x1600,
73535 + GLAMO_REGOFS_RISC = 0x1680,
73536 + GLAMO_REGOFS_2D = 0x1700,
73537 + GLAMO_REGOFS_3D = 0x1b00,
73538 + GLAMO_REGOFS_END = 0x2400,
73539 +};
73540 +
73541 +
73542 +enum glamo_register_generic {
73543 + GLAMO_REG_GCONF1 = 0x0000,
73544 + GLAMO_REG_GCONF2 = 0x0002,
73545 +#define GLAMO_REG_DEVICE_ID GLAMO_REG_GCONF2
73546 + GLAMO_REG_GCONF3 = 0x0004,
73547 +#define GLAMO_REG_REVISION_ID GLAMO_REG_GCONF3
73548 + GLAMO_REG_IRQ_GEN1 = 0x0006,
73549 +#define GLAMO_REG_IRQ_ENABLE GLAMO_REG_IRQ_GEN1
73550 + GLAMO_REG_IRQ_GEN2 = 0x0008,
73551 +#define GLAMO_REG_IRQ_SET GLAMO_REG_IRQ_GEN2
73552 + GLAMO_REG_IRQ_GEN3 = 0x000a,
73553 +#define GLAMO_REG_IRQ_CLEAR GLAMO_REG_IRQ_GEN3
73554 + GLAMO_REG_IRQ_GEN4 = 0x000c,
73555 +#define GLAMO_REG_IRQ_STATUS GLAMO_REG_IRQ_GEN4
73556 + GLAMO_REG_CLOCK_HOST = 0x0010,
73557 + GLAMO_REG_CLOCK_MEMORY = 0x0012,
73558 + GLAMO_REG_CLOCK_LCD = 0x0014,
73559 + GLAMO_REG_CLOCK_MMC = 0x0016,
73560 + GLAMO_REG_CLOCK_ISP = 0x0018,
73561 + GLAMO_REG_CLOCK_JPEG = 0x001a,
73562 + GLAMO_REG_CLOCK_3D = 0x001c,
73563 + GLAMO_REG_CLOCK_2D = 0x001e,
73564 + GLAMO_REG_CLOCK_RISC1 = 0x0020, /* 3365 only? */
73565 + GLAMO_REG_CLOCK_RISC2 = 0x0022, /* 3365 only? */
73566 + GLAMO_REG_CLOCK_MPEG = 0x0024,
73567 + GLAMO_REG_CLOCK_MPROC = 0x0026,
73568 +
73569 + GLAMO_REG_CLOCK_GEN5_1 = 0x0030,
73570 + GLAMO_REG_CLOCK_GEN5_2 = 0x0032,
73571 + GLAMO_REG_CLOCK_GEN6 = 0x0034,
73572 + GLAMO_REG_CLOCK_GEN7 = 0x0036,
73573 + GLAMO_REG_CLOCK_GEN8 = 0x0038,
73574 + GLAMO_REG_CLOCK_GEN9 = 0x003a,
73575 + GLAMO_REG_CLOCK_GEN10 = 0x003c,
73576 + GLAMO_REG_CLOCK_GEN11 = 0x003e,
73577 + GLAMO_REG_PLL_GEN1 = 0x0040,
73578 + GLAMO_REG_PLL_GEN2 = 0x0042,
73579 + GLAMO_REG_PLL_GEN3 = 0x0044,
73580 + GLAMO_REG_PLL_GEN4 = 0x0046,
73581 + GLAMO_REG_PLL_GEN5 = 0x0048,
73582 + GLAMO_REG_GPIO_GEN1 = 0x0050,
73583 + GLAMO_REG_GPIO_GEN2 = 0x0052,
73584 + GLAMO_REG_GPIO_GEN3 = 0x0054,
73585 + GLAMO_REG_GPIO_GEN4 = 0x0056,
73586 + GLAMO_REG_GPIO_GEN5 = 0x0058,
73587 + GLAMO_REG_GPIO_GEN6 = 0x005a,
73588 + GLAMO_REG_GPIO_GEN7 = 0x005c,
73589 + GLAMO_REG_GPIO_GEN8 = 0x005e,
73590 + GLAMO_REG_GPIO_GEN9 = 0x0060,
73591 + GLAMO_REG_GPIO_GEN10 = 0x0062,
73592 + GLAMO_REG_DFT_GEN1 = 0x0070,
73593 + GLAMO_REG_DFT_GEN2 = 0x0072,
73594 + GLAMO_REG_DFT_GEN3 = 0x0074,
73595 + GLAMO_REG_DFT_GEN4 = 0x0076,
73596 +
73597 + GLAMO_REG_DFT_GEN5 = 0x01e0,
73598 + GLAMO_REG_DFT_GEN6 = 0x01f0,
73599 +};
73600 +
73601 +#define GLAMO_REG_HOSTBUS(x) (GLAMO_REGOFS_HOSTBUS-2+(x*2))
73602 +
73603 +#define REG_MEM(x) (GLAMO_REGOFS_MEMORY+(x))
73604 +#define GLAMO_REG_MEM_TIMING(x) (GLAMO_REG_MEM_TIMING1-2+(x*2))
73605 +
73606 +enum glamo_register_mem {
73607 + GLAMO_REG_MEM_TYPE = REG_MEM(0x00),
73608 + GLAMO_REG_MEM_GEN = REG_MEM(0x02),
73609 + GLAMO_REG_MEM_TIMING1 = REG_MEM(0x04),
73610 + GLAMO_REG_MEM_TIMING2 = REG_MEM(0x06),
73611 + GLAMO_REG_MEM_TIMING3 = REG_MEM(0x08),
73612 + GLAMO_REG_MEM_TIMING4 = REG_MEM(0x0a),
73613 + GLAMO_REG_MEM_TIMING5 = REG_MEM(0x0c),
73614 + GLAMO_REG_MEM_TIMING6 = REG_MEM(0x0e),
73615 + GLAMO_REG_MEM_TIMING7 = REG_MEM(0x10),
73616 + GLAMO_REG_MEM_TIMING8 = REG_MEM(0x12),
73617 + GLAMO_REG_MEM_TIMING9 = REG_MEM(0x14),
73618 + GLAMO_REG_MEM_TIMING10 = REG_MEM(0x16),
73619 + GLAMO_REG_MEM_TIMING11 = REG_MEM(0x18),
73620 + GLAMO_REG_MEM_POWER1 = REG_MEM(0x1a),
73621 + GLAMO_REG_MEM_POWER2 = REG_MEM(0x1c),
73622 + GLAMO_REG_MEM_LCD_BUF1 = REG_MEM(0x1e),
73623 + GLAMO_REG_MEM_LCD_BUF2 = REG_MEM(0x20),
73624 + GLAMO_REG_MEM_LCD_BUF3 = REG_MEM(0x22),
73625 + GLAMO_REG_MEM_LCD_BUF4 = REG_MEM(0x24),
73626 + GLAMO_REG_MEM_BIST1 = REG_MEM(0x26),
73627 + GLAMO_REG_MEM_BIST2 = REG_MEM(0x28),
73628 + GLAMO_REG_MEM_BIST3 = REG_MEM(0x2a),
73629 + GLAMO_REG_MEM_BIST4 = REG_MEM(0x2c),
73630 + GLAMO_REG_MEM_BIST5 = REG_MEM(0x2e),
73631 + GLAMO_REG_MEM_MAH1 = REG_MEM(0x30),
73632 + GLAMO_REG_MEM_MAH2 = REG_MEM(0x32),
73633 + GLAMO_REG_MEM_DRAM1 = REG_MEM(0x34),
73634 + GLAMO_REG_MEM_DRAM2 = REG_MEM(0x36),
73635 + GLAMO_REG_MEM_CRC = REG_MEM(0x38),
73636 +};
73637 +
73638 +#define GLAMO_MEM_TYPE_MASK 0x03
73639 +
73640 +enum glamo_reg_mem_dram1 {
73641 + /* b0 - b10 == refresh period, 1 -> 2048 clocks */
73642 + GLAMO_MEM_DRAM1_EN_GATE_CLK = (1 << 11),
73643 + GLAMO_MEM_DRAM1_SELF_REFRESH = (1 << 12),
73644 + GLAMO_MEM_DRAM1_EN_GATE_CKE = (1 << 13),
73645 + GLAMO_MEM_DRAM1_EN_DRAM_REFRESH = (1 << 14),
73646 + GLAMO_MEM_DRAM1_EN_MODEREG_SET = (1 << 15),
73647 +};
73648 +
73649 +enum glamo_reg_mem_dram2 {
73650 + GLAMO_MEM_DRAM2_DEEP_PWRDOWN = (1 << 12),
73651 +};
73652 +
73653 +enum glamo_irq_index {
73654 + GLAMO_IRQIDX_HOSTBUS = 0,
73655 + GLAMO_IRQIDX_JPEG = 1,
73656 + GLAMO_IRQIDX_MPEG = 2,
73657 + GLAMO_IRQIDX_MPROC1 = 3,
73658 + GLAMO_IRQIDX_MPROC0 = 4,
73659 + GLAMO_IRQIDX_CMDQUEUE = 5,
73660 + GLAMO_IRQIDX_2D = 6,
73661 + GLAMO_IRQIDX_MMC = 7,
73662 + GLAMO_IRQIDX_RISC = 8,
73663 +};
73664 +
73665 +enum glamo_irq {
73666 + GLAMO_IRQ_HOSTBUS = (1 << GLAMO_IRQIDX_HOSTBUS),
73667 + GLAMO_IRQ_JPEG = (1 << GLAMO_IRQIDX_JPEG),
73668 + GLAMO_IRQ_MPEG = (1 << GLAMO_IRQIDX_MPEG),
73669 + GLAMO_IRQ_MPROC1 = (1 << GLAMO_IRQIDX_MPROC1),
73670 + GLAMO_IRQ_MPROC0 = (1 << GLAMO_IRQIDX_MPROC0),
73671 + GLAMO_IRQ_CMDQUEUE = (1 << GLAMO_IRQIDX_CMDQUEUE),
73672 + GLAMO_IRQ_2D = (1 << GLAMO_IRQIDX_2D),
73673 + GLAMO_IRQ_MMC = (1 << GLAMO_IRQIDX_MMC),
73674 + GLAMO_IRQ_RISC = (1 << GLAMO_IRQIDX_RISC),
73675 +};
73676 +
73677 +enum glamo_reg_clock_host {
73678 + GLAMO_CLOCK_HOST_DG_BCLK = 0x0001,
73679 + GLAMO_CLOCK_HOST_DG_M0CLK = 0x0004,
73680 + GLAMO_CLOCK_HOST_RESET = 0x1000,
73681 +};
73682 +
73683 +enum glamo_reg_clock_mem {
73684 + GLAMO_CLOCK_MEM_DG_M1CLK = 0x0001,
73685 + GLAMO_CLOCK_MEM_EN_M1CLK = 0x0002,
73686 + GLAMO_CLOCK_MEM_DG_MOCACLK = 0x0004,
73687 + GLAMO_CLOCK_MEM_EN_MOCACLK = 0x0008,
73688 + GLAMO_CLOCK_MEM_RESET = 0x1000,
73689 + GLAMO_CLOCK_MOCA_RESET = 0x2000,
73690 +};
73691 +
73692 +enum glamo_reg_clock_lcd {
73693 + GLAMO_CLOCK_LCD_DG_DCLK = 0x0001,
73694 + GLAMO_CLOCK_LCD_EN_DCLK = 0x0002,
73695 + GLAMO_CLOCK_LCD_DG_DMCLK = 0x0004,
73696 + GLAMO_CLOCK_LCD_EN_DMCLK = 0x0008,
73697 + //
73698 + GLAMO_CLOCK_LCD_EN_DHCLK = 0x0020,
73699 + GLAMO_CLOCK_LCD_DG_M5CLK = 0x0040,
73700 + GLAMO_CLOCK_LCD_EN_M5CLK = 0x0080,
73701 + GLAMO_CLOCK_LCD_RESET = 0x1000,
73702 +};
73703 +
73704 +enum glamo_reg_clock_mmc {
73705 + GLAMO_CLOCK_MMC_DG_TCLK = 0x0001,
73706 + GLAMO_CLOCK_MMC_EN_TCLK = 0x0002,
73707 + GLAMO_CLOCK_MMC_DG_M9CLK = 0x0004,
73708 + GLAMO_CLOCK_MMC_EN_M9CLK = 0x0008,
73709 + GLAMO_CLOCK_MMC_RESET = 0x1000,
73710 +};
73711 +
73712 +enum glamo_reg_basic_mmc {
73713 + /* set to disable CRC error rejection */
73714 + GLAMO_BASIC_MMC_DISABLE_CRC = 0x0001,
73715 + /* enable completion interrupt */
73716 + GLAMO_BASIC_MMC_EN_COMPL_INT = 0x0002,
73717 + /* stop MMC clock while enforced idle waiting for data from card */
73718 + GLAMO_BASIC_MMC_NO_CLK_RD_WAIT = 0x0004,
73719 + /* 0 = 1-bit bus to card, 1 = use 4-bit bus (has to be negotiated) */
73720 + GLAMO_BASIC_MMC_EN_4BIT_DATA = 0x0008,
73721 + /* enable 75K pullups on D3..D0 */
73722 + GLAMO_BASIC_MMC_EN_DATA_PUPS = 0x0010,
73723 + /* enable 75K pullup on CMD */
73724 + GLAMO_BASIC_MMC_EN_CMD_PUP = 0x0020,
73725 + /* IO drive strength 00=weak -> 11=strongest */
73726 + GLAMO_BASIC_MMC_EN_DR_STR0 = 0x0040,
73727 + GLAMO_BASIC_MMC_EN_DR_STR1 = 0x0080,
73728 + /* TCLK delay stage A, 0000 = 500ps --> 1111 = 8ns */
73729 + GLAMO_BASIC_MMC_EN_TCLK_DLYA0 = 0x0100,
73730 + GLAMO_BASIC_MMC_EN_TCLK_DLYA1 = 0x0200,
73731 + GLAMO_BASIC_MMC_EN_TCLK_DLYA2 = 0x0400,
73732 + GLAMO_BASIC_MMC_EN_TCLK_DLYA3 = 0x0800,
73733 + /* TCLK delay stage B (cumulative), 0000 = 500ps --> 1111 = 8ns */
73734 + GLAMO_BASIC_MMC_EN_TCLK_DLYB0 = 0x1000,
73735 + GLAMO_BASIC_MMC_EN_TCLK_DLYB1 = 0x2000,
73736 + GLAMO_BASIC_MMC_EN_TCLK_DLYB2 = 0x4000,
73737 + GLAMO_BASIC_MMC_EN_TCLK_DLYB3 = 0x8000,
73738 +};
73739 +
73740 +enum glamo_reg_stat1_mmc {
73741 + /* command "counter" (really: toggle) */
73742 + GLAMO_STAT1_MMC_CMD_CTR = 0x8000,
73743 + /* engine is idle */
73744 + GLAMO_STAT1_MMC_IDLE = 0x4000,
73745 + /* readback response is ready */
73746 + GLAMO_STAT1_MMC_RB_RRDY = 0x0200,
73747 + /* readback data is ready */
73748 + GLAMO_STAT1_MMC_RB_DRDY = 0x0100,
73749 + /* no response timeout */
73750 + GLAMO_STAT1_MMC_RTOUT = 0x0020,
73751 + /* no data timeout */
73752 + GLAMO_STAT1_MMC_DTOUT = 0x0010,
73753 + /* CRC error on block write */
73754 + GLAMO_STAT1_MMC_BWERR = 0x0004,
73755 + /* CRC error on block read */
73756 + GLAMO_STAT1_MMC_BRERR = 0x0002
73757 +};
73758 +
73759 +enum glamo_reg_fire_mmc {
73760 + /* command "counter" (really: toggle)
73761 + * the STAT1 register reflects this so you can ensure you don't look
73762 + * at status for previous command
73763 + */
73764 + GLAMO_FIRE_MMC_CMD_CTR = 0x8000,
73765 + /* sets kind of response expected */
73766 + GLAMO_FIRE_MMC_RES_MASK = 0x0700,
73767 + /* sets command type */
73768 + GLAMO_FIRE_MMC_TYP_MASK = 0x00C0,
73769 + /* sets command class */
73770 + GLAMO_FIRE_MMC_CLS_MASK = 0x000F,
73771 +};
73772 +
73773 +enum glamo_fire_mmc_response_types {
73774 + GLAMO_FIRE_MMC_RSPT_R1 = 0x0000,
73775 + GLAMO_FIRE_MMC_RSPT_R1b = 0x0100,
73776 + GLAMO_FIRE_MMC_RSPT_R2 = 0x0200,
73777 + GLAMO_FIRE_MMC_RSPT_R3 = 0x0300,
73778 + GLAMO_FIRE_MMC_RSPT_R4 = 0x0400,
73779 + GLAMO_FIRE_MMC_RSPT_R5 = 0x0500,
73780 +};
73781 +
73782 +enum glamo_fire_mmc_command_types {
73783 + /* broadcast, no response */
73784 + GLAMO_FIRE_MMC_CMDT_BNR = 0x0000,
73785 + /* broadcast, with response */
73786 + GLAMO_FIRE_MMC_CMDT_BR = 0x0040,
73787 + /* addressed, no data */
73788 + GLAMO_FIRE_MMC_CMDT_AND = 0x0080,
73789 + /* addressed, with data */
73790 + GLAMO_FIRE_MMC_CMDT_AD = 0x00C0,
73791 +};
73792 +
73793 +enum glamo_fire_mmc_command_class {
73794 + /* "Stream Read" */
73795 + GLAMO_FIRE_MMC_CC_STRR = 0x0000,
73796 + /* Single Block Read */
73797 + GLAMO_FIRE_MMC_CC_SBR = 0x0001,
73798 + /* Multiple Block Read With Stop */
73799 + GLAMO_FIRE_MMC_CC_MBRS = 0x0002,
73800 + /* Multiple Block Read No Stop */
73801 + GLAMO_FIRE_MMC_CC_MBRNS = 0x0003,
73802 + /* RESERVED for "Stream Write" */
73803 + GLAMO_FIRE_MMC_CC_STRW = 0x0004,
73804 + /* "Stream Write" */
73805 + GLAMO_FIRE_MMC_CC_SBW = 0x0005,
73806 + /* RESERVED for Multiple Block Write With Stop */
73807 + GLAMO_FIRE_MMC_CC_MBWS = 0x0006,
73808 + /* Multiple Block Write No Stop */
73809 + GLAMO_FIRE_MMC_CC_MBWNS = 0x0007,
73810 + /* STOP command */
73811 + GLAMO_FIRE_MMC_CC_STOP = 0x0008,
73812 + /* Cancel on Running Command */
73813 + GLAMO_FIRE_MMC_CC_CANCL = 0x0009,
73814 + /* "Basic Command" */
73815 + GLAMO_FIRE_MMC_CC_BASIC = 0x000a,
73816 +};
73817 +
73818 +/* these are offsets from the start of the MMC register region */
73819 +enum glamo_register_mmc {
73820 + /* MMC command, b15..8 = cmd arg b7..0; b7..1 = CRC; b0 = end bit */
73821 + GLAMO_REG_MMC_CMD_REG1 = 0x00,
73822 + /* MMC command, b15..0 = cmd arg b23 .. 8 */
73823 + GLAMO_REG_MMC_CMD_REG2 = 0x02,
73824 + /* MMC command, b15=start, b14=transmission,
73825 + * b13..8=cmd idx, b7..0=cmd arg b31..24
73826 + */
73827 + GLAMO_REG_MMC_CMD_REG3 = 0x04,
73828 + GLAMO_REG_MMC_CMD_FIRE = 0x06,
73829 + GLAMO_REG_MMC_CMD_RSP1 = 0x10,
73830 + GLAMO_REG_MMC_CMD_RSP2 = 0x12,
73831 + GLAMO_REG_MMC_CMD_RSP3 = 0x14,
73832 + GLAMO_REG_MMC_CMD_RSP4 = 0x16,
73833 + GLAMO_REG_MMC_CMD_RSP5 = 0x18,
73834 + GLAMO_REG_MMC_CMD_RSP6 = 0x1a,
73835 + GLAMO_REG_MMC_CMD_RSP7 = 0x1c,
73836 + GLAMO_REG_MMC_CMD_RSP8 = 0x1e,
73837 + GLAMO_REG_MMC_RB_STAT1 = 0x20,
73838 + GLAMO_REG_MMC_RB_BLKCNT = 0x22,
73839 + GLAMO_REG_MMC_RB_BLKLEN = 0x24,
73840 + GLAMO_REG_MMC_BASIC = 0x30,
73841 + GLAMO_REG_MMC_RDATADS1 = 0x34,
73842 + GLAMO_REG_MMC_RDATADS2 = 0x36,
73843 + GLAMO_REG_MMC_WDATADS1 = 0x38,
73844 + GLAMO_REG_MMC_WDATADS2 = 0x3a,
73845 + GLAMO_REG_MMC_DATBLKCNT = 0x3c,
73846 + GLAMO_REG_MMC_DATBLKLEN = 0x3e,
73847 + GLAMO_REG_MMC_TIMEOUT = 0x40,
73848 +
73849 +};
73850 +
73851 +enum glamo_reg_clock_isp {
73852 + GLAMO_CLOCK_ISP_DG_I1CLK = 0x0001,
73853 + GLAMO_CLOCK_ISP_EN_I1CLK = 0x0002,
73854 + GLAMO_CLOCK_ISP_DG_CCLK = 0x0004,
73855 + GLAMO_CLOCK_ISP_EN_CCLK = 0x0008,
73856 + //
73857 + GLAMO_CLOCK_ISP_EN_SCLK = 0x0020,
73858 + GLAMO_CLOCK_ISP_DG_M2CLK = 0x0040,
73859 + GLAMO_CLOCK_ISP_EN_M2CLK = 0x0080,
73860 + GLAMO_CLOCK_ISP_DG_M15CLK = 0x0100,
73861 + GLAMO_CLOCK_ISP_EN_M15CLK = 0x0200,
73862 + GLAMO_CLOCK_ISP1_RESET = 0x1000,
73863 + GLAMO_CLOCK_ISP2_RESET = 0x2000,
73864 +};
73865 +
73866 +enum glamo_reg_clock_jpeg {
73867 + GLAMO_CLOCK_JPEG_DG_JCLK = 0x0001,
73868 + GLAMO_CLOCK_JPEG_EN_JCLK = 0x0002,
73869 + GLAMO_CLOCK_JPEG_DG_M3CLK = 0x0004,
73870 + GLAMO_CLOCK_JPEG_EN_M3CLK = 0x0008,
73871 + GLAMO_CLOCK_JPEG_RESET = 0x1000,
73872 +};
73873 +
73874 +enum glamo_reg_clock_2d {
73875 + GLAMO_CLOCK_2D_DG_GCLK = 0x0001,
73876 + GLAMO_CLOCK_2D_EN_GCLK = 0x0002,
73877 + GLAMO_CLOCK_2D_DG_M7CLK = 0x0004,
73878 + GLAMO_CLOCK_2D_EN_M7CLK = 0x0008,
73879 + GLAMO_CLOCK_2D_DG_M6CLK = 0x0010,
73880 + GLAMO_CLOCK_2D_EN_M6CLK = 0x0020,
73881 + GLAMO_CLOCK_2D_RESET = 0x1000,
73882 + GLAMO_CLOCK_2D_CQ_RESET = 0x2000,
73883 +};
73884 +
73885 +enum glamo_reg_clock_3d {
73886 + GLAMO_CLOCK_3D_DG_ECLK = 0x0001,
73887 + GLAMO_CLOCK_3D_EN_ECLK = 0x0002,
73888 + GLAMO_CLOCK_3D_DG_RCLK = 0x0004,
73889 + GLAMO_CLOCK_3D_EN_RCLK = 0x0008,
73890 + GLAMO_CLOCK_3D_DG_M8CLK = 0x0010,
73891 + GLAMO_CLOCK_3D_EN_M8CLK = 0x0020,
73892 + GLAMO_CLOCK_3D_BACK_RESET = 0x1000,
73893 + GLAMO_CLOCK_3D_FRONT_RESET = 0x2000,
73894 +};
73895 +
73896 +enum glamo_reg_clock_mpeg {
73897 + GLAMO_CLOCK_MPEG_DG_X0CLK = 0x0001,
73898 + GLAMO_CLOCK_MPEG_EN_X0CLK = 0x0002,
73899 + GLAMO_CLOCK_MPEG_DG_X1CLK = 0x0004,
73900 + GLAMO_CLOCK_MPEG_EN_X1CLK = 0x0008,
73901 + GLAMO_CLOCK_MPEG_DG_X2CLK = 0x0010,
73902 + GLAMO_CLOCK_MPEG_EN_X2CLK = 0x0020,
73903 + GLAMO_CLOCK_MPEG_DG_X3CLK = 0x0040,
73904 + GLAMO_CLOCK_MPEG_EN_X3CLK = 0x0080,
73905 + GLAMO_CLOCK_MPEG_DG_X4CLK = 0x0100,
73906 + GLAMO_CLOCK_MPEG_EN_X4CLK = 0x0200,
73907 + GLAMO_CLOCK_MPEG_DG_X6CLK = 0x0400,
73908 + GLAMO_CLOCK_MPEG_EN_X6CLK = 0x0800,
73909 + GLAMO_CLOCK_MPEG_ENC_RESET = 0x1000,
73910 + GLAMO_CLOCK_MPEG_DEC_RESET = 0x2000,
73911 +};
73912 +
73913 +enum glamo_reg_clock51 {
73914 + GLAMO_CLOCK_GEN51_EN_DIV_MCLK = 0x0001,
73915 + GLAMO_CLOCK_GEN51_EN_DIV_SCLK = 0x0002,
73916 + GLAMO_CLOCK_GEN51_EN_DIV_JCLK = 0x0004,
73917 + GLAMO_CLOCK_GEN51_EN_DIV_DCLK = 0x0008,
73918 + GLAMO_CLOCK_GEN51_EN_DIV_DMCLK = 0x0010,
73919 + GLAMO_CLOCK_GEN51_EN_DIV_DHCLK = 0x0020,
73920 + GLAMO_CLOCK_GEN51_EN_DIV_GCLK = 0x0040,
73921 + GLAMO_CLOCK_GEN51_EN_DIV_TCLK = 0x0080,
73922 + /* FIXME: higher bits */
73923 +};
73924 +
73925 +enum glamo_reg_hostbus2 {
73926 + GLAMO_HOSTBUS2_MMIO_EN_ISP = 0x0001,
73927 + GLAMO_HOSTBUS2_MMIO_EN_JPEG = 0x0002,
73928 + GLAMO_HOSTBUS2_MMIO_EN_MPEG = 0x0004,
73929 + GLAMO_HOSTBUS2_MMIO_EN_LCD = 0x0008,
73930 + GLAMO_HOSTBUS2_MMIO_EN_MMC = 0x0010,
73931 + GLAMO_HOSTBUS2_MMIO_EN_MICROP0 = 0x0020,
73932 + GLAMO_HOSTBUS2_MMIO_EN_MICROP1 = 0x0040,
73933 + GLAMO_HOSTBUS2_MMIO_EN_CQ = 0x0080,
73934 + GLAMO_HOSTBUS2_MMIO_EN_RISC = 0x0100,
73935 + GLAMO_HOSTBUS2_MMIO_EN_2D = 0x0200,
73936 + GLAMO_HOSTBUS2_MMIO_EN_3D = 0x0400,
73937 +};
73938 +
73939 +/* LCD Controller */
73940 +
73941 +#define REG_LCD(x) (x)
73942 +enum glamo_reg_lcd {
73943 + GLAMO_REG_LCD_MODE1 = REG_LCD(0x00),
73944 + GLAMO_REG_LCD_MODE2 = REG_LCD(0x02),
73945 + GLAMO_REG_LCD_MODE3 = REG_LCD(0x04),
73946 + GLAMO_REG_LCD_WIDTH = REG_LCD(0x06),
73947 + GLAMO_REG_LCD_HEIGHT = REG_LCD(0x08),
73948 + GLAMO_REG_LCD_POLARITY = REG_LCD(0x0a),
73949 + GLAMO_REG_LCD_A_BASE1 = REG_LCD(0x0c),
73950 + GLAMO_REG_LCD_A_BASE2 = REG_LCD(0x0e),
73951 + GLAMO_REG_LCD_B_BASE1 = REG_LCD(0x10),
73952 + GLAMO_REG_LCD_B_BASE2 = REG_LCD(0x12),
73953 + GLAMO_REG_LCD_C_BASE1 = REG_LCD(0x14),
73954 + GLAMO_REG_LCD_C_BASE2 = REG_LCD(0x16),
73955 + GLAMO_REG_LCD_PITCH = REG_LCD(0x18),
73956 + /* RES */
73957 + GLAMO_REG_LCD_HORIZ_TOTAL = REG_LCD(0x1c),
73958 + /* RES */
73959 + GLAMO_REG_LCD_HORIZ_RETR_START = REG_LCD(0x20),
73960 + /* RES */
73961 + GLAMO_REG_LCD_HORIZ_RETR_END = REG_LCD(0x24),
73962 + /* RES */
73963 + GLAMO_REG_LCD_HORIZ_DISP_START = REG_LCD(0x28),
73964 + /* RES */
73965 + GLAMO_REG_LCD_HORIZ_DISP_END = REG_LCD(0x2c),
73966 + /* RES */
73967 + GLAMO_REG_LCD_VERT_TOTAL = REG_LCD(0x30),
73968 + /* RES */
73969 + GLAMO_REG_LCD_VERT_RETR_START = REG_LCD(0x34),
73970 + /* RES */
73971 + GLAMO_REG_LCD_VERT_RETR_END = REG_LCD(0x38),
73972 + /* RES */
73973 + GLAMO_REG_LCD_VERT_DISP_START = REG_LCD(0x3c),
73974 + /* RES */
73975 + GLAMO_REG_LCD_VERT_DISP_END = REG_LCD(0x40),
73976 + /* RES */
73977 + GLAMO_REG_LCD_POL = REG_LCD(0x44),
73978 + GLAMO_REG_LCD_DATA_START = REG_LCD(0x46),
73979 + GLAMO_REG_LCD_FRATE_CONTRO = REG_LCD(0x48),
73980 + GLAMO_REG_LCD_DATA_CMD_HDR = REG_LCD(0x4a),
73981 + GLAMO_REG_LCD_SP_START = REG_LCD(0x4c),
73982 + GLAMO_REG_LCD_SP_END = REG_LCD(0x4e),
73983 + GLAMO_REG_LCD_CURSOR_BASE1 = REG_LCD(0x50),
73984 + GLAMO_REG_LCD_CURSOR_BASE2 = REG_LCD(0x52),
73985 + GLAMO_REG_LCD_CURSOR_PITCH = REG_LCD(0x54),
73986 + GLAMO_REG_LCD_CURSOR_X_SIZE = REG_LCD(0x56),
73987 + GLAMO_REG_LCD_CURSOR_Y_SIZE = REG_LCD(0x58),
73988 + GLAMO_REG_LCD_CURSOR_X_POS = REG_LCD(0x5a),
73989 + GLAMO_REG_LCD_CURSOR_Y_POS = REG_LCD(0x5c),
73990 + GLAMO_REG_LCD_CURSOR_PRESET = REG_LCD(0x5e),
73991 + GLAMO_REG_LCD_CURSOR_FG_COLOR = REG_LCD(0x60),
73992 + /* RES */
73993 + GLAMO_REG_LCD_CURSOR_BG_COLOR = REG_LCD(0x64),
73994 + /* RES */
73995 + GLAMO_REG_LCD_CURSOR_DST_COLOR = REG_LCD(0x68),
73996 + /* RES */
73997 + GLAMO_REG_LCD_STATUS1 = REG_LCD(0x80),
73998 + GLAMO_REG_LCD_STATUS2 = REG_LCD(0x82),
73999 + GLAMO_REG_LCD_STATUS3 = REG_LCD(0x84),
74000 + GLAMO_REG_LCD_STATUS4 = REG_LCD(0x86),
74001 + /* RES */
74002 + GLAMO_REG_LCD_COMMAND1 = REG_LCD(0xa0),
74003 + GLAMO_REG_LCD_COMMAND2 = REG_LCD(0xa2),
74004 + /* RES */
74005 + GLAMO_REG_LCD_WFORM_DELAY1 = REG_LCD(0xb0),
74006 + GLAMO_REG_LCD_WFORM_DELAY2 = REG_LCD(0xb2),
74007 + /* RES */
74008 + GLAMO_REG_LCD_GAMMA_CORR = REG_LCD(0x100),
74009 + /* RES */
74010 + GLAMO_REG_LCD_GAMMA_R_ENTRY01 = REG_LCD(0x110),
74011 + GLAMO_REG_LCD_GAMMA_R_ENTRY23 = REG_LCD(0x112),
74012 + GLAMO_REG_LCD_GAMMA_R_ENTRY45 = REG_LCD(0x114),
74013 + GLAMO_REG_LCD_GAMMA_R_ENTRY67 = REG_LCD(0x116),
74014 + GLAMO_REG_LCD_GAMMA_R_ENTRY8 = REG_LCD(0x118),
74015 + /* RES */
74016 + GLAMO_REG_LCD_GAMMA_G_ENTRY01 = REG_LCD(0x130),
74017 + GLAMO_REG_LCD_GAMMA_G_ENTRY23 = REG_LCD(0x132),
74018 + GLAMO_REG_LCD_GAMMA_G_ENTRY45 = REG_LCD(0x134),
74019 + GLAMO_REG_LCD_GAMMA_G_ENTRY67 = REG_LCD(0x136),
74020 + GLAMO_REG_LCD_GAMMA_G_ENTRY8 = REG_LCD(0x138),
74021 + /* RES */
74022 + GLAMO_REG_LCD_GAMMA_B_ENTRY01 = REG_LCD(0x150),
74023 + GLAMO_REG_LCD_GAMMA_B_ENTRY23 = REG_LCD(0x152),
74024 + GLAMO_REG_LCD_GAMMA_B_ENTRY45 = REG_LCD(0x154),
74025 + GLAMO_REG_LCD_GAMMA_B_ENTRY67 = REG_LCD(0x156),
74026 + GLAMO_REG_LCD_GAMMA_B_ENTRY8 = REG_LCD(0x158),
74027 + /* RES */
74028 + GLAMO_REG_LCD_SRAM_DRIVING1 = REG_LCD(0x160),
74029 + GLAMO_REG_LCD_SRAM_DRIVING2 = REG_LCD(0x162),
74030 + GLAMO_REG_LCD_SRAM_DRIVING3 = REG_LCD(0x164),
74031 +};
74032 +
74033 +enum glamo_reg_lcd_mode1 {
74034 + GLAMO_LCD_MODE1_PWRSAVE = 0x0001,
74035 + GLAMO_LCD_MODE1_PARTIAL_PRT = 0x0002,
74036 + GLAMO_LCD_MODE1_HWFLIP = 0x0004,
74037 + GLAMO_LCD_MODE1_LCD2 = 0x0008,
74038 + /* RES */
74039 + GLAMO_LCD_MODE1_PARTIAL_MODE = 0x0020,
74040 + GLAMO_LCD_MODE1_CURSOR_DSTCOLOR = 0x0040,
74041 + GLAMO_LCD_MODE1_PARTIAL_ENABLE = 0x0080,
74042 + GLAMO_LCD_MODE1_TVCLK_IN_ENABLE = 0x0100,
74043 + GLAMO_LCD_MODE1_HSYNC_HIGH_ACT = 0x0200,
74044 + GLAMO_LCD_MODE1_VSYNC_HIGH_ACT = 0x0400,
74045 + GLAMO_LCD_MODE1_HSYNC_FLIP = 0x0800,
74046 + GLAMO_LCD_MODE1_GAMMA_COR_EN = 0x1000,
74047 + GLAMO_LCD_MODE1_DITHER_EN = 0x2000,
74048 + GLAMO_LCD_MODE1_CURSOR_EN = 0x4000,
74049 + GLAMO_LCD_MODE1_ROTATE_EN = 0x8000,
74050 +};
74051 +
74052 +enum glamo_reg_lcd_mode2 {
74053 + GLAMO_LCD_MODE2_CRC_CHECK_EN = 0x0001,
74054 + GLAMO_LCD_MODE2_DCMD_PER_LINE = 0x0002,
74055 + GLAMO_LCD_MODE2_NOUSE_BDEF = 0x0004,
74056 + GLAMO_LCD_MODE2_OUT_POS_MODE = 0x0008,
74057 + GLAMO_LCD_MODE2_FRATE_CTRL_EN = 0x0010,
74058 + GLAMO_LCD_MODE2_SINGLE_BUFFER = 0x0020,
74059 + GLAMO_LCD_MODE2_SER_LSB_TO_MSB = 0x0040,
74060 + /* FIXME */
74061 +};
74062 +
74063 +enum glamo_reg_lcd_mode3 {
74064 + /* LCD color source data format */
74065 + GLAMO_LCD_SRC_RGB565 = 0x0000,
74066 + GLAMO_LCD_SRC_ARGB1555 = 0x4000,
74067 + GLAMO_LCD_SRC_ARGB4444 = 0x8000,
74068 + /* interface type */
74069 + GLAMO_LCD_MODE3_LCD = 0x1000,
74070 + GLAMO_LCD_MODE3_RGB = 0x0800,
74071 + GLAMO_LCD_MODE3_CPU = 0x0000,
74072 + /* mode */
74073 + GLAMO_LCD_MODE3_RGB332 = 0x0000,
74074 + GLAMO_LCD_MODE3_RGB444 = 0x0100,
74075 + GLAMO_LCD_MODE3_RGB565 = 0x0200,
74076 + GLAMO_LCD_MODE3_RGB666 = 0x0300,
74077 + /* depth */
74078 + GLAMO_LCD_MODE3_6BITS = 0x0000,
74079 + GLAMO_LCD_MODE3_8BITS = 0x0010,
74080 + GLAMO_LCD_MODE3_9BITS = 0x0020,
74081 + GLAMO_LCD_MODE3_16BITS = 0x0030,
74082 + GLAMO_LCD_MODE3_18BITS = 0x0040,
74083 +};
74084 +
74085 +enum glamo_lcd_rot_mode {
74086 + GLAMO_LCD_ROT_MODE_0 = 0x0000,
74087 + GLAMO_LCD_ROT_MODE_180 = 0x2000,
74088 + GLAMO_LCD_ROT_MODE_MIRROR = 0x4000,
74089 + GLAMO_LCD_ROT_MODE_FLIP = 0x6000,
74090 + GLAMO_LCD_ROT_MODE_90 = 0x8000,
74091 + GLAMO_LCD_ROT_MODE_270 = 0xa000,
74092 +};
74093 +#define GLAMO_LCD_ROT_MODE_MASK 0xe000
74094 +
74095 +enum glamo_lcd_cmd_type {
74096 + GLAMO_LCD_CMD_TYPE_DISP = 0x0000,
74097 + GLAMO_LCD_CMD_TYPE_PARALLEL = 0x4000,
74098 + GLAMO_LCD_CMD_TYPE_SERIAL = 0x8000,
74099 + GLAMO_LCD_CMD_TYPE_SERIAL_DIRECT= 0xc000,
74100 +};
74101 +#define GLAMO_LCD_CMD_TYPE_MASK 0xc000
74102 +
74103 +enum glamo_lcd_cmds {
74104 + GLAMO_LCD_CMD_DATA_DISP_FIRE = 0x00,
74105 + GLAMO_LCD_CMD_DATA_DISP_SYNC = 0x01, /* RGB only */
74106 + /* switch to command mode, no display */
74107 + GLAMO_LCD_CMD_DATA_FIRE_NO_DISP = 0x02,
74108 + /* display until VSYNC, switch to command */
74109 + GLAMO_LCD_CMD_DATA_FIRE_VSYNC = 0x11,
74110 + /* display until HSYNC, switch to command */
74111 + GLAMO_LCD_CMD_DATA_FIRE_HSYNC = 0x12,
74112 + /* display until VSYNC, 1 black frame, VSYNC, switch to command */
74113 + GLAMO_LCD_CMD_DATA_FIRE_VSYNC_B = 0x13,
74114 + /* don't care about display and switch to command */
74115 + GLAMO_LCD_CMD_DATA_FIRE_FREE = 0x14, /* RGB only */
74116 + /* don't care about display, keep data display but disable data,
74117 + * and switch to command */
74118 + GLAMO_LCD_CMD_DATA_FIRE_FREE_D = 0x15, /* RGB only */
74119 +};
74120 +
74121 +enum glamo_core_revisions {
74122 + GLAMO_CORE_REV_A0 = 0x0000,
74123 + GLAMO_CORE_REV_A1 = 0x0001,
74124 + GLAMO_CORE_REV_A2 = 0x0002,
74125 + GLAMO_CORE_REV_A3 = 0x0003,
74126 +};
74127 +
74128 +#endif /* _GLAMO_REGS_H */
74129 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-spi-gpio.c linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-spi-gpio.c
74130 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/glamo-spi-gpio.c 1970-01-01 01:00:00.000000000 +0100
74131 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/glamo-spi-gpio.c 2009-05-10 22:28:00.000000000 +0200
74132 @@ -0,0 +1,278 @@
74133 +/*
74134 + * Copyright (C) 2007 Openmoko, Inc.
74135 + * Author: Harald Welte <laforge@openmoko.org>
74136 + *
74137 + * Smedia Glamo GPIO based SPI driver
74138 + *
74139 + * This program is free software; you can redistribute it and/or modify
74140 + * it under the terms of the GNU General Public License version 2 as
74141 + * published by the Free Software Foundation.
74142 + *
74143 + * This driver currently only implements a minimum subset of the hardware
74144 + * features, esp. those features that are required to drive the jbt6k74
74145 + * LCM controller asic in the TD028TTEC1 LCM.
74146 + *
74147 +*/
74148 +
74149 +#define DEBUG
74150 +
74151 +#include <linux/kernel.h>
74152 +#include <linux/init.h>
74153 +#include <linux/delay.h>
74154 +#include <linux/device.h>
74155 +#include <linux/spinlock.h>
74156 +#include <linux/workqueue.h>
74157 +#include <linux/platform_device.h>
74158 +
74159 +#include <linux/spi/spi.h>
74160 +#include <linux/spi/spi_bitbang.h>
74161 +#include <linux/spi/glamo.h>
74162 +
74163 +#include <linux/glamofb.h>
74164 +
74165 +#include <mach/hardware.h>
74166 +
74167 +#include "glamo-core.h"
74168 +#include "glamo-regs.h"
74169 +
74170 +struct glamo_spigpio {
74171 + struct spi_bitbang bitbang;
74172 + struct spi_master *master;
74173 + struct glamo_spigpio_info *info;
74174 + struct glamo_core *glamo;
74175 +};
74176 +
74177 +static inline struct glamo_spigpio *to_sg(struct spi_device *spi)
74178 +{
74179 + return dev_get_drvdata(&spi->master->dev);
74180 +}
74181 +
74182 +static inline void setsck(struct spi_device *dev, int on)
74183 +{
74184 + struct glamo_spigpio *sg = to_sg(dev);
74185 + glamo_gpio_setpin(sg->glamo, sg->info->pin_clk, on ? 1 : 0);
74186 +}
74187 +
74188 +static inline void setmosi(struct spi_device *dev, int on)
74189 +{
74190 + struct glamo_spigpio *sg = to_sg(dev);
74191 + glamo_gpio_setpin(sg->glamo, sg->info->pin_mosi, on ? 1 : 0);
74192 +}
74193 +
74194 +static inline u32 getmiso(struct spi_device *dev)
74195 +{
74196 + struct glamo_spigpio *sg = to_sg(dev);
74197 + if (sg->info->pin_miso)
74198 + return glamo_gpio_getpin(sg->glamo, sg->info->pin_miso) ? 1 : 0;
74199 + else
74200 + return 0;
74201 +}
74202 +
74203 +#define spidelay(x) ndelay(x)
74204 +
74205 +#define EXPAND_BITBANG_TXRX
74206 +#include <linux/spi/spi_bitbang.h>
74207 +
74208 +static u32 glamo_spigpio_txrx_mode0(struct spi_device *spi,
74209 + unsigned nsecs, u32 word, u8 bits)
74210 +{
74211 + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
74212 +}
74213 +
74214 +static u32 glamo_spigpio_txrx_mode1(struct spi_device *spi,
74215 + unsigned nsecs, u32 word, u8 bits)
74216 +{
74217 + return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
74218 +}
74219 +
74220 +static u32 glamo_spigpio_txrx_mode2(struct spi_device *spi,
74221 + unsigned nsecs, u32 word, u8 bits)
74222 +{
74223 + return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
74224 +}
74225 +
74226 +static u32 glamo_spigpio_txrx_mode3(struct spi_device *spi,
74227 + unsigned nsecs, u32 word, u8 bits)
74228 +{
74229 + return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
74230 +}
74231 +
74232 +
74233 +#if 0
74234 +static int glamo_spigpio_setupxfer(struct spi_device *spi,
74235 + struct spi_transfer *t)
74236 +{
74237 + struct glamo_spi *gs = to_sg(spi);
74238 + unsigned int bpw;
74239 +
74240 + bpw = t ? t->bits_per_word : spi->bits_per_word;
74241 +
74242 + if (bpw != 9 && bpw != 8) {
74243 + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
74244 + return -EINVAL;
74245 + }
74246 +
74247 + return 0;
74248 +}
74249 +#endif
74250 +
74251 +static void glamo_spigpio_chipsel(struct spi_device *spi, int value)
74252 +{
74253 + struct glamo_spigpio *gs = to_sg(spi);
74254 +#if 0
74255 + dev_dbg(&spi->dev, "chipsel %d: spi=%p, gs=%p, info=%p, handle=%p\n",
74256 + value, spi, gs, gs->info, gs->info->glamo);
74257 +#endif
74258 + glamo_gpio_setpin(gs->glamo, gs->info->pin_cs, value ? 0 : 1);
74259 +}
74260 +
74261 +
74262 +static int glamo_spigpio_probe(struct platform_device *pdev)
74263 +{
74264 + struct spi_master *master;
74265 + struct glamo_spigpio *sp;
74266 + int ret;
74267 +
74268 + master = spi_alloc_master(&pdev->dev, sizeof(struct glamo_spigpio));
74269 + if (master == NULL) {
74270 + dev_err(&pdev->dev, "failed to allocate spi master\n");
74271 + ret = -ENOMEM;
74272 + goto err;
74273 + }
74274 +
74275 + sp = spi_master_get_devdata(master);
74276 + platform_set_drvdata(pdev, sp);
74277 + sp->info = pdev->dev.platform_data;
74278 + if (!sp->info) {
74279 + dev_err(&pdev->dev, "can't operate without platform data\n");
74280 + ret = -EIO;
74281 + goto err_no_pdev;
74282 + }
74283 +
74284 + master->num_chipselect = 1;
74285 + master->bus_num = 2; /* FIXME: use dynamic number */
74286 +
74287 + sp->master = spi_master_get(master);
74288 + sp->glamo = sp->info->glamo;
74289 +
74290 + sp->bitbang.master = sp->master;
74291 + sp->bitbang.chipselect = glamo_spigpio_chipsel;
74292 + sp->bitbang.txrx_word[SPI_MODE_0] = glamo_spigpio_txrx_mode0;
74293 + sp->bitbang.txrx_word[SPI_MODE_1] = glamo_spigpio_txrx_mode1;
74294 + sp->bitbang.txrx_word[SPI_MODE_2] = glamo_spigpio_txrx_mode2;
74295 + sp->bitbang.txrx_word[SPI_MODE_3] = glamo_spigpio_txrx_mode3;
74296 +
74297 + /* set state of spi pins */
74298 + glamo_gpio_setpin(sp->glamo, sp->info->pin_clk, 0);
74299 + glamo_gpio_setpin(sp->glamo, sp->info->pin_mosi, 0);
74300 + glamo_gpio_setpin(sp->glamo, sp->info->pin_cs, 1);
74301 +
74302 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_clk);
74303 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_mosi);
74304 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_cs);
74305 + if (sp->info->pin_miso)
74306 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_miso);
74307 +
74308 + /* bring the LCM panel out of reset if it isn't already */
74309 +
74310 + glamo_gpio_setpin(sp->glamo, GLAMO_GPIO4, 1);
74311 + glamo_gpio_cfgpin(sp->glamo, GLAMO_GPIO4_OUTPUT);
74312 + msleep(90);
74313 +
74314 +#if 0
74315 + sp->dev = &pdev->dev;
74316 +
74317 + sp->bitbang.setup_transfer = glamo_spi_setupxfer;
74318 + sp->bitbang.txrx_bufs = glamo_spi_txrx;
74319 + sp->bitbang.master->setup = glamo_spi_setup;
74320 +#endif
74321 +
74322 + dev_set_drvdata(&sp->master->dev, sp);
74323 +
74324 + ret = spi_bitbang_start(&sp->bitbang);
74325 + if (ret)
74326 + goto err_no_bitbang;
74327 +
74328 + return 0;
74329 +
74330 +err_no_bitbang:
74331 + platform_set_drvdata(pdev, NULL);
74332 +err_no_pdev:
74333 + spi_master_put(sp->bitbang.master);
74334 +err:
74335 + return ret;
74336 +
74337 +}
74338 +
74339 +static int glamo_spigpio_remove(struct platform_device *pdev)
74340 +{
74341 + struct glamo_spigpio *sp = platform_get_drvdata(pdev);
74342 +
74343 + spi_bitbang_stop(&sp->bitbang);
74344 + spi_master_put(sp->bitbang.master);
74345 +
74346 + return 0;
74347 +}
74348 +
74349 +/*#define glamo_spigpio_suspend NULL
74350 +#define glamo_spigpio_resume NULL
74351 +*/
74352 +
74353 +
74354 +#ifdef CONFIG_PM
74355 +static int glamo_spigpio_suspend(struct platform_device *pdev, pm_message_t state)
74356 +{
74357 + return 0;
74358 +}
74359 +
74360 +static int glamo_spigpio_resume(struct platform_device *pdev)
74361 +{
74362 + struct glamo_spigpio *sp = platform_get_drvdata(pdev);
74363 +
74364 + if (!sp)
74365 + return 0;
74366 +
74367 + /* set state of spi pins */
74368 + glamo_gpio_setpin(sp->glamo, sp->info->pin_clk, 0);
74369 + glamo_gpio_setpin(sp->glamo, sp->info->pin_mosi, 0);
74370 + glamo_gpio_setpin(sp->glamo, sp->info->pin_cs, 1);
74371 +
74372 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_clk);
74373 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_mosi);
74374 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_cs);
74375 + if (sp->info->pin_miso)
74376 + glamo_gpio_cfgpin(sp->glamo, sp->info->pin_miso);
74377 +
74378 + return 0;
74379 +}
74380 +#endif
74381 +
74382 +static struct platform_driver glamo_spi_drv = {
74383 + .probe = glamo_spigpio_probe,
74384 + .remove = glamo_spigpio_remove,
74385 +#ifdef CONFIG_PM
74386 + .suspend_late = glamo_spigpio_suspend,
74387 + .resume_early = glamo_spigpio_resume,
74388 +#endif
74389 + .driver = {
74390 + .name = "glamo-spi-gpio",
74391 + .owner = THIS_MODULE,
74392 + },
74393 +};
74394 +
74395 +static int __init glamo_spi_init(void)
74396 +{
74397 + return platform_driver_register(&glamo_spi_drv);
74398 +}
74399 +
74400 +static void __exit glamo_spi_exit(void)
74401 +{
74402 + platform_driver_unregister(&glamo_spi_drv);
74403 +}
74404 +
74405 +module_init(glamo_spi_init);
74406 +module_exit(glamo_spi_exit);
74407 +
74408 +MODULE_DESCRIPTION("Smedia Glamo 336x/337x LCM serial command SPI Driver");
74409 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>")
74410 +MODULE_LICENSE("GPL");
74411 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/Kconfig linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/Kconfig
74412 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/Kconfig 1970-01-01 01:00:00.000000000 +0100
74413 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/Kconfig 2009-05-10 22:28:00.000000000 +0200
74414 @@ -0,0 +1,57 @@
74415 +config MFD_GLAMO
74416 + bool "Smedia Glamo 336x/337x support"
74417 + help
74418 + This enables the core driver for the Smedia Glamo 336x/337x
74419 + multi-function device. It includes irq_chip demultiplex as
74420 + well as clock / power management and GPIO support.
74421 +
74422 +config MFD_GLAMO_FB
74423 + tristate "Smedia Glamo 336x/337x framebuffer support"
74424 + depends on FB && MFD_GLAMO
74425 + select FB_CFB_FILLRECT
74426 + select FB_CFB_COPYAREA
74427 + select FB_CFB_IMAGEBLIT
74428 + help
74429 + Frame buffer driver for the LCD controller in the Smedia Glamo
74430 + 336x/337x.
74431 +
74432 + This driver is also available as a module ( = code which can be
74433 + inserted and removed from the running kernel whenever you want). The
74434 + module will be called glamofb. If you want to compile it as a module,
74435 + say M here and read <file:Documentation/modules.txt>.
74436 +
74437 + If unsure, say N.
74438 +
74439 +config MFD_GLAMO_FB_XGLAMO_WORKAROUND
74440 + bool "Smedia Glamo 336x/337x Xglamo rotation workaround"
74441 + depends on MFD_GLAMO_FB
74442 + help
74443 + This is a workaround for a Xglamo bug. This should be fixed
74444 + in Xglamo and not in kernel space.
74445 +
74446 + If unsure, say N.
74447 +
74448 +
74449 +config MFD_GLAMO_SPI_GPIO
74450 + tristate "Glamo GPIO SPI bitbang support"
74451 + depends on MFD_GLAMO
74452 + help
74453 + Enable a bitbanging SPI adapter driver for the Smedia Glamo.
74454 +
74455 +config MFD_GLAMO_SPI_FB
74456 + tristate "Glamo LCM control channel SPI support"
74457 + depends on MFD_GLAMO_FB
74458 + help
74459 + Enable a bitbanging SPI adapter driver for the Smedia Glamo LCM
74460 + control channel. This SPI interface is frequently used to
74461 + interconnect the LCM control interface.
74462 +
74463 +config MFD_GLAMO_MCI
74464 + tristate "Glamo S3C SD/MMC Card Interface support"
74465 + depends on MFD_GLAMO && MMC
74466 + help
74467 + This selects a driver for the MCI interface found in
74468 + the S-Media GLAMO chip, as used in Openmoko
74469 + neo1973 GTA-02.
74470 +
74471 + If unsure, say N.
74472 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/glamo/Makefile linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/Makefile
74473 --- linux-2.6.29-rc3.owrt/drivers/mfd/glamo/Makefile 1970-01-01 01:00:00.000000000 +0100
74474 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/glamo/Makefile 2009-05-10 22:28:00.000000000 +0200
74475 @@ -0,0 +1,12 @@
74476 +#
74477 +# Makefile for the Smedia Glamo framebuffer driver
74478 +#
74479 +
74480 +obj-$(CONFIG_MFD_GLAMO) += glamo-core.o glamo-gpio.o
74481 +obj-$(CONFIG_MFD_GLAMO_SPI) += glamo-spi.o
74482 +obj-$(CONFIG_MFD_GLAMO_SPI_GPIO) += glamo-spi-gpio.o
74483 +
74484 +obj-$(CONFIG_MFD_GLAMO_FB) += glamo-fb.o
74485 +obj-$(CONFIG_MFD_GLAMO_SPI_FB) += glamo-lcm-spi.o
74486 +obj-$(CONFIG_MFD_GLAMO_MCI) += glamo-mci.o
74487 +
74488 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/Kconfig linux-2.6.29-rc3.owrt.om/drivers/mfd/Kconfig
74489 --- linux-2.6.29-rc3.owrt/drivers/mfd/Kconfig 2009-05-10 22:04:49.000000000 +0200
74490 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/Kconfig 2009-05-10 22:28:00.000000000 +0200
74491 @@ -240,6 +240,33 @@
74492 Say yes here if you want to include support GPIO for pins on
74493 the PCF50633 chip.
74494
74495 +
74496 +config MFD_PCF50606
74497 + tristate "Support for NXP PCF50606"
74498 + depends on I2C
74499 + help
74500 + Say yes here if you have NXP PCF50606 chip on your board.
74501 + This core driver provides register access and IRQ handling
74502 + facilities, and registers devices for the various functions
74503 + so that function-specific drivers can bind to them.
74504 +
74505 +config PCF50606_ADC
74506 + tristate "Support for NXP PCF50606 ADC"
74507 + depends on MFD_PCF50606
74508 + help
74509 + Say yes here if you want to include support for ADC in the
74510 + NXP PCF50606 chip.
74511 +
74512 +config PCF50606_GPO
74513 + tristate "Support for NXP PCF50606 GPO"
74514 + depends on MFD_PCF50606
74515 + help
74516 + Say yes here if you want to include support GPO for pins on
74517 + the PCF50606 chip.
74518 +
74519 +
74520 +source "drivers/mfd/glamo/Kconfig"
74521 +
74522 endmenu
74523
74524 menu "Multimedia Capabilities Port drivers"
74525 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/Makefile linux-2.6.29-rc3.owrt.om/drivers/mfd/Makefile
74526 --- linux-2.6.29-rc3.owrt/drivers/mfd/Makefile 2009-05-10 22:04:49.000000000 +0200
74527 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/Makefile 2009-05-10 22:28:00.000000000 +0200
74528 @@ -4,6 +4,7 @@
74529
74530 obj-$(CONFIG_MFD_SM501) += sm501.o
74531 obj-$(CONFIG_MFD_ASIC3) += asic3.o
74532 +obj-$(CONFIG_MFD_GLAMO) += glamo/
74533
74534 obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
74535 obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
74536 @@ -40,4 +41,8 @@
74537
74538 obj-$(CONFIG_MFD_PCF50633) += pcf50633-core.o
74539 obj-$(CONFIG_PCF50633_ADC) += pcf50633-adc.o
74540 -obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
74541 \ No newline at end of file
74542 +obj-$(CONFIG_PCF50633_GPIO) += pcf50633-gpio.o
74543 +
74544 +obj-$(CONFIG_MFD_PCF50606) += pcf50606-core.o
74545 +obj-$(CONFIG_PCF50606_ADC) += pcf50606-adc.o
74546 +obj-$(CONFIG_PCF50606_GPO) += pcf50606-gpo.o
74547 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/pcf50606-adc.c linux-2.6.29-rc3.owrt.om/drivers/mfd/pcf50606-adc.c
74548 --- linux-2.6.29-rc3.owrt/drivers/mfd/pcf50606-adc.c 1970-01-01 01:00:00.000000000 +0100
74549 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/pcf50606-adc.c 2009-05-10 22:28:00.000000000 +0200
74550 @@ -0,0 +1,279 @@
74551 +/* Philips PCF50606 ADC Driver
74552 + *
74553 + * (C) 2006-2008 by Openmoko, Inc.
74554 + * Author: Balaji Rao <balajirrao@openmoko.org>
74555 + * All rights reserved.
74556 + *
74557 + * Broken down from monstrous PCF50606 driver mainly by
74558 + * Harald Welte, Andy Green, Werner Almesberger and Matt Hsu
74559 + *
74560 + * This program is free software; you can redistribute it and/or modify it
74561 + * under the terms of the GNU General Public License as published by the
74562 + * Free Software Foundation; either version 2 of the License, or (at your
74563 + * option) any later version.
74564 + *
74565 + * NOTE: This driver does not yet support subtractive ADC mode, which means
74566 + * you can do only one measurement per read request.
74567 + */
74568 +
74569 +#include <linux/kernel.h>
74570 +#include <linux/module.h>
74571 +#include <linux/init.h>
74572 +#include <linux/device.h>
74573 +#include <linux/platform_device.h>
74574 +#include <linux/completion.h>
74575 +
74576 +#include <linux/mfd/pcf50606/core.h>
74577 +#include <linux/mfd/pcf50606/adc.h>
74578 +
74579 +struct pcf50606_adc_request {
74580 + int mux;
74581 + int result;
74582 + void (*callback)(struct pcf50606 *, void *, int);
74583 + void *callback_param;
74584 +
74585 + /* Used in case of sync requests */
74586 + struct completion completion;
74587 +
74588 +};
74589 +
74590 +#define PCF50606_MAX_ADC_FIFO_DEPTH 8
74591 +
74592 +struct pcf50606_adc {
74593 + struct pcf50606 *pcf;
74594 +
74595 + /* Private stuff */
74596 + struct pcf50606_adc_request *queue[PCF50606_MAX_ADC_FIFO_DEPTH];
74597 + int queue_head;
74598 + int queue_tail;
74599 + struct mutex queue_mutex;
74600 +};
74601 +
74602 +static inline struct pcf50606_adc *__to_adc(struct pcf50606 *pcf)
74603 +{
74604 + return platform_get_drvdata(pcf->adc_pdev);
74605 +}
74606 +
74607 +static void adc_setup(struct pcf50606 *pcf, int channel)
74608 +{
74609 + channel &= PCF50606_ADCC2_ADCMUX_MASK;
74610 +
74611 + /* start ADC conversion of selected channel */
74612 + pcf50606_reg_write(pcf, PCF50606_REG_ADCC2, channel |
74613 + PCF50606_ADCC2_ADCSTART | PCF50606_ADCC2_RES_10BIT);
74614 +
74615 +}
74616 +
74617 +static void trigger_next_adc_job_if_any(struct pcf50606 *pcf)
74618 +{
74619 + struct pcf50606_adc *adc = __to_adc(pcf);
74620 + int head, tail;
74621 +
74622 + mutex_lock(&adc->queue_mutex);
74623 +
74624 + head = adc->queue_head;
74625 + tail = adc->queue_tail;
74626 +
74627 + if (!adc->queue[head])
74628 + goto out;
74629 +
74630 + adc_setup(pcf, adc->queue[head]->mux);
74631 +out:
74632 + mutex_unlock(&adc->queue_mutex);
74633 +}
74634 +
74635 +static int
74636 +adc_enqueue_request(struct pcf50606 *pcf, struct pcf50606_adc_request *req)
74637 +{
74638 + struct pcf50606_adc *adc = __to_adc(pcf);
74639 + int head, tail;
74640 +
74641 + mutex_lock(&adc->queue_mutex);
74642 + head = adc->queue_head;
74643 + tail = adc->queue_tail;
74644 +
74645 + if (adc->queue[tail]) {
74646 + mutex_unlock(&adc->queue_mutex);
74647 + return -EBUSY;
74648 + }
74649 +
74650 + adc->queue[tail] = req;
74651 +
74652 + adc->queue_tail =
74653 + (tail + 1) & (PCF50606_MAX_ADC_FIFO_DEPTH - 1);
74654 +
74655 + mutex_unlock(&adc->queue_mutex);
74656 +
74657 + trigger_next_adc_job_if_any(pcf);
74658 +
74659 + return 0;
74660 +}
74661 +
74662 +static void
74663 +pcf50606_adc_sync_read_callback(struct pcf50606 *pcf, void *param, int result)
74664 +{
74665 + struct pcf50606_adc_request *req;
74666 +
74667 + /*We know here that the passed param is an adc_request object */
74668 + req = (struct pcf50606_adc_request *)param;
74669 +
74670 + req->result = result;
74671 + complete(&req->completion);
74672 +}
74673 +
74674 +int pcf50606_adc_sync_read(struct pcf50606 *pcf, int mux)
74675 +{
74676 +
74677 + struct pcf50606_adc_request *req;
74678 + int result;
74679 +
74680 + /* req is freed when the result is ready, in irq handler*/
74681 + req = kzalloc(sizeof(*req), GFP_KERNEL);
74682 + if (!req)
74683 + return -ENOMEM;
74684 +
74685 + req->mux = mux;
74686 + req->callback = pcf50606_adc_sync_read_callback;
74687 + req->callback_param = req;
74688 + init_completion(&req->completion);
74689 +
74690 + adc_enqueue_request(pcf, req);
74691 +
74692 + if (wait_for_completion_timeout(&req->completion, 5 * HZ) == 5 * HZ) {
74693 + dev_err(pcf->dev, "ADC read timed out \n");
74694 + }
74695 +
74696 + result = req->result;
74697 +
74698 + return result;
74699 +}
74700 +EXPORT_SYMBOL_GPL(pcf50606_adc_sync_read);
74701 +
74702 +int pcf50606_adc_async_read(struct pcf50606 *pcf, int mux,
74703 + void (*callback)(struct pcf50606 *, void *, int),
74704 + void *callback_param)
74705 +{
74706 + struct pcf50606_adc_request *req;
74707 +
74708 + /* req is freed when the result is ready, in pcf50606_work*/
74709 + req = kmalloc(sizeof(*req), GFP_KERNEL);
74710 + if (!req)
74711 + return -ENOMEM;
74712 +
74713 + req->mux = mux;
74714 + req->callback = callback;
74715 + req->callback_param = callback_param;
74716 +
74717 + adc_enqueue_request(pcf, req);
74718 +
74719 + return 0;
74720 +}
74721 +EXPORT_SYMBOL_GPL(pcf50606_adc_async_read);
74722 +
74723 +static int adc_result(struct pcf50606 *pcf)
74724 +{
74725 + u16 ret = (pcf50606_reg_read(pcf, PCF50606_REG_ADCS1) << 2) |
74726 + (pcf50606_reg_read(pcf, PCF50606_REG_ADCS2) & 0x03);
74727 +
74728 + dev_dbg(pcf->dev, "adc result = %d\n", ret);
74729 +
74730 + return ret;
74731 +}
74732 +
74733 +static void pcf50606_adc_irq(int irq, void *data)
74734 +{
74735 + struct pcf50606_adc *adc = data;
74736 + struct pcf50606 *pcf = adc->pcf;
74737 + struct pcf50606_adc_request *req;
74738 + int head;
74739 +
74740 + mutex_lock(&adc->queue_mutex);
74741 + head = adc->queue_head;
74742 +
74743 + req = adc->queue[head];
74744 + if (WARN_ON(!req)) {
74745 + dev_err(pcf->dev, "pcf50606-adc irq: ADC queue empty!\n");
74746 + mutex_unlock(&adc->queue_mutex);
74747 + return;
74748 + }
74749 +
74750 + adc->queue[head] = NULL;
74751 + adc->queue_head = (head + 1) &
74752 + (PCF50606_MAX_ADC_FIFO_DEPTH - 1);
74753 +
74754 + mutex_unlock(&adc->queue_mutex);
74755 +
74756 + req->callback(pcf, req->callback_param, adc_result(pcf));
74757 + kfree(req);
74758 +
74759 + trigger_next_adc_job_if_any(pcf);
74760 +}
74761 +
74762 +static int __devinit pcf50606_adc_probe(struct platform_device *pdev)
74763 +{
74764 + struct pcf50606_subdev_pdata *pdata = pdev->dev.platform_data;
74765 + struct pcf50606_adc *adc;
74766 +
74767 + adc = kzalloc(sizeof(*adc), GFP_KERNEL);
74768 + if (!adc)
74769 + return -ENOMEM;
74770 +
74771 + adc->pcf = pdata->pcf;
74772 + platform_set_drvdata(pdev, adc);
74773 +
74774 + pcf50606_register_irq(pdata->pcf, PCF50606_IRQ_ADCRDY,
74775 + pcf50606_adc_irq, adc);
74776 +
74777 + mutex_init(&adc->queue_mutex);
74778 +
74779 + return 0;
74780 +}
74781 +
74782 +static int __devexit pcf50606_adc_remove(struct platform_device *pdev)
74783 +{
74784 + struct pcf50606_adc *adc = platform_get_drvdata(pdev);
74785 + int i, head;
74786 +
74787 + pcf50606_free_irq(adc->pcf, PCF50606_IRQ_ADCRDY);
74788 +
74789 + mutex_lock(&adc->queue_mutex);
74790 + head = adc->queue_head;
74791 +
74792 + if (WARN_ON(adc->queue[head]))
74793 + dev_err(adc->pcf->dev,
74794 + "adc driver removed with request pending\n");
74795 +
74796 + for (i = 0; i < PCF50606_MAX_ADC_FIFO_DEPTH; i++)
74797 + kfree(adc->queue[i]);
74798 +
74799 + mutex_unlock(&adc->queue_mutex);
74800 + kfree(adc);
74801 +
74802 + return 0;
74803 +}
74804 +
74805 +struct platform_driver pcf50606_adc_driver = {
74806 + .driver = {
74807 + .name = "pcf50606-adc",
74808 + },
74809 + .probe = pcf50606_adc_probe,
74810 + .remove = __devexit_p(pcf50606_adc_remove),
74811 +};
74812 +
74813 +static int __init pcf50606_adc_init(void)
74814 +{
74815 + return platform_driver_register(&pcf50606_adc_driver);
74816 +}
74817 +module_init(pcf50606_adc_init);
74818 +
74819 +static void __exit pcf50606_adc_exit(void)
74820 +{
74821 + platform_driver_unregister(&pcf50606_adc_driver);
74822 +}
74823 +module_exit(pcf50606_adc_exit);
74824 +
74825 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
74826 +MODULE_DESCRIPTION("PCF50606 adc driver");
74827 +MODULE_LICENSE("GPL");
74828 +MODULE_ALIAS("platform:pcf50606-adc");
74829 +
74830 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/pcf50606-core.c linux-2.6.29-rc3.owrt.om/drivers/mfd/pcf50606-core.c
74831 --- linux-2.6.29-rc3.owrt/drivers/mfd/pcf50606-core.c 1970-01-01 01:00:00.000000000 +0100
74832 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/pcf50606-core.c 2009-05-10 22:28:00.000000000 +0200
74833 @@ -0,0 +1,680 @@
74834 +/* Philips PCF50606 Power Management Unit (PMU) driver
74835 + *
74836 + * (C) 2006-2008 by Openmoko, Inc.
74837 + * Author: Harald Welte <laforge@openmoko.org>
74838 + * Matt Hsu <matt@openmoko.org>
74839 + * All rights reserved.
74840 + *
74841 + * This program is free software; you can redistribute it and/or
74842 + * modify it under the terms of the GNU General Public License as
74843 + * published by the Free Software Foundation; either version 2 of
74844 + * the License, or (at your option) any later version.
74845 + *
74846 + */
74847 +#include <linux/kernel.h>
74848 +#include <linux/device.h>
74849 +#include <linux/sysfs.h>
74850 +#include <linux/device.h>
74851 +#include <linux/module.h>
74852 +#include <linux/types.h>
74853 +#include <linux/interrupt.h>
74854 +#include <linux/workqueue.h>
74855 +#include <linux/platform_device.h>
74856 +#include <linux/i2c.h>
74857 +#include <linux/irq.h>
74858 +#include <linux/device.h>
74859 +#include <linux/module.h>
74860 +
74861 +#include <linux/mfd/pcf50606/core.h>
74862 +
74863 +static int __pcf50606_read(struct pcf50606 *pcf, u8 reg, int num, u8 *data)
74864 +{
74865 + int ret;
74866 +
74867 + ret = i2c_smbus_read_i2c_block_data(pcf->i2c_client, reg,
74868 + num, data);
74869 + if (ret < 0)
74870 + dev_err(pcf->dev, "Error reading %d regs at %d\n", num, reg);
74871 +
74872 + return ret;
74873 +}
74874 +
74875 +static int __pcf50606_write(struct pcf50606 *pcf, u8 reg, int num, u8 *data)
74876 +{
74877 + int ret;
74878 +
74879 + ret = i2c_smbus_write_i2c_block_data(pcf->i2c_client, reg,
74880 + num, data);
74881 + if (ret < 0)
74882 + dev_err(pcf->dev, "Error writing %d regs at %d\n", num, reg);
74883 +
74884 + return ret;
74885 +
74886 +}
74887 +
74888 +/* Read a block of upto 32 regs */
74889 +int pcf50606_read_block(struct pcf50606 *pcf, u8 reg,
74890 + int nr_regs, u8 *data)
74891 +{
74892 + int ret;
74893 +
74894 + mutex_lock(&pcf->lock);
74895 + ret = __pcf50606_read(pcf, reg, nr_regs, data);
74896 + mutex_unlock(&pcf->lock);
74897 +
74898 + return ret;
74899 +}
74900 +EXPORT_SYMBOL_GPL(pcf50606_read_block);
74901 +
74902 +/* Write a block of upto 32 regs */
74903 +int pcf50606_write_block(struct pcf50606 *pcf , u8 reg,
74904 + int nr_regs, u8 *data)
74905 +{
74906 + int ret;
74907 +
74908 + mutex_lock(&pcf->lock);
74909 + ret = __pcf50606_write(pcf, reg, nr_regs, data);
74910 + mutex_unlock(&pcf->lock);
74911 +
74912 + return ret;
74913 +}
74914 +EXPORT_SYMBOL_GPL(pcf50606_write_block);
74915 +
74916 +u8 pcf50606_reg_read(struct pcf50606 *pcf, u8 reg)
74917 +{
74918 + u8 val;
74919 +
74920 + mutex_lock(&pcf->lock);
74921 + __pcf50606_read(pcf, reg, 1, &val);
74922 + mutex_unlock(&pcf->lock);
74923 +
74924 + return val;
74925 +}
74926 +EXPORT_SYMBOL_GPL(pcf50606_reg_read);
74927 +
74928 +int pcf50606_reg_write(struct pcf50606 *pcf, u8 reg, u8 val)
74929 +{
74930 + int ret;
74931 +
74932 + mutex_lock(&pcf->lock);
74933 + ret = __pcf50606_write(pcf, reg, 1, &val);
74934 + mutex_unlock(&pcf->lock);
74935 +
74936 + return ret;
74937 +}
74938 +EXPORT_SYMBOL_GPL(pcf50606_reg_write);
74939 +
74940 +int pcf50606_reg_set_bit_mask(struct pcf50606 *pcf, u8 reg, u8 mask, u8 val)
74941 +{
74942 + int ret;
74943 + u8 tmp;
74944 +
74945 + val &= mask;
74946 +
74947 + mutex_lock(&pcf->lock);
74948 + ret = __pcf50606_read(pcf, reg, 1, &tmp);
74949 + if (ret < 0)
74950 + goto out;
74951 +
74952 + tmp &= ~mask;
74953 + tmp |= val;
74954 + ret = __pcf50606_write(pcf, reg, 1, &tmp);
74955 +
74956 +out:
74957 + mutex_unlock(&pcf->lock);
74958 +
74959 + return ret;
74960 +}
74961 +EXPORT_SYMBOL_GPL(pcf50606_reg_set_bit_mask);
74962 +
74963 +int pcf50606_reg_clear_bits(struct pcf50606 *pcf, u8 reg, u8 val)
74964 +{
74965 + int ret;
74966 + u8 tmp;
74967 +
74968 + mutex_lock(&pcf->lock);
74969 + ret = __pcf50606_read(pcf, reg, 1, &tmp);
74970 + if (ret < 0)
74971 + goto out;
74972 +
74973 + tmp &= ~val;
74974 + ret = __pcf50606_write(pcf, reg, 1, &tmp);
74975 +
74976 +out:
74977 + mutex_unlock(&pcf->lock);
74978 +
74979 + return ret;
74980 +}
74981 +EXPORT_SYMBOL_GPL(pcf50606_reg_clear_bits);
74982 +
74983 +/* sysfs attributes */
74984 +static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr,
74985 + char *buf)
74986 +{
74987 + struct pcf50606 *pcf = dev_get_drvdata(dev);
74988 + u8 dump[16];
74989 + int n, n1, idx = 0;
74990 + char *buf1 = buf;
74991 + static u8 address_no_read[] = { /* must be ascending */
74992 + PCF50606_REG_INT1,
74993 + PCF50606_REG_INT2,
74994 + PCF50606_REG_INT3,
74995 + 0 /* terminator */
74996 + };
74997 +
74998 + for (n = 0; n < 256; n += sizeof(dump)) {
74999 + for (n1 = 0; n1 < sizeof(dump); n1++)
75000 + if (n == address_no_read[idx]) {
75001 + idx++;
75002 + dump[n1] = 0x00;
75003 + } else
75004 + dump[n1] = pcf50606_reg_read(pcf, n + n1);
75005 +
75006 + hex_dump_to_buffer(dump, sizeof(dump), 16, 1, buf1, 128, 0);
75007 + buf1 += strlen(buf1);
75008 + *buf1++ = '\n';
75009 + *buf1 = '\0';
75010 + }
75011 +
75012 + return buf1 - buf;
75013 +}
75014 +static DEVICE_ATTR(dump_regs, 0400, show_dump_regs, NULL);
75015 +
75016 +static ssize_t show_resume_reason(struct device *dev,
75017 + struct device_attribute *attr, char *buf)
75018 +{
75019 + struct pcf50606 *pcf = dev_get_drvdata(dev);
75020 + int n;
75021 +
75022 + n = sprintf(buf, "%02x%02x%02x\n",
75023 + pcf->resume_reason[0],
75024 + pcf->resume_reason[1],
75025 + pcf->resume_reason[2]);
75026 +
75027 + return n;
75028 +}
75029 +static DEVICE_ATTR(resume_reason, 0400, show_resume_reason, NULL);
75030 +
75031 +static struct attribute *pcf_sysfs_entries[] = {
75032 + &dev_attr_dump_regs.attr,
75033 + &dev_attr_resume_reason.attr,
75034 + NULL,
75035 +};
75036 +
75037 +static struct attribute_group pcf_attr_group = {
75038 + .name = NULL, /* put in device directory */
75039 + .attrs = pcf_sysfs_entries,
75040 +};
75041 +
75042 +int pcf50606_register_irq(struct pcf50606 *pcf, int irq,
75043 + void (*handler) (int, void *), void *data)
75044 +{
75045 + if (irq < 0 || irq > PCF50606_NUM_IRQ || !handler)
75046 + return -EINVAL;
75047 +
75048 + if (WARN_ON(pcf->irq_handler[irq].handler))
75049 + return -EBUSY;
75050 +
75051 + mutex_lock(&pcf->lock);
75052 + pcf->irq_handler[irq].handler = handler;
75053 + pcf->irq_handler[irq].data = data;
75054 + mutex_unlock(&pcf->lock);
75055 +
75056 + return 0;
75057 +}
75058 +EXPORT_SYMBOL_GPL(pcf50606_register_irq);
75059 +
75060 +int pcf50606_free_irq(struct pcf50606 *pcf, int irq)
75061 +{
75062 + if (irq < 0 || irq > PCF50606_NUM_IRQ)
75063 + return -EINVAL;
75064 +
75065 + mutex_lock(&pcf->lock);
75066 + pcf->irq_handler[irq].handler = NULL;
75067 + mutex_unlock(&pcf->lock);
75068 +
75069 + return 0;
75070 +}
75071 +EXPORT_SYMBOL_GPL(pcf50606_free_irq);
75072 +
75073 +static int __pcf50606_irq_mask_set(struct pcf50606 *pcf, int irq, u8 mask)
75074 +{
75075 + u8 reg, bits, tmp;
75076 + int ret = 0, idx;
75077 +
75078 + idx = irq >> 3;
75079 + reg = PCF50606_REG_INT1M + idx;
75080 + bits = 1 << (irq & 0x07);
75081 +
75082 + mutex_lock(&pcf->lock);
75083 +
75084 + if (mask) {
75085 + ret = __pcf50606_read(pcf, reg, 1, &tmp);
75086 + if (ret < 0)
75087 + goto out;
75088 +
75089 + tmp |= bits;
75090 +
75091 + ret = __pcf50606_write(pcf, reg, 1, &tmp);
75092 + if (ret < 0)
75093 + goto out;
75094 +
75095 + pcf->mask_regs[idx] &= ~bits;
75096 + pcf->mask_regs[idx] |= bits;
75097 + } else {
75098 + ret = __pcf50606_read(pcf, reg, 1, &tmp);
75099 + if (ret < 0)
75100 + goto out;
75101 +
75102 + tmp &= ~bits;
75103 +
75104 + ret = __pcf50606_write(pcf, reg, 1, &tmp);
75105 + if (ret < 0)
75106 + goto out;
75107 +
75108 + pcf->mask_regs[idx] &= ~bits;
75109 + }
75110 +out:
75111 + mutex_unlock(&pcf->lock);
75112 +
75113 + return ret;
75114 +}
75115 +
75116 +int pcf50606_irq_mask(struct pcf50606 *pcf, int irq)
75117 +{
75118 + dev_info(pcf->dev, "Masking IRQ %d\n", irq);
75119 +
75120 + return __pcf50606_irq_mask_set(pcf, irq, 1);
75121 +}
75122 +EXPORT_SYMBOL_GPL(pcf50606_irq_mask);
75123 +
75124 +int pcf50606_irq_unmask(struct pcf50606 *pcf, int irq)
75125 +{
75126 + dev_info(pcf->dev, "Unmasking IRQ %d\n", irq);
75127 +
75128 + return __pcf50606_irq_mask_set(pcf, irq, 0);
75129 +}
75130 +EXPORT_SYMBOL_GPL(pcf50606_irq_unmask);
75131 +
75132 +int pcf50606_irq_mask_get(struct pcf50606 *pcf, int irq)
75133 +{
75134 + u8 reg, bits;
75135 +
75136 + reg = (irq / 8);
75137 + bits = (1 << (irq % 8));
75138 +
75139 + return pcf->mask_regs[reg] & bits;
75140 +}
75141 +EXPORT_SYMBOL_GPL(pcf50606_irq_mask_get);
75142 +
75143 +static void pcf50606_irq_call_handler(struct pcf50606 *pcf,
75144 + int irq)
75145 +{
75146 + if (pcf->irq_handler[irq].handler)
75147 + pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
75148 +}
75149 +
75150 +#define PCF50606_ONKEY1S_TIMEOUT 8
75151 +
75152 +#define PCF50606_REG_MBCS1 0x2c
75153 +
75154 +static void pcf50606_irq_worker(struct work_struct *work)
75155 +{
75156 + struct pcf50606 *pcf;
75157 + int ret, i, j;
75158 + u8 pcf_int[3], chgstat;
75159 +
75160 + pcf = container_of(work, struct pcf50606, irq_work);
75161 +
75162 + /* Read the 3 INT regs in one transaction */
75163 + ret = pcf50606_read_block(pcf, PCF50606_REG_INT1,
75164 + ARRAY_SIZE(pcf_int), pcf_int);
75165 + if (ret != ARRAY_SIZE(pcf_int)) {
75166 + dev_info(pcf->dev, "Error reading INT registers\n");
75167 +
75168 + /*
75169 + * If this doesn't ACK the interrupt to the chip, we'll be
75170 + * called once again as we're level triggered.
75171 + */
75172 + goto out;
75173 + }
75174 +
75175 + /* We immediately read the charger status. We thus make sure
75176 + * only of CHGINS/CHGRM interrupt handlers are called */
75177 + if (pcf_int[1] & (PCF50606_INT2_CHGINS | PCF50606_INT2_CHGRM)) {
75178 + chgstat = pcf50606_reg_read(pcf, PCF50606_REG_MBCS1);
75179 + if (chgstat & (0x1 << 4))
75180 + pcf_int[1] &= ~(1 << PCF50606_INT2_CHGRM);
75181 + else
75182 + pcf_int[1] &= ~(1 << PCF50606_INT2_CHGINS);
75183 + }
75184 +
75185 + dev_dbg(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x\n",
75186 + pcf_int[0], pcf_int[1], pcf_int[2]);
75187 +
75188 + /* Some revisions of the chip don't have a 8s standby mode on
75189 + * ONKEY1S press. We try to manually do it in such cases. */
75190 + if (pcf_int[0] & PCF50606_INT1_SECOND && pcf->onkey1s_held) {
75191 + dev_info(pcf->dev, "ONKEY1S held for %d secs\n",
75192 + pcf->onkey1s_held);
75193 + if (pcf->onkey1s_held++ == PCF50606_ONKEY1S_TIMEOUT)
75194 + if (pcf->pdata->force_shutdown)
75195 + pcf->pdata->force_shutdown(pcf);
75196 + }
75197 +
75198 + if (pcf_int[0] & PCF50606_INT1_ONKEY1S) {
75199 + dev_info(pcf->dev, "ONKEY1S held\n");
75200 + pcf->onkey1s_held = 1 ;
75201 +
75202 + /* Unmask IRQ_SECOND */
75203 + pcf50606_reg_clear_bits(pcf, PCF50606_REG_INT1M,
75204 + PCF50606_INT1_SECOND);
75205 +
75206 + /* Unmask IRQ_ONKEYF */
75207 + pcf50606_reg_clear_bits(pcf, PCF50606_REG_INT1M,
75208 + PCF50606_INT1_ONKEYF);
75209 + }
75210 +
75211 + if ((pcf_int[0] & PCF50606_INT1_ONKEYR) && pcf->onkey1s_held) {
75212 + pcf->onkey1s_held = 0;
75213 +
75214 + /* Mask SECOND and ONKEYF interrupts */
75215 + if (pcf->mask_regs[0] & PCF50606_INT1_SECOND)
75216 + pcf50606_reg_set_bit_mask(pcf,
75217 + PCF50606_REG_INT1M,
75218 + PCF50606_INT1_SECOND,
75219 + PCF50606_INT1_SECOND);
75220 +
75221 + if (pcf->mask_regs[0] & PCF50606_INT1_ONKEYF)
75222 + pcf50606_reg_set_bit_mask(pcf,
75223 + PCF50606_REG_INT1M,
75224 + PCF50606_INT1_ONKEYF,
75225 + PCF50606_INT1_ONKEYF);
75226 + }
75227 +
75228 + /* Have we just resumed ? */
75229 + if (pcf->is_suspended) {
75230 +
75231 + pcf->is_suspended = 0;
75232 +
75233 + /* Set the resume reason filtering out non resumers */
75234 + for (i = 0; i < ARRAY_SIZE(pcf_int); i++)
75235 + pcf->resume_reason[i] = pcf_int[i] &
75236 + pcf->pdata->resumers[i];
75237 +
75238 + /* Make sure we don't pass on ONKEY events to
75239 + * userspace now */
75240 + pcf_int[1] &= ~(PCF50606_INT1_ONKEYR | PCF50606_INT1_ONKEYF);
75241 + }
75242 +
75243 + for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
75244 + /* Unset masked interrupts */
75245 + pcf_int[i] &= ~pcf->mask_regs[i];
75246 +
75247 + for (j = 0; j < 8 ; j++)
75248 + if (pcf_int[i] & (1 << j))
75249 + pcf50606_irq_call_handler(pcf, (i * 8) + j);
75250 + }
75251 +
75252 +out:
75253 + put_device(pcf->dev);
75254 + enable_irq(pcf->irq);
75255 +}
75256 +
75257 +static irqreturn_t pcf50606_irq(int irq, void *data)
75258 +{
75259 + struct pcf50606 *pcf = data;
75260 +
75261 + get_device(pcf->dev);
75262 + disable_irq(pcf->irq);
75263 + schedule_work(&pcf->irq_work);
75264 +
75265 + return IRQ_HANDLED;
75266 +}
75267 +
75268 +static void
75269 +pcf50606_client_dev_register(struct pcf50606 *pcf, const char *name,
75270 + struct platform_device **pdev)
75271 +{
75272 + struct pcf50606_subdev_pdata subdev_pdata;
75273 + int ret;
75274 +
75275 + *pdev = platform_device_alloc(name, -1);
75276 + if (!*pdev) {
75277 + dev_err(pcf->dev, "Falied to allocate %s\n", name);
75278 + return;
75279 + }
75280 +
75281 + subdev_pdata.pcf = pcf;
75282 + platform_device_add_data(*pdev, &subdev_pdata, sizeof(subdev_pdata));
75283 +
75284 + (*pdev)->dev.parent = pcf->dev;
75285 +
75286 + ret = platform_device_add(*pdev);
75287 + if (ret) {
75288 + dev_err(pcf->dev, "Failed to register %s: %d\n", name, ret);
75289 + platform_device_put(*pdev);
75290 + *pdev = NULL;
75291 + }
75292 +}
75293 +
75294 +#ifdef CONFIG_PM
75295 +static int pcf50606_suspend(struct device *dev, pm_message_t state)
75296 +{
75297 + struct pcf50606 *pcf;
75298 + int ret, i;
75299 + u8 res[3];
75300 +
75301 + pcf = dev_get_drvdata(dev);
75302 +
75303 + /* Make sure our interrupt handlers are not called
75304 + * henceforth */
75305 + disable_irq(pcf->irq);
75306 +
75307 + /* Make sure that any running IRQ worker has quit */
75308 + cancel_work_sync(&pcf->irq_work);
75309 +
75310 + /* Save the masks */
75311 + ret = pcf50606_read_block(pcf, PCF50606_REG_INT1M,
75312 + ARRAY_SIZE(pcf->suspend_irq_masks),
75313 + pcf->suspend_irq_masks);
75314 + if (ret < 0) {
75315 + dev_err(pcf->dev, "error saving irq masks\n");
75316 + goto out;
75317 + }
75318 +
75319 + /* Write wakeup irq masks */
75320 + for (i = 0; i < ARRAY_SIZE(res); i++)
75321 + res[i] = ~pcf->pdata->resumers[i];
75322 +
75323 + ret = pcf50606_write_block(pcf, PCF50606_REG_INT1M,
75324 + ARRAY_SIZE(res), &res[0]);
75325 + if (ret < 0) {
75326 + dev_err(pcf->dev, "error writing wakeup irq masks\n");
75327 + goto out;
75328 + }
75329 +
75330 + pcf->is_suspended = 1;
75331 +
75332 +out:
75333 + return ret;
75334 +}
75335 +
75336 +static int pcf50606_resume(struct device *dev)
75337 +{
75338 + struct pcf50606 *pcf;
75339 + int ret;
75340 +
75341 + pcf = dev_get_drvdata(dev);
75342 +
75343 + /* Write the saved mask registers */
75344 + ret = pcf50606_write_block(pcf, PCF50606_REG_INT1M,
75345 + ARRAY_SIZE(pcf->suspend_irq_masks),
75346 + pcf->suspend_irq_masks);
75347 + if (ret < 0)
75348 + dev_err(pcf->dev, "Error restoring saved suspend masks\n");
75349 +
75350 + get_device(pcf->dev);
75351 +
75352 + /*
75353 + * Clear any pending interrupts and set resume reason if any.
75354 + * This will leave with enable_irq()
75355 + */
75356 + pcf50606_irq_worker(&pcf->irq_work);
75357 +
75358 + return 0;
75359 +}
75360 +#else
75361 +#define pcf50606_suspend NULL
75362 +#define pcf50606_resume NULL
75363 +#endif
75364 +
75365 +static int pcf50606_probe(struct i2c_client *client,
75366 + const struct i2c_device_id *ids)
75367 +{
75368 + struct pcf50606 *pcf;
75369 + struct pcf50606_platform_data *pdata = client->dev.platform_data;
75370 + int i, ret = 0;
75371 + int version, variant;
75372 +
75373 + pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
75374 + if (!pcf)
75375 + return -ENOMEM;
75376 +
75377 + pcf->pdata = pdata;
75378 +
75379 + mutex_init(&pcf->lock);
75380 +
75381 + i2c_set_clientdata(client, pcf);
75382 + pcf->dev = &client->dev;
75383 + pcf->i2c_client = client;
75384 + pcf->irq = client->irq;
75385 +
75386 + INIT_WORK(&pcf->irq_work, pcf50606_irq_worker);
75387 +
75388 + version = pcf50606_reg_read(pcf, 0);
75389 + variant = pcf50606_reg_read(pcf, 1);
75390 + if (version < 0 || variant < 0) {
75391 + dev_err(pcf->dev, "Unable to probe pcf50606\n");
75392 + ret = -ENODEV;
75393 + goto err;
75394 + }
75395 +
75396 + dev_info(pcf->dev, "Probed device version %d variant %d\n",
75397 + version, variant);
75398 + /* Enable all inteerupts except RTC SECOND */
75399 + pcf->mask_regs[0] = 0x40;
75400 + pcf50606_reg_write(pcf, PCF50606_REG_INT1M, pcf->mask_regs[0]);
75401 + pcf50606_reg_write(pcf, PCF50606_REG_INT2M, 0x00);
75402 + pcf50606_reg_write(pcf, PCF50606_REG_INT3M, 0x00);
75403 +
75404 + pcf50606_client_dev_register(pcf, "pcf50606-input",
75405 + &pcf->input_pdev);
75406 + pcf50606_client_dev_register(pcf, "pcf50606-rtc",
75407 + &pcf->rtc_pdev);
75408 + pcf50606_client_dev_register(pcf, "pcf50606-mbc",
75409 + &pcf->mbc_pdev);
75410 + pcf50606_client_dev_register(pcf, "pcf50606-adc",
75411 + &pcf->adc_pdev);
75412 + pcf50606_client_dev_register(pcf, "pcf50606-wdt",
75413 + &pcf->wdt_pdev);
75414 + for (i = 0; i < PCF50606_NUM_REGULATORS; i++) {
75415 + struct platform_device *pdev;
75416 +
75417 + pdev = platform_device_alloc("pcf50606-regltr", i);
75418 + if (!pdev) {
75419 + dev_err(pcf->dev, "Cannot create regulator\n");
75420 + continue;
75421 + }
75422 +
75423 + pdev->dev.parent = pcf->dev;
75424 + pdev->dev.platform_data = &pdata->reg_init_data[i];
75425 + pdev->dev.driver_data = pcf;
75426 + pcf->regulator_pdev[i] = pdev;
75427 +
75428 + platform_device_add(pdev);
75429 + }
75430 +
75431 + if (client->irq) {
75432 + set_irq_handler(client->irq, handle_level_irq);
75433 + ret = request_irq(client->irq, pcf50606_irq,
75434 + IRQF_TRIGGER_LOW, "pcf50606", pcf);
75435 +
75436 + if (ret) {
75437 + dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
75438 + goto err;
75439 + }
75440 + } else {
75441 + dev_err(pcf->dev, "No IRQ configured\n");
75442 + goto err;
75443 + }
75444 +
75445 + if (enable_irq_wake(client->irq) < 0)
75446 + dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up source"
75447 + "in this hardware revision", client->irq);
75448 +
75449 + ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
75450 + if (ret)
75451 + dev_err(pcf->dev, "error creating sysfs entries\n");
75452 +
75453 + if (pdata->probe_done)
75454 + pdata->probe_done(pcf);
75455 +
75456 + return 0;
75457 +
75458 +err:
75459 + kfree(pcf);
75460 + return ret;
75461 +}
75462 +
75463 +static int pcf50606_remove(struct i2c_client *client)
75464 +{
75465 + struct pcf50606 *pcf = i2c_get_clientdata(client);
75466 + int i;
75467 +
75468 + free_irq(pcf->irq, pcf);
75469 +
75470 + platform_device_unregister(pcf->input_pdev);
75471 + platform_device_unregister(pcf->rtc_pdev);
75472 + platform_device_unregister(pcf->mbc_pdev);
75473 + platform_device_unregister(pcf->adc_pdev);
75474 +
75475 + for (i = 0; i < PCF50606_NUM_REGULATORS; i++)
75476 + platform_device_unregister(pcf->regulator_pdev[i]);
75477 +
75478 + kfree(pcf);
75479 +
75480 + return 0;
75481 +}
75482 +
75483 +static struct i2c_device_id pcf50606_id_table[] = {
75484 + {"pcf50606", 0x08},
75485 +};
75486 +
75487 +static struct i2c_driver pcf50606_driver = {
75488 + .driver = {
75489 + .name = "pcf50606",
75490 + .suspend = pcf50606_suspend,
75491 + .resume = pcf50606_resume,
75492 + },
75493 + .id_table = pcf50606_id_table,
75494 + .probe = pcf50606_probe,
75495 + .remove = pcf50606_remove,
75496 +};
75497 +
75498 +static int __init pcf50606_init(void)
75499 +{
75500 + return i2c_add_driver(&pcf50606_driver);
75501 +}
75502 +
75503 +static void pcf50606_exit(void)
75504 +{
75505 + i2c_del_driver(&pcf50606_driver);
75506 +}
75507 +
75508 +MODULE_DESCRIPTION("I2C chip driver for NXP PCF50606 PMU");
75509 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
75510 +MODULE_LICENSE("GPL");
75511 +
75512 +module_init(pcf50606_init);
75513 +module_exit(pcf50606_exit);
75514 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/pcf50606-gpo.c linux-2.6.29-rc3.owrt.om/drivers/mfd/pcf50606-gpo.c
75515 --- linux-2.6.29-rc3.owrt/drivers/mfd/pcf50606-gpo.c 1970-01-01 01:00:00.000000000 +0100
75516 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/pcf50606-gpo.c 2009-05-10 22:28:00.000000000 +0200
75517 @@ -0,0 +1,119 @@
75518 +/* Philips PCF50606 GPO Driver
75519 + *
75520 + * (C) 2006-2008 by Openmoko, Inc.
75521 + * Author: Balaji Rao <balajirrao@openmoko.org>
75522 + * All rights reserved.
75523 + *
75524 + * Broken down from monstrous PCF50606 driver mainly by
75525 + * Harald Welte, Andy Green Werner Almesberger and Matt Hsu
75526 + *
75527 + * This program is free software; you can redistribute it and/or
75528 + * modify it under the terms of the GNU General Public License as
75529 + * published by the Free Software Foundation; either version 2 of
75530 + * the License, or (at your option) any later version.
75531 + */
75532 +
75533 +#include <linux/kernel.h>
75534 +
75535 +#include <linux/mfd/pcf50606/core.h>
75536 +#include <linux/mfd/pcf50606/gpo.h>
75537 +
75538 +void pcf50606_gpo_set_active(struct pcf50606 *pcf, int gpo, int val)
75539 +{
75540 + u8 reg, value, mask;
75541 +
75542 + reg = gpo;
75543 + value = val;
75544 + mask = 0x07;
75545 +
75546 + if (gpo == PCF50606_GPO2) {
75547 + value = val << 4;
75548 + mask = 0x07 << 4;
75549 + }
75550 + pcf50606_reg_set_bit_mask(pcf, reg, mask, value);
75551 +}
75552 +EXPORT_SYMBOL_GPL(pcf50606_gpo_set_active);
75553 +
75554 +int pcf50606_gpo_get_active(struct pcf50606 *pcf, int gpo)
75555 +{
75556 + u8 reg, value, shift = 0;
75557 +
75558 + reg = gpo;
75559 + if (gpo == PCF50606_GPO2)
75560 + shift = 4;
75561 +
75562 + value = pcf50606_reg_read(pcf, reg);
75563 +
75564 + return (value >> shift) & 0x07;
75565 +}
75566 +EXPORT_SYMBOL_GPL(pcf50606_gpo_get_active);
75567 +
75568 +void pcf50606_gpo_set_standby(struct pcf50606 *pcf, int gpo, int val)
75569 +{
75570 + u8 reg;
75571 +
75572 + if (gpo == PCF50606_GPO1 || gpo == PCF50606_GPO2) {
75573 + dev_err(pcf->dev, "Can't set standby settings for GPO[12]n");
75574 + return;
75575 + }
75576 +
75577 + reg = gpo;
75578 +
75579 + pcf50606_reg_set_bit_mask(pcf, gpo, 0x07 << 3, val);
75580 +}
75581 +EXPORT_SYMBOL_GPL(pcf50606_gpo_set_standby);
75582 +
75583 +int pcf50606_gpo_get_standby(struct pcf50606 *pcf, int gpo)
75584 +{
75585 + u8 reg, value;
75586 +
75587 + if (gpo == PCF50606_GPO1 || gpo == PCF50606_GPO2) {
75588 + dev_err(pcf->dev, "Can't get standby settings for GPO[12]n");
75589 + return -EINVAL;
75590 + }
75591 +
75592 + reg = gpo;
75593 + value = pcf50606_reg_read(pcf, reg);
75594 +
75595 + return (value >> 3) & 0x07;
75596 +}
75597 +EXPORT_SYMBOL_GPL(pcf50606_gpo_get_standby);
75598 +
75599 +void pcf50606_gpo_invert_set(struct pcf50606 *pcf, int gpo, int invert)
75600 +{
75601 + u8 reg, value, mask;
75602 +
75603 + reg = gpo;
75604 + value = !!invert << 6;
75605 + mask = 0x01 << 6;
75606 +
75607 + if (gpo == PCF50606_GPO1) {
75608 + mask = 0x01 << 4;
75609 + value = !!invert << 4;
75610 + }
75611 + else if (gpo == PCF50606_GPO2) {
75612 + mask = 0x01 << 7;
75613 + value = !!invert << 7;
75614 + }
75615 +
75616 + pcf50606_reg_set_bit_mask(pcf, reg, mask, value);
75617 +}
75618 +EXPORT_SYMBOL_GPL(pcf50606_gpo_invert_set);
75619 +
75620 +int pcf50606_gpo_invert_get(struct pcf50606 *pcf, int gpo)
75621 +{
75622 + u8 reg, value, shift;
75623 +
75624 + reg = gpo;
75625 + shift = 6;
75626 +
75627 + if (gpo == PCF50606_GPO1)
75628 + shift = 4;
75629 + else if (gpo == PCF50606_GPO2)
75630 + shift = 7;
75631 +
75632 + value = pcf50606_reg_read(pcf, reg);
75633 +
75634 + return (value >> shift) & 0x01;
75635 +}
75636 +EXPORT_SYMBOL_GPL(pcf50606_gpo_invert_get);
75637 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mfd/pcf50633-core.c linux-2.6.29-rc3.owrt.om/drivers/mfd/pcf50633-core.c
75638 --- linux-2.6.29-rc3.owrt/drivers/mfd/pcf50633-core.c 2009-05-10 22:08:43.000000000 +0200
75639 +++ linux-2.6.29-rc3.owrt.om/drivers/mfd/pcf50633-core.c 2009-05-10 22:28:00.000000000 +0200
75640 @@ -346,6 +346,8 @@
75641 goto out;
75642 }
75643
75644 + pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04 ); /* defeat 8s death from lowsys on A5 */
75645 +
75646 /* We immediately read the usb and adapter status. We thus make sure
75647 * only of USBINS/USBREM IRQ handlers are called */
75648 if (pcf_int[0] & (PCF50633_INT1_USBINS | PCF50633_INT1_USBREM)) {
75649 @@ -445,6 +447,7 @@
75650
75651 get_device(pcf->dev);
75652 disable_irq(pcf->irq);
75653 +
75654 schedule_work(&pcf->irq_work);
75655
75656 return IRQ_HANDLED;
75657 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/misc/Kconfig linux-2.6.29-rc3.owrt.om/drivers/misc/Kconfig
75658 --- linux-2.6.29-rc3.owrt/drivers/misc/Kconfig 2009-05-10 22:08:43.000000000 +0200
75659 +++ linux-2.6.29-rc3.owrt.om/drivers/misc/Kconfig 2009-05-10 22:28:00.000000000 +0200
75660 @@ -225,4 +225,10 @@
75661 source "drivers/misc/c2port/Kconfig"
75662 source "drivers/misc/eeprom/Kconfig"
75663
75664 +config MACH_NEO1973
75665 + bool
75666 + help
75667 + Common machine code for Openmoko GTAxx hardware
75668 +
75669 endif # MISC_DEVICES
75670 +
75671 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/misc/Makefile linux-2.6.29-rc3.owrt.om/drivers/misc/Makefile
75672 --- linux-2.6.29-rc3.owrt/drivers/misc/Makefile 2009-05-10 22:04:49.000000000 +0200
75673 +++ linux-2.6.29-rc3.owrt.om/drivers/misc/Makefile 2009-05-10 22:28:00.000000000 +0200
75674 @@ -20,3 +20,8 @@
75675 obj-$(CONFIG_HP_ILO) += hpilo.o
75676 obj-$(CONFIG_C2PORT) += c2port/
75677 obj-y += eeprom/
75678 +obj-$(CONFIG_MACH_SMDK6410) += smdk6410-sleeptest.o
75679 +obj-$(CONFIG_MACH_NEO1973) += neo1973_version.o \
75680 + neo1973_pm_host.o \
75681 + neo1973_pm_resume_reason.o
75682 +
75683 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/misc/neo1973_pm_charging_led.c linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_pm_charging_led.c
75684 --- linux-2.6.29-rc3.owrt/drivers/misc/neo1973_pm_charging_led.c 1970-01-01 01:00:00.000000000 +0100
75685 +++ linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_pm_charging_led.c 2009-05-10 22:28:00.000000000 +0200
75686 @@ -0,0 +1,106 @@
75687 +/*
75688 + * Charging LED sysfs for the FIC Neo1973 GSM Phone
75689 + * (currently only implemented in GTA02 but ready for GTA01 implementation)
75690 + *
75691 + * (C) 2008 by Openmoko Inc.
75692 + * Author: Andy Green <andy@openmoko.com>
75693 + * All rights reserved.
75694 + *
75695 + * This program is free software; you can redistribute it and/or modify
75696 + * it under the terms of the GNU General Public License charging_led 2 as
75697 + * published by the Free Software Foundation
75698 + *
75699 + */
75700 +
75701 +#include <linux/module.h>
75702 +#include <linux/init.h>
75703 +#include <linux/kernel.h>
75704 +#include <linux/platform_device.h>
75705 +
75706 +#include <asm/hardware.h>
75707 +#include <asm/mach-types.h>
75708 +
75709 +#ifdef CONFIG_MACH_NEO1973_GTA02
75710 +#include <asm/arch/gta02.h>
75711 +
75712 +static enum neo1973_charging_led_modes charging_mode;
75713 +
75714 +static char *charging_led_mode_names[] = {
75715 + "Disabled",
75716 + "Aux LED",
75717 + "Power LED"
75718 +};
75719 +
75720 +static ssize_t charging_led_read(struct device *dev,
75721 + struct device_attribute *attr, char *buf)
75722 +{
75723 + return sprintf(buf, "0x%03X\n", gta02_get_pcb_revision());
75724 +}
75725 +
75726 +static ssize_t charging_led_read(struct device *dev,
75727 + struct device_attribute *attr, char *buf)
75728 +{
75729 + return sprintf(buf, "0x%03X\n", gta02_get_pcb_revision());
75730 +}
75731 +
75732 +
75733 +static DEVICE_ATTR(pcb, 0644, charging_led_read, charging_led_write);
75734 +
75735 +static struct attribute *neo1973_charging_led_sysfs_entries[] = {
75736 + &dev_attr_pcb.attr,
75737 + NULL
75738 +};
75739 +
75740 +static struct attribute_group neo1973_charging_led_attr_group = {
75741 + .name = NULL,
75742 + .attrs = neo1973_charging_led_sysfs_entries,
75743 +};
75744 +
75745 +static int __init neo1973_charging_led_probe(struct platform_device *pdev)
75746 +{
75747 + dev_info(&pdev->dev, "starting\n");
75748 +
75749 + switch (machine_arch_type) {
75750 +#ifdef CONFIG_MACH_NEO1973_GTA01
75751 + case MACH_TYPE_NEO1973_GTA01:
75752 + return -EINVAL;
75753 +#endif /* CONFIG_MACH_NEO1973_GTA01 */
75754 + default:
75755 + break;
75756 + }
75757 +
75758 + return sysfs_create_group(&pdev->dev.kobj,
75759 + &neo1973_charging_led_attr_group);
75760 +}
75761 +
75762 +static int neo1973_charging_led_remove(struct platform_device *pdev)
75763 +{
75764 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_charging_led_attr_group);
75765 + return 0;
75766 +}
75767 +
75768 +static struct platform_driver neo1973_charging_led_driver = {
75769 + .probe = neo1973_charging_led_probe,
75770 + .remove = neo1973_charging_led_remove,
75771 + .driver = {
75772 + .name = "neo1973-charging-led",
75773 + },
75774 +};
75775 +
75776 +static int __devinit neo1973_charging_led_init(void)
75777 +{
75778 + return platform_driver_register(&neo1973_charging_led_driver);
75779 +}
75780 +
75781 +static void neo1973_charging_led_exit(void)
75782 +{
75783 + platform_driver_unregister(&neo1973_charging_led_driver);
75784 +}
75785 +
75786 +module_init(neo1973_charging_led_init);
75787 +module_exit(neo1973_charging_led_exit);
75788 +
75789 +MODULE_LICENSE("GPL");
75790 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
75791 +MODULE_DESCRIPTION("Neo1973 PCB charging_led");
75792 +#endif
75793 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/misc/neo1973_pm_host.c linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_pm_host.c
75794 --- linux-2.6.29-rc3.owrt/drivers/misc/neo1973_pm_host.c 1970-01-01 01:00:00.000000000 +0100
75795 +++ linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_pm_host.c 2009-05-10 22:28:00.000000000 +0200
75796 @@ -0,0 +1,109 @@
75797 +/*
75798 + * Bluetooth PM code for the FIC Neo1973 GSM Phone
75799 + *
75800 + * (C) 2007 by Openmoko Inc.
75801 + * Author: Harald Welte <laforge@openmoko.org>
75802 + * All rights reserved.
75803 + *
75804 + * This program is free software; you can redistribute it and/or modify
75805 + * it under the terms of the GNU General Public License version 2 as
75806 + * published by the Free Software Foundation
75807 + *
75808 + */
75809 +
75810 +#include <linux/module.h>
75811 +#include <linux/init.h>
75812 +#include <linux/kernel.h>
75813 +#include <linux/platform_device.h>
75814 +
75815 +#include <mach/hardware.h>
75816 +#include <asm/mach-types.h>
75817 +
75818 +#ifdef CONFIG_MACH_NEO1973_GTA02
75819 +#include <mach/gta02.h>
75820 +#include <linux/mfd/pcf50633/gpio.h>
75821 +
75822 +static ssize_t pm_host_read(struct device *dev, struct device_attribute *attr,
75823 + char *buf)
75824 +{
75825 + return sprintf(buf, "%d\n",
75826 + pcf50633_gpio_get(gta02_pcf, PCF50633_GPO)
75827 + == PCF50633_GPOCFG_GPOSEL_1);
75828 +}
75829 +
75830 +static ssize_t pm_host_write(struct device *dev, struct device_attribute *attr,
75831 + const char *buf, size_t count)
75832 +{
75833 + unsigned long on = simple_strtoul(buf, NULL, 10);
75834 + u8 val;
75835 +
75836 + if (on)
75837 + val = PCF50633_GPOCFG_GPOSEL_1;
75838 + else
75839 + val = PCF50633_GPOCFG_GPOSEL_0;
75840 +
75841 +
75842 + pcf50633_gpio_set(gta02_pcf, PCF50633_GPO, val);
75843 +
75844 + return count;
75845 +}
75846 +
75847 +static DEVICE_ATTR(hostmode, 0644, pm_host_read, pm_host_write);
75848 +
75849 +static struct attribute *neo1973_pm_host_sysfs_entries[] = {
75850 + &dev_attr_hostmode.attr,
75851 + NULL
75852 +};
75853 +
75854 +static struct attribute_group neo1973_pm_host_attr_group = {
75855 + .name = NULL,
75856 + .attrs = neo1973_pm_host_sysfs_entries,
75857 +};
75858 +
75859 +static int __init neo1973_pm_host_probe(struct platform_device *pdev)
75860 +{
75861 + dev_info(&pdev->dev, "starting\n");
75862 +
75863 + switch (machine_arch_type) {
75864 +#ifdef CONFIG_MACH_NEO1973_GTA01
75865 + case MACH_TYPE_NEO1973_GTA01:
75866 + return -EINVAL;
75867 +#endif /* CONFIG_MACH_NEO1973_GTA01 */
75868 + default:
75869 + break;
75870 + }
75871 +
75872 + return sysfs_create_group(&pdev->dev.kobj, &neo1973_pm_host_attr_group);
75873 +}
75874 +
75875 +static int neo1973_pm_host_remove(struct platform_device *pdev)
75876 +{
75877 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_pm_host_attr_group);
75878 + return 0;
75879 +}
75880 +
75881 +static struct platform_driver neo1973_pm_host_driver = {
75882 + .probe = neo1973_pm_host_probe,
75883 + .remove = neo1973_pm_host_remove,
75884 + .driver = {
75885 + .name = "neo1973-pm-host",
75886 + },
75887 +};
75888 +
75889 +static int __devinit neo1973_pm_host_init(void)
75890 +{
75891 + return platform_driver_register(&neo1973_pm_host_driver);
75892 +}
75893 +
75894 +static void neo1973_pm_host_exit(void)
75895 +{
75896 + platform_driver_unregister(&neo1973_pm_host_driver);
75897 +}
75898 +
75899 +module_init(neo1973_pm_host_init);
75900 +module_exit(neo1973_pm_host_exit);
75901 +
75902 +MODULE_LICENSE("GPL");
75903 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
75904 +MODULE_DESCRIPTION("Neo1973 USB Host Power Management");
75905 +#endif
75906 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/misc/neo1973_pm_resume_reason.c linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_pm_resume_reason.c
75907 --- linux-2.6.29-rc3.owrt/drivers/misc/neo1973_pm_resume_reason.c 1970-01-01 01:00:00.000000000 +0100
75908 +++ linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_pm_resume_reason.c 2009-05-10 22:28:00.000000000 +0200
75909 @@ -0,0 +1,147 @@
75910 +/*
75911 + * Resume reason sysfs for the FIC Neo1973 GSM Phone
75912 + *
75913 + * (C) 2008 by Openmoko Inc.
75914 + * Author: Andy Green <andy@openmoko.com>
75915 + * All rights reserved.
75916 + *
75917 + * This program is free software; you can redistribute it and/or modify
75918 + * it under the terms of the GNU General Public License resume_reason 2 as
75919 + * published by the Free Software Foundation
75920 + *
75921 + */
75922 +
75923 +#include <linux/module.h>
75924 +#include <linux/init.h>
75925 +#include <linux/kernel.h>
75926 +#include <linux/platform_device.h>
75927 +#include <linux/io.h>
75928 +
75929 +#include <mach/hardware.h>
75930 +#include <asm/mach-types.h>
75931 +
75932 +#ifdef CONFIG_MACH_NEO1973_GTA02
75933 +#include <mach/gta02.h>
75934 +#include <linux/mfd/pcf50633/core.h>
75935 +#endif
75936 +
75937 +static unsigned int *gstatus4_mapped;
75938 +static char *resume_reasons[][17] = { { /* GTA01 */
75939 + "EINT00_NULL",
75940 + "EINT01_GSM",
75941 + "EINT02_NULL",
75942 + "EINT03_NULL",
75943 + "EINT04_JACK",
75944 + "EINT05_SDCARD",
75945 + "EINT06_AUXKEY",
75946 + "EINT07_HOLDKEY",
75947 + "EINT08_NULL",
75948 + "EINT09_NULL",
75949 + "EINT10_NULL",
75950 + "EINT11_NULL",
75951 + "EINT12_NULL",
75952 + "EINT13_NULL",
75953 + "EINT14_NULL",
75954 + "EINT15_NULL",
75955 + NULL
75956 +}, { /* GTA02 */
75957 + "EINT00_ACCEL1",
75958 + "EINT01_GSM",
75959 + "EINT02_BLUETOOTH",
75960 + "EINT03_DEBUGBRD",
75961 + "EINT04_JACK",
75962 + "EINT05_WLAN",
75963 + "EINT06_AUXKEY",
75964 + "EINT07_HOLDKEY",
75965 + "EINT08_ACCEL2",
75966 + "EINT09_PMU",
75967 + "EINT10_NULL",
75968 + "EINT11_NULL",
75969 + "EINT12_GLAMO",
75970 + "EINT13_NULL",
75971 + "EINT14_NULL",
75972 + "EINT15_NULL",
75973 + NULL
75974 +} };
75975 +
75976 +static ssize_t resume_reason_read(struct device *dev,
75977 + struct device_attribute *attr,
75978 + char *buf)
75979 +{
75980 + int bit = 0;
75981 + char *end = buf;
75982 + int gta = !!machine_is_neo1973_gta02();
75983 +
75984 + for (bit = 0; resume_reasons[gta][bit]; bit++) {
75985 + if ((*gstatus4_mapped) & (1 << bit))
75986 + end += sprintf(end, "* %s\n", resume_reasons[gta][bit]);
75987 + else
75988 + end += sprintf(end, " %s\n", resume_reasons[gta][bit]);
75989 +
75990 +#ifdef CONFIG_MACH_NEO1973_GTA02
75991 + if ((gta) && (bit == 9)); /* PMU */
75992 +// end += pcf50633_report_resumers(gta02_pcf_pdata.pcf, end);
75993 +#endif
75994 + }
75995 +
75996 + return end - buf;
75997 +}
75998 +
75999 +
76000 +static DEVICE_ATTR(resume_reason, 0644, resume_reason_read, NULL);
76001 +
76002 +static struct attribute *neo1973_resume_reason_sysfs_entries[] = {
76003 + &dev_attr_resume_reason.attr,
76004 + NULL
76005 +};
76006 +
76007 +static struct attribute_group neo1973_resume_reason_attr_group = {
76008 + .name = NULL,
76009 + .attrs = neo1973_resume_reason_sysfs_entries,
76010 +};
76011 +
76012 +static int __init neo1973_resume_reason_probe(struct platform_device *pdev)
76013 +{
76014 + dev_info(&pdev->dev, "starting\n");
76015 +
76016 + gstatus4_mapped = ioremap(0x560000BC /* GSTATUS4 */, 0x4);
76017 + if (!gstatus4_mapped) {
76018 + dev_err(&pdev->dev, "failed to ioremap() memory region\n");
76019 + return -EINVAL;
76020 + }
76021 +
76022 + return sysfs_create_group(&pdev->dev.kobj,
76023 + &neo1973_resume_reason_attr_group);
76024 +}
76025 +
76026 +static int neo1973_resume_reason_remove(struct platform_device *pdev)
76027 +{
76028 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_resume_reason_attr_group);
76029 + iounmap(gstatus4_mapped);
76030 + return 0;
76031 +}
76032 +
76033 +static struct platform_driver neo1973_resume_reason_driver = {
76034 + .probe = neo1973_resume_reason_probe,
76035 + .remove = neo1973_resume_reason_remove,
76036 + .driver = {
76037 + .name = "neo1973-resume",
76038 + },
76039 +};
76040 +
76041 +static int __devinit neo1973_resume_reason_init(void)
76042 +{
76043 + return platform_driver_register(&neo1973_resume_reason_driver);
76044 +}
76045 +
76046 +static void neo1973_resume_reason_exit(void)
76047 +{
76048 + platform_driver_unregister(&neo1973_resume_reason_driver);
76049 +}
76050 +
76051 +module_init(neo1973_resume_reason_init);
76052 +module_exit(neo1973_resume_reason_exit);
76053 +
76054 +MODULE_LICENSE("GPL");
76055 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
76056 +MODULE_DESCRIPTION("Neo1973 resume_reason");
76057 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/misc/neo1973_pm_usbhost.c linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_pm_usbhost.c
76058 --- linux-2.6.29-rc3.owrt/drivers/misc/neo1973_pm_usbhost.c 1970-01-01 01:00:00.000000000 +0100
76059 +++ linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_pm_usbhost.c 2009-05-10 22:28:00.000000000 +0200
76060 @@ -0,0 +1,132 @@
76061 +/*
76062 + * Bluetooth PM code for the FIC Neo1973 GSM Phone
76063 + *
76064 + * (C) 2007 by OpenMoko Inc.
76065 + * Author: Harald Welte <laforge@openmoko.org>
76066 + * All rights reserved.
76067 + *
76068 + * This program is free software; you can redistribute it and/or modify
76069 + * it under the terms of the GNU General Public License version 2 as
76070 + * published by the Free Software Foundation
76071 + *
76072 + */
76073 +
76074 +#include <linux/module.h>
76075 +#include <linux/init.h>
76076 +#include <linux/kernel.h>
76077 +#include <linux/platform_device.h>
76078 +
76079 +#include <asm/hardware.h>
76080 +#include <asm/mach-types.h>
76081 +
76082 +#ifdef CONFIG_MACH_NEO1973_GTA02
76083 +#include <asm/arch/gta02.h>
76084 +#include <linux/pcf50633.h>
76085 +#endif
76086 +
76087 +static ssize_t pm_usbhost_read(struct device *dev, struct device_attribute *attr,
76088 + char *buf)
76089 +{
76090 + return sprintf(buf, "%d\n",
76091 + pcf50633_gpio_get(pcf50633_global, PCF50633_GPO));
76092 +}
76093 +
76094 +static ssize_t pm_usbhost_write(struct device *dev, struct device_attribute *attr,
76095 + const char *buf, size_t count)
76096 +{
76097 + unsigned long on = simple_strtoul(buf, NULL, 10);
76098 +
76099 + pcf50633_gpio_set(pcf50633_global, PCF50633_GPO, on);
76100 +
76101 + return count;
76102 +}
76103 +
76104 +static DEVICE_ATTR(hostmode, 0644, pm_usbhost_read, pm_usbhost_write);
76105 +
76106 +#ifdef CONFIG_PM
76107 +static int neo1973_usbhost_suspend(struct platform_device *pdev, pm_message_t state)
76108 +{
76109 + dev_dbg(&pdev->dev, "suspending\n");
76110 + /* FIXME: The PMU should save the PMU status, and the GPIO code should
76111 + * preserve the GPIO level, so there shouldn't be anything left to do
76112 + * for us, should there? */
76113 +
76114 + return 0;
76115 +}
76116 +
76117 +static int neo1973_usbhost_resume(struct platform_device *pdev)
76118 +{
76119 + dev_dbg(&pdev->dev, "resuming\n");
76120 +
76121 + return 0;
76122 +}
76123 +#else
76124 +#define neo1973_usbhost_suspend NULL
76125 +#define neo1973_usbhost_resume NULL
76126 +#endif
76127 +
76128 +static struct attribute *neo1973_usbhost_sysfs_entries[] = {
76129 + &dev_attr_hostmode.attr,
76130 + NULL
76131 +};
76132 +
76133 +static struct attribute_group neo1973_usbhost_attr_group = {
76134 + .name = NULL,
76135 + .attrs = neo1973_usbhost_sysfs_entries,
76136 +};
76137 +
76138 +static int __init neo1973_usbhost_probe(struct platform_device *pdev)
76139 +{
76140 + dev_info(&pdev->dev, "starting\n");
76141 +
76142 + switch (machine_arch_type) {
76143 +
76144 +#ifdef CONFIG_MACH_NEO1973_GTA01
76145 + case MACH_TYPE_NEO1973_GTA01:
76146 + return -EINVAL;
76147 +#endif /* CONFIG_MACH_NEO1973_GTA01 */
76148 +
76149 +#ifdef CONFIG_MACH_NEO1973_GTA02
76150 + case MACH_TYPE_NEO1973_GTA02:
76151 +/* race */
76152 +/* pcf50633_gpio_set(pcf50633_global, PCF50633_GPO, 0); */
76153 + break;
76154 +#endif /* CONFIG_MACH_NEO1973_GTA02 */
76155 + }
76156 +
76157 + return sysfs_create_group(&pdev->dev.kobj, &neo1973_usbhost_attr_group);
76158 +}
76159 +
76160 +static int neo1973_usbhost_remove(struct platform_device *pdev)
76161 +{
76162 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_usbhost_attr_group);
76163 +
76164 + return 0;
76165 +}
76166 +
76167 +static struct platform_driver neo1973_usbhost_driver = {
76168 + .probe = neo1973_usbhost_probe,
76169 + .remove = neo1973_usbhost_remove,
76170 + .suspend = neo1973_usbhost_suspend,
76171 + .resume = neo1973_usbhost_resume,
76172 + .driver = {
76173 + .name = "neo1973-pm-host",
76174 + },
76175 +};
76176 +
76177 +static int __devinit neo1973_usbhost_init(void)
76178 +{
76179 + return platform_driver_register(&neo1973_usbhost_driver);
76180 +}
76181 +
76182 +static void neo1973_usbhost_exit(void)
76183 +{
76184 + platform_driver_unregister(&neo1973_usbhost_driver);
76185 +}
76186 +
76187 +module_init(neo1973_usbhost_init);
76188 +module_exit(neo1973_usbhost_exit);
76189 +
76190 +MODULE_LICENSE("GPL");
76191 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
76192 +MODULE_DESCRIPTION("Neo1973 USB Host Power Management");
76193 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/misc/neo1973_version.c linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_version.c
76194 --- linux-2.6.29-rc3.owrt/drivers/misc/neo1973_version.c 1970-01-01 01:00:00.000000000 +0100
76195 +++ linux-2.6.29-rc3.owrt.om/drivers/misc/neo1973_version.c 2009-05-10 22:28:00.000000000 +0200
76196 @@ -0,0 +1,90 @@
76197 +/*
76198 + * PCB version sysfs for the FIC Neo1973 GSM Phone
76199 + *
76200 + * (C) 2007 by Openmoko Inc.
76201 + * Author: Andy Green <andy@openmoko.com>
76202 + * All rights reserved.
76203 + *
76204 + * This program is free software; you can redistribute it and/or modify
76205 + * it under the terms of the GNU General Public License version 2 as
76206 + * published by the Free Software Foundation
76207 + *
76208 + */
76209 +
76210 +#include <linux/module.h>
76211 +#include <linux/init.h>
76212 +#include <linux/kernel.h>
76213 +#include <linux/platform_device.h>
76214 +
76215 +#include <mach/hardware.h>
76216 +#include <asm/mach-types.h>
76217 +
76218 +#ifdef CONFIG_MACH_NEO1973_GTA02
76219 +#include <mach/gta02.h>
76220 +
76221 +static ssize_t version_read(struct device *dev, struct device_attribute *attr,
76222 + char *buf)
76223 +{
76224 + return sprintf(buf, "0x%03X\n", gta02_get_pcb_revision());
76225 +}
76226 +
76227 +
76228 +static DEVICE_ATTR(pcb, 0644, version_read, NULL);
76229 +
76230 +static struct attribute *neo1973_version_sysfs_entries[] = {
76231 + &dev_attr_pcb.attr,
76232 + NULL
76233 +};
76234 +
76235 +static struct attribute_group neo1973_version_attr_group = {
76236 + .name = NULL,
76237 + .attrs = neo1973_version_sysfs_entries,
76238 +};
76239 +
76240 +static int __init neo1973_version_probe(struct platform_device *pdev)
76241 +{
76242 + dev_info(&pdev->dev, "starting\n");
76243 +
76244 + switch (machine_arch_type) {
76245 +#ifdef CONFIG_MACH_NEO1973_GTA01
76246 + case MACH_TYPE_NEO1973_GTA01:
76247 + return -EINVAL;
76248 +#endif /* CONFIG_MACH_NEO1973_GTA01 */
76249 + default:
76250 + break;
76251 + }
76252 +
76253 + return sysfs_create_group(&pdev->dev.kobj, &neo1973_version_attr_group);
76254 +}
76255 +
76256 +static int neo1973_version_remove(struct platform_device *pdev)
76257 +{
76258 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_version_attr_group);
76259 + return 0;
76260 +}
76261 +
76262 +static struct platform_driver neo1973_version_driver = {
76263 + .probe = neo1973_version_probe,
76264 + .remove = neo1973_version_remove,
76265 + .driver = {
76266 + .name = "neo1973-version",
76267 + },
76268 +};
76269 +
76270 +static int __devinit neo1973_version_init(void)
76271 +{
76272 + return platform_driver_register(&neo1973_version_driver);
76273 +}
76274 +
76275 +static void neo1973_version_exit(void)
76276 +{
76277 + platform_driver_unregister(&neo1973_version_driver);
76278 +}
76279 +
76280 +module_init(neo1973_version_init);
76281 +module_exit(neo1973_version_exit);
76282 +
76283 +MODULE_LICENSE("GPL");
76284 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
76285 +MODULE_DESCRIPTION("Neo1973 PCB version");
76286 +#endif
76287 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/misc/smdk6410-sleeptest.c linux-2.6.29-rc3.owrt.om/drivers/misc/smdk6410-sleeptest.c
76288 --- linux-2.6.29-rc3.owrt/drivers/misc/smdk6410-sleeptest.c 1970-01-01 01:00:00.000000000 +0100
76289 +++ linux-2.6.29-rc3.owrt.om/drivers/misc/smdk6410-sleeptest.c 2009-05-10 22:28:00.000000000 +0200
76290 @@ -0,0 +1,65 @@
76291 +/* linux/drivers/misc/smdk6410-sleeptest.c
76292 + *
76293 + * Copyright 2008 Simtec Electronics
76294 + * Ben Dooks <ben@simtec.co.uk>
76295 + * http://armlinux.simtec.co.uk/
76296 + *
76297 + * This program is free software; you can redistribute it and/or modify
76298 + * it under the terms of the GNU General Public License version 2 as
76299 + * published by the Free Software Foundation.
76300 +*/
76301 +
76302 +#include <linux/init.h>
76303 +#include <linux/kernel.h>
76304 +#include <linux/module.h>
76305 +#include <linux/init.h>
76306 +#include <linux/gpio.h>
76307 +#include <linux/err.h>
76308 +#include <linux/interrupt.h>
76309 +
76310 +#include <plat/gpio-cfg.h>
76311 +
76312 +static irqreturn_t sleep_action(int irq, void *pw)
76313 +{
76314 + printk(KERN_INFO "%s: irq %d\n", __func__, irq);
76315 + return IRQ_HANDLED;
76316 +}
76317 +
76318 +static void sleep_setup(unsigned int irq, unsigned int gpio)
76319 +{
76320 + int ret;
76321 +
76322 + WARN_ON(s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)) < 0);
76323 + WARN_ON(s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP) < 0);
76324 +
76325 + ret = request_irq(irq, sleep_action, IRQF_TRIGGER_FALLING,
76326 + "sleep", NULL);
76327 + if (ret < 0)
76328 + printk(KERN_ERR "%s: request_irq() failed\n", __func__);
76329 +
76330 + ret = set_irq_wake(irq, 1);
76331 + if (ret < 0)
76332 + printk(KERN_ERR "%s: set_irq_wake() failed\n", __func__);
76333 +}
76334 +
76335 +static void sleep_led(unsigned int gpio)
76336 +{
76337 +// gpio_request(gpio, "sleep led");
76338 +// gpio_direction_output(gpio, 0);
76339 +}
76340 +
76341 +static __init int smdk6410_sleeptest_init(void)
76342 +{
76343 + sleep_setup(IRQ_EINT(10), S3C64XX_GPN(10));
76344 +// sleep_led(S3C64XX_GPN(15));
76345 +// sleep_led(S3C64XX_GPN(14));
76346 +// sleep_led(S3C64XX_GPN(13));
76347 +// sleep_led(S3C64XX_GPN(12));
76348 +
76349 + return 0;
76350 +}
76351 +
76352 +module_init(smdk6410_sleeptest_init);
76353 +
76354 +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
76355 +MODULE_LICENSE("GPL");
76356 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mmc/core/core.c linux-2.6.29-rc3.owrt.om/drivers/mmc/core/core.c
76357 --- linux-2.6.29-rc3.owrt/drivers/mmc/core/core.c 2009-05-10 22:04:48.000000000 +0200
76358 +++ linux-2.6.29-rc3.owrt.om/drivers/mmc/core/core.c 2009-05-10 22:28:00.000000000 +0200
76359 @@ -58,10 +58,11 @@
76360 /*
76361 * Internal function. Flush all scheduled work from the MMC work queue.
76362 */
76363 -static void mmc_flush_scheduled_work(void)
76364 +void mmc_flush_scheduled_work(void)
76365 {
76366 flush_workqueue(workqueue);
76367 }
76368 +EXPORT_SYMBOL_GPL(mmc_flush_scheduled_work);
76369
76370 /**
76371 * mmc_request_done - finish processing an MMC request
76372 @@ -572,7 +573,13 @@
76373 */
76374 static void mmc_power_up(struct mmc_host *host)
76375 {
76376 - int bit = fls(host->ocr_avail) - 1;
76377 + int bit;
76378 +
76379 + /* If ocr is set, we use it */
76380 + if (host->ocr)
76381 + bit = ffs(host->ocr) - 1;
76382 + else
76383 + bit = fls(host->ocr_avail) - 1;
76384
76385 host->ios.vdd = bit;
76386 if (mmc_host_is_spi(host)) {
76387 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mmc/host/Kconfig linux-2.6.29-rc3.owrt.om/drivers/mmc/host/Kconfig
76388 --- linux-2.6.29-rc3.owrt/drivers/mmc/host/Kconfig 2009-05-10 22:08:43.000000000 +0200
76389 +++ linux-2.6.29-rc3.owrt.om/drivers/mmc/host/Kconfig 2009-05-10 22:28:00.000000000 +0200
76390 @@ -48,6 +48,18 @@
76391
76392 If unsure, say N.
76393
76394 +config MMC_SDHCI_S3C
76395 + tristate "SDHCI support on Samsung S3C SoC"
76396 + depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX)
76397 + help
76398 + This selects the Secure Digital Host Controller Interface (SDHCI)
76399 + often referrered to as the HSMMC block in some of the Samsung S3C
76400 + range of SoC.
76401 +
76402 + If you have a controller with this interface, say Y or M here.
76403 +
76404 + If unsure, say N.
76405 +
76406 config MMC_RICOH_MMC
76407 tristate "Ricoh MMC Controller Disabler (EXPERIMENTAL)"
76408 depends on MMC_SDHCI_PCI
76409 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mmc/host/Makefile linux-2.6.29-rc3.owrt.om/drivers/mmc/host/Makefile
76410 --- linux-2.6.29-rc3.owrt/drivers/mmc/host/Makefile 2009-05-10 22:08:43.000000000 +0200
76411 +++ linux-2.6.29-rc3.owrt.om/drivers/mmc/host/Makefile 2009-05-10 22:28:00.000000000 +0200
76412 @@ -11,6 +11,7 @@
76413 obj-$(CONFIG_MMC_IMX) += imxmmc.o
76414 obj-$(CONFIG_MMC_SDHCI) += sdhci.o
76415 obj-$(CONFIG_MMC_SDHCI_PCI) += sdhci-pci.o
76416 +obj-$(CONFIG_MMC_SDHCI_S3C) += sdhci-s3c.o
76417 obj-$(CONFIG_MMC_RICOH_MMC) += ricoh_mmc.o
76418 obj-$(CONFIG_MMC_WBSD) += wbsd.o
76419 obj-$(CONFIG_MMC_AU1X) += au1xmmc.o
76420 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mmc/host/s3cmci.c linux-2.6.29-rc3.owrt.om/drivers/mmc/host/s3cmci.c
76421 --- linux-2.6.29-rc3.owrt/drivers/mmc/host/s3cmci.c 2009-05-10 22:08:43.000000000 +0200
76422 +++ linux-2.6.29-rc3.owrt.om/drivers/mmc/host/s3cmci.c 2009-05-10 22:28:00.000000000 +0200
76423 @@ -2,6 +2,7 @@
76424 * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
76425 *
76426 * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
76427 + * Copyright (C) 2007 Harald Welte <laforge@gnumonks.org>
76428 *
76429 * Current driver maintained by Ben Dooks and Simtec Electronics
76430 * Copyright (C) 2008 Simtec Electronics <ben-linux@fluff.org>
76431 @@ -24,9 +25,18 @@
76432
76433 #include <mach/regs-sdi.h>
76434 #include <mach/regs-gpio.h>
76435 +#include <mach/hardware.h>
76436
76437 #include <plat/mci.h>
76438
76439 +#include <asm/dma.h>
76440 +#include <asm/dma-mapping.h>
76441 +
76442 +#include <asm/io.h>
76443 +#include <mach/regs-gpio.h>
76444 +#include <mach/mci.h>
76445 +#include <mach/dma.h>
76446 +
76447 #include "s3cmci.h"
76448
76449 #define DRIVER_NAME "s3c-mci"
76450 @@ -47,6 +57,9 @@
76451 static const int dbgmap_info = dbg_info | dbg_conf;
76452 static const int dbgmap_debug = dbg_err | dbg_debug;
76453
76454 +static int f_max = -1; /* override maximum frequency limit */
76455 +static int persist; /* keep interface alive across suspend/resume */
76456 +
76457 #define dbg(host, channels, args...) \
76458 do { \
76459 if (dbgmap_err & channels) \
76460 @@ -280,8 +293,11 @@
76461 * an even multiple of 4. */
76462 if (fifo >= host->pio_bytes)
76463 fifo = host->pio_bytes;
76464 - else
76465 + else {
76466 fifo -= fifo & 3;
76467 + if (!fifo)
76468 + break;
76469 + }
76470
76471 host->pio_bytes -= fifo;
76472 host->pio_count += fifo;
76473 @@ -353,8 +369,11 @@
76474 * words, so round down to an even multiple of 4. */
76475 if (fifo >= host->pio_bytes)
76476 fifo = host->pio_bytes;
76477 - else
76478 + else {
76479 fifo -= fifo & 3;
76480 + if (!fifo)
76481 + break;
76482 + }
76483
76484 host->pio_bytes -= fifo;
76485 host->pio_count += fifo;
76486 @@ -373,7 +392,6 @@
76487 {
76488 struct s3cmci_host *host = (struct s3cmci_host *) data;
76489
76490 -
76491 disable_irq(host->irq);
76492
76493 if (host->pio_active == XFER_WRITE)
76494 @@ -614,7 +632,6 @@
76495
76496 spin_unlock_irqrestore(&host->complete_lock, iflags);
76497 return IRQ_HANDLED;
76498 -
76499 }
76500
76501 /*
76502 @@ -789,12 +806,11 @@
76503
76504 last_source = source;
76505
76506 - s3c2410_dma_devconfig(host->dma, source, 3,
76507 + s3c2410_dma_devconfig(host->dma, source,
76508 host->mem->start + host->sdidata);
76509
76510 if (!setup_ok) {
76511 - s3c2410_dma_config(host->dma, 4,
76512 - (S3C2410_DCON_HWTRIG | S3C2410_DCON_CH0_SDI));
76513 + s3c2410_dma_config(host->dma, 4);
76514 s3c2410_dma_set_buffdone_fn(host->dma,
76515 s3cmci_dma_done_callback);
76516 s3c2410_dma_setflags(host->dma, S3C2410_DMAF_AUTOSTART);
76517 @@ -1027,6 +1043,7 @@
76518 dbg(host, dbg_err, "data prepare error %d\n", res);
76519 cmd->error = res;
76520 cmd->data->error = res;
76521 + cmd->data->error = -EIO;
76522
76523 mmc_request_done(mmc, mrq);
76524 return;
76525 @@ -1264,10 +1281,8 @@
76526 host->is2440 = is2440;
76527
76528 host->pdata = pdev->dev.platform_data;
76529 - if (!host->pdata) {
76530 - pdev->dev.platform_data = &s3cmci_def_pdata;
76531 + if (!host->pdata)
76532 host->pdata = &s3cmci_def_pdata;
76533 - }
76534
76535 spin_lock_init(&host->complete_lock);
76536 tasklet_init(&host->pio_tasklet, pio_tasklet, (unsigned long) host);
76537 @@ -1380,6 +1395,18 @@
76538 mmc->f_min = host->clk_rate / (host->clk_div * 256);
76539 mmc->f_max = host->clk_rate / host->clk_div;
76540
76541 + if (f_max >= 0) {
76542 + unsigned f = f_max;
76543 +
76544 + if (f < mmc->f_min)
76545 + f = mmc->f_min;
76546 + if (mmc->f_max > f) {
76547 + dev_info(&pdev->dev, "f_max lowered from %u to %u Hz\n",
76548 + mmc->f_max, f);
76549 + mmc->f_max = f;
76550 + }
76551 + }
76552 +
76553 if (host->pdata->ocr_avail)
76554 mmc->ocr_avail = host->pdata->ocr_avail;
76555
76556 @@ -1492,18 +1519,60 @@
76557
76558 #ifdef CONFIG_PM
76559
76560 +static int save_regs(struct mmc_host *mmc)
76561 +{
76562 + struct s3cmci_host *host = mmc_priv(mmc);
76563 + unsigned long flags;
76564 + unsigned from;
76565 + u32 *to = host->saved;
76566 +
76567 + mmc_flush_scheduled_work();
76568 +
76569 + local_irq_save(flags);
76570 + for (from = S3C2410_SDICON; from != S3C2410_SDIIMSK+4; from += 4)
76571 + if (from != host->sdidata)
76572 + *to++ = readl(host->base + from);
76573 + BUG_ON(to-host->saved != ARRAY_SIZE(host->saved));
76574 + local_irq_restore(flags);
76575 +
76576 + return 0;
76577 +}
76578 +
76579 +static int restore_regs(struct mmc_host *mmc)
76580 +{
76581 + struct s3cmci_host *host = mmc_priv(mmc);
76582 + unsigned long flags;
76583 + unsigned to;
76584 + u32 *from = host->saved;
76585 +
76586 + /*
76587 + * Before we begin with the necromancy, make sure we don't
76588 + * inadvertently start something we'll regret microseconds later.
76589 + */
76590 + from[S3C2410_SDICMDCON - S3C2410_SDICON] = 0;
76591 +
76592 + local_irq_save(flags);
76593 + for (to = S3C2410_SDICON; to != S3C2410_SDIIMSK+4; to += 4)
76594 + if (to != host->sdidata)
76595 + writel(*from++, host->base + to);
76596 + BUG_ON(from-host->saved != ARRAY_SIZE(host->saved));
76597 + local_irq_restore(flags);
76598 +
76599 + return 0;
76600 +}
76601 +
76602 static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
76603 {
76604 struct mmc_host *mmc = platform_get_drvdata(dev);
76605
76606 - return mmc_suspend_host(mmc, state);
76607 + return persist ? save_regs(mmc) : mmc_suspend_host(mmc, state);
76608 }
76609
76610 static int s3cmci_resume(struct platform_device *dev)
76611 {
76612 struct mmc_host *mmc = platform_get_drvdata(dev);
76613
76614 - return mmc_resume_host(mmc);
76615 + return persist ? restore_regs(mmc) : mmc_resume_host(mmc);
76616 }
76617
76618 #else /* CONFIG_PM */
76619 @@ -1561,9 +1630,13 @@
76620 module_init(s3cmci_init);
76621 module_exit(s3cmci_exit);
76622
76623 +module_param(f_max, int, 0644);
76624 +module_param(persist, int, 0644);
76625 +
76626 MODULE_DESCRIPTION("Samsung S3C MMC/SD Card Interface driver");
76627 MODULE_LICENSE("GPL v2");
76628 MODULE_AUTHOR("Thomas Kleffel <tk@maintech.de>, Ben Dooks <ben-linux@fluff.org>");
76629 MODULE_ALIAS("platform:s3c2410-sdi");
76630 MODULE_ALIAS("platform:s3c2412-sdi");
76631 MODULE_ALIAS("platform:s3c2440-sdi");
76632 +
76633 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mmc/host/s3cmci.h linux-2.6.29-rc3.owrt.om/drivers/mmc/host/s3cmci.h
76634 --- linux-2.6.29-rc3.owrt/drivers/mmc/host/s3cmci.h 2009-05-10 22:04:48.000000000 +0200
76635 +++ linux-2.6.29-rc3.owrt.om/drivers/mmc/host/s3cmci.h 2009-05-10 22:28:00.000000000 +0200
76636 @@ -8,6 +8,10 @@
76637 * published by the Free Software Foundation.
76638 */
76639
76640 +
76641 +#include <mach/regs-sdi.h>
76642 +#include <linux/regulator/consumer.h>
76643 +
76644 /* FIXME: DMA Resource management ?! */
76645 #define S3CMCI_DMA 0
76646
76647 @@ -68,7 +72,16 @@
76648 unsigned int ccnt, dcnt;
76649 struct tasklet_struct pio_tasklet;
76650
76651 + /*
76652 + * Here's where we save the registers during suspend. Note that we skip
76653 + * SDIDATA, which is at different positions on 2410 and 2440, so
76654 + * there's no "+1" in the array size.
76655 + */
76656 + u32 saved[(S3C2410_SDIIMSK-S3C2410_SDICON)/4];
76657 +
76658 #ifdef CONFIG_CPU_FREQ
76659 struct notifier_block freq_transition;
76660 #endif
76661 +
76662 + struct regulator *regulator;
76663 };
76664 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mmc/host/sdhci.c linux-2.6.29-rc3.owrt.om/drivers/mmc/host/sdhci.c
76665 --- linux-2.6.29-rc3.owrt/drivers/mmc/host/sdhci.c 2009-05-10 22:08:43.000000000 +0200
76666 +++ linux-2.6.29-rc3.owrt.om/drivers/mmc/host/sdhci.c 2009-05-10 22:28:00.000000000 +0200
76667 @@ -78,6 +78,11 @@
76668 readl(host->ioaddr + SDHCI_CAPABILITIES),
76669 readl(host->ioaddr + SDHCI_MAX_CURRENT));
76670
76671 + if (host->flags & SDHCI_USE_ADMA)
76672 + printk(KERN_DEBUG DRIVER_NAME ": ADMA Err: 0x%08x | ADMA Ptr: 0x%08x\n",
76673 + readl(host->ioaddr + SDHCI_ADMA_ERROR),
76674 + readl(host->ioaddr + SDHCI_ADMA_ADDRESS));
76675 +
76676 printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
76677 }
76678
76679 @@ -736,6 +741,23 @@
76680 writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
76681 }
76682
76683 +static void shdci_check_dma_overrun(struct sdhci_host *host, struct mmc_data *data)
76684 +{
76685 + u32 dma_pos = readl(host->ioaddr + SDHCI_DMA_ADDRESS);
76686 + u32 dma_start = sg_dma_address(data->sg);
76687 + u32 dma_end = dma_start + data->sg->length;
76688 +
76689 + /* Test whether we ended up moving more data than
76690 + * was originally requested. */
76691 +
76692 + if (dma_pos <= dma_end)
76693 + return;
76694 +
76695 + printk(KERN_ERR "%s: dma overrun, dma %08x, req %08x..%08x\n",
76696 + mmc_hostname(host->mmc), dma_pos,
76697 + dma_start, dma_end);
76698 +}
76699 +
76700 static void sdhci_finish_data(struct sdhci_host *host)
76701 {
76702 struct mmc_data *data;
76703 @@ -749,6 +771,8 @@
76704 if (host->flags & SDHCI_USE_ADMA)
76705 sdhci_adma_table_post(host, data);
76706 else {
76707 + shdci_check_dma_overrun(host, data);
76708 +
76709 dma_unmap_sg(mmc_dev(host->mmc), data->sg,
76710 data->sg_len, (data->flags & MMC_DATA_READ) ?
76711 DMA_FROM_DEVICE : DMA_TO_DEVICE);
76712 @@ -888,13 +912,18 @@
76713
76714 static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
76715 {
76716 + if (clock == host->clock)
76717 + return;
76718 +
76719 + host->ops->change_clock(host, clock);
76720 +}
76721 +
76722 +void sdhci_change_clock(struct sdhci_host *host, unsigned int clock)
76723 +{
76724 int div;
76725 u16 clk;
76726 unsigned long timeout;
76727
76728 - if (clock == host->clock)
76729 - return;
76730 -
76731 writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
76732
76733 if (clock == 0)
76734 @@ -931,6 +960,8 @@
76735 host->clock = clock;
76736 }
76737
76738 +EXPORT_SYMBOL_GPL(sdhci_set_clock);
76739 +
76740 static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
76741 {
76742 u8 pwr;
76743 @@ -1004,12 +1035,13 @@
76744 #endif
76745
76746 host->mrq = mrq;
76747 -
76748 +/*
76749 if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)
76750 || (host->flags & SDHCI_DEVICE_DEAD)) {
76751 host->mrq->cmd->error = -ENOMEDIUM;
76752 tasklet_schedule(&host->finish_tasklet);
76753 } else
76754 +*/
76755 sdhci_send_command(host, mrq->cmd);
76756
76757 mmiowb();
76758 @@ -1038,6 +1070,9 @@
76759 sdhci_init(host);
76760 }
76761
76762 + if (host->ops->set_ios)
76763 + host->ops->set_ios(host, ios);
76764 +
76765 sdhci_set_clock(host, ios->clock);
76766
76767 if (ios->power_mode == MMC_POWER_OFF)
76768 @@ -1141,7 +1176,7 @@
76769 host = (struct sdhci_host*)param;
76770
76771 spin_lock_irqsave(&host->lock, flags);
76772 -
76773 +/*
76774 if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
76775 if (host->mrq) {
76776 printk(KERN_ERR "%s: Card removed during transfer!\n",
76777 @@ -1156,7 +1191,7 @@
76778 tasklet_schedule(&host->finish_tasklet);
76779 }
76780 }
76781 -
76782 +*/
76783 spin_unlock_irqrestore(&host->lock, flags);
76784
76785 mmc_detect_change(host->mmc, msecs_to_jiffies(200));
76786 @@ -1288,11 +1323,24 @@
76787 * controllers.
76788 */
76789 if (host->cmd->flags & MMC_RSP_BUSY) {
76790 + u32 present;
76791 +
76792 if (host->cmd->data)
76793 DBG("Cannot wait for busy signal when also "
76794 "doing a data transfer");
76795 - else
76796 + else if (!(host->quirks & SDHCI_QUIRK_NO_TCIRQ_ON_NOT_BUSY))
76797 return;
76798 +
76799 + /* The Samsung SDHCI does not seem to provide an INT_DATA_END
76800 + * when the system goes non-busy, so check the state of the
76801 + * transfer by reading SDHCI_PRESENT_STATE to see if the
76802 + * controller is ready
76803 + */
76804 +
76805 + present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
76806 + DBG("busy? present %08x, intstat %08x\n", present, intmask);
76807 +
76808 + /* fall through and take the SDHCI_INT_RESPONSE */
76809 }
76810
76811 if (intmask & SDHCI_INT_RESPONSE)
76812 @@ -1609,17 +1657,23 @@
76813 mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
76814 }
76815
76816 - host->max_clk =
76817 - (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
76818 + if (host->ops->get_max_clock)
76819 + host->max_clk = host->ops->get_max_clock(host);
76820 + else {
76821 + host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
76822 + host->max_clk *= 1000000;
76823 + }
76824 if (host->max_clk == 0) {
76825 printk(KERN_ERR "%s: Hardware doesn't specify base clock "
76826 "frequency.\n", mmc_hostname(mmc));
76827 return -ENODEV;
76828 }
76829 - host->max_clk *= 1000000;
76830
76831 - host->timeout_clk =
76832 - (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
76833 + if (host->ops->get_timeout_clock)
76834 + host->timeout_clk = host->ops->get_timeout_clock(host);
76835 + else
76836 + host->timeout_clk =
76837 + (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT;
76838 if (host->timeout_clk == 0) {
76839 printk(KERN_ERR "%s: Hardware doesn't specify timeout clock "
76840 "frequency.\n", mmc_hostname(mmc));
76841 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mmc/host/sdhci.h linux-2.6.29-rc3.owrt.om/drivers/mmc/host/sdhci.h
76842 --- linux-2.6.29-rc3.owrt/drivers/mmc/host/sdhci.h 2009-05-10 22:08:43.000000000 +0200
76843 +++ linux-2.6.29-rc3.owrt.om/drivers/mmc/host/sdhci.h 2009-05-10 22:28:00.000000000 +0200
76844 @@ -57,6 +57,7 @@
76845 #define SDHCI_DATA_AVAILABLE 0x00000800
76846 #define SDHCI_CARD_PRESENT 0x00010000
76847 #define SDHCI_WRITE_PROTECT 0x00080000
76848 +#define SDHCI_DATA_BIT(x) (1 << ((x) + 20))
76849
76850 #define SDHCI_HOST_CONTROL 0x28
76851 #define SDHCI_CTRL_LED 0x01
76852 @@ -210,6 +211,8 @@
76853 #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13)
76854 /* Controller supports high speed but doesn't have the caps bit set */
76855 #define SDHCI_QUIRK_FORCE_HIGHSPEED (1<<14)
76856 +/* Controller does not provide transfer-complete interrupt when not busy */
76857 +#define SDHCI_QUIRK_NO_TCIRQ_ON_NOT_BUSY (1<<15)
76858
76859 int irq; /* Device IRQ */
76860 void __iomem * ioaddr; /* Mapped address */
76861 @@ -267,6 +270,14 @@
76862
76863 struct sdhci_ops {
76864 int (*enable_dma)(struct sdhci_host *host);
76865 + unsigned int (*get_max_clock)(struct sdhci_host *host);
76866 + unsigned int (*get_timeout_clock)(struct sdhci_host *host);
76867 +
76868 + void (*change_clock)(struct sdhci_host *host,
76869 + unsigned int clock);
76870 +
76871 + void (*set_ios)(struct sdhci_host *host,
76872 + struct mmc_ios *ios);
76873 };
76874
76875
76876 @@ -274,6 +285,8 @@
76877 size_t priv_size);
76878 extern void sdhci_free_host(struct sdhci_host *host);
76879
76880 +extern void sdhci_change_clock(struct sdhci_host *host, unsigned int clock);
76881 +
76882 static inline void *sdhci_priv(struct sdhci_host *host)
76883 {
76884 return (void *)host->private;
76885 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mmc/host/sdhci-pci.c linux-2.6.29-rc3.owrt.om/drivers/mmc/host/sdhci-pci.c
76886 --- linux-2.6.29-rc3.owrt/drivers/mmc/host/sdhci-pci.c 2009-05-10 22:08:43.000000000 +0200
76887 +++ linux-2.6.29-rc3.owrt.om/drivers/mmc/host/sdhci-pci.c 2009-05-10 22:28:00.000000000 +0200
76888 @@ -391,6 +391,7 @@
76889
76890 static struct sdhci_ops sdhci_pci_ops = {
76891 .enable_dma = sdhci_pci_enable_dma,
76892 + .change_clock = sdhci_change_clock,
76893 };
76894
76895 /*****************************************************************************\
76896 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mmc/host/sdhci-s3c.c linux-2.6.29-rc3.owrt.om/drivers/mmc/host/sdhci-s3c.c
76897 --- linux-2.6.29-rc3.owrt/drivers/mmc/host/sdhci-s3c.c 1970-01-01 01:00:00.000000000 +0100
76898 +++ linux-2.6.29-rc3.owrt.om/drivers/mmc/host/sdhci-s3c.c 2009-05-10 22:28:00.000000000 +0200
76899 @@ -0,0 +1,419 @@
76900 +/* linux/drivers/mmc/host/sdhci-s3c.c
76901 + *
76902 + * Copyright 2008 Openmoko Inc.
76903 + * Copyright 2008 Simtec Electronics
76904 + * Ben Dooks <ben@simtec.co.uk>
76905 + * http://armlinux.simtec.co.uk/
76906 + *
76907 + * SDHCI (HSMMC) support for Samsung SoC
76908 + *
76909 + * This program is free software; you can redistribute it and/or modify
76910 + * it under the terms of the GNU General Public License version 2 as
76911 + * published by the Free Software Foundation.
76912 + */
76913 +
76914 +#include <linux/delay.h>
76915 +#include <linux/dma-mapping.h>
76916 +#include <linux/platform_device.h>
76917 +#include <linux/clk.h>
76918 +#include <linux/io.h>
76919 +
76920 +#include <linux/mmc/host.h>
76921 +
76922 +#include <plat/regs-sdhci.h>
76923 +#include <plat/sdhci.h>
76924 +
76925 +#include "sdhci.h"
76926 +
76927 +#define MAX_BUS_CLK (4)
76928 +
76929 +struct sdhci_s3c {
76930 + struct sdhci_host *host;
76931 + struct platform_device *pdev;
76932 + struct resource *ioarea;
76933 + struct s3c_sdhci_platdata *pdata;
76934 + unsigned int cur_clk;
76935 +
76936 + struct clk *clk_io; /* clock for io bus */
76937 + struct clk *clk_bus[MAX_BUS_CLK];
76938 +};
76939 +
76940 +static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
76941 +{
76942 + return sdhci_priv(host);
76943 +}
76944 +
76945 +static u32 get_curclk(u32 ctrl2)
76946 +{
76947 + ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
76948 + ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
76949 +
76950 + return ctrl2;
76951 +}
76952 +
76953 +static void sdhci_s3c_check_sclk(struct sdhci_host *host)
76954 +{
76955 + struct sdhci_s3c *ourhost = to_s3c(host);
76956 + u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
76957 +
76958 + if (get_curclk(tmp) != ourhost->cur_clk) {
76959 + dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n");
76960 +
76961 + tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
76962 + tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
76963 + writel(tmp, host->ioaddr + 0x80);
76964 + }
76965 +}
76966 +
76967 +static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
76968 +{
76969 + struct sdhci_s3c *ourhost = to_s3c(host);
76970 + struct clk *busclk;
76971 + unsigned int rate, max;
76972 + int clk;
76973 +
76974 + /* note, a reset will reset the clock source */
76975 +
76976 + sdhci_s3c_check_sclk(host);
76977 +
76978 + for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) {
76979 + busclk = ourhost->clk_bus[clk];
76980 + if (!busclk)
76981 + continue;
76982 +
76983 + rate = clk_get_rate(busclk);
76984 + if (rate > max)
76985 + max = rate;
76986 + }
76987 +
76988 + return max;
76989 +}
76990 +
76991 +static unsigned int sdhci_s3c_get_timeout_clk(struct sdhci_host *host)
76992 +{
76993 + return sdhci_s3c_get_max_clk(host) / 1000000;
76994 +}
76995 +
76996 +static void sdhci_s3c_set_ios(struct sdhci_host *host,
76997 + struct mmc_ios *ios)
76998 +{
76999 + struct sdhci_s3c *ourhost = to_s3c(host);
77000 + struct s3c_sdhci_platdata *pdata = ourhost->pdata;
77001 + int width;
77002 +
77003 + sdhci_s3c_check_sclk(host);
77004 +
77005 + if (ios->power_mode != MMC_POWER_OFF) {
77006 + switch (ios->bus_width) {
77007 + case MMC_BUS_WIDTH_4:
77008 + width = 4;
77009 + break;
77010 + case MMC_BUS_WIDTH_1:
77011 + width = 1;
77012 + break;
77013 + default:
77014 + BUG();
77015 + }
77016 +
77017 + if (pdata->cfg_gpio)
77018 + pdata->cfg_gpio(ourhost->pdev, width);
77019 + }
77020 +
77021 + if (pdata->cfg_card)
77022 + pdata->cfg_card(ourhost->pdev, host->ioaddr,
77023 + ios, host->mmc->card);
77024 +}
77025 +
77026 +static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
77027 + unsigned int src,
77028 + unsigned int wanted)
77029 +{
77030 + unsigned long rate;
77031 + struct clk *clksrc = ourhost->clk_bus[src];
77032 + int div;
77033 +
77034 + if (!clksrc)
77035 + return UINT_MAX;
77036 +
77037 + rate = clk_get_rate(clksrc);
77038 +
77039 + for (div = 1; div < 256; div *= 2) {
77040 + if ((rate / div) <= wanted)
77041 + break;
77042 + }
77043 +
77044 + dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
77045 + src, rate, wanted, rate / div);
77046 +
77047 + return (wanted - (rate / div));
77048 +}
77049 +
77050 +static void sdhci_s3c_change_clock(struct sdhci_host *host, unsigned int clock)
77051 +{
77052 + struct sdhci_s3c *ourhost = to_s3c(host);
77053 + unsigned int best = UINT_MAX;
77054 + unsigned int delta;
77055 + int best_src = 0;
77056 + int src;
77057 + u32 ctrl;
77058 +
77059 + for (src = 0; src < MAX_BUS_CLK; src++) {
77060 + delta = sdhci_s3c_consider_clock(ourhost, src, clock);
77061 + if (delta < best) {
77062 + best = delta;
77063 + best_src = src;
77064 + }
77065 + }
77066 +
77067 + dev_dbg(&ourhost->pdev->dev,
77068 + "selected source %d, clock %d, delta %d\n",
77069 + best_src, clock, best);
77070 +
77071 + /* turn clock off to card before changing clock source */
77072 + writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
77073 +
77074 + /* select the new clock source */
77075 +
77076 + if (ourhost->cur_clk != best_src) {
77077 + struct clk *clk = ourhost->clk_bus[best_src];
77078 +
77079 + ourhost->cur_clk = best_src;
77080 + host->max_clk = clk_get_rate(clk);
77081 + host->timeout_clk = host->max_clk / 1000000;
77082 +
77083 + ctrl = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
77084 + ctrl &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
77085 + ctrl |= best_src << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
77086 + writel(ctrl, host->ioaddr + S3C_SDHCI_CONTROL2);
77087 + }
77088 +
77089 + sdhci_change_clock(host, clock);
77090 +}
77091 +
77092 +static struct sdhci_ops sdhci_s3c_ops = {
77093 + .get_max_clock = sdhci_s3c_get_max_clk,
77094 + .get_timeout_clock = sdhci_s3c_get_timeout_clk,
77095 + .change_clock = sdhci_s3c_change_clock,
77096 + .set_ios = sdhci_s3c_set_ios,
77097 +};
77098 +
77099 +/*
77100 + * call this when you need sd stack to recognize insertion or removal of card
77101 + * that can't be told by SDHCI regs
77102 + */
77103 +
77104 +void sdhci_s3c_force_presence_change(struct platform_device *pdev)
77105 +{
77106 + struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
77107 +
77108 + dev_info(&pdev->dev, "sdhci_s3c_force_presence_change called\n");
77109 + mmc_detect_change(pdata->sdhci_host->mmc, msecs_to_jiffies(200));
77110 +}
77111 +EXPORT_SYMBOL_GPL(sdhci_s3c_force_presence_change);
77112 +
77113 +
77114 +static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
77115 +{
77116 + struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
77117 + struct device *dev = &pdev->dev;
77118 + struct sdhci_host *host;
77119 + struct sdhci_s3c *sc;
77120 + struct resource *res;
77121 + int ret, irq, ptr, clks;
77122 +
77123 + if (!pdata) {
77124 + dev_err(dev, "no device data specified\n");
77125 + return -ENOENT;
77126 + }
77127 +
77128 + irq = platform_get_irq(pdev, 0);
77129 + if (irq < 0) {
77130 + dev_err(dev, "no irq specified\n");
77131 + return irq;
77132 + }
77133 +
77134 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
77135 + if (!res) {
77136 + dev_err(dev, "no memory specified\n");
77137 + return -ENOENT;
77138 + }
77139 +
77140 + host = sdhci_alloc_host(dev, sizeof(struct sdhci_s3c));
77141 + if (IS_ERR(host)) {
77142 + dev_err(dev, "sdhci_alloc_host() failed\n");
77143 + return PTR_ERR(host);
77144 + }
77145 +
77146 + pdata->sdhci_host = host;
77147 +
77148 + sc = sdhci_priv(host);
77149 +
77150 + sc->host = host;
77151 + sc->pdev = pdev;
77152 + sc->pdata = pdata;
77153 +
77154 + platform_set_drvdata(pdev, host);
77155 +
77156 + sc->clk_io = clk_get(dev, "hsmmc");
77157 + if (IS_ERR(sc->clk_io)) {
77158 + dev_err(dev, "failed to get io clock\n");
77159 + ret = PTR_ERR(sc->clk_io);
77160 + goto err_io_clk;
77161 + }
77162 +
77163 + /* enable the local io clock and keep it running for the moment. */
77164 + clk_enable(sc->clk_io);
77165 +
77166 + for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
77167 + struct clk *clk;
77168 + char *name = pdata->clocks[ptr];
77169 +
77170 + if (name == NULL)
77171 + continue;
77172 +
77173 + clk = clk_get(dev, name);
77174 + if (IS_ERR(clk)) {
77175 + dev_err(dev, "failed to get clock %s\n", name);
77176 + continue;
77177 + }
77178 +
77179 + clks++;
77180 + sc->clk_bus[ptr] = clk;
77181 + clk_enable(clk);
77182 +
77183 + dev_info(dev, "clock source %d: %s (%ld Hz)\n",
77184 + ptr, name, clk_get_rate(clk));
77185 + }
77186 +
77187 + if (clks == 0) {
77188 + dev_err(dev, "failed to find any bus clocks\n");
77189 + ret = -ENOENT;
77190 + goto err_no_busclks;
77191 + }
77192 +
77193 + sc->ioarea = request_mem_region(res->start, resource_size(res),
77194 + mmc_hostname(host->mmc));
77195 + if (!sc->ioarea) {
77196 + dev_err(dev, "failed to reserve register area\n");
77197 + ret = -ENXIO;
77198 + goto err_req_regs;
77199 + }
77200 +
77201 + host->ioaddr = ioremap_nocache(res->start, resource_size(res));
77202 + if (!host->ioaddr) {
77203 + dev_err(dev, "failed to map registers\n");
77204 + ret = -ENXIO;
77205 + goto err_req_regs;
77206 + }
77207 +
77208 + /* Ensure we have minimal gpio selected CMD/CLK/Detect */
77209 + if (pdata->cfg_gpio)
77210 + pdata->cfg_gpio(pdev, 0);
77211 +
77212 + sdhci_s3c_check_sclk(host);
77213 +
77214 + host->hw_name = "samsung-hsmmc";
77215 + host->ops = &sdhci_s3c_ops;
77216 + host->quirks = 0;
77217 + host->irq = irq;
77218 +
77219 + /* Setup quirks for the controller */
77220 +
77221 + /* Currently with ADMA enabled we are getting some length
77222 + * interrupts that are not being dealt with, do disable
77223 + * ADMA until this is sorted out. */
77224 + host->quirks |= SDHCI_QUIRK_BROKEN_ADMA;
77225 + host->quirks |= SDHCI_QUIRK_32BIT_ADMA_SIZE;
77226 +
77227 + /* It seems we do not get an DATA transfer complete on non-busy
77228 + * transfers, not sure if this is a problem with this specific
77229 + * SDHCI block, or a missing configuration that needs to be set. */
77230 + host->quirks |= SDHCI_QUIRK_NO_TCIRQ_ON_NOT_BUSY;
77231 +
77232 + host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
77233 + SDHCI_QUIRK_32BIT_DMA_SIZE);
77234 +
77235 + ret = sdhci_add_host(host);
77236 + if (ret) {
77237 + dev_err(dev, "sdhci_add_host() failed\n");
77238 + goto err_add_host;
77239 + }
77240 +
77241 + return 0;
77242 +
77243 + err_add_host:
77244 + release_resource(sc->ioarea);
77245 + kfree(sc->ioarea);
77246 +
77247 + err_req_regs:
77248 + for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
77249 + clk_disable(sc->clk_bus[ptr]);
77250 + clk_put(sc->clk_bus[ptr]);
77251 + }
77252 +
77253 + err_no_busclks:
77254 + clk_disable(sc->clk_io);
77255 + clk_put(sc->clk_io);
77256 +
77257 + err_io_clk:
77258 + sdhci_free_host(host);
77259 +
77260 + return ret;
77261 +}
77262 +
77263 +static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
77264 +{
77265 + return 0;
77266 +}
77267 +
77268 +#ifdef CONFIG_PM
77269 +
77270 +static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
77271 +{
77272 + struct sdhci_host *host = platform_get_drvdata(dev);
77273 +
77274 + sdhci_suspend_host(host, pm);
77275 + return 0;
77276 +}
77277 +
77278 +static int sdhci_s3c_resume(struct platform_device *dev)
77279 +{
77280 + struct sdhci_host *host = platform_get_drvdata(dev);
77281 +
77282 + sdhci_resume_host(host);
77283 + return 0;
77284 +}
77285 +
77286 +#else
77287 +#define sdhci_s3c_suspend NULL
77288 +#define sdhci_s3c_resume NULL
77289 +#endif
77290 +
77291 +static struct platform_driver sdhci_s3c_driver = {
77292 + .probe = sdhci_s3c_probe,
77293 + .remove = __devexit_p(sdhci_s3c_remove),
77294 + .suspend = sdhci_s3c_suspend,
77295 + .resume = sdhci_s3c_resume,
77296 + .driver = {
77297 + .owner = THIS_MODULE,
77298 + .name = "s3c-sdhci",
77299 + },
77300 +};
77301 +
77302 +static int __init sdhci_s3c_init(void)
77303 +{
77304 + return platform_driver_register(&sdhci_s3c_driver);
77305 +}
77306 +
77307 +static void __exit sdhci_s3c_exit(void)
77308 +{
77309 + platform_driver_unregister(&sdhci_s3c_driver);
77310 +}
77311 +
77312 +module_init(sdhci_s3c_init);
77313 +module_exit(sdhci_s3c_exit);
77314 +
77315 +MODULE_DESCRIPTION("Samsung SDHCI (HSMMC) glue");
77316 +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
77317 +MODULE_LICENSE("GPL v2");
77318 +MODULE_ALIAS("platform:s3c-sdhci");
77319 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/mtd/nand/s3c2410.c linux-2.6.29-rc3.owrt.om/drivers/mtd/nand/s3c2410.c
77320 --- linux-2.6.29-rc3.owrt/drivers/mtd/nand/s3c2410.c 2009-05-10 22:04:49.000000000 +0200
77321 +++ linux-2.6.29-rc3.owrt.om/drivers/mtd/nand/s3c2410.c 2009-05-10 22:28:00.000000000 +0200
77322 @@ -231,8 +231,6 @@
77323 BUG();
77324 }
77325
77326 - dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
77327 -
77328 local_irq_save(flags);
77329
77330 cfg = readl(info->regs + S3C2410_NFCONF);
77331 @@ -240,6 +238,8 @@
77332 cfg |= set;
77333 writel(cfg, info->regs + S3C2410_NFCONF);
77334
77335 + dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
77336 +
77337 local_irq_restore(flags);
77338
77339 return 0;
77340 @@ -438,7 +438,7 @@
77341 if ((diff0 & ~(1<<fls(diff0))) == 0)
77342 return 1;
77343
77344 - return -1;
77345 + return -EBADMSG;
77346 }
77347
77348 /* ECC functions
77349 @@ -530,7 +530,12 @@
77350 static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
77351 {
77352 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
77353 + u8 *ptr = buf + (len & ~3);
77354 + int i;
77355 +
77356 readsl(info->regs + S3C2440_NFDATA, buf, len / 4);
77357 + for (i = 0; i != (len & 3); i++)
77358 + ptr[i] = readb(info->regs + S3C2440_NFDATA);
77359 }
77360
77361 static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
77362 @@ -645,17 +650,31 @@
77363 }
77364
77365 #ifdef CONFIG_MTD_PARTITIONS
77366 +const char *part_probes[] = { "cmdlinepart", NULL };
77367 static int s3c2410_nand_add_partition(struct s3c2410_nand_info *info,
77368 struct s3c2410_nand_mtd *mtd,
77369 struct s3c2410_nand_set *set)
77370 {
77371 + struct mtd_partition *part_info;
77372 + int nr_part = 0;
77373 +
77374 if (set == NULL)
77375 return add_mtd_device(&mtd->mtd);
77376
77377 - if (set->nr_partitions > 0 && set->partitions != NULL) {
77378 - return add_mtd_partitions(&mtd->mtd, set->partitions, set->nr_partitions);
77379 + if (set->nr_partitions == 0) {
77380 + mtd->mtd.name = set->name;
77381 + nr_part = parse_mtd_partitions(&mtd->mtd, part_probes,
77382 + &part_info, 0);
77383 + } else {
77384 + if (set->nr_partitions > 0 && set->partitions != NULL) {
77385 + nr_part = set->nr_partitions;
77386 + part_info = set->partitions;
77387 + }
77388 }
77389
77390 + if (nr_part > 0 && part_info)
77391 + return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
77392 +
77393 return add_mtd_device(&mtd->mtd);
77394 }
77395 #else
77396 @@ -684,9 +703,13 @@
77397 chip->select_chip = s3c2410_nand_select_chip;
77398 chip->chip_delay = 50;
77399 chip->priv = nmtd;
77400 - chip->options = 0;
77401 chip->controller = &info->controller;
77402
77403 + if (set->flags & S3C2410_NAND_BBT)
77404 + chip->options = NAND_USE_FLASH_BBT;
77405 + else
77406 + chip->options = 0;
77407 +
77408 switch (info->cpu_type) {
77409 case TYPE_S3C2410:
77410 chip->IO_ADDR_W = regs + S3C2410_NFDATA;
77411 @@ -726,7 +749,7 @@
77412 nmtd->mtd.owner = THIS_MODULE;
77413 nmtd->set = set;
77414
77415 - if (hardware_ecc) {
77416 + if (!info->platform->software_ecc && hardware_ecc) {
77417 chip->ecc.calculate = s3c2410_nand_calculate_ecc;
77418 chip->ecc.correct = s3c2410_nand_correct_data;
77419 chip->ecc.mode = NAND_ECC_HW;
77420 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/net/ppp_deflate.c linux-2.6.29-rc3.owrt.om/drivers/net/ppp_deflate.c
77421 --- linux-2.6.29-rc3.owrt/drivers/net/ppp_deflate.c 2009-05-10 22:04:48.000000000 +0200
77422 +++ linux-2.6.29-rc3.owrt.om/drivers/net/ppp_deflate.c 2009-05-10 22:28:00.000000000 +0200
77423 @@ -306,7 +306,7 @@
77424
77425 if (state) {
77426 zlib_inflateEnd(&state->strm);
77427 - kfree(state->strm.workspace);
77428 + vfree(state->strm.workspace);
77429 kfree(state);
77430 }
77431 }
77432 @@ -346,8 +346,7 @@
77433
77434 state->w_size = w_size;
77435 state->strm.next_out = NULL;
77436 - state->strm.workspace = kmalloc(zlib_inflate_workspacesize(),
77437 - GFP_KERNEL|__GFP_REPEAT);
77438 + state->strm.workspace = vmalloc(zlib_inflate_workspacesize());
77439 if (state->strm.workspace == NULL)
77440 goto out_free;
77441
77442 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/net/wireless/libertas/if_sdio.c linux-2.6.29-rc3.owrt.om/drivers/net/wireless/libertas/if_sdio.c
77443 --- linux-2.6.29-rc3.owrt/drivers/net/wireless/libertas/if_sdio.c 2009-05-10 22:04:49.000000000 +0200
77444 +++ linux-2.6.29-rc3.owrt.om/drivers/net/wireless/libertas/if_sdio.c 2009-05-10 22:28:00.000000000 +0200
77445 @@ -49,6 +49,7 @@
77446
77447 static const struct sdio_device_id if_sdio_ids[] = {
77448 { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_LIBERTAS) },
77449 + { SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_88W8688) },
77450 { /* end: all zeroes */ },
77451 };
77452
77453 @@ -73,7 +74,12 @@
77454 .helper = "sd8686_helper.bin",
77455 .firmware = "sd8686.bin",
77456 },
77457 -};
77458 + {
77459 + /* 8688 */
77460 + .model = 0x10,
77461 + .helper = "sd8688_helper.bin",
77462 + .firmware = "sd8688.bin",
77463 + },};
77464
77465 struct if_sdio_packet {
77466 struct if_sdio_packet *next;
77467 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/pnp/Kconfig linux-2.6.29-rc3.owrt.om/drivers/pnp/Kconfig
77468 --- linux-2.6.29-rc3.owrt/drivers/pnp/Kconfig 2009-05-10 22:04:48.000000000 +0200
77469 +++ linux-2.6.29-rc3.owrt.om/drivers/pnp/Kconfig 2009-05-10 22:28:00.000000000 +0200
77470 @@ -5,7 +5,7 @@
77471 menuconfig PNP
77472 bool "Plug and Play support"
77473 depends on HAS_IOMEM
77474 - depends on ISA || ACPI
77475 + depends on ISA || ACPI || SDIO
77476 ---help---
77477 Plug and Play (PnP) is a standard for peripherals which allows those
77478 peripherals to be configured by software, e.g. assign IRQ's or other
77479 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/pnp/resource.c linux-2.6.29-rc3.owrt.om/drivers/pnp/resource.c
77480 --- linux-2.6.29-rc3.owrt/drivers/pnp/resource.c 2009-05-10 22:04:48.000000000 +0200
77481 +++ linux-2.6.29-rc3.owrt.om/drivers/pnp/resource.c 2009-05-10 22:28:00.000000000 +0200
77482 @@ -436,6 +436,7 @@
77483 }
77484 }
77485
77486 +#if 0
77487 /* check if the resource is already in use, skip if the
77488 * device is active because it itself may be in use */
77489 if (!dev->active) {
77490 @@ -443,6 +444,7 @@
77491 return 0;
77492 free_dma(*dma);
77493 }
77494 +#endif
77495
77496 /* check for conflicts with other pnp devices */
77497 pnp_for_each_dev(tdev) {
77498 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/power/bq27000_battery.c linux-2.6.29-rc3.owrt.om/drivers/power/bq27000_battery.c
77499 --- linux-2.6.29-rc3.owrt/drivers/power/bq27000_battery.c 1970-01-01 01:00:00.000000000 +0100
77500 +++ linux-2.6.29-rc3.owrt.om/drivers/power/bq27000_battery.c 2009-05-10 22:28:00.000000000 +0200
77501 @@ -0,0 +1,474 @@
77502 +/*
77503 + * Driver for batteries with bq27000 chips inside via HDQ
77504 + *
77505 + * Copyright 2008 Openmoko, Inc
77506 + * Andy Green <andy@openmoko.com>
77507 + *
77508 + * based on ds2760 driver, original copyright notice for that --->
77509 + *
77510 + * Copyright © 2007 Anton Vorontsov
77511 + * 2004-2007 Matt Reimer
77512 + * 2004 Szabolcs Gyurko
77513 + *
77514 + * Use consistent with the GNU GPL is permitted,
77515 + * provided that this copyright notice is
77516 + * preserved in its entirety in all copies and derived works.
77517 + *
77518 + * Author: Anton Vorontsov <cbou@mail.ru>
77519 + * February 2007
77520 + *
77521 + * Matt Reimer <mreimer@vpop.net>
77522 + * April 2004, 2005, 2007
77523 + *
77524 + * Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
77525 + * September 2004
77526 + */
77527 +
77528 +#include <linux/module.h>
77529 +#include <linux/param.h>
77530 +#include <linux/jiffies.h>
77531 +#include <linux/delay.h>
77532 +#include <linux/pm.h>
77533 +#include <linux/workqueue.h>
77534 +#include <linux/platform_device.h>
77535 +#include <linux/power_supply.h>
77536 +#include <linux/bq27000_battery.h>
77537 +
77538 +enum bq27000_regs {
77539 + /* RAM regs */
77540 + /* read-write after this */
77541 + BQ27000_CTRL = 0, /* Device Control Register */
77542 + BQ27000_MODE, /* Device Mode Register */
77543 + BQ27000_AR_L, /* At-Rate H L */
77544 + BQ27000_AR_H,
77545 + /* read-only after this */
77546 + BQ27000_ARTTE_L, /* At-Rate Time To Empty H L */
77547 + BQ27000_ARTTE_H,
77548 + BQ27000_TEMP_L, /* Reported Temperature H L */
77549 + BQ27000_TEMP_H,
77550 + BQ27000_VOLT_L, /* Reported Voltage H L */
77551 + BQ27000_VOLT_H,
77552 + BQ27000_FLAGS, /* Status Flags */
77553 + BQ27000_RSOC, /* Relative State of Charge */
77554 + BQ27000_NAC_L, /* Nominal Available Capacity H L */
77555 + BQ27000_NAC_H,
77556 + BQ27000_CACD_L, /* Discharge Compensated H L */
77557 + BQ27000_CACD_H,
77558 + BQ27000_CACT_L, /* Temperature Compensated H L */
77559 + BQ27000_CACT_H,
77560 + BQ27000_LMD_L, /* Last measured discharge H L */
77561 + BQ27000_LMD_H,
77562 + BQ27000_AI_L, /* Average Current H L */
77563 + BQ27000_AI_H,
77564 + BQ27000_TTE_L, /* Time to Empty H L */
77565 + BQ27000_TTE_H,
77566 + BQ27000_TTF_L, /* Time to Full H L */
77567 + BQ27000_TTF_H,
77568 + BQ27000_SI_L, /* Standby Current H L */
77569 + BQ27000_SI_H,
77570 + BQ27000_STTE_L, /* Standby Time To Empty H L */
77571 + BQ27000_STTE_H,
77572 + BQ27000_MLI_L, /* Max Load Current H L */
77573 + BQ27000_MLI_H,
77574 + BQ27000_MLTTE_L, /* Max Load Time To Empty H L */
77575 + BQ27000_MLTTE_H,
77576 + BQ27000_SAE_L, /* Available Energy H L */
77577 + BQ27000_SAE_H,
77578 + BQ27000_AP_L, /* Available Power H L */
77579 + BQ27000_AP_H,
77580 + BQ27000_TTECP_L, /* Time to Empty at Constant Power H L */
77581 + BQ27000_TTECP_H,
77582 + BQ27000_CYCL_L, /* Cycle count since learning cycle H L */
77583 + BQ27000_CYCL_H,
77584 + BQ27000_CYCT_L, /* Cycle Count Total H L */
77585 + BQ27000_CYCT_H,
77586 + BQ27000_CSOC, /* Compensated State Of Charge */
77587 + /* EEPROM regs */
77588 + /* read-write after this */
77589 + BQ27000_EE_EE_EN = 0x6e, /* EEPROM Program Enable */
77590 + BQ27000_EE_ILMD = 0x76, /* Initial Last Measured Discharge High Byte */
77591 + BQ27000_EE_SEDVF, /* Scaled EDVF Threshold */
77592 + BQ27000_EE_SEDV1, /* Scaled EDV1 Threshold */
77593 + BQ27000_EE_ISLC, /* Initial Standby Load Current */
77594 + BQ27000_EE_DMFSD, /* Digital Magnitude Filter and Self Discharge */
77595 + BQ27000_EE_TAPER, /* Aging Estimate Enable, Charge Termination Taper */
77596 + BQ27000_EE_PKCFG, /* Pack Configuration Values */
77597 + BQ27000_EE_IMLC, /* Initial Max Load Current or ID #3 */
77598 + BQ27000_EE_DCOMP, /* Discharge rate compensation constants or ID #2 */
77599 + BQ27000_EE_TCOMP, /* Temperature Compensation constants or ID #1 */
77600 +};
77601 +
77602 +enum bq27000_status_flags {
77603 + BQ27000_STATUS_CHGS = 0x80, /* 1 = being charged */
77604 + BQ27000_STATUS_NOACT = 0x40, /* 1 = no activity */
77605 + BQ27000_STATUS_IMIN = 0x20, /* 1 = Lion taper current mode */
77606 + BQ27000_STATUS_CI = 0x10, /* 1 = capacity likely innacurate */
77607 + BQ27000_STATUS_CALIP = 0x08, /* 1 = calibration in progress */
77608 + BQ27000_STATUS_VDQ = 0x04, /* 1 = capacity should be accurate */
77609 + BQ27000_STATUS_EDV1 = 0x02, /* 1 = end of discharge.. <6% left */
77610 + BQ27000_STATUS_EDVF = 0x01, /* 1 = no, it's really empty now */
77611 +};
77612 +
77613 +#define NANOVOLTS_UNIT 3750
77614 +
77615 +struct bq27000_bat_regs {
77616 + int ai;
77617 + int flags;
77618 + int lmd;
77619 + int rsoc;
77620 + int temp;
77621 + int tte;
77622 + int ttf;
77623 + int volt;
77624 +};
77625 +
77626 +struct bq27000_device_info {
77627 + struct device *dev;
77628 + struct power_supply bat;
77629 + struct power_supply ac;
77630 + struct power_supply usb;
77631 + struct delayed_work work;
77632 + struct bq27000_platform_data *pdata;
77633 +
77634 + struct bq27000_bat_regs regs;
77635 +};
77636 +
77637 +static unsigned int cache_time = 5000;
77638 +module_param(cache_time, uint, 0644);
77639 +MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
77640 +
77641 +/*
77642 + * reading 16 bit values over HDQ has a special hazard where the
77643 + * hdq device firmware can update the 16-bit register during the time we
77644 + * read the two halves. TI document SLUS556D recommends the algorithm here
77645 + * to avoid trouble
77646 + */
77647 +
77648 +static int hdq_read16(struct bq27000_device_info *di, int address)
77649 +{
77650 + int acc;
77651 + int high;
77652 + int retries = 3;
77653 +
77654 + while (retries--) {
77655 +
77656 + high = (di->pdata->hdq_read)(address + 1); /* high part */
77657 +
77658 + if (high < 0)
77659 + return high;
77660 + acc = (di->pdata->hdq_read)(address);
77661 + if (acc < 0)
77662 + return acc;
77663 +
77664 + /* confirm high didn't change between reading it and low */
77665 + if (high == (di->pdata->hdq_read)(address + 1))
77666 + return (high << 8) | acc;
77667 + }
77668 +
77669 + return -ETIME;
77670 +}
77671 +
77672 +static void bq27000_battery_external_power_changed(struct power_supply *psy)
77673 +{
77674 + struct bq27000_device_info *di = container_of(psy, struct bq27000_device_info, bat);
77675 +
77676 + dev_dbg(di->dev, "%s\n", __FUNCTION__);
77677 + schedule_delayed_work(&di->work, 0);
77678 +}
77679 +
77680 +static int bq27000_battery_get_property(struct power_supply *psy,
77681 + enum power_supply_property psp,
77682 + union power_supply_propval *val)
77683 +{
77684 + int n;
77685 + struct bq27000_device_info *di = container_of(psy, struct bq27000_device_info, bat);
77686 +
77687 + switch (psp) {
77688 + case POWER_SUPPLY_PROP_STATUS:
77689 + val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
77690 +
77691 + if (!di->pdata->get_charger_online_status)
77692 + goto use_bat;
77693 + if ((di->pdata->get_charger_online_status)()) {
77694 + /*
77695 + * charger is definitively present
77696 + * we report our state in terms of what it says it
77697 + * is doing
77698 + */
77699 + if (!di->pdata->get_charger_active_status)
77700 + goto use_bat;
77701 +
77702 + if ((di->pdata->get_charger_active_status)()) {
77703 + val->intval = POWER_SUPPLY_STATUS_CHARGING;
77704 + break;
77705 + }
77706 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
77707 + break;
77708 + }
77709 +
77710 + /*
77711 + * platform provided definite indication of charger presence,
77712 + * and it is telling us it isn't there... but we are on so we
77713 + * must be running from battery --->
77714 + */
77715 +
77716 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
77717 + break;
77718 +
77719 +use_bat:
77720 + /*
77721 + * either the charger is not connected, or the
77722 + * platform doesn't give info about charger, use battery state
77723 + * but... battery state can be out of date by 4 seconds or
77724 + * so... use the platform callbacks if possible.
77725 + */
77726 +
77727 + /* no real activity on the battery */
77728 + if (di->regs.ai < 2) {
77729 + if (!di->regs.ttf)
77730 + val->intval = POWER_SUPPLY_STATUS_FULL;
77731 + else
77732 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
77733 + break;
77734 + }
77735 + /* power is actually going in or out... */
77736 + if (di->regs.flags < 0)
77737 + return di->regs.flags;
77738 + if (di->regs.flags & BQ27000_STATUS_CHGS)
77739 + val->intval = POWER_SUPPLY_STATUS_CHARGING;
77740 + else
77741 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
77742 + break;
77743 + case POWER_SUPPLY_PROP_HEALTH:
77744 + val->intval = POWER_SUPPLY_HEALTH_UNKNOWN;
77745 + /* Do we have accurate readings... */
77746 + if (di->regs.flags < 0)
77747 + return di->regs.flags;
77748 + if (di->regs.flags & BQ27000_STATUS_VDQ)
77749 + val->intval = POWER_SUPPLY_HEALTH_GOOD;
77750 + break;
77751 + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
77752 + if (di->regs.volt < 0)
77753 + return di->regs.volt;
77754 + /* mV -> uV */
77755 + val->intval = di->regs.volt * 1000;
77756 + break;
77757 + case POWER_SUPPLY_PROP_CURRENT_NOW:
77758 + if (di->regs.flags < 0)
77759 + return di->regs.flags;
77760 + if (di->regs.flags & BQ27000_STATUS_CHGS)
77761 + n = -NANOVOLTS_UNIT;
77762 + else
77763 + n = NANOVOLTS_UNIT;
77764 + if (di->regs.ai < 0)
77765 + return di->regs.ai;
77766 + val->intval = (di->regs.ai * n) / di->pdata->rsense_mohms;
77767 + break;
77768 + case POWER_SUPPLY_PROP_CHARGE_FULL:
77769 + if (di->regs.lmd < 0)
77770 + return di->regs.lmd;
77771 + val->intval = (di->regs.lmd * 3570) / di->pdata->rsense_mohms;
77772 + break;
77773 + case POWER_SUPPLY_PROP_TEMP:
77774 + if (di->regs.temp < 0)
77775 + return di->regs.temp;
77776 + /* K (in 0.25K units) is 273.15 up from C (in 0.1C)*/
77777 + /* 10926 = 27315 * 4 / 10 */
77778 + val->intval = (((long)di->regs.temp * 10l) - 10926) / 4;
77779 + break;
77780 + case POWER_SUPPLY_PROP_TECHNOLOGY:
77781 + val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
77782 + break;
77783 + case POWER_SUPPLY_PROP_CAPACITY:
77784 + val->intval = di->regs.rsoc;
77785 + if (val->intval < 0)
77786 + return val->intval;
77787 + break;
77788 + case POWER_SUPPLY_PROP_PRESENT:
77789 + val->intval = !(di->regs.rsoc < 0);
77790 + break;
77791 + case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
77792 + if (di->regs.tte < 0)
77793 + return di->regs.tte;
77794 + val->intval = 60 * di->regs.tte;
77795 + break;
77796 + case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
77797 + if (di->regs.ttf < 0)
77798 + return di->regs.ttf;
77799 + val->intval = 60 * di->regs.ttf;
77800 + break;
77801 + case POWER_SUPPLY_PROP_ONLINE:
77802 + if (di->pdata->get_charger_online_status)
77803 + val->intval = (di->pdata->get_charger_online_status)();
77804 + else
77805 + return -EINVAL;
77806 + break;
77807 + default:
77808 + return -EINVAL;
77809 + }
77810 +
77811 + return 0;
77812 +}
77813 +
77814 +static void bq27000_battery_work(struct work_struct *work)
77815 +{
77816 + struct bq27000_device_info *di =
77817 + container_of(work, struct bq27000_device_info, work.work);
77818 +
77819 + if ((di->pdata->hdq_initialized)()) {
77820 + struct bq27000_bat_regs regs;
77821 +
77822 + regs.ai = hdq_read16(di, BQ27000_AI_L);
77823 + regs.flags = (di->pdata->hdq_read)(BQ27000_FLAGS);
77824 + regs.lmd = hdq_read16(di, BQ27000_LMD_L);
77825 + regs.rsoc = (di->pdata->hdq_read)(BQ27000_RSOC);
77826 + regs.temp = hdq_read16(di, BQ27000_TEMP_L);
77827 + regs.tte = hdq_read16(di, BQ27000_TTE_L);
77828 + regs.ttf = hdq_read16(di, BQ27000_TTF_L);
77829 + regs.volt = hdq_read16(di, BQ27000_VOLT_L);
77830 +
77831 + if (memcmp (&regs, &di->regs, sizeof(regs)) != 0) {
77832 + di->regs = regs;
77833 + power_supply_changed(&di->bat);
77834 + }
77835 + }
77836 +
77837 + if (!schedule_delayed_work(&di->work, cache_time))
77838 + dev_err(di->dev, "battery service reschedule failed\n");
77839 +}
77840 +
77841 +static enum power_supply_property bq27000_battery_props[] = {
77842 + POWER_SUPPLY_PROP_STATUS,
77843 + POWER_SUPPLY_PROP_HEALTH,
77844 + POWER_SUPPLY_PROP_VOLTAGE_NOW,
77845 + POWER_SUPPLY_PROP_CURRENT_NOW,
77846 + POWER_SUPPLY_PROP_CHARGE_FULL,
77847 + POWER_SUPPLY_PROP_TEMP,
77848 + POWER_SUPPLY_PROP_TECHNOLOGY,
77849 + POWER_SUPPLY_PROP_PRESENT,
77850 + POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
77851 + POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
77852 + POWER_SUPPLY_PROP_CAPACITY,
77853 + POWER_SUPPLY_PROP_ONLINE
77854 +};
77855 +
77856 +static int bq27000_battery_probe(struct platform_device *pdev)
77857 +{
77858 + int retval = 0;
77859 + struct bq27000_device_info *di;
77860 + struct bq27000_platform_data *pdata;
77861 +
77862 + dev_info(&pdev->dev, "BQ27000 Battery Driver (C) 2008 Openmoko, Inc\n");
77863 +
77864 + di = kzalloc(sizeof(*di), GFP_KERNEL);
77865 + if (!di) {
77866 + retval = -ENOMEM;
77867 + goto di_alloc_failed;
77868 + }
77869 +
77870 + platform_set_drvdata(pdev, di);
77871 +
77872 + pdata = pdev->dev.platform_data;
77873 + di->dev = &pdev->dev;
77874 + /* di->w1_dev = pdev->dev.parent; */
77875 + di->bat.name = pdata->name;
77876 + di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
77877 + di->bat.properties = bq27000_battery_props;
77878 + di->bat.num_properties = ARRAY_SIZE(bq27000_battery_props);
77879 + di->bat.get_property = bq27000_battery_get_property;
77880 + di->bat.external_power_changed =
77881 + bq27000_battery_external_power_changed;
77882 + di->bat.use_for_apm = 1;
77883 + di->pdata = pdata;
77884 +
77885 + retval = power_supply_register(&pdev->dev, &di->bat);
77886 + if (retval) {
77887 + dev_err(di->dev, "failed to register battery\n");
77888 + goto batt_failed;
77889 + }
77890 +
77891 + INIT_DELAYED_WORK(&di->work, bq27000_battery_work);
77892 +
77893 + if (!schedule_delayed_work(&di->work, 0))
77894 + dev_err(di->dev, "failed to schedule bq27000_battery_work\n");
77895 +
77896 + return 0;
77897 +
77898 +batt_failed:
77899 + kfree(di);
77900 +di_alloc_failed:
77901 + return retval;
77902 +}
77903 +
77904 +static int bq27000_battery_remove(struct platform_device *pdev)
77905 +{
77906 + struct bq27000_device_info *di = platform_get_drvdata(pdev);
77907 +
77908 + cancel_delayed_work(&di->work);
77909 +
77910 + power_supply_unregister(&di->bat);
77911 +
77912 + return 0;
77913 +}
77914 +
77915 +void bq27000_charging_state_change(struct platform_device *pdev)
77916 +{
77917 + struct bq27000_device_info *di = platform_get_drvdata(pdev);
77918 +
77919 + if (!di)
77920 + return;
77921 +}
77922 +EXPORT_SYMBOL_GPL(bq27000_charging_state_change);
77923 +
77924 +#ifdef CONFIG_PM
77925 +
77926 +static int bq27000_battery_suspend(struct platform_device *pdev,
77927 + pm_message_t state)
77928 +{
77929 + struct bq27000_device_info *di = platform_get_drvdata(pdev);
77930 +
77931 + cancel_delayed_work(&di->work);
77932 + return 0;
77933 +}
77934 +
77935 +static int bq27000_battery_resume(struct platform_device *pdev)
77936 +{
77937 + struct bq27000_device_info *di = platform_get_drvdata(pdev);
77938 +
77939 + schedule_delayed_work(&di->work, 0);
77940 + return 0;
77941 +}
77942 +
77943 +#else
77944 +
77945 +#define bq27000_battery_suspend NULL
77946 +#define bq27000_battery_resume NULL
77947 +
77948 +#endif /* CONFIG_PM */
77949 +
77950 +static struct platform_driver bq27000_battery_driver = {
77951 + .driver = {
77952 + .name = "bq27000-battery",
77953 + },
77954 + .probe = bq27000_battery_probe,
77955 + .remove = bq27000_battery_remove,
77956 + .suspend = bq27000_battery_suspend,
77957 + .resume = bq27000_battery_resume,
77958 +};
77959 +
77960 +static int __init bq27000_battery_init(void)
77961 +{
77962 + return platform_driver_register(&bq27000_battery_driver);
77963 +}
77964 +
77965 +static void __exit bq27000_battery_exit(void)
77966 +{
77967 + platform_driver_unregister(&bq27000_battery_driver);
77968 +}
77969 +
77970 +module_init(bq27000_battery_init);
77971 +module_exit(bq27000_battery_exit);
77972 +
77973 +MODULE_LICENSE("GPL");
77974 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
77975 +MODULE_DESCRIPTION("bq27000 battery driver");
77976 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/power/gta01_battery.c linux-2.6.29-rc3.owrt.om/drivers/power/gta01_battery.c
77977 --- linux-2.6.29-rc3.owrt/drivers/power/gta01_battery.c 1970-01-01 01:00:00.000000000 +0100
77978 +++ linux-2.6.29-rc3.owrt.om/drivers/power/gta01_battery.c 2009-05-10 22:28:00.000000000 +0200
77979 @@ -0,0 +1,117 @@
77980 +/*
77981 + * Dumb driver for gta01 battery
77982 + *
77983 + * Copyright 2009 Openmoko, Inc
77984 + * Balaji Rao <balajirrao@openmoko.org>
77985 + */
77986 +
77987 +#include <linux/module.h>
77988 +#include <linux/param.h>
77989 +#include <linux/delay.h>
77990 +#include <linux/workqueue.h>
77991 +#include <linux/platform_device.h>
77992 +#include <linux/power_supply.h>
77993 +#include <linux/gta01_battery.h>
77994 +
77995 +struct gta01_battery {
77996 + struct power_supply psy;
77997 + struct gta01_bat_platform_data *pdata;
77998 +};
77999 +
78000 +static enum power_supply_property gta01_bat_props[] = {
78001 + POWER_SUPPLY_PROP_PRESENT,
78002 + POWER_SUPPLY_PROP_STATUS,
78003 + POWER_SUPPLY_PROP_VOLTAGE_NOW,
78004 + POWER_SUPPLY_PROP_CURRENT_NOW,
78005 +};
78006 +
78007 +static int gta01_bat_get_property(struct power_supply *psy,
78008 + enum power_supply_property psp,
78009 + union power_supply_propval *val)
78010 +{
78011 + struct gta01_battery *bat = container_of(psy, struct gta01_battery, psy);
78012 +
78013 + switch(psp) {
78014 + case POWER_SUPPLY_PROP_STATUS:
78015 + if (bat->pdata->get_charging_status())
78016 + val->intval = POWER_SUPPLY_STATUS_CHARGING;
78017 + else
78018 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
78019 + break;
78020 + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
78021 + val->intval = bat->pdata->get_voltage();
78022 + break;
78023 + case POWER_SUPPLY_PROP_CURRENT_NOW:
78024 + val->intval = bat->pdata->get_current();
78025 + break;
78026 + case POWER_SUPPLY_PROP_PRESENT:
78027 + val->intval = 1; /* You must never run GTA01 without battery. */
78028 + break;
78029 + default:
78030 + return -EINVAL;
78031 + }
78032 +
78033 + return 0;
78034 +}
78035 +
78036 +static void gta01_bat_ext_changed(struct power_supply *psy)
78037 +{
78038 + struct gta01_battery *bat = container_of(psy, struct gta01_battery, psy);
78039 + power_supply_changed(&bat->psy);
78040 +}
78041 +
78042 +static int gta01_battery_probe(struct platform_device *pdev)
78043 +{
78044 + struct gta01_battery *gta01_bat;
78045 +
78046 + gta01_bat = kzalloc(sizeof(*gta01_bat), GFP_KERNEL);
78047 + if (!gta01_bat)
78048 + return -ENOMEM;
78049 +
78050 + gta01_bat->psy.name = "battery";
78051 + gta01_bat->psy.type = POWER_SUPPLY_TYPE_BATTERY;
78052 + gta01_bat->psy.properties = gta01_bat_props;
78053 + gta01_bat->psy.num_properties = ARRAY_SIZE(gta01_bat_props);
78054 + gta01_bat->psy.get_property = gta01_bat_get_property;
78055 + gta01_bat->psy.external_power_changed = gta01_bat_ext_changed;
78056 +
78057 + gta01_bat->pdata = pdev->dev.platform_data;
78058 + power_supply_register(&pdev->dev, &gta01_bat->psy);
78059 +
78060 + return 0;
78061 +}
78062 +
78063 +static int gta01_battery_remove(struct platform_device *pdev)
78064 +{
78065 + struct gta01_battery *bat = platform_get_drvdata(pdev);
78066 +
78067 + power_supply_unregister(&bat->psy);
78068 + kfree(bat);
78069 +
78070 + return 0;
78071 +}
78072 +
78073 +static struct platform_driver gta01_battery_driver = {
78074 + .driver = {
78075 + .name = "gta01_battery",
78076 + },
78077 + .probe = gta01_battery_probe,
78078 + .remove = gta01_battery_remove,
78079 +};
78080 +
78081 +static int __init gta01_battery_init(void)
78082 +{
78083 + return platform_driver_register(&gta01_battery_driver);
78084 +}
78085 +
78086 +static void __exit gta01_battery_exit(void)
78087 +{
78088 + platform_driver_unregister(&gta01_battery_driver);
78089 +}
78090 +
78091 +module_init(gta01_battery_init);
78092 +module_exit(gta01_battery_exit);
78093 +
78094 +MODULE_LICENSE("GPL");
78095 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
78096 +MODULE_DESCRIPTION("gta01 battery driver");
78097 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/power/hdq.c linux-2.6.29-rc3.owrt.om/drivers/power/hdq.c
78098 --- linux-2.6.29-rc3.owrt/drivers/power/hdq.c 1970-01-01 01:00:00.000000000 +0100
78099 +++ linux-2.6.29-rc3.owrt.om/drivers/power/hdq.c 2009-05-10 22:28:00.000000000 +0200
78100 @@ -0,0 +1,515 @@
78101 +/*
78102 + * HDQ generic GPIO bitbang driver using FIQ
78103 + *
78104 + * (C) 2006-2007 by Openmoko, Inc.
78105 + * Author: Andy Green <andy@openmoko.com>
78106 + * All rights reserved.
78107 + *
78108 + * This program is free software; you can redistribute it and/or modify
78109 + * it under the terms of the GNU General Public License version 2 as
78110 + * published by the Free Software Foundation.
78111 + *
78112 + */
78113 +
78114 +#include <linux/kernel.h>
78115 +#include <linux/init.h>
78116 +#include <linux/delay.h>
78117 +#include <linux/platform_device.h>
78118 +#include <linux/hdq.h>
78119 +
78120 +#define HDQ_READ 0
78121 +#define HDQ_WRITE 0x80
78122 +
78123 +enum hdq_bitbang_states {
78124 + HDQB_IDLE = 0,
78125 + HDQB_TX_BREAK,
78126 + HDQB_TX_BREAK_RECOVERY,
78127 + HDQB_ADS_CALC,
78128 + HDQB_ADS_LOW,
78129 + HDQB_ADS_HIGH,
78130 + HDQB_WAIT_RX,
78131 + HDQB_DATA_RX_LOW,
78132 + HDQB_DATA_RX_HIGH,
78133 + HDQB_WAIT_TX,
78134 +};
78135 +
78136 +static struct hdq_priv {
78137 + u8 hdq_probed; /* nonzero after HDQ driver probed */
78138 + struct mutex hdq_lock; /* if you want to use hdq, you have to take lock */
78139 + unsigned long hdq_gpio_pin; /* GTA02 = GPD14 which pin to meddle with */
78140 + u8 hdq_ads; /* b7..b6 = register address, b0 = r/w */
78141 + u8 hdq_tx_data; /* data to tx for write action */
78142 + u8 hdq_rx_data; /* data received in read action */
78143 + u8 hdq_request_ctr; /* incremented by "user" to request a transfer */
78144 + u8 hdq_transaction_ctr; /* incremented after each transfer */
78145 + u8 hdq_error; /* 0 = no error */
78146 + u8 hdq_ctr;
78147 + u8 hdq_ctr2;
78148 + u8 hdq_bit;
78149 + u8 hdq_shifter;
78150 + u8 hdq_tx_data_done;
78151 + enum hdq_bitbang_states hdq_state;
78152 + int reported_error;
78153 +
78154 + struct hdq_platform_data *pdata;
78155 +} hdq_priv;
78156 +
78157 +
78158 +static void hdq_bad(void)
78159 +{
78160 + if (!hdq_priv.reported_error)
78161 + printk(KERN_ERR "HDQ error: %d\n", hdq_priv.hdq_error);
78162 + hdq_priv.reported_error = 1;
78163 +}
78164 +
78165 +static void hdq_good(void)
78166 +{
78167 + if (hdq_priv.reported_error)
78168 + printk(KERN_INFO "HDQ responds again\n");
78169 + hdq_priv.reported_error = 0;
78170 +}
78171 +
78172 +int hdq_fiq_handler(void)
78173 +{
78174 + if (!hdq_priv.hdq_probed)
78175 + return 0;
78176 +
78177 + switch (hdq_priv.hdq_state) {
78178 + case HDQB_IDLE:
78179 + if (hdq_priv.hdq_request_ctr == hdq_priv.hdq_transaction_ctr)
78180 + break;
78181 + hdq_priv.hdq_ctr = 250 / HDQ_SAMPLE_PERIOD_US;
78182 + hdq_priv.pdata->gpio_set(0);
78183 + hdq_priv.pdata->gpio_dir_out();
78184 + hdq_priv.hdq_tx_data_done = 0;
78185 + hdq_priv.hdq_state = HDQB_TX_BREAK;
78186 + break;
78187 +
78188 + case HDQB_TX_BREAK: /* issue low for > 190us */
78189 + if (--hdq_priv.hdq_ctr == 0) {
78190 + hdq_priv.hdq_ctr = 60 / HDQ_SAMPLE_PERIOD_US;
78191 + hdq_priv.hdq_state = HDQB_TX_BREAK_RECOVERY;
78192 + hdq_priv.pdata->gpio_set(1);
78193 + }
78194 + break;
78195 +
78196 + case HDQB_TX_BREAK_RECOVERY: /* issue low for > 40us */
78197 + if (--hdq_priv.hdq_ctr)
78198 + break;
78199 + hdq_priv.hdq_shifter = hdq_priv.hdq_ads;
78200 + hdq_priv.hdq_bit = 8; /* 8 bits of ads / rw */
78201 + hdq_priv.hdq_tx_data_done = 0; /* doing ads */
78202 + /* fallthru on last one */
78203 + case HDQB_ADS_CALC:
78204 + if (hdq_priv.hdq_shifter & 1)
78205 + hdq_priv.hdq_ctr = 50 / HDQ_SAMPLE_PERIOD_US;
78206 + else
78207 + hdq_priv.hdq_ctr = 120 / HDQ_SAMPLE_PERIOD_US;
78208 + /* carefully precompute the other phase length */
78209 + hdq_priv.hdq_ctr2 = (210 - (hdq_priv.hdq_ctr * HDQ_SAMPLE_PERIOD_US)) /
78210 + HDQ_SAMPLE_PERIOD_US;
78211 + hdq_priv.hdq_state = HDQB_ADS_LOW;
78212 + hdq_priv.hdq_shifter >>= 1;
78213 + hdq_priv.hdq_bit--;
78214 + hdq_priv.pdata->gpio_set(0);
78215 + break;
78216 +
78217 + case HDQB_ADS_LOW:
78218 + if (--hdq_priv.hdq_ctr)
78219 + break;
78220 + hdq_priv.pdata->gpio_set(1);
78221 + hdq_priv.hdq_state = HDQB_ADS_HIGH;
78222 + break;
78223 +
78224 + case HDQB_ADS_HIGH:
78225 + if (--hdq_priv.hdq_ctr2 > 1) /* account for HDQB_ADS_CALC */
78226 + break;
78227 + if (hdq_priv.hdq_bit) { /* more bits to do */
78228 + hdq_priv.hdq_state = HDQB_ADS_CALC;
78229 + break;
78230 + }
78231 + /* no more bits, wait it out until hdq_priv.hdq_ctr2 exhausted */
78232 + if (hdq_priv.hdq_ctr2)
78233 + break;
78234 + /* ok no more bits and very last state */
78235 + hdq_priv.hdq_ctr = 60 / HDQ_SAMPLE_PERIOD_US;
78236 + /* FIXME 0 = read */
78237 + if (hdq_priv.hdq_ads & 0x80) { /* write the byte out */
78238 + /* set delay before payload */
78239 + hdq_priv.hdq_ctr = 300 / HDQ_SAMPLE_PERIOD_US;
78240 + /* already high, no need to write */
78241 + hdq_priv.hdq_state = HDQB_WAIT_TX;
78242 + break;
78243 + }
78244 + /* read the next byte */
78245 + hdq_priv.hdq_bit = 8; /* 8 bits of data */
78246 + hdq_priv.hdq_ctr = 2500 / HDQ_SAMPLE_PERIOD_US;
78247 + hdq_priv.hdq_state = HDQB_WAIT_RX;
78248 + hdq_priv.pdata->gpio_dir_in();
78249 + break;
78250 +
78251 + case HDQB_WAIT_TX: /* issue low for > 40us */
78252 + if (--hdq_priv.hdq_ctr)
78253 + break;
78254 + if (!hdq_priv.hdq_tx_data_done) { /* was that the data sent? */
78255 + hdq_priv.hdq_tx_data_done++;
78256 + hdq_priv.hdq_shifter = hdq_priv.hdq_tx_data;
78257 + hdq_priv.hdq_bit = 8; /* 8 bits of data */
78258 + hdq_priv.hdq_state = HDQB_ADS_CALC; /* start sending */
78259 + break;
78260 + }
78261 + hdq_priv.hdq_error = 0;
78262 + hdq_priv.hdq_transaction_ctr = hdq_priv.hdq_request_ctr;
78263 + hdq_priv.hdq_state = HDQB_IDLE; /* all tx is done */
78264 + /* idle in input mode, it's pulled up by 10K */
78265 + hdq_priv.pdata->gpio_dir_in();
78266 + break;
78267 +
78268 + case HDQB_WAIT_RX: /* wait for battery to talk to us */
78269 + if (hdq_priv.pdata->gpio_get() == 0) {
78270 + /* it talks to us! */
78271 + hdq_priv.hdq_ctr2 = 1;
78272 + hdq_priv.hdq_bit = 8; /* 8 bits of data */
78273 + /* timeout */
78274 + hdq_priv.hdq_ctr = 500 / HDQ_SAMPLE_PERIOD_US;
78275 + hdq_priv.hdq_state = HDQB_DATA_RX_LOW;
78276 + break;
78277 + }
78278 + if (--hdq_priv.hdq_ctr == 0) { /* timed out, error */
78279 + hdq_priv.hdq_error = 1;
78280 + hdq_priv.hdq_transaction_ctr = hdq_priv.hdq_request_ctr;
78281 + hdq_priv.hdq_state = HDQB_IDLE; /* abort */
78282 + }
78283 + break;
78284 +
78285 + /*
78286 + * HDQ basically works by measuring the low time of the bit cell
78287 + * 32-50us --> '1', 80 - 145us --> '0'
78288 + */
78289 +
78290 + case HDQB_DATA_RX_LOW:
78291 + if (hdq_priv.pdata->gpio_get()) {
78292 + hdq_priv.hdq_rx_data >>= 1;
78293 + if (hdq_priv.hdq_ctr2 <= (65 / HDQ_SAMPLE_PERIOD_US))
78294 + hdq_priv.hdq_rx_data |= 0x80;
78295 +
78296 + if (--hdq_priv.hdq_bit == 0) {
78297 + hdq_priv.hdq_error = 0;
78298 + hdq_priv.hdq_transaction_ctr =
78299 + hdq_priv.hdq_request_ctr;
78300 +
78301 + hdq_priv.hdq_state = HDQB_IDLE;
78302 + } else
78303 + hdq_priv.hdq_state = HDQB_DATA_RX_HIGH;
78304 + /* timeout */
78305 + hdq_priv.hdq_ctr = 1000 / HDQ_SAMPLE_PERIOD_US;
78306 + hdq_priv.hdq_ctr2 = 1;
78307 + break;
78308 + }
78309 + hdq_priv.hdq_ctr2++;
78310 + if (--hdq_priv.hdq_ctr)
78311 + break;
78312 + /* timed out, error */
78313 + hdq_priv.hdq_error = 2;
78314 + hdq_priv.hdq_transaction_ctr = hdq_priv.hdq_request_ctr;
78315 + hdq_priv.hdq_state = HDQB_IDLE; /* abort */
78316 + break;
78317 +
78318 + case HDQB_DATA_RX_HIGH:
78319 + if (!hdq_priv.pdata->gpio_get()) {
78320 + /* it talks to us! */
78321 + hdq_priv.hdq_ctr2 = 1;
78322 + /* timeout */
78323 + hdq_priv.hdq_ctr = 400 / HDQ_SAMPLE_PERIOD_US;
78324 + hdq_priv.hdq_state = HDQB_DATA_RX_LOW;
78325 + break;
78326 + }
78327 + if (--hdq_priv.hdq_ctr)
78328 + break;
78329 + /* timed out, error */
78330 + hdq_priv.hdq_error = 3;
78331 + hdq_priv.hdq_transaction_ctr = hdq_priv.hdq_request_ctr;
78332 +
78333 + /* we're in input mode already */
78334 + hdq_priv.hdq_state = HDQB_IDLE; /* abort */
78335 + break;
78336 + }
78337 +
78338 + /* Are we interested in keeping the FIQ source alive ? */
78339 + if (hdq_priv.hdq_state != HDQB_IDLE)
78340 + return 1;
78341 + else
78342 + return 0;
78343 +}
78344 +static int fiq_busy(void)
78345 +{
78346 + int request = (volatile u8)hdq_priv.hdq_request_ctr;
78347 + int transact = (volatile u8)hdq_priv.hdq_transaction_ctr;
78348 +
78349 +
78350 + return (request != transact);
78351 +}
78352 +
78353 +int hdq_initialized(void)
78354 +{
78355 + return hdq_priv.hdq_probed;
78356 +}
78357 +EXPORT_SYMBOL_GPL(hdq_initialized);
78358 +
78359 +int hdq_read(int address)
78360 +{
78361 + int count_sleeps = 5;
78362 + int ret = -ETIME;
78363 +
78364 + if (!hdq_priv.hdq_probed)
78365 + return -EINVAL;
78366 +
78367 + mutex_lock(&hdq_priv.hdq_lock);
78368 +
78369 + hdq_priv.hdq_error = 0;
78370 + hdq_priv.hdq_ads = address | HDQ_READ;
78371 + hdq_priv.hdq_request_ctr++;
78372 + hdq_priv.pdata->kick_fiq();
78373 + /*
78374 + * FIQ takes care of it while we block our calling process
78375 + * But we're not spinning -- other processes run normally while
78376 + * we wait for the result
78377 + */
78378 + while (count_sleeps--) {
78379 + msleep(10); /* valid transaction always completes in < 10ms */
78380 +
78381 + if (fiq_busy())
78382 + continue;
78383 +
78384 + if (hdq_priv.hdq_error) {
78385 + hdq_bad();
78386 + goto done; /* didn't see a response in good time */
78387 + }
78388 + hdq_good();
78389 +
78390 + ret = hdq_priv.hdq_rx_data;
78391 + goto done;
78392 + }
78393 +
78394 +done:
78395 + mutex_unlock(&hdq_priv.hdq_lock);
78396 + return ret;
78397 +}
78398 +EXPORT_SYMBOL_GPL(hdq_read);
78399 +
78400 +int hdq_write(int address, u8 data)
78401 +{
78402 + int count_sleeps = 5;
78403 + int ret = -ETIME;
78404 +
78405 + if (!hdq_priv.hdq_probed)
78406 + return -EINVAL;
78407 +
78408 + mutex_lock(&hdq_priv.hdq_lock);
78409 +
78410 + hdq_priv.hdq_error = 0;
78411 + hdq_priv.hdq_ads = address | HDQ_WRITE;
78412 + hdq_priv.hdq_tx_data = data;
78413 + hdq_priv.hdq_request_ctr++;
78414 + hdq_priv.pdata->kick_fiq();
78415 + /*
78416 + * FIQ takes care of it while we block our calling process
78417 + * But we're not spinning -- other processes run normally while
78418 + * we wait for the result
78419 + */
78420 + while (count_sleeps--) {
78421 + msleep(10); /* valid transaction always completes in < 10ms */
78422 +
78423 + if (fiq_busy())
78424 + continue; /* something bad with FIQ */
78425 +
78426 + if (hdq_priv.hdq_error) {
78427 + hdq_bad();
78428 + goto done; /* didn't see a response in good time */
78429 + }
78430 + hdq_good();
78431 +
78432 + ret = 0;
78433 + goto done;
78434 + }
78435 +
78436 +done:
78437 + mutex_unlock(&hdq_priv.hdq_lock);
78438 + return ret;
78439 +}
78440 +EXPORT_SYMBOL_GPL(hdq_write);
78441 +
78442 +/* sysfs */
78443 +
78444 +static ssize_t hdq_sysfs_dump(struct device *dev, struct device_attribute *attr,
78445 + char *buf)
78446 +{
78447 + int n;
78448 + int v;
78449 + u8 u8a[128]; /* whole address space for HDQ */
78450 + char *end = buf;
78451 +
78452 + if (!hdq_priv.hdq_probed)
78453 + return -EINVAL;
78454 +
78455 + /* the dump does not take care about 16 bit regs, because at this
78456 + * bus level we don't know about the chip details
78457 + */
78458 + for (n = 0; n < sizeof(u8a); n++) {
78459 + v = hdq_read(n);
78460 + if (v < 0)
78461 + goto bail;
78462 + u8a[n] = v;
78463 + }
78464 +
78465 + for (n = 0; n < sizeof(u8a); n += 16) {
78466 + hex_dump_to_buffer(u8a + n, sizeof(u8a), 16, 1, end, 4096, 0);
78467 + end += strlen(end);
78468 + *end++ = '\n';
78469 + *end = '\0';
78470 + }
78471 + return (end - buf);
78472 +
78473 +bail:
78474 + return sprintf(buf, "ERROR %d\n", v);
78475 +}
78476 +
78477 +/* you write by <address> <data>, eg, "34 128" */
78478 +
78479 +#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
78480 +
78481 +static ssize_t hdq_sysfs_write(struct device *dev,
78482 + struct device_attribute *attr,
78483 + const char *buf, size_t count)
78484 +{
78485 + const char *end = buf + count;
78486 + int address = atoi(buf);
78487 +
78488 + if (!hdq_priv.hdq_probed)
78489 + return -EINVAL;
78490 +
78491 + while ((buf != end) && (*buf != ' '))
78492 + buf++;
78493 + if (buf >= end)
78494 + return 0;
78495 + while ((buf < end) && (*buf == ' '))
78496 + buf++;
78497 + if (buf >= end)
78498 + return 0;
78499 +
78500 + hdq_write(address, atoi(buf));
78501 +
78502 + return count;
78503 +}
78504 +
78505 +static DEVICE_ATTR(dump, 0400, hdq_sysfs_dump, NULL);
78506 +static DEVICE_ATTR(write, 0600, NULL, hdq_sysfs_write);
78507 +
78508 +static struct attribute *hdq_sysfs_entries[] = {
78509 + &dev_attr_dump.attr,
78510 + &dev_attr_write.attr,
78511 + NULL
78512 +};
78513 +
78514 +static struct attribute_group hdq_attr_group = {
78515 + .name = "hdq",
78516 + .attrs = hdq_sysfs_entries,
78517 +};
78518 +
78519 +
78520 +#ifdef CONFIG_PM
78521 +static int hdq_suspend(struct platform_device *pdev, pm_message_t state)
78522 +{
78523 + /* after 18s of this, the battery monitor will also go to sleep */
78524 + hdq_priv.pdata->gpio_dir_in();
78525 + hdq_priv.pdata->disable_fiq();
78526 + return 0;
78527 +}
78528 +
78529 +static int hdq_resume(struct platform_device *pdev)
78530 +{
78531 + hdq_priv.pdata->gpio_set(1);
78532 + hdq_priv.pdata->gpio_dir_out();
78533 + hdq_priv.pdata->enable_fiq();
78534 + return 0;
78535 +}
78536 +#endif
78537 +
78538 +static int __init hdq_probe(struct platform_device *pdev)
78539 +{
78540 + struct resource *r = platform_get_resource(pdev, 0, 0);
78541 + int ret;
78542 + struct hdq_platform_data *pdata = pdev->dev.platform_data;
78543 +
78544 + if (!r || !pdata)
78545 + return -EINVAL;
78546 +
78547 + platform_set_drvdata(pdev, NULL);
78548 +
78549 + mutex_init(&hdq_priv.hdq_lock);
78550 +
78551 + /* set our HDQ comms pin from the platform data */
78552 + hdq_priv.hdq_gpio_pin = r->start;
78553 + hdq_priv.pdata = pdata;
78554 +
78555 + hdq_priv.pdata->gpio_set(1);
78556 + hdq_priv.pdata->gpio_dir_out();
78557 +
78558 + /* Initialize FIQ */
78559 + if (hdq_priv.pdata->enable_fiq() < 0) {
78560 + dev_err(&pdev->dev, "Could not enable FIQ source\n");
78561 + return -EINVAL;
78562 + }
78563 +
78564 + ret = sysfs_create_group(&pdev->dev.kobj, &hdq_attr_group);
78565 + if (ret)
78566 + return ret;
78567 +
78568 + hdq_priv.hdq_probed = 1; /* we are ready to do stuff now */
78569 +
78570 + /*
78571 + * if wanted, users can defer registration of devices
78572 + * that depend on HDQ until after we register, and can use our
78573 + * device as parent so suspend-resume ordering is correct
78574 + */
78575 + if (pdata->attach_child_devices)
78576 + (pdata->attach_child_devices)(&pdev->dev);
78577 +
78578 + hdq_priv.pdata = pdata;
78579 +
78580 + return 0;
78581 +}
78582 +
78583 +static int hdq_remove(struct platform_device *pdev)
78584 +{
78585 + sysfs_remove_group(&pdev->dev.kobj, &hdq_attr_group);
78586 + return 0;
78587 +}
78588 +
78589 +static struct platform_driver hdq_driver = {
78590 + .probe = hdq_probe,
78591 + .remove = hdq_remove,
78592 +#ifdef CONFIG_PM
78593 + .suspend = hdq_suspend,
78594 + .resume = hdq_resume,
78595 +#endif
78596 + .driver = {
78597 + .name = "hdq",
78598 + },
78599 +};
78600 +
78601 +static int __init hdq_init(void)
78602 +{
78603 + return platform_driver_register(&hdq_driver);
78604 +}
78605 +
78606 +static void __exit hdq_exit(void)
78607 +{
78608 + platform_driver_unregister(&hdq_driver);
78609 +}
78610 +
78611 +module_init(hdq_init);
78612 +module_exit(hdq_exit);
78613 +
78614 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
78615 +MODULE_DESCRIPTION("HDQ driver");
78616 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/power/Kconfig linux-2.6.29-rc3.owrt.om/drivers/power/Kconfig
78617 --- linux-2.6.29-rc3.owrt/drivers/power/Kconfig 2009-05-10 22:04:48.000000000 +0200
78618 +++ linux-2.6.29-rc3.owrt.om/drivers/power/Kconfig 2009-05-10 22:28:00.000000000 +0200
78619 @@ -88,4 +88,27 @@
78620 help
78621 Say Y to include support for NXP PCF50633 Main Battery Charger.
78622
78623 +config BATTERY_BQ27000_HDQ
78624 + tristate "BQ27000 HDQ battery monitor driver"
78625 + help
78626 + Say Y to enable support for the battery on the Neo Freerunner
78627 +
78628 +config HDQ_GPIO_BITBANG
78629 + bool "Generic gpio based HDQ bitbang"
78630 + help
78631 + Say Y to enable supoort for generic gpio based HDQ bitbang driver.
78632 + This can not be built as a module.
78633 +
78634 +config CHARGER_PCF50606
78635 + tristate "Support for NXP PCF50606 MBC"
78636 + depends on MFD_PCF50606
78637 + help
78638 + Say Y to include support for NXP PCF50606 Battery Charger.
78639 +
78640 +config BATTERY_GTA01
78641 + tristate "GTA01 battery driver"
78642 + help
78643 + Say Y here to enable this dumb driver for dumb gta01 batteries
78644 +
78645 endif # POWER_SUPPLY
78646 +
78647 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/power/Makefile linux-2.6.29-rc3.owrt.om/drivers/power/Makefile
78648 --- linux-2.6.29-rc3.owrt/drivers/power/Makefile 2009-05-10 22:04:48.000000000 +0200
78649 +++ linux-2.6.29-rc3.owrt.om/drivers/power/Makefile 2009-05-10 22:28:00.000000000 +0200
78650 @@ -25,4 +25,10 @@
78651 obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
78652 obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
78653 obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
78654 -obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
78655 \ No newline at end of file
78656 +obj-$(CONFIG_CHARGER_PCF50633) += pcf50633-charger.o
78657 +obj-$(CONFIG_CHARGER_PCF50606) += pcf50606-charger.o
78658 +obj-$(CONFIG_BATTERY_PALMTX) += palmtx_battery.o
78659 +obj-$(CONFIG_BATTERY_BQ27000_HDQ) += bq27000_battery.o
78660 +obj-$(CONFIG_BATTERY_GTA01) += gta01_battery.o
78661 +
78662 +obj-$(CONFIG_HDQ_GPIO_BITBANG) += hdq.o
78663 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/power/pcf50606-charger.c linux-2.6.29-rc3.owrt.om/drivers/power/pcf50606-charger.c
78664 --- linux-2.6.29-rc3.owrt/drivers/power/pcf50606-charger.c 1970-01-01 01:00:00.000000000 +0100
78665 +++ linux-2.6.29-rc3.owrt.om/drivers/power/pcf50606-charger.c 2009-05-10 22:28:00.000000000 +0200
78666 @@ -0,0 +1,244 @@
78667 +/* NXP PCF50606 Main Battery Charger Driver
78668 + *
78669 + * (C) 2006-2008 by Openmoko, Inc.
78670 + * Author: Balaji Rao <balajirrao@openmoko.org>
78671 + * All rights reserved.
78672 + *
78673 + * Broken down from monstrous PCF50606 driver mainly by
78674 + * Harald Welte, Andy Green and Werner Almesberger
78675 + *
78676 + * This program is free software; you can redistribute it and/or modify it
78677 + * under the terms of the GNU General Public License as published by the
78678 + * Free Software Foundation; either version 2 of the License, or (at your
78679 + * option) any later version.
78680 + *
78681 + */
78682 +
78683 +#include <linux/kernel.h>
78684 +#include <linux/module.h>
78685 +#include <linux/init.h>
78686 +#include <linux/types.h>
78687 +#include <linux/device.h>
78688 +#include <linux/sysfs.h>
78689 +#include <linux/platform_device.h>
78690 +#include <linux/power_supply.h>
78691 +
78692 +#include <linux/mfd/pcf50606/core.h>
78693 +#include <linux/mfd/pcf50606/mbc.h>
78694 +
78695 +struct pcf50606_mbc {
78696 + struct pcf50606 *pcf;
78697 +
78698 + int charger_online;
78699 + struct power_supply charger;
78700 +};
78701 +
78702 +void pcf50606_charge_fast(struct pcf50606 *pcf, int on)
78703 +{
78704 + struct pcf50606_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
78705 +
78706 + /*
78707 + * This is a fix to work around boot-time ordering problems if
78708 + * the s3c2410_udc is initialized before the pcf50606 mbc is
78709 + * ready.
78710 + */
78711 + if (!mbc)
78712 + return;
78713 +
78714 + if (on) {
78715 + pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_MBCC1,
78716 + PCF50606_MBCC1_AUTOFST,
78717 + PCF50606_MBCC1_AUTOFST);\
78718 + mbc->charger_online = 1;
78719 + } else {
78720 + /* disable automatic fast-charge */
78721 + pcf50606_reg_clear_bits(pcf, PCF50606_REG_MBCC1,
78722 + PCF50606_MBCC1_AUTOFST);
78723 + /* switch to idle mode to abort existing charge process */
78724 + pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_MBCC1,
78725 + PCF50606_MBCC1_CHGMOD_MASK,
78726 + PCF50606_MBCC1_CHGMOD_IDLE);
78727 + mbc->charger_online = 0;
78728 + }
78729 +}
78730 +EXPORT_SYMBOL_GPL(pcf50606_charge_fast);
78731 +
78732 +static ssize_t
78733 +show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
78734 +{
78735 + struct pcf50606_mbc *mbc = dev_get_drvdata(dev);
78736 +
78737 + u8 mbcc1 = pcf50606_reg_read(mbc->pcf, PCF50606_REG_MBCC1);
78738 + u8 chgmod = (mbcc1 & PCF50606_MBCC1_CHGMOD_MASK);
78739 +
78740 + return sprintf(buf, "%d\n", chgmod);
78741 +}
78742 +
78743 +static ssize_t set_chgmode(struct device *dev, struct device_attribute *attr,
78744 + const char *buf, size_t count)
78745 +{
78746 + struct pcf50606_mbc *mbc = dev_get_drvdata(dev);
78747 + u_int8_t mbcc1 = pcf50606_reg_read(mbc->pcf, PCF50606_REG_MBCC1);
78748 +
78749 + mbcc1 &= ~PCF50606_MBCC1_CHGMOD_MASK;
78750 +
78751 + if (!strcmp(buf, "qualification"))
78752 + mbcc1 |= PCF50606_MBCC1_CHGMOD_QUAL;
78753 + else if (!strcmp(buf, "pre"))
78754 + mbcc1 |= PCF50606_MBCC1_CHGMOD_PRE;
78755 + else if (!strcmp(buf, "trickle"))
78756 + mbcc1 |= PCF50606_MBCC1_CHGMOD_TRICKLE;
78757 + else if (!strcmp(buf, "fast_cccv"))
78758 + mbcc1 |= PCF50606_MBCC1_CHGMOD_FAST_CCCV;
78759 + /* We don't allow the other fast modes for security reasons */
78760 + else if (!strcmp(buf, "idle"))
78761 + mbcc1 |= PCF50606_MBCC1_CHGMOD_IDLE;
78762 + else
78763 + return -EINVAL;
78764 +
78765 + pcf50606_reg_write(mbc->pcf, PCF50606_REG_MBCC1, mbcc1);
78766 +
78767 + return count;
78768 +}
78769 +
78770 +static DEVICE_ATTR(chgmode, S_IRUGO, show_chgmode, set_chgmode);
78771 +
78772 +
78773 +static struct attribute *pcf50606_mbc_sysfs_entries[] = {
78774 + &dev_attr_chgmode.attr,
78775 + NULL,
78776 +};
78777 +
78778 +static struct attribute_group mbc_attr_group = {
78779 + .name = NULL, /* put in device directory */
78780 + .attrs = pcf50606_mbc_sysfs_entries,
78781 +};
78782 +
78783 +static void
78784 +pcf50606_mbc_irq_handler(int irq, void *data)
78785 +{
78786 + struct pcf50606_mbc *mbc = data;
78787 +
78788 + power_supply_changed(&mbc->charger);
78789 +
78790 + if (mbc->pcf->pdata->mbc_event_callback)
78791 + mbc->pcf->pdata->mbc_event_callback(mbc->pcf, irq);
78792 +}
78793 +
78794 +static int charger_get_property(struct power_supply *psy,
78795 + enum power_supply_property psp,
78796 + union power_supply_propval *val)
78797 +{
78798 + struct pcf50606_mbc *mbc = container_of(psy, struct pcf50606_mbc, charger);
78799 + int ret = 0;
78800 +
78801 + switch (psp) {
78802 + case POWER_SUPPLY_PROP_ONLINE:
78803 + val->intval = mbc->charger_online;
78804 + break;
78805 + default:
78806 + ret = -EINVAL;
78807 + break;
78808 + }
78809 + return ret;
78810 +}
78811 +
78812 +static enum power_supply_property power_props[] = {
78813 + POWER_SUPPLY_PROP_ONLINE,
78814 +};
78815 +
78816 +static const u8 mbc_irq_handlers[] = {
78817 + PCF50606_IRQ_CHGINS,
78818 + PCF50606_IRQ_CHGRM,
78819 + PCF50606_IRQ_CHGFOK,
78820 + PCF50606_IRQ_CHGERR,
78821 + PCF50606_IRQ_CHGFRDY,
78822 + PCF50606_IRQ_CHGPROT,
78823 +};
78824 +
78825 +static int __devinit pcf50606_mbc_probe(struct platform_device *pdev)
78826 +{
78827 + struct pcf50606_mbc *mbc;
78828 + struct pcf50606_subdev_pdata *pdata = pdev->dev.platform_data;
78829 + int ret;
78830 + int i;
78831 + u8 oocs;
78832 +
78833 + mbc = kzalloc(sizeof(*mbc), GFP_KERNEL);
78834 + if (!mbc)
78835 + return -ENOMEM;
78836 +
78837 + platform_set_drvdata(pdev, mbc);
78838 + mbc->pcf = pdata->pcf;
78839 +
78840 + /* Set up IRQ handlers */
78841 + for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
78842 + pcf50606_register_irq(mbc->pcf, mbc_irq_handlers[i],
78843 + pcf50606_mbc_irq_handler, mbc);
78844 +
78845 + mbc->charger.name = "charger";
78846 + mbc->charger.type = POWER_SUPPLY_TYPE_MAINS;
78847 + mbc->charger.properties = power_props;
78848 + mbc->charger.num_properties = ARRAY_SIZE(power_props);
78849 + mbc->charger.get_property = &charger_get_property;
78850 + mbc->charger.supplied_to = mbc->pcf->pdata->batteries;
78851 + mbc->charger.num_supplicants = mbc->pcf->pdata->num_batteries;
78852 +
78853 + ret = power_supply_register(&pdev->dev, &mbc->charger);
78854 + if (ret) {
78855 + dev_err(mbc->pcf->dev, "failed to register charger\n");
78856 + kfree(mbc);
78857 + return ret;
78858 + }
78859 +
78860 + ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
78861 + if (ret)
78862 + dev_err(mbc->pcf->dev, "failed to create sysfs entries\n");
78863 +
78864 + oocs = pcf50606_reg_read(mbc->pcf, PCF50606_REG_OOCS);
78865 + if (oocs & PCF50606_OOCS_CHGOK)
78866 + pcf50606_mbc_irq_handler(PCF50606_IRQ_CHGINS, mbc);
78867 +
78868 + return 0;
78869 +}
78870 +
78871 +static int __devexit pcf50606_mbc_remove(struct platform_device *pdev)
78872 +{
78873 + struct pcf50606_mbc *mbc = platform_get_drvdata(pdev);
78874 + int i;
78875 +
78876 + /* Remove IRQ handlers */
78877 + for (i = 0; i < ARRAY_SIZE(mbc_irq_handlers); i++)
78878 + pcf50606_free_irq(mbc->pcf, mbc_irq_handlers[i]);
78879 +
78880 + power_supply_unregister(&mbc->charger);
78881 +
78882 + kfree(mbc);
78883 +
78884 + return 0;
78885 +}
78886 +
78887 +static struct platform_driver pcf50606_mbc_driver = {
78888 + .driver = {
78889 + .name = "pcf50606-mbc",
78890 + },
78891 + .probe = pcf50606_mbc_probe,
78892 + .remove = __devexit_p(pcf50606_mbc_remove),
78893 +};
78894 +
78895 +static int __init pcf50606_mbc_init(void)
78896 +{
78897 + return platform_driver_register(&pcf50606_mbc_driver);
78898 +}
78899 +module_init(pcf50606_mbc_init);
78900 +
78901 +static void __exit pcf50606_mbc_exit(void)
78902 +{
78903 + platform_driver_unregister(&pcf50606_mbc_driver);
78904 +}
78905 +module_exit(pcf50606_mbc_exit);
78906 +
78907 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
78908 +MODULE_DESCRIPTION("PCF50606 mbc driver");
78909 +MODULE_LICENSE("GPL");
78910 +MODULE_ALIAS("platform:pcf50606-mbc");
78911 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/power/pcf50633-charger.c linux-2.6.29-rc3.owrt.om/drivers/power/pcf50633-charger.c
78912 --- linux-2.6.29-rc3.owrt/drivers/power/pcf50633-charger.c 2009-05-10 22:08:44.000000000 +0200
78913 +++ linux-2.6.29-rc3.owrt.om/drivers/power/pcf50633-charger.c 2009-05-10 22:28:00.000000000 +0200
78914 @@ -36,6 +36,9 @@
78915
78916 struct power_supply usb;
78917 struct power_supply adapter;
78918 + struct power_supply ac;
78919 +
78920 + struct delayed_work charging_restart_work;
78921 };
78922
78923 int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
78924 @@ -43,15 +46,24 @@
78925 struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
78926 int ret = 0;
78927 u8 bits;
78928 + int charging_start = 1;
78929 + u8 mbcs2, chgmod;
78930 + unsigned int mbcc5;
78931
78932 - if (ma >= 1000)
78933 + if (ma >= 1000) {
78934 bits = PCF50633_MBCC7_USB_1000mA;
78935 - else if (ma >= 500)
78936 + ma = 1000;
78937 + } else if (ma >= 500) {
78938 bits = PCF50633_MBCC7_USB_500mA;
78939 - else if (ma >= 100)
78940 + ma = 500;
78941 + } else if (ma >= 100) {
78942 bits = PCF50633_MBCC7_USB_100mA;
78943 - else
78944 + ma = 100;
78945 + } else {
78946 bits = PCF50633_MBCC7_USB_SUSPEND;
78947 + charging_start = 0;
78948 + ma = 0;
78949 + }
78950
78951 ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7,
78952 PCF50633_MBCC7_USB_MASK, bits);
78953 @@ -60,6 +72,37 @@
78954 else
78955 dev_info(pcf->dev, "usb curlim to %d mA\n", ma);
78956
78957 + /*
78958 + * We limit the charging current to be the USB current limit.
78959 + * The reason is that on pcf50633, when it enters PMU Standby mode,
78960 + * which it does when the device goes "off", the USB current limit
78961 + * reverts to the variant default. In at least one common case, that
78962 + * default is 500mA. By setting the charging current to be the same
78963 + * as the USB limit we set here before PMU standby, we enforce it only
78964 + * using the correct amount of current even when the USB current limit
78965 + * gets reset to the wrong thing
78966 + */
78967 +
78968 + mbcc5 = (ma << 8) / mbc->pcf->pdata->chg_ref_current_ma;
78969 + if (mbcc5 > 255)
78970 + mbcc5 = 255;
78971 + pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
78972 +
78973 + mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
78974 + chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
78975 +
78976 + /* If chgmod == BATFULL, setting chgena has no effect.
78977 + * We need to set resume instead.
78978 + */
78979 + if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL)
78980 + pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1,
78981 + PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA);
78982 + else
78983 + pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1,
78984 + PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME);
78985 +
78986 + mbc->usb_active = charging_start;
78987 +
78988 power_supply_changed(&mbc->usb);
78989
78990 return ret;
78991 @@ -84,21 +127,6 @@
78992 }
78993 EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status);
78994
78995 -void pcf50633_mbc_set_status(struct pcf50633 *pcf, int what, int status)
78996 -{
78997 - struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
78998 -
78999 - if (what & PCF50633_MBC_USB_ONLINE)
79000 - mbc->usb_online = !!status;
79001 - if (what & PCF50633_MBC_USB_ACTIVE)
79002 - mbc->usb_active = !!status;
79003 - if (what & PCF50633_MBC_ADAPTER_ONLINE)
79004 - mbc->adapter_online = !!status;
79005 - if (what & PCF50633_MBC_ADAPTER_ACTIVE)
79006 - mbc->adapter_active = !!status;
79007 -}
79008 -EXPORT_SYMBOL_GPL(pcf50633_mbc_set_status);
79009 -
79010 static ssize_t
79011 show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
79012 {
79013 @@ -149,9 +177,44 @@
79014
79015 static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim);
79016
79017 +static ssize_t
79018 +show_chglim(struct device *dev, struct device_attribute *attr, char *buf)
79019 +{
79020 + struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
79021 + u8 mbcc5 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC5);
79022 + unsigned int ma;
79023 +
79024 + ma = (mbc->pcf->pdata->chg_ref_current_ma * mbcc5) >> 8;
79025 +
79026 + return sprintf(buf, "%u\n", ma);
79027 +}
79028 +
79029 +static ssize_t set_chglim(struct device *dev,
79030 + struct device_attribute *attr, const char *buf, size_t count)
79031 +{
79032 + struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
79033 + unsigned long ma;
79034 + unsigned int mbcc5;
79035 + int ret;
79036 +
79037 + ret = strict_strtoul(buf, 10, &ma);
79038 + if (ret)
79039 + return -EINVAL;
79040 +
79041 + mbcc5 = (ma << 8) / mbc->pcf->pdata->chg_ref_current_ma;
79042 + if (mbcc5 > 255)
79043 + mbcc5 = 255;
79044 + pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
79045 +
79046 + return count;
79047 +}
79048 +
79049 +static DEVICE_ATTR(chg_curlim, S_IRUGO | S_IWUSR, show_chglim, set_chglim);
79050 +
79051 static struct attribute *pcf50633_mbc_sysfs_entries[] = {
79052 &dev_attr_chgmode.attr,
79053 &dev_attr_usb_curlim.attr,
79054 + &dev_attr_chg_curlim.attr,
79055 NULL,
79056 };
79057
79058 @@ -160,10 +223,44 @@
79059 .attrs = pcf50633_mbc_sysfs_entries,
79060 };
79061
79062 +/* MBC state machine switches into charging mode when the battery voltage
79063 + * falls below 96% of a battery float voltage. But the voltage drop in Li-ion
79064 + * batteries is marginal(1~2 %) till about 80% of its capacity - which means,
79065 + * after a BATFULL, charging won't be restarted until 80%.
79066 + *
79067 + * This work_struct function restarts charging every few seconds and makes
79068 + * sure we don't discharge too much
79069 + */
79070 +
79071 +static void pcf50633_mbc_charging_restart(struct work_struct *work)
79072 +{
79073 + struct pcf50633_mbc *mbc;
79074 + u8 mbcs2, chgmod;
79075 +
79076 + mbc = container_of(work, struct pcf50633_mbc,
79077 + charging_restart_work.work);
79078 +
79079 + mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
79080 + chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
79081 +
79082 + if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL)
79083 + return;
79084 +
79085 + /* Restart charging */
79086 + pcf50633_reg_set_bit_mask(mbc->pcf, PCF50633_REG_MBCC1,
79087 + PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME);
79088 + mbc->usb_active = 1;
79089 + power_supply_changed(&mbc->usb);
79090 +
79091 + dev_info(mbc->pcf->dev, "Charging restarted\n");
79092 +}
79093 +
79094 static void
79095 pcf50633_mbc_irq_handler(int irq, void *data)
79096 {
79097 struct pcf50633_mbc *mbc = data;
79098 + int chg_restart_interval =
79099 + mbc->pcf->pdata->charging_restart_interval;
79100
79101 /* USB */
79102 if (irq == PCF50633_IRQ_USBINS) {
79103 @@ -171,7 +268,8 @@
79104 } else if (irq == PCF50633_IRQ_USBREM) {
79105 mbc->usb_online = 0;
79106 mbc->usb_active = 0;
79107 - pcf50633_mbc_usb_curlim_set(mbc->pcf, 0);
79108 + pcf50633_mbc_usb_curlim_set(mbc->pcf, 0);
79109 + cancel_delayed_work_sync(&mbc->charging_restart_work);
79110 }
79111
79112 /* Adapter */
79113 @@ -186,10 +284,18 @@
79114 if (irq == PCF50633_IRQ_BATFULL) {
79115 mbc->usb_active = 0;
79116 mbc->adapter_active = 0;
79117 - }
79118 +
79119 + if (chg_restart_interval > 0)
79120 + schedule_delayed_work(&mbc->charging_restart_work,
79121 + chg_restart_interval);
79122 + } else if (irq == PCF50633_IRQ_USBLIMON)
79123 + mbc->usb_active = 0;
79124 + else if (irq == PCF50633_IRQ_USBLIMOFF)
79125 + mbc->usb_active = 1;
79126
79127 power_supply_changed(&mbc->usb);
79128 power_supply_changed(&mbc->adapter);
79129 + power_supply_changed(&mbc->ac);
79130
79131 if (mbc->pcf->pdata->mbc_event_callback)
79132 mbc->pcf->pdata->mbc_event_callback(mbc->pcf, irq);
79133 @@ -199,7 +305,7 @@
79134 enum power_supply_property psp,
79135 union power_supply_propval *val)
79136 {
79137 - struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
79138 + struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, adapter);
79139 int ret = 0;
79140
79141 switch (psp) {
79142 @@ -219,10 +325,34 @@
79143 {
79144 struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
79145 int ret = 0;
79146 + u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
79147 + PCF50633_MBCC7_USB_MASK;
79148 +
79149 + switch (psp) {
79150 + case POWER_SUPPLY_PROP_ONLINE:
79151 + val->intval = mbc->usb_online &&
79152 + (usblim <= PCF50633_MBCC7_USB_500mA);
79153 + break;
79154 + default:
79155 + ret = -EINVAL;
79156 + break;
79157 + }
79158 + return ret;
79159 +}
79160 +
79161 +static int ac_get_property(struct power_supply *psy,
79162 + enum power_supply_property psp,
79163 + union power_supply_propval *val)
79164 +{
79165 + struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, ac);
79166 + int ret = 0;
79167 + u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
79168 + PCF50633_MBCC7_USB_MASK;
79169
79170 switch (psp) {
79171 case POWER_SUPPLY_PROP_ONLINE:
79172 - val->intval = mbc->usb_online;
79173 + val->intval = mbc->usb_online &&
79174 + (usblim == PCF50633_MBCC7_USB_1000mA);
79175 break;
79176 default:
79177 ret = -EINVAL;
79178 @@ -287,6 +417,17 @@
79179 mbc->usb.supplied_to = mbc->pcf->pdata->batteries;
79180 mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries;
79181
79182 + mbc->ac.name = "ac";
79183 + mbc->ac.type = POWER_SUPPLY_TYPE_MAINS;
79184 + mbc->ac.properties = power_props;
79185 + mbc->ac.num_properties = ARRAY_SIZE(power_props);
79186 + mbc->ac.get_property = ac_get_property;
79187 + mbc->ac.supplied_to = mbc->pcf->pdata->batteries;
79188 + mbc->ac.num_supplicants = mbc->pcf->pdata->num_batteries;
79189 +
79190 + INIT_DELAYED_WORK(&mbc->charging_restart_work,
79191 + pcf50633_mbc_charging_restart);
79192 +
79193 ret = power_supply_register(&pdev->dev, &mbc->adapter);
79194 if (ret) {
79195 dev_err(mbc->pcf->dev, "failed to register adapter\n");
79196 @@ -302,6 +443,15 @@
79197 return ret;
79198 }
79199
79200 + ret = power_supply_register(&pdev->dev, &mbc->ac);
79201 + if (ret) {
79202 + dev_err(mbc->pcf->dev, "failed to register ac\n");
79203 + power_supply_unregister(&mbc->adapter);
79204 + power_supply_unregister(&mbc->usb);
79205 + kfree(mbc);
79206 + return ret;
79207 + }
79208 +
79209 ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
79210 if (ret)
79211 dev_err(mbc->pcf->dev, "failed to create sysfs entries\n");
79212 @@ -327,6 +477,8 @@
79213 power_supply_unregister(&mbc->usb);
79214 power_supply_unregister(&mbc->adapter);
79215
79216 + cancel_delayed_work_sync(&mbc->charging_restart_work);
79217 +
79218 kfree(mbc);
79219
79220 return 0;
79221 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/regulator/core.c linux-2.6.29-rc3.owrt.om/drivers/regulator/core.c
79222 --- linux-2.6.29-rc3.owrt/drivers/regulator/core.c 2009-05-10 22:04:48.000000000 +0200
79223 +++ linux-2.6.29-rc3.owrt.om/drivers/regulator/core.c 2009-05-10 22:28:00.000000000 +0200
79224 @@ -1102,18 +1102,19 @@
79225 struct regulator_dev *rdev = regulator->rdev;
79226 int ret = 0;
79227
79228 - mutex_lock(&rdev->mutex);
79229 - if (regulator->enabled == 1) {
79230 - ret = _regulator_disable(rdev);
79231 - if (ret == 0)
79232 - regulator->uA_load = 0;
79233 - } else if (WARN(regulator->enabled <= 0,
79234 - "unbalanced disables for supply %s\n",
79235 - regulator->supply_name))
79236 - ret = -EIO;
79237 - if (ret == 0)
79238 - regulator->enabled--;
79239 - mutex_unlock(&rdev->mutex);
79240 + if (!regulator->enabled) {
79241 + printk(KERN_ERR "%s: not in use by this consumer\n",
79242 + __func__);
79243 + WARN_ON(1);
79244 + return 0;
79245 + }
79246 +
79247 + mutex_lock(&regulator->rdev->mutex);
79248 + regulator->enabled = 0;
79249 + regulator->uA_load = 0;
79250 + ret = _regulator_disable(regulator->rdev);
79251 + mutex_unlock(&regulator->rdev->mutex);
79252 +
79253 return ret;
79254 }
79255 EXPORT_SYMBOL_GPL(regulator_disable);
79256 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/regulator/Kconfig linux-2.6.29-rc3.owrt.om/drivers/regulator/Kconfig
79257 --- linux-2.6.29-rc3.owrt/drivers/regulator/Kconfig 2009-05-10 22:04:48.000000000 +0200
79258 +++ linux-2.6.29-rc3.owrt.om/drivers/regulator/Kconfig 2009-05-10 22:28:00.000000000 +0200
79259 @@ -80,4 +80,10 @@
79260 Say Y here to support the voltage regulators and convertors
79261 on PCF50633
79262
79263 +config REGULATOR_PCF50606
79264 + bool "PCF50606 regulator driver"
79265 + depends on MFD_PCF50606
79266 + help
79267 + Say Y here to support the voltage regulators and convertors
79268 + on PCF50606
79269 endif
79270 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/regulator/Makefile linux-2.6.29-rc3.owrt.om/drivers/regulator/Makefile
79271 --- linux-2.6.29-rc3.owrt/drivers/regulator/Makefile 2009-05-10 22:04:48.000000000 +0200
79272 +++ linux-2.6.29-rc3.owrt.om/drivers/regulator/Makefile 2009-05-10 22:28:00.000000000 +0200
79273 @@ -12,5 +12,6 @@
79274 obj-$(CONFIG_REGULATOR_WM8400) += wm8400-regulator.o
79275 obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
79276 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
79277 +obj-$(CONFIG_REGULATOR_PCF50606) += pcf50606-regulator.o
79278
79279 ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
79280 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/regulator/pcf50606-regulator.c linux-2.6.29-rc3.owrt.om/drivers/regulator/pcf50606-regulator.c
79281 --- linux-2.6.29-rc3.owrt/drivers/regulator/pcf50606-regulator.c 1970-01-01 01:00:00.000000000 +0100
79282 +++ linux-2.6.29-rc3.owrt.om/drivers/regulator/pcf50606-regulator.c 2009-05-10 22:28:00.000000000 +0200
79283 @@ -0,0 +1,380 @@
79284 +/* NXP PCF50606 PMIC Driver
79285 + *
79286 + * (C) 2006-2008 by Openmoko, Inc.
79287 + * Author: Balaji Rao <balajirrao@openmoko.org>
79288 + * All rights reserved.
79289 + *
79290 + * Broken down from monstrous PCF50606 driver mainly by
79291 + * Harald Welte and Andy Green and Werner Almesberger
79292 + *
79293 + * This program is free software; you can redistribute it and/or modify it
79294 + * under the terms of the GNU General Public License as published by the
79295 + * Free Software Foundation; either version 2 of the License, or (at your
79296 + * option) any later version.
79297 + *
79298 + */
79299 +
79300 +#include <linux/kernel.h>
79301 +#include <linux/module.h>
79302 +#include <linux/init.h>
79303 +#include <linux/device.h>
79304 +#include <linux/err.h>
79305 +#include <linux/platform_device.h>
79306 +
79307 +#include <linux/mfd/pcf50606/core.h>
79308 +#include <linux/mfd/pcf50606/pmic.h>
79309 +
79310 +#define PCF50606_REGULATOR(_name, _id) \
79311 + { \
79312 + .name = _name, \
79313 + .id = _id, \
79314 + .ops = &pcf50606_regulator_ops, \
79315 + .type = REGULATOR_VOLTAGE, \
79316 + .owner = THIS_MODULE, \
79317 + }
79318 +
79319 +static const u8 pcf50606_regulator_registers[PCF50606_NUM_REGULATORS] = {
79320 + [PCF50606_REGULATOR_DCD] = PCF50606_REG_DCDC1,
79321 + [PCF50606_REGULATOR_DCDE] = PCF50606_REG_DCDEC1,
79322 + [PCF50606_REGULATOR_DCUD] = PCF50606_REG_DCUDC1,
79323 + [PCF50606_REGULATOR_D1REG] = PCF50606_REG_D1REGC1,
79324 + [PCF50606_REGULATOR_D2REG] = PCF50606_REG_D2REGC1,
79325 + [PCF50606_REGULATOR_D3REG] = PCF50606_REG_D3REGC1,
79326 + [PCF50606_REGULATOR_LPREG] = PCF50606_REG_LPREGC1,
79327 + [PCF50606_REGULATOR_IOREG] = PCF50606_REG_IOREGC,
79328 +};
79329 +
79330 +static u8 dcudc_voltage(unsigned int millivolts)
79331 +{
79332 + if (millivolts < 900)
79333 + return 0;
79334 + if (millivolts > 5500)
79335 + return 0x1f;
79336 + if (millivolts <= 3300) {
79337 + millivolts -= 900;
79338 + return millivolts/300;
79339 + }
79340 + if (millivolts < 4000)
79341 + return 0x0f;
79342 + else {
79343 + millivolts -= 4000;
79344 + return millivolts/100;
79345 + }
79346 +}
79347 +
79348 +static unsigned int dcudc_2voltage(u8 bits)
79349 +{
79350 + bits &= 0x1f;
79351 + if (bits < 0x08)
79352 + return 900 + bits * 300;
79353 + else if (bits < 0x10)
79354 + return 3300;
79355 + else
79356 + return 4000 + bits * 100;
79357 +}
79358 +
79359 +static u8 dcdec_voltage(unsigned int millivolts)
79360 +{
79361 + if (millivolts < 900)
79362 + return 0;
79363 + else if (millivolts > 3300)
79364 + return 0x0f;
79365 +
79366 + millivolts -= 900;
79367 + return millivolts/300;
79368 +}
79369 +
79370 +static unsigned int dcdec_2voltage(u8 bits)
79371 +{
79372 + bits &= 0x0f;
79373 + return 900 + bits*300;
79374 +}
79375 +
79376 +static u8 dcdc_voltage(unsigned int millivolts)
79377 +{
79378 + if (millivolts < 900)
79379 + return 0;
79380 + else if (millivolts > 3600)
79381 + return 0x1f;
79382 +
79383 + if (millivolts < 1500) {
79384 + millivolts -= 900;
79385 + return millivolts/25;
79386 + } else {
79387 + millivolts -= 1500;
79388 + return 0x18 + millivolts/300;
79389 + }
79390 +}
79391 +
79392 +static unsigned int dcdc_2voltage(u8 bits)
79393 +{
79394 + bits &= 0x1f;
79395 + if ((bits & 0x18) == 0x18)
79396 + return 1500 + ((bits & 0x7) * 300);
79397 + else
79398 + return 900 + (bits * 25);
79399 +}
79400 +
79401 +static u8 dx_voltage(unsigned int millivolts)
79402 +{
79403 + if (millivolts < 900)
79404 + return 0;
79405 + else if (millivolts > 3300)
79406 + return 0x18;
79407 +
79408 + millivolts -= 900;
79409 + return millivolts/100;
79410 +}
79411 +
79412 +static unsigned int dx_2voltage(u8 bits)
79413 +{
79414 + bits &= 0x1f;
79415 + return 900 + (bits * 100);
79416 +}
79417 +
79418 +static int pcf50606_regulator_set_voltage(struct regulator_dev *rdev,
79419 + int min_uV, int max_uV)
79420 +{
79421 + struct pcf50606 *pcf;
79422 + int regulator_id, millivolts, rc;
79423 + u8 volt_bits, regnr;
79424 +
79425 + pcf = rdev_get_drvdata(rdev);
79426 +
79427 + regulator_id = rdev_get_id(rdev);
79428 + if (regulator_id >= PCF50606_NUM_REGULATORS)
79429 + return -EINVAL;
79430 +
79431 + millivolts = min_uV / 1000;
79432 +
79433 + switch (regulator_id) {
79434 + case PCF50606_REGULATOR_DCD:
79435 + volt_bits = dcdc_voltage(millivolts);
79436 + rc = pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_DCDC1, 0x1f,
79437 + volt_bits);
79438 + break;
79439 + case PCF50606_REGULATOR_DCDE:
79440 + volt_bits = dcdec_voltage(millivolts);
79441 + rc = pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_DCDEC1, 0x0f,
79442 + volt_bits);
79443 + break;
79444 + case PCF50606_REGULATOR_DCUD:
79445 + volt_bits = dcudc_voltage(millivolts);
79446 + rc = pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_DCUDC1, 0x1f,
79447 + volt_bits);
79448 + break;
79449 + case PCF50606_REGULATOR_D1REG:
79450 + case PCF50606_REGULATOR_D2REG:
79451 + case PCF50606_REGULATOR_D3REG:
79452 + regnr = PCF50606_REG_D1REGC1 +
79453 + (regulator_id - PCF50606_REGULATOR_D1REG);
79454 + volt_bits = dx_voltage(millivolts);
79455 + rc = pcf50606_reg_set_bit_mask(pcf, regnr, 0x1f, volt_bits);
79456 + break;
79457 + case PCF50606_REGULATOR_LPREG:
79458 + volt_bits = dx_voltage(millivolts);
79459 + rc = pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_LPREGC1, 0x1f,
79460 + volt_bits);
79461 + break;
79462 + case PCF50606_REGULATOR_IOREG:
79463 + if (millivolts < 1800)
79464 + return -EINVAL;
79465 + volt_bits = dx_voltage(millivolts);
79466 + rc = pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_IOREGC, 0x1f,
79467 + volt_bits);
79468 + break;
79469 + default:
79470 + return -EINVAL;
79471 + }
79472 +
79473 + return rc;
79474 +}
79475 +
79476 +static int pcf50606_regulator_get_voltage(struct regulator_dev *rdev)
79477 +{
79478 + struct pcf50606 *pcf;
79479 + u8 volt_bits, regnr;
79480 + int rc = 0, regulator_id;
79481 +
79482 +
79483 + pcf = rdev_get_drvdata(rdev);
79484 +
79485 + regulator_id = rdev_get_id(rdev);
79486 + if (regulator_id >= PCF50606_NUM_REGULATORS)
79487 + return -EINVAL;
79488 +
79489 + switch (regulator_id) {
79490 + case PCF50606_REGULATOR_DCD:
79491 + volt_bits = pcf50606_reg_read(pcf, PCF50606_REG_DCDC1) & 0x1f;
79492 + rc = dcdc_2voltage(volt_bits);
79493 + break;
79494 + case PCF50606_REGULATOR_DCDE:
79495 + volt_bits = pcf50606_reg_read(pcf, PCF50606_REG_DCDEC1) & 0x0f;
79496 + rc = dcdec_2voltage(volt_bits);
79497 + break;
79498 + case PCF50606_REGULATOR_DCUD:
79499 + volt_bits = pcf50606_reg_read(pcf, PCF50606_REG_DCUDC1) & 0x1f;
79500 + rc = dcudc_2voltage(volt_bits);
79501 + break;
79502 + case PCF50606_REGULATOR_D1REG:
79503 + case PCF50606_REGULATOR_D2REG:
79504 + case PCF50606_REGULATOR_D3REG:
79505 + regnr = PCF50606_REG_D1REGC1 + (regulator_id - PCF50606_REGULATOR_D1REG);
79506 + volt_bits = pcf50606_reg_read(pcf, regnr) & 0x1f;
79507 + if (volt_bits > 0x18)
79508 + volt_bits = 0x18;
79509 + rc = dx_2voltage(volt_bits);
79510 + break;
79511 + case PCF50606_REGULATOR_LPREG:
79512 + volt_bits = pcf50606_reg_read(pcf, PCF50606_REG_LPREGC1) & 0x1f;
79513 + if (volt_bits > 0x18)
79514 + volt_bits = 0x18;
79515 + rc = dx_2voltage(volt_bits);
79516 + break;
79517 + case PCF50606_REGULATOR_IOREG:
79518 + volt_bits = pcf50606_reg_read(pcf, PCF50606_REG_IOREGC) & 0x1f;
79519 + if (volt_bits > 0x18)
79520 + volt_bits = 0x18;
79521 + rc = dx_2voltage(volt_bits);
79522 + break;
79523 + default:
79524 + return -EINVAL;
79525 + }
79526 +
79527 + return rc * 1000;
79528 +
79529 +}
79530 +
79531 +static int pcf50606_regulator_enable(struct regulator_dev *rdev)
79532 +{
79533 + struct pcf50606 *pcf = rdev_get_drvdata(rdev);
79534 + int regulator_id;
79535 + u8 regnr;
79536 +
79537 + regulator_id = rdev_get_id(rdev);
79538 + if (regulator_id >= PCF50606_NUM_REGULATORS)
79539 + return -EINVAL;
79540 +
79541 + regnr = pcf50606_regulator_registers[regulator_id];
79542 +
79543 + return pcf50606_reg_set_bit_mask(pcf, regnr, 0xe0, 0xe0);
79544 +}
79545 +
79546 +static int pcf50606_regulator_disable(struct regulator_dev *rdev)
79547 +{
79548 + struct pcf50606 *pcf = rdev_get_drvdata(rdev);
79549 + int regulator_id;
79550 + u8 regnr;
79551 +
79552 + regulator_id = rdev_get_id(rdev);
79553 + if (regulator_id >= PCF50606_NUM_REGULATORS)
79554 + return -EINVAL;
79555 +
79556 + /* IOREG cannot be powered off since it powers the PMU I2C */
79557 + if (regulator_id == PCF50606_REGULATOR_IOREG)
79558 + return -EINVAL;
79559 +
79560 + regnr = pcf50606_regulator_registers[regulator_id];
79561 +
79562 + return pcf50606_reg_set_bit_mask(pcf, regnr, 0xe0, 0);
79563 +}
79564 +
79565 +static int pcf50606_regulator_is_enabled(struct regulator_dev *rdev)
79566 +{
79567 + struct pcf50606 *pcf = rdev_get_drvdata(rdev);
79568 + int regulator_id = rdev_get_id(rdev);
79569 + u8 regnr, val;
79570 +
79571 + regulator_id = rdev_get_id(rdev);
79572 + if (regulator_id >= PCF50606_NUM_REGULATORS)
79573 + return -EINVAL;
79574 +
79575 + /* the *ENA register is always one after the *OUT register */
79576 + regnr = pcf50606_regulator_registers[regulator_id];
79577 + val = (pcf50606_reg_read(pcf, regnr) & 0xe0) >> 5;
79578 +
79579 + /* PWREN1 = 1, PWREN2 = 1, see table 16 of datasheet */
79580 + if (val == 0 || val == 5)
79581 + return 0;
79582 +
79583 + return 1;
79584 +}
79585 +
79586 +static struct regulator_ops pcf50606_regulator_ops = {
79587 + .set_voltage = pcf50606_regulator_set_voltage,
79588 + .get_voltage = pcf50606_regulator_get_voltage,
79589 + .enable = pcf50606_regulator_enable,
79590 + .disable = pcf50606_regulator_disable,
79591 + .is_enabled = pcf50606_regulator_is_enabled,
79592 +};
79593 +
79594 +static struct regulator_desc regulators[] = {
79595 + [PCF50606_REGULATOR_DCD] =
79596 + PCF50606_REGULATOR("dcd", PCF50606_REGULATOR_DCD),
79597 + [PCF50606_REGULATOR_DCDE] =
79598 + PCF50606_REGULATOR("dcde", PCF50606_REGULATOR_DCDE),
79599 + [PCF50606_REGULATOR_DCUD] =
79600 + PCF50606_REGULATOR("dcud", PCF50606_REGULATOR_DCUD),
79601 + [PCF50606_REGULATOR_D1REG] =
79602 + PCF50606_REGULATOR("d1reg", PCF50606_REGULATOR_D1REG),
79603 + [PCF50606_REGULATOR_D2REG] =
79604 + PCF50606_REGULATOR("d2reg", PCF50606_REGULATOR_D2REG),
79605 + [PCF50606_REGULATOR_D3REG] =
79606 + PCF50606_REGULATOR("d3reg", PCF50606_REGULATOR_D3REG),
79607 + [PCF50606_REGULATOR_LPREG] =
79608 + PCF50606_REGULATOR("lpreg", PCF50606_REGULATOR_LPREG),
79609 + [PCF50606_REGULATOR_IOREG] =
79610 + PCF50606_REGULATOR("ioreg", PCF50606_REGULATOR_IOREG),
79611 +};
79612 +
79613 +static int __devinit pcf50606_regulator_probe(struct platform_device *pdev)
79614 +{
79615 + struct regulator_dev *rdev;
79616 + struct pcf50606 *pcf;
79617 +
79618 + /* Already set by core driver */
79619 + pcf = platform_get_drvdata(pdev);
79620 +
79621 + rdev = regulator_register(&regulators[pdev->id], &pdev->dev, pcf);
79622 + if (IS_ERR(rdev))
79623 + return PTR_ERR(rdev);
79624 +
79625 + if (pcf->pdata->regulator_registered)
79626 + pcf->pdata->regulator_registered(pcf, pdev->id);
79627 +
79628 + return 0;
79629 +}
79630 +
79631 +static int __devexit pcf50606_regulator_remove(struct platform_device *pdev)
79632 +{
79633 + struct regulator_dev *rdev = platform_get_drvdata(pdev);
79634 +
79635 + regulator_unregister(rdev);
79636 +
79637 + return 0;
79638 +}
79639 +
79640 +static struct platform_driver pcf50606_regulator_driver = {
79641 + .driver = {
79642 + .name = "pcf50606-regltr",
79643 + },
79644 + .probe = pcf50606_regulator_probe,
79645 + .remove = __devexit_p(pcf50606_regulator_remove),
79646 +};
79647 +
79648 +static int __init pcf50606_regulator_init(void)
79649 +{
79650 + return platform_driver_register(&pcf50606_regulator_driver);
79651 +}
79652 +module_init(pcf50606_regulator_init);
79653 +
79654 +static void __exit pcf50606_regulator_exit(void)
79655 +{
79656 + platform_driver_unregister(&pcf50606_regulator_driver);
79657 +}
79658 +module_exit(pcf50606_regulator_exit);
79659 +
79660 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
79661 +MODULE_DESCRIPTION("PCF50606 regulator driver");
79662 +MODULE_LICENSE("GPL");
79663 +MODULE_ALIAS("platform:pcf50606-regulator");
79664 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/rtc/Kconfig linux-2.6.29-rc3.owrt.om/drivers/rtc/Kconfig
79665 --- linux-2.6.29-rc3.owrt/drivers/rtc/Kconfig 2009-05-10 22:08:44.000000000 +0200
79666 +++ linux-2.6.29-rc3.owrt.om/drivers/rtc/Kconfig 2009-05-10 22:28:00.000000000 +0200
79667 @@ -223,6 +223,13 @@
79668 This driver can also be built as a module. If so, the module
79669 will be called rtc-pcf8583.
79670
79671 +config RTC_DRV_PCF50606
79672 + depends on MFD_PCF50606
79673 + tristate "Philips PCF50606"
79674 + help
79675 + If you say yes here you get support for the Philips PCF50606
79676 + PMU's RTC.
79677 +
79678 config RTC_DRV_M41T80
79679 tristate "ST M41T65/M41T80/81/82/83/84/85/87"
79680 help
79681 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/rtc/Makefile linux-2.6.29-rc3.owrt.om/drivers/rtc/Makefile
79682 --- linux-2.6.29-rc3.owrt/drivers/rtc/Makefile 2009-05-10 22:08:44.000000000 +0200
79683 +++ linux-2.6.29-rc3.owrt.om/drivers/rtc/Makefile 2009-05-10 22:28:00.000000000 +0200
79684 @@ -76,3 +76,4 @@
79685 obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o
79686 obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o
79687 obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o
79688 +obj-$(CONFIG_RTC_DRV_PCF50606) += rtc-pcf50606.o
79689 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/rtc/rtc-pcf50606.c linux-2.6.29-rc3.owrt.om/drivers/rtc/rtc-pcf50606.c
79690 --- linux-2.6.29-rc3.owrt/drivers/rtc/rtc-pcf50606.c 1970-01-01 01:00:00.000000000 +0100
79691 +++ linux-2.6.29-rc3.owrt.om/drivers/rtc/rtc-pcf50606.c 2009-05-10 22:28:00.000000000 +0200
79692 @@ -0,0 +1,335 @@
79693 +/* NXP PCF50606 RTC Driver
79694 + *
79695 + * (C) 2006-2008 by Openmoko, Inc.
79696 + * Author: Balaji Rao <balajirrao@openmoko.org>
79697 + * All rights reserved.
79698 + *
79699 + * Broken down from monstrous PCF50606 driver mainly by
79700 + * Harald Welte, Andy Green and Werner Almesberger
79701 + *
79702 + * This program is free software; you can redistribute it and/or modify it
79703 + * under the terms of the GNU General Public License as published by the
79704 + * Free Software Foundation; either version 2 of the License, or (at your
79705 + * option) any later version.
79706 + *
79707 + */
79708 +
79709 +#include <linux/kernel.h>
79710 +#include <linux/module.h>
79711 +#include <linux/init.h>
79712 +#include <linux/device.h>
79713 +#include <linux/platform_device.h>
79714 +#include <linux/rtc.h>
79715 +#include <linux/bcd.h>
79716 +#include <linux/err.h>
79717 +
79718 +#include <linux/mfd/pcf50606/core.h>
79719 +
79720 +#define PCF50606_REG_RTCSC 0x0a /* Second */
79721 +#define PCF50606_REG_RTCMN 0x0b /* Minute */
79722 +#define PCF50606_REG_RTCHR 0x0c /* Hour */
79723 +#define PCF50606_REG_RTCWD 0x0d /* Weekday */
79724 +#define PCF50606_REG_RTCDT 0x0e /* Day */
79725 +#define PCF50606_REG_RTCMT 0x0f /* Month */
79726 +#define PCF50606_REG_RTCYR 0x10 /* Year */
79727 +#define PCF50606_REG_RTCSCA 0x11 /* Alarm Second */
79728 +#define PCF50606_REG_RTCMNA 0x12 /* Alarm Minute */
79729 +#define PCF50606_REG_RTCHRA 0x13 /* Alarm Hour */
79730 +#define PCF50606_REG_RTCWDA 0x14 /* Alarm Weekday */
79731 +#define PCF50606_REG_RTCDTA 0x15 /* Alarm Day */
79732 +#define PCF50606_REG_RTCMTA 0x16 /* Alarm Month */
79733 +#define PCF50606_REG_RTCYRA 0x17 /* Alarm Year */
79734 +
79735 +enum pcf50606_time_indexes {
79736 + PCF50606_TI_SEC,
79737 + PCF50606_TI_MIN,
79738 + PCF50606_TI_HOUR,
79739 + PCF50606_TI_WKDAY,
79740 + PCF50606_TI_DAY,
79741 + PCF50606_TI_MONTH,
79742 + PCF50606_TI_YEAR,
79743 + PCF50606_TI_EXTENT /* always last */
79744 +};
79745 +
79746 +struct pcf50606_time {
79747 + u_int8_t time[PCF50606_TI_EXTENT];
79748 +};
79749 +
79750 +struct pcf50606_rtc {
79751 + int alarm_enabled;
79752 + int second_enabled;
79753 +
79754 + struct pcf50606 *pcf;
79755 + struct rtc_device *rtc_dev;
79756 +};
79757 +
79758 +static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50606_time *pcf)
79759 +{
79760 + rtc->tm_sec = bcd2bin(pcf->time[PCF50606_TI_SEC]);
79761 + rtc->tm_min = bcd2bin(pcf->time[PCF50606_TI_MIN]);
79762 + rtc->tm_hour = bcd2bin(pcf->time[PCF50606_TI_HOUR]);
79763 + rtc->tm_wday = bcd2bin(pcf->time[PCF50606_TI_WKDAY]);
79764 + rtc->tm_mday = bcd2bin(pcf->time[PCF50606_TI_DAY]);
79765 + rtc->tm_mon = bcd2bin(pcf->time[PCF50606_TI_MONTH]) - 1;
79766 + rtc->tm_year = bcd2bin(pcf->time[PCF50606_TI_YEAR]) + 100;
79767 +}
79768 +
79769 +static void rtc2pcf_time(struct pcf50606_time *pcf, struct rtc_time *rtc)
79770 +{
79771 + pcf->time[PCF50606_TI_SEC] = bin2bcd(rtc->tm_sec);
79772 + pcf->time[PCF50606_TI_MIN] = bin2bcd(rtc->tm_min);
79773 + pcf->time[PCF50606_TI_HOUR] = bin2bcd(rtc->tm_hour);
79774 + pcf->time[PCF50606_TI_WKDAY] = bin2bcd(rtc->tm_wday);
79775 + pcf->time[PCF50606_TI_DAY] = bin2bcd(rtc->tm_mday);
79776 + pcf->time[PCF50606_TI_MONTH] = bin2bcd(rtc->tm_mon + 1);
79777 + pcf->time[PCF50606_TI_YEAR] = bin2bcd(rtc->tm_year % 100);
79778 +}
79779 +
79780 +static int
79781 +pcf50606_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
79782 +{
79783 + struct pcf50606_rtc *rtc = dev_get_drvdata(dev);
79784 +
79785 + switch (cmd) {
79786 + case RTC_AIE_OFF:
79787 + rtc->alarm_enabled = 0;
79788 + pcf50606_irq_mask(rtc->pcf, PCF50606_IRQ_ALARM);
79789 + return 0;
79790 + case RTC_AIE_ON:
79791 + rtc->alarm_enabled = 1;
79792 + pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_ALARM);
79793 + return 0;
79794 + case RTC_UIE_OFF:
79795 + rtc->second_enabled = 0;
79796 + pcf50606_irq_mask(rtc->pcf, PCF50606_IRQ_SECOND);
79797 + return 0;
79798 + case RTC_UIE_ON:
79799 + rtc->second_enabled = 1;
79800 + pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_SECOND);
79801 + return 0;
79802 + }
79803 +
79804 + return -ENOIOCTLCMD;
79805 +}
79806 +
79807 +static int pcf50606_rtc_read_time(struct device *dev, struct rtc_time *tm)
79808 +{
79809 + struct pcf50606_rtc *rtc;
79810 + struct pcf50606_time pcf_tm;
79811 + int ret;
79812 +
79813 + rtc = dev_get_drvdata(dev);
79814 +
79815 + ret = pcf50606_read_block(rtc->pcf, PCF50606_REG_RTCSC,
79816 + PCF50606_TI_EXTENT,
79817 + &pcf_tm.time[0]);
79818 + if (ret != PCF50606_TI_EXTENT) {
79819 + dev_err(dev, "Failed to read time\n");
79820 + return -EIO;
79821 + }
79822 +
79823 + dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
79824 + pcf_tm.time[PCF50606_TI_DAY],
79825 + pcf_tm.time[PCF50606_TI_MONTH],
79826 + pcf_tm.time[PCF50606_TI_YEAR],
79827 + pcf_tm.time[PCF50606_TI_HOUR],
79828 + pcf_tm.time[PCF50606_TI_MIN],
79829 + pcf_tm.time[PCF50606_TI_SEC]);
79830 +
79831 + pcf2rtc_time(tm, &pcf_tm);
79832 +
79833 + dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
79834 + tm->tm_mday, tm->tm_mon, tm->tm_year,
79835 + tm->tm_hour, tm->tm_min, tm->tm_sec);
79836 +
79837 + return rtc_valid_tm(tm);
79838 +}
79839 +
79840 +static int pcf50606_rtc_set_time(struct device *dev, struct rtc_time *tm)
79841 +{
79842 + struct pcf50606_rtc *rtc;
79843 + struct pcf50606_time pcf_tm;
79844 + int second_masked, alarm_masked, ret = 0;
79845 +
79846 + rtc = dev_get_drvdata(dev);
79847 +
79848 + dev_dbg(dev, "RTC_TIME: %u.%u.%u %u:%u:%u\n",
79849 + tm->tm_mday, tm->tm_mon, tm->tm_year,
79850 + tm->tm_hour, tm->tm_min, tm->tm_sec);
79851 +
79852 + rtc2pcf_time(&pcf_tm, tm);
79853 +
79854 + dev_dbg(dev, "PCF_TIME: %02x.%02x.%02x %02x:%02x:%02x\n",
79855 + pcf_tm.time[PCF50606_TI_DAY],
79856 + pcf_tm.time[PCF50606_TI_MONTH],
79857 + pcf_tm.time[PCF50606_TI_YEAR],
79858 + pcf_tm.time[PCF50606_TI_HOUR],
79859 + pcf_tm.time[PCF50606_TI_MIN],
79860 + pcf_tm.time[PCF50606_TI_SEC]);
79861 +
79862 +
79863 + second_masked = pcf50606_irq_mask_get(rtc->pcf, PCF50606_IRQ_SECOND);
79864 + alarm_masked = pcf50606_irq_mask_get(rtc->pcf, PCF50606_IRQ_ALARM);
79865 +
79866 + if (!second_masked)
79867 + pcf50606_irq_mask(rtc->pcf, PCF50606_IRQ_SECOND);
79868 + if (!alarm_masked)
79869 + pcf50606_irq_mask(rtc->pcf, PCF50606_IRQ_ALARM);
79870 +
79871 + /* Returns 0 on success */
79872 + ret = pcf50606_write_block(rtc->pcf, PCF50606_REG_RTCSC,
79873 + PCF50606_TI_EXTENT,
79874 + &pcf_tm.time[0]);
79875 +
79876 + if (!second_masked)
79877 + pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_SECOND);
79878 + if (!alarm_masked)
79879 + pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_ALARM);
79880 +
79881 + return ret;
79882 +}
79883 +
79884 +static int pcf50606_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
79885 +{
79886 + struct pcf50606_rtc *rtc;
79887 + struct pcf50606_time pcf_tm;
79888 + int ret = 0;
79889 +
79890 + rtc = dev_get_drvdata(dev);
79891 +
79892 + alrm->enabled = rtc->alarm_enabled;
79893 +
79894 + ret = pcf50606_read_block(rtc->pcf, PCF50606_REG_RTCSCA,
79895 + PCF50606_TI_EXTENT, &pcf_tm.time[0]);
79896 + if (ret != PCF50606_TI_EXTENT) {
79897 + dev_err(dev, "Failed to read time\n");
79898 + return -EIO;
79899 + }
79900 +
79901 + pcf2rtc_time(&alrm->time, &pcf_tm);
79902 +
79903 + return rtc_valid_tm(&alrm->time);
79904 +}
79905 +
79906 +static int pcf50606_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
79907 +{
79908 + struct pcf50606_rtc *rtc;
79909 + struct pcf50606_time pcf_tm;
79910 + int alarm_masked, ret = 0;
79911 +
79912 + rtc = dev_get_drvdata(dev);
79913 +
79914 + rtc2pcf_time(&pcf_tm, &alrm->time);
79915 +
79916 + /* do like mktime does and ignore tm_wday */
79917 + pcf_tm.time[PCF50606_TI_WKDAY] = 7;
79918 +
79919 + alarm_masked = pcf50606_irq_mask_get(rtc->pcf, PCF50606_IRQ_ALARM);
79920 +
79921 + /* disable alarm interrupt */
79922 + if (!alarm_masked)
79923 + pcf50606_irq_mask(rtc->pcf, PCF50606_IRQ_ALARM);
79924 +
79925 + /* Returns 0 on success */
79926 + ret = pcf50606_write_block(rtc->pcf, PCF50606_REG_RTCSCA,
79927 + PCF50606_TI_EXTENT, &pcf_tm.time[0]);
79928 +
79929 + if (!alarm_masked)
79930 + pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_ALARM);
79931 +
79932 + return ret;
79933 +}
79934 +
79935 +static struct rtc_class_ops pcf50606_rtc_ops = {
79936 + .ioctl = pcf50606_rtc_ioctl,
79937 + .read_time = pcf50606_rtc_read_time,
79938 + .set_time = pcf50606_rtc_set_time,
79939 + .read_alarm = pcf50606_rtc_read_alarm,
79940 + .set_alarm = pcf50606_rtc_set_alarm,
79941 +};
79942 +
79943 +static void pcf50606_rtc_irq(int irq, void *data)
79944 +{
79945 + struct pcf50606_rtc *rtc = data;
79946 +
79947 + switch (irq) {
79948 + case PCF50606_IRQ_ALARM:
79949 + rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
79950 + break;
79951 + case PCF50606_IRQ_SECOND:
79952 + rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
79953 + break;
79954 + }
79955 +}
79956 +
79957 +static int __devinit pcf50606_rtc_probe(struct platform_device *pdev)
79958 +{
79959 + struct pcf50606_subdev_pdata *pdata;
79960 + struct pcf50606_rtc *rtc;
79961 +
79962 +
79963 + rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
79964 + if (!rtc)
79965 + return -ENOMEM;
79966 +
79967 + pdata = pdev->dev.platform_data;
79968 + rtc->pcf = pdata->pcf;
79969 + platform_set_drvdata(pdev, rtc);
79970 + rtc->rtc_dev = rtc_device_register("pcf50606-rtc", &pdev->dev,
79971 + &pcf50606_rtc_ops, THIS_MODULE);
79972 +
79973 + if (IS_ERR(rtc->rtc_dev)) {
79974 + kfree(rtc);
79975 + return PTR_ERR(rtc->rtc_dev);
79976 + }
79977 +
79978 + pcf50606_register_irq(rtc->pcf, PCF50606_IRQ_ALARM,
79979 + pcf50606_rtc_irq, rtc);
79980 + pcf50606_register_irq(rtc->pcf, PCF50606_IRQ_SECOND,
79981 + pcf50606_rtc_irq, rtc);
79982 +
79983 + return 0;
79984 +}
79985 +
79986 +
79987 +static int __devexit pcf50606_rtc_remove(struct platform_device *pdev)
79988 +{
79989 + struct pcf50606_rtc *rtc;
79990 +
79991 + rtc = platform_get_drvdata(pdev);
79992 +
79993 + pcf50606_free_irq(rtc->pcf, PCF50606_IRQ_ALARM);
79994 + pcf50606_free_irq(rtc->pcf, PCF50606_IRQ_SECOND);
79995 +
79996 + rtc_device_unregister(rtc->rtc_dev);
79997 +
79998 + kfree(rtc);
79999 +
80000 + return 0;
80001 +}
80002 +
80003 +
80004 +static struct platform_driver pcf50606_rtc_driver = {
80005 + .driver = {
80006 + .name = "pcf50606-rtc",
80007 + },
80008 + .probe = pcf50606_rtc_probe,
80009 + .remove = __devexit_p(pcf50606_rtc_remove),
80010 +};
80011 +
80012 +static int __init pcf50606_rtc_init(void)
80013 +{
80014 + return platform_driver_register(&pcf50606_rtc_driver);
80015 +}
80016 +module_init(pcf50606_rtc_init);
80017 +
80018 +static void __exit pcf50606_rtc_exit(void)
80019 +{
80020 + platform_driver_unregister(&pcf50606_rtc_driver);
80021 +}
80022 +module_exit(pcf50606_rtc_exit);
80023 +
80024 +MODULE_DESCRIPTION("PCF50606 RTC driver");
80025 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
80026 +MODULE_LICENSE("GPL");
80027 +
80028 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/rtc/rtc-pcf50633.c linux-2.6.29-rc3.owrt.om/drivers/rtc/rtc-pcf50633.c
80029 --- linux-2.6.29-rc3.owrt/drivers/rtc/rtc-pcf50633.c 2009-05-10 22:04:49.000000000 +0200
80030 +++ linux-2.6.29-rc3.owrt.om/drivers/rtc/rtc-pcf50633.c 2009-05-10 22:28:00.000000000 +0200
80031 @@ -58,6 +58,7 @@
80032 struct pcf50633_rtc {
80033 int alarm_enabled;
80034 int second_enabled;
80035 + int alarm_pending;
80036
80037 struct pcf50633 *pcf;
80038 struct rtc_device *rtc_dev;
80039 @@ -70,7 +71,7 @@
80040 rtc->tm_hour = bcd2bin(pcf->time[PCF50633_TI_HOUR]);
80041 rtc->tm_wday = bcd2bin(pcf->time[PCF50633_TI_WKDAY]);
80042 rtc->tm_mday = bcd2bin(pcf->time[PCF50633_TI_DAY]);
80043 - rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]);
80044 + rtc->tm_mon = bcd2bin(pcf->time[PCF50633_TI_MONTH]) - 1;
80045 rtc->tm_year = bcd2bin(pcf->time[PCF50633_TI_YEAR]) + 100;
80046 }
80047
80048 @@ -81,7 +82,7 @@
80049 pcf->time[PCF50633_TI_HOUR] = bin2bcd(rtc->tm_hour);
80050 pcf->time[PCF50633_TI_WKDAY] = bin2bcd(rtc->tm_wday);
80051 pcf->time[PCF50633_TI_DAY] = bin2bcd(rtc->tm_mday);
80052 - pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon);
80053 + pcf->time[PCF50633_TI_MONTH] = bin2bcd(rtc->tm_mon + 1);
80054 pcf->time[PCF50633_TI_YEAR] = bin2bcd(rtc->tm_year % 100);
80055 }
80056
80057 @@ -209,6 +210,7 @@
80058 rtc = dev_get_drvdata(dev);
80059
80060 alrm->enabled = rtc->alarm_enabled;
80061 + alrm->pending = rtc->alarm_pending;
80062
80063 ret = pcf50633_read_block(rtc->pcf, PCF50633_REG_RTCSCA,
80064 PCF50633_TI_EXTENT, &pcf_tm.time[0]);
80065 @@ -244,9 +246,12 @@
80066 /* Returns 0 on success */
80067 ret = pcf50633_write_block(rtc->pcf, PCF50633_REG_RTCSCA,
80068 PCF50633_TI_EXTENT, &pcf_tm.time[0]);
80069 + if (!alrm->enabled)
80070 + rtc->alarm_pending = 0;
80071
80072 - if (!alarm_masked)
80073 + if (!alarm_masked || alrm->enabled)
80074 pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_ALARM);
80075 + rtc->alarm_enabled = alrm->enabled;
80076
80077 return ret;
80078 }
80079 @@ -267,6 +272,7 @@
80080 switch (irq) {
80081 case PCF50633_IRQ_ALARM:
80082 rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
80083 + rtc->alarm_pending = 1;
80084 break;
80085 case PCF50633_IRQ_SECOND:
80086 rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
80087 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/serial/s3c2410.c linux-2.6.29-rc3.owrt.om/drivers/serial/s3c2410.c
80088 --- linux-2.6.29-rc3.owrt/drivers/serial/s3c2410.c 2009-05-10 22:04:48.000000000 +0200
80089 +++ linux-2.6.29-rc3.owrt.om/drivers/serial/s3c2410.c 2009-05-10 22:28:00.000000000 +0200
80090 @@ -19,6 +19,7 @@
80091 #include <linux/serial.h>
80092
80093 #include <asm/irq.h>
80094 +
80095 #include <mach/hardware.h>
80096
80097 #include <plat/regs-serial.h>
80098 @@ -85,6 +86,7 @@
80099
80100 static int s3c2410_serial_probe(struct platform_device *dev)
80101 {
80102 + dbg("s3c2410_serial_probe: dev=%p\n", dev);
80103 return s3c24xx_serial_probe(dev, &s3c2410_uart_inf);
80104 }
80105
80106 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/serial/s3c6400.c linux-2.6.29-rc3.owrt.om/drivers/serial/s3c6400.c
80107 --- linux-2.6.29-rc3.owrt/drivers/serial/s3c6400.c 2009-05-10 22:04:48.000000000 +0200
80108 +++ linux-2.6.29-rc3.owrt.om/drivers/serial/s3c6400.c 2009-05-10 22:28:00.000000000 +0200
80109 @@ -102,6 +102,7 @@
80110 .name = "Samsung S3C6400 UART",
80111 .type = PORT_S3C6400,
80112 .fifosize = 64,
80113 + .has_divslot = 1,
80114 .rx_fifomask = S3C2440_UFSTAT_RXMASK,
80115 .rx_fifoshift = S3C2440_UFSTAT_RXSHIFT,
80116 .rx_fifofull = S3C2440_UFSTAT_RXFULL,
80117 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/serial/samsung.c linux-2.6.29-rc3.owrt.om/drivers/serial/samsung.c
80118 --- linux-2.6.29-rc3.owrt/drivers/serial/samsung.c 2009-05-10 22:04:48.000000000 +0200
80119 +++ linux-2.6.29-rc3.owrt.om/drivers/serial/samsung.c 2009-05-10 22:28:00.000000000 +0200
80120 @@ -50,6 +50,10 @@
80121 #include <mach/map.h>
80122
80123 #include <plat/regs-serial.h>
80124 +#if defined(CONFIG_MACH_NEO1973) && !defined(CONFIG_CPU_S3C6410)
80125 +#include <mach/regs-gpio.h>
80126 +#include <mach/regs-clock.h>
80127 +#endif
80128
80129 #include "samsung.h"
80130
80131 @@ -235,8 +239,8 @@
80132 port->icount.rx++;
80133
80134 if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
80135 - dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
80136 - ch, uerstat);
80137 + printk(KERN_DEBUG "rxerr: port=%d ch=0x%02x, rxs=0x%08x\n",
80138 + port->line, ch, uerstat);
80139
80140 /* check for break */
80141 if (uerstat & S3C2410_UERSTAT_BREAK) {
80142 @@ -265,8 +269,8 @@
80143 if (uart_handle_sysrq_char(port, ch))
80144 goto ignore_char;
80145
80146 - uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
80147 - ch, flag);
80148 + if ((uerstat & port->ignore_status_mask & ~S3C2410_UERSTAT_OVERRUN) == 0)
80149 + tty_insert_flip_char(tty, ch, flag);
80150
80151 ignore_char:
80152 continue;
80153 @@ -508,6 +512,7 @@
80154 struct baud_calc {
80155 struct s3c24xx_uart_clksrc *clksrc;
80156 unsigned int calc;
80157 + unsigned int divslot;
80158 unsigned int quot;
80159 struct clk *src;
80160 };
80161 @@ -517,6 +522,7 @@
80162 struct s3c24xx_uart_clksrc *clksrc,
80163 unsigned int baud)
80164 {
80165 + struct s3c24xx_uart_port *ourport = to_ourport(port);
80166 unsigned long rate;
80167
80168 calc->src = clk_get(port->dev, clksrc->name);
80169 @@ -527,8 +533,24 @@
80170 rate /= clksrc->divisor;
80171
80172 calc->clksrc = clksrc;
80173 - calc->quot = (rate + (8 * baud)) / (16 * baud);
80174 - calc->calc = (rate / (calc->quot * 16));
80175 +
80176 + if (ourport->info->has_divslot) {
80177 + unsigned long div = rate / baud;
80178 +
80179 + /* The UDIVSLOT register on the newer UARTs allows us to
80180 + * get a divisor adjustment of 1/16th on the baud clock.
80181 + *
80182 + * We don't keep the UDIVSLOT value (the 16ths we calculated
80183 + * by not multiplying the baud by 16) as it is easy enough
80184 + * to recalculate.
80185 + */
80186 +
80187 + calc->quot = div / 16;
80188 + calc->calc = rate / div;
80189 + } else {
80190 + calc->quot = (rate + (8 * baud)) / (16 * baud);
80191 + calc->calc = (rate / (calc->quot * 16));
80192 + }
80193
80194 calc->quot--;
80195 return 1;
80196 @@ -611,6 +633,30 @@
80197 return best->quot;
80198 }
80199
80200 +/* udivslot_table[]
80201 + *
80202 + * This table takes the fractional value of the baud divisor and gives
80203 + * the recommended setting for the UDIVSLOT register.
80204 + */
80205 +static u16 udivslot_table[16] = {
80206 + [0] = 0x0000,
80207 + [1] = 0x0080,
80208 + [2] = 0x0808,
80209 + [3] = 0x0888,
80210 + [4] = 0x2222,
80211 + [5] = 0x4924,
80212 + [6] = 0x4A52,
80213 + [7] = 0x54AA,
80214 + [8] = 0x5555,
80215 + [9] = 0xD555,
80216 + [10] = 0xD5D5,
80217 + [11] = 0xDDD5,
80218 + [12] = 0xDDDD,
80219 + [13] = 0xDFDD,
80220 + [14] = 0xDFDF,
80221 + [15] = 0xFFDF,
80222 +};
80223 +
80224 static void s3c24xx_serial_set_termios(struct uart_port *port,
80225 struct ktermios *termios,
80226 struct ktermios *old)
80227 @@ -623,6 +669,7 @@
80228 unsigned int baud, quot;
80229 unsigned int ulcon;
80230 unsigned int umcon;
80231 + unsigned int udivslot = 0;
80232
80233 /*
80234 * We don't support modem control lines.
80235 @@ -644,6 +691,7 @@
80236 /* check to see if we need to change clock source */
80237
80238 if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
80239 + dbg("selecting clock %p\n", clk);
80240 s3c24xx_serial_setsource(port, clksrc);
80241
80242 if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
80243 @@ -658,6 +706,13 @@
80244 ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
80245 }
80246
80247 + if (ourport->info->has_divslot) {
80248 + unsigned int div = ourport->baudclk_rate / baud;
80249 +
80250 + udivslot = udivslot_table[div & 15];
80251 + dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
80252 + }
80253 +
80254 switch (termios->c_cflag & CSIZE) {
80255 case CS5:
80256 dbg("config: 5bits/char\n");
80257 @@ -697,12 +752,16 @@
80258
80259 spin_lock_irqsave(&port->lock, flags);
80260
80261 - dbg("setting ulcon to %08x, brddiv to %d\n", ulcon, quot);
80262 + dbg("setting ulcon to %08x, brddiv to %d, udivslot %08x\n",
80263 + ulcon, quot, udivslot);
80264
80265 wr_regl(port, S3C2410_ULCON, ulcon);
80266 wr_regl(port, S3C2410_UBRDIV, quot);
80267 wr_regl(port, S3C2410_UMCON, umcon);
80268
80269 + if (ourport->info->has_divslot)
80270 + wr_regl(port, S3C2443_DIVSLOT, udivslot);
80271 +
80272 dbg("uart: ulcon = 0x%08x, ucon = 0x%08x, ufcon = 0x%08x\n",
80273 rd_regl(port, S3C2410_ULCON),
80274 rd_regl(port, S3C2410_UCON),
80275 @@ -887,6 +946,70 @@
80276 #endif
80277 };
80278
80279 +#ifdef CONFIG_MACH_NEO1973_GTA02
80280 +static void s3c24xx_serial_force_debug_port_up(void)
80281 +{
80282 + struct s3c24xx_uart_port *ourport = &s3c24xx_serial_ports[
80283 + CONFIG_DEBUG_S3C_UART];
80284 + struct s3c24xx_uart_clksrc *clksrc = NULL;
80285 + struct clk *clk = NULL;
80286 + unsigned long tmp;
80287 +
80288 + s3c24xx_serial_getclk(&ourport->port, &clksrc, &clk, 115200);
80289 +
80290 + tmp = __raw_readl(S3C2410_CLKCON);
80291 +
80292 + /* re-start uart clocks */
80293 + tmp |= S3C2410_CLKCON_UART0;
80294 + tmp |= S3C2410_CLKCON_UART1;
80295 + tmp |= S3C2410_CLKCON_UART2;
80296 +
80297 + __raw_writel(tmp, S3C2410_CLKCON);
80298 + udelay(10);
80299 +
80300 + s3c24xx_serial_setsource(&ourport->port, clksrc);
80301 +
80302 + if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
80303 + clk_disable(ourport->baudclk);
80304 + ourport->baudclk = NULL;
80305 + }
80306 +
80307 + clk_enable(clk);
80308 +
80309 + ourport->clksrc = clksrc;
80310 + ourport->baudclk = clk;
80311 +}
80312 +
80313 +static void s3c2410_printascii(const char *sz)
80314 +{
80315 + struct s3c24xx_uart_port *ourport = &s3c24xx_serial_ports[
80316 + CONFIG_DEBUG_S3C_UART];
80317 + struct uart_port *port = &ourport->port;
80318 +
80319 + /* 8 N 1 */
80320 + wr_regl(port, S3C2410_ULCON, (rd_regl(port, S3C2410_ULCON)) | 3);
80321 + /* polling mode */
80322 + wr_regl(port, S3C2410_UCON, (rd_regl(port, S3C2410_UCON) & ~0xc0f) | 5);
80323 + /* disable FIFO */
80324 + wr_regl(port, S3C2410_UFCON, (rd_regl(port, S3C2410_UFCON) & ~0x01));
80325 + /* fix baud rate */
80326 + wr_regl(port, S3C2410_UBRDIV, 26);
80327 +
80328 + while (*sz) {
80329 + int timeout = 10000000;
80330 +
80331 + /* spin on it being busy */
80332 + while ((!(rd_regl(port, S3C2410_UTRSTAT) & 2)) && timeout--)
80333 + ;
80334 +
80335 + /* transmit register */
80336 + wr_regl(port, S3C2410_UTXH, *sz);
80337 +
80338 + sz++;
80339 + }
80340 +}
80341 +#endif
80342 +
80343 /* s3c24xx_serial_resetport
80344 *
80345 * wrapper to call the specific reset for this port (reset the fifos
80346 @@ -937,13 +1060,17 @@
80347 struct ktermios *termios;
80348 struct tty_struct *tty;
80349
80350 - if (uport->info == NULL)
80351 + if (uport->info == NULL) {
80352 + printk(KERN_WARNING "%s: info NULL\n", __func__);
80353 goto exit;
80354 + }
80355
80356 tty = uport->info->port.tty;
80357
80358 - if (tty == NULL)
80359 + if (tty == NULL) {
80360 + printk(KERN_WARNING "%s: tty is NULL\n", __func__);
80361 goto exit;
80362 + }
80363
80364 termios = tty->termios;
80365
80366 @@ -1092,6 +1219,7 @@
80367
80368 ourport = &s3c24xx_serial_ports[probe_index];
80369 probe_index++;
80370 + init_resume_dependency_list(&ourport->resume_dependency);
80371
80372 dbg("%s: initialising port %p...\n", __func__, ourport);
80373
80374 @@ -1148,6 +1276,16 @@
80375 return 0;
80376 }
80377
80378 +void s3c24xx_serial_register_resume_dependency(struct resume_dependency *
80379 + resume_dependency, int uart_index)
80380 +{
80381 + struct s3c24xx_uart_port *ourport = &s3c24xx_serial_ports[uart_index];
80382 +
80383 + register_resume_dependency(&ourport->resume_dependency,
80384 + resume_dependency);
80385 +}
80386 +EXPORT_SYMBOL(s3c24xx_serial_register_resume_dependency);
80387 +
80388 static int s3c24xx_serial_resume(struct platform_device *dev)
80389 {
80390 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
80391 @@ -1159,6 +1297,9 @@
80392 clk_disable(ourport->clk);
80393
80394 uart_resume_port(&s3c24xx_uart_drv, port);
80395 +
80396 + callback_all_resume_dependencies(&ourport->resume_dependency);
80397 +
80398 }
80399
80400 return 0;
80401 @@ -1169,6 +1310,12 @@
80402 struct s3c24xx_uart_info *info)
80403 {
80404 dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
80405 +#ifdef CONFIG_MACH_NEO1973_GTA02
80406 + /* set up the emergency debug UART functions */
80407 +
80408 + printk_emergency_debug_spew_init = s3c24xx_serial_force_debug_port_up;
80409 + printk_emergency_debug_spew_send_string = s3c2410_printascii;
80410 +#endif
80411
80412 #ifdef CONFIG_PM
80413 drv->suspend = s3c24xx_serial_suspend;
80414 @@ -1208,6 +1355,13 @@
80415 #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
80416
80417 static struct uart_port *cons_uart;
80418 +static int cons_silenced;
80419 +
80420 +void s3c24xx_serial_console_set_silence(int silenced)
80421 +{
80422 + cons_silenced = silenced;
80423 +}
80424 +EXPORT_SYMBOL(s3c24xx_serial_console_set_silence);
80425
80426 static int
80427 s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)
80428 @@ -1232,9 +1386,21 @@
80429 s3c24xx_serial_console_putchar(struct uart_port *port, int ch)
80430 {
80431 unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
80432 + unsigned int umcon = rd_regl(cons_uart, S3C2410_UMCON);
80433 +
80434 + if (cons_silenced)
80435 + return;
80436 +
80437 + /* If auto HW flow control enabled, temporarily turn it off */
80438 + if (umcon & S3C2410_UMCOM_AFC)
80439 + wr_regl(port, S3C2410_UMCON, (umcon & !S3C2410_UMCOM_AFC));
80440 +
80441 while (!s3c24xx_serial_console_txrdy(port, ufcon))
80442 barrier();
80443 wr_regb(cons_uart, S3C2410_UTXH, ch);
80444 +
80445 + if (umcon & S3C2410_UMCOM_AFC)
80446 + wr_regl(port, S3C2410_UMCON, umcon);
80447 }
80448
80449 static void
80450 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/serial/samsung.h linux-2.6.29-rc3.owrt.om/drivers/serial/samsung.h
80451 --- linux-2.6.29-rc3.owrt/drivers/serial/samsung.h 2009-05-10 22:04:48.000000000 +0200
80452 +++ linux-2.6.29-rc3.owrt.om/drivers/serial/samsung.h 2009-05-10 22:28:00.000000000 +0200
80453 @@ -10,6 +10,8 @@
80454 * published by the Free Software Foundation.
80455 */
80456
80457 +#include <linux/resume-dependency.h>
80458 +
80459 struct s3c24xx_uart_info {
80460 char *name;
80461 unsigned int type;
80462 @@ -21,6 +23,10 @@
80463 unsigned long tx_fifoshift;
80464 unsigned long tx_fifofull;
80465
80466 + /* uart port features */
80467 +
80468 + unsigned int has_divslot:1;
80469 +
80470 /* clock source control */
80471
80472 int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
80473 @@ -48,6 +54,8 @@
80474 #ifdef CONFIG_CPU_FREQ
80475 struct notifier_block freq_transition;
80476 #endif
80477 +
80478 + struct resume_dependency resume_dependency;
80479 };
80480
80481 /* conversion functions */
80482 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/spi/Kconfig linux-2.6.29-rc3.owrt.om/drivers/spi/Kconfig
80483 --- linux-2.6.29-rc3.owrt/drivers/spi/Kconfig 2009-05-10 22:04:49.000000000 +0200
80484 +++ linux-2.6.29-rc3.owrt.om/drivers/spi/Kconfig 2009-05-10 22:28:00.000000000 +0200
80485 @@ -257,6 +257,15 @@
80486 sysfs interface, with each line presented as a kind of GPIO
80487 exposing both switch control and diagnostic feedback.
80488
80489 +config SPI_S3C64XX_GPIO
80490 + tristate "Samsung S3C64XX series SPI by GPIO"
80491 + depends on ARCH_S3C64XX && EXPERIMENTAL
80492 + select SPI_BITBANG
80493 + help
80494 + SPI driver for Samsung S3C64XX series ARM SoCs using
80495 + GPIO lines to provide the SPI bus. This can be used where
80496 + the inbuilt hardware cannot provide the transfer mode, or
80497 + where the board is using non hardware connected pins.
80498 #
80499 # Add new SPI protocol masters in alphabetical order above this line
80500 #
80501 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/spi/Makefile linux-2.6.29-rc3.owrt.om/drivers/spi/Makefile
80502 --- linux-2.6.29-rc3.owrt/drivers/spi/Makefile 2009-05-10 22:04:49.000000000 +0200
80503 +++ linux-2.6.29-rc3.owrt.om/drivers/spi/Makefile 2009-05-10 22:28:00.000000000 +0200
80504 @@ -31,6 +31,7 @@
80505 obj-$(CONFIG_SPI_TXX9) += spi_txx9.o
80506 obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o
80507 obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o
80508 +obj-$(CONFIG_SPI_S3C64XX_GPIO) += spi_s3c64xx_gpio.o
80509 # ... add above this line ...
80510
80511 # SPI protocol drivers (device/link on bus)
80512 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/spi/spi_bitbang.c linux-2.6.29-rc3.owrt.om/drivers/spi/spi_bitbang.c
80513 --- linux-2.6.29-rc3.owrt/drivers/spi/spi_bitbang.c 2009-05-10 22:04:49.000000000 +0200
80514 +++ linux-2.6.29-rc3.owrt.om/drivers/spi/spi_bitbang.c 2009-05-10 22:28:00.000000000 +0200
80515 @@ -264,6 +264,123 @@
80516 * Drivers can provide word-at-a-time i/o primitives, or provide
80517 * transfer-at-a-time ones to leverage dma or fifo hardware.
80518 */
80519 +
80520 +/* Synchronous non blocking transfer */
80521 +int
80522 +spi_bitbang_transfer_sync(struct spi_device *spi, struct spi_message *m)
80523 +{
80524 + struct spi_bitbang *bitbang = spi_master_get_devdata(spi->master);
80525 + struct spi_transfer *t;
80526 + unsigned long flags;
80527 + int cs_change = 1;
80528 + int status;
80529 + int nsecs;
80530 + int (*setup_transfer)(struct spi_device *, struct spi_transfer *);
80531 +
80532 + /* FIXME this is made-up ... the correct value is known to
80533 + * word-at-a-time bitbang code, and presumably chipselect()
80534 + * should enforce these requirements too?
80535 + */
80536 + nsecs = 100;
80537 + cs_change = 1;
80538 + status = 0;
80539 + setup_transfer = NULL;
80540 +
80541 + local_irq_save(flags);
80542 + list_for_each_entry (t, &m->transfers, transfer_list) {
80543 + /* override or restore speed and wordsize */
80544 + if (t->speed_hz || t->bits_per_word) {
80545 + setup_transfer = bitbang->setup_transfer;
80546 + if (!setup_transfer) {
80547 + status = -ENOPROTOOPT;
80548 + break;
80549 + }
80550 + }
80551 + if (setup_transfer) {
80552 + status = setup_transfer(spi, t);
80553 + if (status < 0)
80554 + break;
80555 + }
80556 +
80557 + /* set up default clock polarity, and activate chip;
80558 + * this implicitly updates clock and spi modes as
80559 + * previously recorded for this device via setup().
80560 + * (and also deselects any other chip that might be
80561 + * selected ...)
80562 + */
80563 +
80564 + if (cs_change) {
80565 + bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
80566 + ndelay(nsecs);
80567 + }
80568 +
80569 + cs_change = t->cs_change;
80570 + if (!t->tx_buf && !t->rx_buf && t->len) {
80571 + status = -EINVAL;
80572 + break;
80573 + }
80574 +
80575 + /* transfer data. the lower level code handles any
80576 + * new dma mappings it needs. our caller always gave
80577 + * us dma-safe buffers.
80578 + */
80579 + if (t->len) {
80580 + /* REVISIT dma API still needs a designated
80581 + * DMA_ADDR_INVALID; ~0 might be better.
80582 + */
80583 + if (!m->is_dma_mapped)
80584 + t->rx_dma = t->tx_dma = 0;
80585 + status = bitbang->txrx_bufs(spi, t);
80586 + }
80587 +
80588 + if (status > 0)
80589 + m->actual_length += status;
80590 + if (status != t->len) {
80591 + /* always report some kind of error */
80592 + if (status >= 0)
80593 + status = -EREMOTEIO;
80594 + break;
80595 + }
80596 + status = 0;
80597 + /* protocol tweaks before next transfer */
80598 + if (t->delay_usecs)
80599 + udelay(t->delay_usecs);
80600 + if (!cs_change)
80601 + continue;
80602 + if (t->transfer_list.next == &m->transfers)
80603 + break;
80604 + /* sometimes a short mid-message deselect of the chip
80605 + * may be needed to terminate a mode or command
80606 + */
80607 + ndelay(nsecs);
80608 + bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
80609 + ndelay(nsecs);
80610 + }
80611 +
80612 + m->status = status;
80613 + if (m->complete)
80614 + m->complete(m->context);
80615 +
80616 + /* restore speed and wordsize */
80617 + if (setup_transfer)
80618 + setup_transfer(spi, NULL);
80619 +
80620 + /* normally deactivate chipselect ... unless no error and
80621 + * cs_change has hinted that the next message will probably
80622 + * be for this chip too.
80623 + */
80624 + if (!(status == 0 && cs_change)) {
80625 + ndelay(nsecs);
80626 + bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
80627 + ndelay(nsecs);
80628 + }
80629 +
80630 + local_irq_restore(flags);
80631 +
80632 + return status;
80633 +}
80634 +EXPORT_SYMBOL_GPL(spi_bitbang_transfer_sync);
80635 +
80636 static void bitbang_work(struct work_struct *work)
80637 {
80638 struct spi_bitbang *bitbang =
80639 @@ -274,120 +391,13 @@
80640 bitbang->busy = 1;
80641 while (!list_empty(&bitbang->queue)) {
80642 struct spi_message *m;
80643 - struct spi_device *spi;
80644 - unsigned nsecs;
80645 - struct spi_transfer *t = NULL;
80646 - unsigned tmp;
80647 - unsigned cs_change;
80648 - int status;
80649 - int (*setup_transfer)(struct spi_device *,
80650 - struct spi_transfer *);
80651
80652 m = container_of(bitbang->queue.next, struct spi_message,
80653 queue);
80654 list_del_init(&m->queue);
80655 - spin_unlock_irqrestore(&bitbang->lock, flags);
80656 -
80657 - /* FIXME this is made-up ... the correct value is known to
80658 - * word-at-a-time bitbang code, and presumably chipselect()
80659 - * should enforce these requirements too?
80660 - */
80661 - nsecs = 100;
80662 -
80663 - spi = m->spi;
80664 - tmp = 0;
80665 - cs_change = 1;
80666 - status = 0;
80667 - setup_transfer = NULL;
80668 -
80669 - list_for_each_entry (t, &m->transfers, transfer_list) {
80670 -
80671 - /* override or restore speed and wordsize */
80672 - if (t->speed_hz || t->bits_per_word) {
80673 - setup_transfer = bitbang->setup_transfer;
80674 - if (!setup_transfer) {
80675 - status = -ENOPROTOOPT;
80676 - break;
80677 - }
80678 - }
80679 - if (setup_transfer) {
80680 - status = setup_transfer(spi, t);
80681 - if (status < 0)
80682 - break;
80683 - }
80684 -
80685 - /* set up default clock polarity, and activate chip;
80686 - * this implicitly updates clock and spi modes as
80687 - * previously recorded for this device via setup().
80688 - * (and also deselects any other chip that might be
80689 - * selected ...)
80690 - */
80691 - if (cs_change) {
80692 - bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
80693 - ndelay(nsecs);
80694 - }
80695 - cs_change = t->cs_change;
80696 - if (!t->tx_buf && !t->rx_buf && t->len) {
80697 - status = -EINVAL;
80698 - break;
80699 - }
80700 -
80701 - /* transfer data. the lower level code handles any
80702 - * new dma mappings it needs. our caller always gave
80703 - * us dma-safe buffers.
80704 - */
80705 - if (t->len) {
80706 - /* REVISIT dma API still needs a designated
80707 - * DMA_ADDR_INVALID; ~0 might be better.
80708 - */
80709 - if (!m->is_dma_mapped)
80710 - t->rx_dma = t->tx_dma = 0;
80711 - status = bitbang->txrx_bufs(spi, t);
80712 - }
80713 - if (status > 0)
80714 - m->actual_length += status;
80715 - if (status != t->len) {
80716 - /* always report some kind of error */
80717 - if (status >= 0)
80718 - status = -EREMOTEIO;
80719 - break;
80720 - }
80721 - status = 0;
80722 -
80723 - /* protocol tweaks before next transfer */
80724 - if (t->delay_usecs)
80725 - udelay(t->delay_usecs);
80726 -
80727 - if (!cs_change)
80728 - continue;
80729 - if (t->transfer_list.next == &m->transfers)
80730 - break;
80731 -
80732 - /* sometimes a short mid-message deselect of the chip
80733 - * may be needed to terminate a mode or command
80734 - */
80735 - ndelay(nsecs);
80736 - bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
80737 - ndelay(nsecs);
80738 - }
80739 -
80740 - m->status = status;
80741 - m->complete(m->context);
80742 -
80743 - /* restore speed and wordsize */
80744 - if (setup_transfer)
80745 - setup_transfer(spi, NULL);
80746 -
80747 - /* normally deactivate chipselect ... unless no error and
80748 - * cs_change has hinted that the next message will probably
80749 - * be for this chip too.
80750 - */
80751 - if (!(status == 0 && cs_change)) {
80752 - ndelay(nsecs);
80753 - bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
80754 - ndelay(nsecs);
80755 - }
80756
80757 + spin_unlock_irqrestore(&bitbang->lock, flags);
80758 + spi_bitbang_transfer_sync(m->spi, m);
80759 spin_lock_irqsave(&bitbang->lock, flags);
80760 }
80761 bitbang->busy = 0;
80762 @@ -459,6 +469,9 @@
80763
80764 if (!bitbang->master->transfer)
80765 bitbang->master->transfer = spi_bitbang_transfer;
80766 + if (!bitbang->master->transfer_sync && bitbang->non_blocking_transfer)
80767 + bitbang->master->transfer_sync = spi_bitbang_transfer_sync;
80768 +
80769 if (!bitbang->txrx_bufs) {
80770 bitbang->use_dma = 0;
80771 bitbang->txrx_bufs = spi_bitbang_bufs;
80772 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/spi/spi_s3c24xx_gpio.c linux-2.6.29-rc3.owrt.om/drivers/spi/spi_s3c24xx_gpio.c
80773 --- linux-2.6.29-rc3.owrt/drivers/spi/spi_s3c24xx_gpio.c 2009-05-10 22:04:49.000000000 +0200
80774 +++ linux-2.6.29-rc3.owrt.om/drivers/spi/spi_s3c24xx_gpio.c 2009-05-10 22:28:00.000000000 +0200
80775 @@ -91,7 +91,7 @@
80776 struct s3c2410_spigpio *sg = spidev_to_sg(dev);
80777
80778 if (sg->info && sg->info->chip_select)
80779 - (sg->info->chip_select)(sg->info, value);
80780 + (sg->info->chip_select)(sg->info, dev->chip_select, value);
80781 }
80782
80783 static int s3c2410_spigpio_probe(struct platform_device *dev)
80784 @@ -112,14 +112,17 @@
80785
80786 platform_set_drvdata(dev, sp);
80787
80788 - /* copy in the plkatform data */
80789 + /* copy in the platform data */
80790 info = sp->info = dev->dev.platform_data;
80791
80792 + master->num_chipselect = info->num_chipselect;
80793 +
80794 /* setup spi bitbang adaptor */
80795 sp->bitbang.master = spi_master_get(master);
80796 sp->bitbang.master->bus_num = info->bus_num;
80797 sp->bitbang.master->num_chipselect = info->num_chipselect;
80798 sp->bitbang.chipselect = s3c2410_spigpio_chipselect;
80799 + sp->bitbang.non_blocking_transfer = info->non_blocking_transfer;
80800
80801 sp->bitbang.txrx_word[SPI_MODE_0] = s3c2410_spigpio_txrx_mode0;
80802 sp->bitbang.txrx_word[SPI_MODE_1] = s3c2410_spigpio_txrx_mode1;
80803 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/spi/spi_s3c64xx_gpio.c linux-2.6.29-rc3.owrt.om/drivers/spi/spi_s3c64xx_gpio.c
80804 --- linux-2.6.29-rc3.owrt/drivers/spi/spi_s3c64xx_gpio.c 1970-01-01 01:00:00.000000000 +0100
80805 +++ linux-2.6.29-rc3.owrt.om/drivers/spi/spi_s3c64xx_gpio.c 2009-05-10 22:28:00.000000000 +0200
80806 @@ -0,0 +1,187 @@
80807 +/* linux/drivers/spi/spi_s3c64xx_gpio.c
80808 + *
80809 + * Copyright (c) 2009 Openmoko Inc.
80810 + * Author: Matt Hsu <matt_hsu@openmoko.org>
80811 + *
80812 + * S3C64XX GPIO-SPI driver.
80813 + * This driver is based on spi_s3c24xx_gpio.c
80814 + *
80815 + * Copyright (c) 2006 Ben Dooks
80816 + * Copyright (c) 2006 Simtec Electronics
80817 + *
80818 + * This program is free software; you can redistribute it and/or modify
80819 + * it under the terms of the GNU General Public License version 2 as
80820 + * published by the Free Software Foundation.
80821 + *
80822 + */
80823 +
80824 +#include <linux/kernel.h>
80825 +#include <linux/init.h>
80826 +#include <linux/delay.h>
80827 +#include <linux/spinlock.h>
80828 +#include <linux/workqueue.h>
80829 +#include <linux/platform_device.h>
80830 +#include <linux/gpio.h>
80831 +
80832 +#include <linux/spi/spi.h>
80833 +#include <linux/spi/spi_bitbang.h>
80834 +
80835 +#include <plat/gpio-cfg.h>
80836 +#include <mach/spi-gpio.h>
80837 +
80838 +struct s3c64xx_spigpio {
80839 + struct spi_bitbang bitbang;
80840 + struct s3c64xx_spigpio_info *info;
80841 + struct platform_device *dev;
80842 +};
80843 +
80844 +static inline struct s3c64xx_spigpio *spidev_to_sg(struct spi_device *spi)
80845 +{
80846 + return dev_get_drvdata(&spi->master->dev);
80847 +}
80848 +
80849 +static inline void setsck(struct spi_device *dev, int on)
80850 +{
80851 + struct s3c64xx_spigpio *sg = spidev_to_sg(dev);
80852 + gpio_direction_output(sg->info->pin_clk, on ? 1 : 0);
80853 +}
80854 +
80855 +static inline void setmosi(struct spi_device *dev, int on)
80856 +{
80857 + struct s3c64xx_spigpio *sg = spidev_to_sg(dev);
80858 + gpio_direction_output(sg->info->pin_mosi, on ? 1 : 0);
80859 +}
80860 +
80861 +static inline u32 getmiso(struct spi_device *dev)
80862 +{
80863 + struct s3c64xx_spigpio *sg = spidev_to_sg(dev);
80864 + return gpio_direction_input(sg->info->pin_miso) ? 1 : 0;
80865 +}
80866 +
80867 +#define spidelay(x) ndelay(x)
80868 +
80869 +#define EXPAND_BITBANG_TXRX
80870 +#include <linux/spi/spi_bitbang.h>
80871 +
80872 +static u32 s3c64xx_spigpio_txrx_mode0(struct spi_device *spi,
80873 + unsigned nsecs, u32 word, u8 bits)
80874 +{
80875 + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
80876 +}
80877 +
80878 +static u32 s3c64xx_spigpio_txrx_mode1(struct spi_device *spi,
80879 + unsigned nsecs, u32 word, u8 bits)
80880 +{
80881 + return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
80882 +}
80883 +
80884 +static u32 s3c64xx_spigpio_txrx_mode2(struct spi_device *spi,
80885 + unsigned nsecs, u32 word, u8 bits)
80886 +{
80887 + return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
80888 +}
80889 +
80890 +static u32 s3c64xx_spigpio_txrx_mode3(struct spi_device *spi,
80891 + unsigned nsecs, u32 word, u8 bits)
80892 +{
80893 + return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
80894 +}
80895 +static void s3c64xx_spigpio_chipselect(struct spi_device *dev, int value)
80896 +{
80897 + struct s3c64xx_spigpio *sg = spidev_to_sg(dev);
80898 +
80899 + if (sg && sg->info && sg->info->chip_select)
80900 + (sg->info->chip_select)(sg->info, dev->chip_select, value);
80901 +}
80902 +
80903 +static int s3c64xx_spigpio_probe(struct platform_device *dev)
80904 +{
80905 + struct s3c64xx_spigpio_info *info;
80906 + struct spi_master *master;
80907 + struct s3c64xx_spigpio *spi;
80908 +
80909 + int ret;
80910 +
80911 + master = spi_alloc_master(&dev->dev, sizeof(struct s3c64xx_spigpio));
80912 + if (master == NULL) {
80913 + dev_err(&dev->dev, "failed to allocate spi master\n");
80914 + ret = -ENOMEM;
80915 + goto err;
80916 + }
80917 +
80918 + spi = spi_master_get_devdata(master);
80919 +
80920 + /* copy in the platform data */
80921 + info = spi->info = dev->dev.platform_data;
80922 +
80923 + master->num_chipselect = info->num_chipselect;
80924 +
80925 + /* setup spi bitbang adaptor */
80926 + spi->bitbang.master = spi_master_get(master);
80927 + spi->bitbang.master->bus_num = info->bus_num;
80928 +
80929 + spi->bitbang.chipselect = s3c64xx_spigpio_chipselect;
80930 +
80931 + spi->bitbang.txrx_word[SPI_MODE_0] = s3c64xx_spigpio_txrx_mode0;
80932 + spi->bitbang.txrx_word[SPI_MODE_1] = s3c64xx_spigpio_txrx_mode1;
80933 + spi->bitbang.txrx_word[SPI_MODE_2] = s3c64xx_spigpio_txrx_mode2;
80934 + spi->bitbang.txrx_word[SPI_MODE_3] = s3c64xx_spigpio_txrx_mode3;
80935 +
80936 + /* set state of spi pins. */
80937 + gpio_direction_output(info->pin_clk, 0);
80938 + s3c_gpio_cfgpin(info->pin_clk, S3C_GPIO_OUTPUT);
80939 +
80940 + dev_set_drvdata(&master->dev, spi);
80941 +
80942 + ret = spi_bitbang_start(&spi->bitbang);
80943 + if (ret)
80944 + goto err_no_bitbang;
80945 +
80946 + return 0;
80947 +
80948 + err_no_bitbang:
80949 + spi_master_put(spi->bitbang.master);
80950 + err:
80951 + return ret;
80952 +}
80953 +
80954 +static int s3c64xx_spigpio_remove(struct platform_device *dev)
80955 +{
80956 + struct s3c64xx_spigpio *sp = platform_get_drvdata(dev);
80957 +
80958 + spi_bitbang_stop(&sp->bitbang);
80959 + spi_master_put(sp->bitbang.master);
80960 +
80961 + return 0;
80962 +}
80963 +
80964 +#define s3c64xx_spigpio_suspend NULL
80965 +#define s3c64xx_spigpio_resume NULL
80966 +
80967 +static struct platform_driver s3c64xx_spigpio_drv = {
80968 + .probe = s3c64xx_spigpio_probe,
80969 + .remove = s3c64xx_spigpio_remove,
80970 + .suspend = s3c64xx_spigpio_suspend,
80971 + .resume = s3c64xx_spigpio_resume,
80972 + .driver = {
80973 + .name = "spi_s3c64xx_gpio",
80974 + .owner = THIS_MODULE,
80975 + },
80976 +};
80977 +
80978 +static int __init s3c64xx_spigpio_init(void)
80979 +{
80980 + return platform_driver_register(&s3c64xx_spigpio_drv);
80981 +}
80982 +
80983 +static void __exit s3c64xx_spigpio_exit(void)
80984 +{
80985 + platform_driver_unregister(&s3c64xx_spigpio_drv);
80986 +}
80987 +
80988 +module_init(s3c64xx_spigpio_init);
80989 +module_exit(s3c64xx_spigpio_exit);
80990 +
80991 +MODULE_DESCRIPTION("S3C64XX GPIO-SPI Driver");
80992 +MODULE_AUTHOR("Matt Hsu, <matt_hsu@openmoko.org>");
80993 +MODULE_LICENSE("GPLv2");
80994 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/alarm.c linux-2.6.29-rc3.owrt.om/drivers/staging/android/alarm.c
80995 --- linux-2.6.29-rc3.owrt/drivers/staging/android/alarm.c 1970-01-01 01:00:00.000000000 +0100
80996 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/alarm.c 2009-05-10 22:28:00.000000000 +0200
80997 @@ -0,0 +1,567 @@
80998 +/* drivers/rtc/alarm.c
80999 + *
81000 + * Copyright (C) 2007 Google, Inc.
81001 + *
81002 + * This software is licensed under the terms of the GNU General Public
81003 + * License version 2, as published by the Free Software Foundation, and
81004 + * may be copied, distributed, and modified under those terms.
81005 + *
81006 + * This program is distributed in the hope that it will be useful,
81007 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
81008 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81009 + * GNU General Public License for more details.
81010 + *
81011 + */
81012 +
81013 +#include <asm/mach/time.h>
81014 +#include <linux/android_alarm.h>
81015 +#include <linux/device.h>
81016 +#include <linux/miscdevice.h>
81017 +#include <linux/platform_device.h>
81018 +#include <linux/rtc.h>
81019 +#include <linux/spinlock.h>
81020 +#include <linux/sysdev.h>
81021 +#include <linux/wakelock.h>
81022 +
81023 +#define ANDROID_ALARM_PRINT_ERRORS (1U << 0)
81024 +#define ANDROID_ALARM_PRINT_INIT_STATUS (1U << 1)
81025 +#define ANDROID_ALARM_PRINT_INFO (1U << 2)
81026 +#define ANDROID_ALARM_PRINT_IO (1U << 3)
81027 +#define ANDROID_ALARM_PRINT_INT (1U << 4)
81028 +#define ANDROID_ALARM_PRINT_FLOW (1U << 5)
81029 +
81030 +#if 0
81031 +#define ANDROID_ALARM_DPRINTF_MASK (~0)
81032 +#define ANDROID_ALARM_DPRINTF(debug_level_mask, args...) \
81033 + do { \
81034 + if (ANDROID_ALARM_DPRINTF_MASK & debug_level_mask) { \
81035 + printk(args); \
81036 + } \
81037 + } while (0)
81038 +#else
81039 +#define ANDROID_ALARM_DPRINTF(args...)
81040 +#endif
81041 +
81042 +#define ANDROID_ALARM_WAKEUP_MASK ( \
81043 + ANDROID_ALARM_RTC_WAKEUP_MASK | \
81044 + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
81045 +
81046 +/* support old usespace code */
81047 +#define ANDROID_ALARM_SET_OLD _IOW('a', 2, time_t) /* set alarm */
81048 +#define ANDROID_ALARM_SET_AND_WAIT_OLD _IOW('a', 3, time_t)
81049 +
81050 +static struct rtc_device *alarm_rtc_dev;
81051 +static int alarm_opened;
81052 +static DEFINE_SPINLOCK(alarm_slock);
81053 +static DEFINE_MUTEX(alarm_setrtc_mutex);
81054 +static struct wake_lock alarm_wake_lock;
81055 +static struct wake_lock alarm_rtc_wake_lock;
81056 +static DECLARE_WAIT_QUEUE_HEAD(alarm_wait_queue);
81057 +static uint32_t alarm_pending;
81058 +static uint32_t alarm_enabled;
81059 +static uint32_t wait_pending;
81060 +static struct platform_device *alarm_platform_dev;
81061 +static struct hrtimer alarm_timer[ANDROID_ALARM_TYPE_COUNT];
81062 +static struct timespec alarm_time[ANDROID_ALARM_TYPE_COUNT];
81063 +static struct timespec elapsed_rtc_delta;
81064 +
81065 +static void alarm_start_hrtimer(enum android_alarm_type alarm_type)
81066 +{
81067 + struct timespec hr_alarm_time;
81068 + if (!(alarm_enabled & (1U << alarm_type)))
81069 + return;
81070 + hr_alarm_time = alarm_time[alarm_type];
81071 + if (alarm_type == ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP ||
81072 + alarm_type == ANDROID_ALARM_ELAPSED_REALTIME)
81073 + set_normalized_timespec(&hr_alarm_time,
81074 + hr_alarm_time.tv_sec + elapsed_rtc_delta.tv_sec,
81075 + hr_alarm_time.tv_nsec + elapsed_rtc_delta.tv_nsec);
81076 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_FLOW,
81077 + "alarm start hrtimer %d at %ld.%09ld\n",
81078 + alarm_type, hr_alarm_time.tv_sec, hr_alarm_time.tv_nsec);
81079 + hrtimer_start(&alarm_timer[alarm_type],
81080 + timespec_to_ktime(hr_alarm_time), HRTIMER_MODE_ABS);
81081 +}
81082 +
81083 +static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
81084 +{
81085 + int rv = 0;
81086 + unsigned long flags;
81087 + int i;
81088 + struct timespec new_alarm_time;
81089 + struct timespec new_rtc_time;
81090 + struct timespec tmp_time;
81091 + struct rtc_time rtc_new_rtc_time;
81092 + enum android_alarm_type alarm_type = ANDROID_ALARM_IOCTL_TO_TYPE(cmd);
81093 + uint32_t alarm_type_mask = 1U << alarm_type;
81094 +
81095 + if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
81096 + return -EINVAL;
81097 +
81098 + if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
81099 + if ((file->f_flags & O_ACCMODE) == O_RDONLY)
81100 + return -EPERM;
81101 + if (file->private_data == NULL &&
81102 + cmd != ANDROID_ALARM_SET_RTC) {
81103 + spin_lock_irqsave(&alarm_slock, flags);
81104 + if (alarm_opened) {
81105 + spin_unlock_irqrestore(&alarm_slock, flags);
81106 + return -EBUSY;
81107 + }
81108 + alarm_opened = 1;
81109 + file->private_data = (void *)1;
81110 + spin_unlock_irqrestore(&alarm_slock, flags);
81111 + }
81112 + }
81113 +
81114 + switch (ANDROID_ALARM_BASE_CMD(cmd)) {
81115 + case ANDROID_ALARM_CLEAR(0):
81116 + spin_lock_irqsave(&alarm_slock, flags);
81117 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_IO,
81118 + "alarm %d clear\n", alarm_type);
81119 + hrtimer_try_to_cancel(&alarm_timer[alarm_type]);
81120 + if (alarm_pending) {
81121 + alarm_pending &= ~alarm_type_mask;
81122 + if (!alarm_pending && !wait_pending)
81123 + wake_unlock(&alarm_wake_lock);
81124 + }
81125 + alarm_enabled &= ~alarm_type_mask;
81126 + spin_unlock_irqrestore(&alarm_slock, flags);
81127 + break;
81128 +
81129 + case ANDROID_ALARM_SET_OLD:
81130 + case ANDROID_ALARM_SET_AND_WAIT_OLD:
81131 + if (get_user(new_alarm_time.tv_sec, (int __user *)arg)) {
81132 + rv = -EFAULT;
81133 + goto err1;
81134 + }
81135 + new_alarm_time.tv_nsec = 0;
81136 + goto from_old_alarm_set;
81137 +
81138 + case ANDROID_ALARM_SET_AND_WAIT(0):
81139 + case ANDROID_ALARM_SET(0):
81140 + if (copy_from_user(&new_alarm_time, (void __user *)arg,
81141 + sizeof(new_alarm_time))) {
81142 + rv = -EFAULT;
81143 + goto err1;
81144 + }
81145 +from_old_alarm_set:
81146 + spin_lock_irqsave(&alarm_slock, flags);
81147 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_IO,
81148 + "alarm %d set %ld.%09ld\n", alarm_type,
81149 + new_alarm_time.tv_sec, new_alarm_time.tv_nsec);
81150 + alarm_time[alarm_type] = new_alarm_time;
81151 + alarm_enabled |= alarm_type_mask;
81152 + alarm_start_hrtimer(alarm_type);
81153 + spin_unlock_irqrestore(&alarm_slock, flags);
81154 + if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_SET_AND_WAIT(0)
81155 + && cmd != ANDROID_ALARM_SET_AND_WAIT_OLD)
81156 + break;
81157 + /* fall though */
81158 + case ANDROID_ALARM_WAIT:
81159 + spin_lock_irqsave(&alarm_slock, flags);
81160 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_IO, "alarm wait\n");
81161 + if (!alarm_pending && wait_pending) {
81162 + wake_unlock(&alarm_wake_lock);
81163 + wait_pending = 0;
81164 + }
81165 + spin_unlock_irqrestore(&alarm_slock, flags);
81166 + rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
81167 + if (rv)
81168 + goto err1;
81169 + spin_lock_irqsave(&alarm_slock, flags);
81170 + rv = alarm_pending;
81171 + wait_pending = 1;
81172 + alarm_pending = 0;
81173 + if (rv & ANDROID_ALARM_WAKEUP_MASK)
81174 + wake_unlock(&alarm_rtc_wake_lock);
81175 + spin_unlock_irqrestore(&alarm_slock, flags);
81176 + break;
81177 + case ANDROID_ALARM_SET_RTC:
81178 + if (copy_from_user(&new_rtc_time, (void __user *)arg,
81179 + sizeof(new_rtc_time))) {
81180 + rv = -EFAULT;
81181 + goto err1;
81182 + }
81183 + rtc_time_to_tm(new_rtc_time.tv_sec, &rtc_new_rtc_time);
81184 +
81185 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_IO,
81186 + "set rtc %ld %ld - rtc %02d:%02d:%02d %02d/%02d/%04d\n",
81187 + new_rtc_time.tv_sec, new_rtc_time.tv_nsec,
81188 + rtc_new_rtc_time.tm_hour, rtc_new_rtc_time.tm_min,
81189 + rtc_new_rtc_time.tm_sec, rtc_new_rtc_time.tm_mon + 1,
81190 + rtc_new_rtc_time.tm_mday,
81191 + rtc_new_rtc_time.tm_year + 1900);
81192 +
81193 + mutex_lock(&alarm_setrtc_mutex);
81194 + spin_lock_irqsave(&alarm_slock, flags);
81195 + for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++)
81196 + hrtimer_try_to_cancel(&alarm_timer[i]);
81197 + getnstimeofday(&tmp_time);
81198 + elapsed_rtc_delta = timespec_sub(elapsed_rtc_delta,
81199 + timespec_sub(tmp_time, new_rtc_time));
81200 + spin_unlock_irqrestore(&alarm_slock, flags);
81201 + rv = do_settimeofday(&new_rtc_time);
81202 + spin_lock_irqsave(&alarm_slock, flags);
81203 + for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++)
81204 + alarm_start_hrtimer(i);
81205 + spin_unlock_irqrestore(&alarm_slock, flags);
81206 + if (rv < 0) {
81207 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_ERRORS,
81208 + "Failed to set time\n");
81209 + mutex_unlock(&alarm_setrtc_mutex);
81210 + goto err1;
81211 + }
81212 + rv = rtc_set_time(alarm_rtc_dev, &rtc_new_rtc_time);
81213 + spin_lock_irqsave(&alarm_slock, flags);
81214 + alarm_pending |= ANDROID_ALARM_TIME_CHANGE_MASK;
81215 + wake_up(&alarm_wait_queue);
81216 + spin_unlock_irqrestore(&alarm_slock, flags);
81217 + mutex_unlock(&alarm_setrtc_mutex);
81218 + if (rv < 0) {
81219 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_ERRORS,
81220 + "Failed to set RTC, time will be lost on reboot\n");
81221 + goto err1;
81222 + }
81223 + break;
81224 + case ANDROID_ALARM_GET_TIME(0):
81225 + mutex_lock(&alarm_setrtc_mutex);
81226 + spin_lock_irqsave(&alarm_slock, flags);
81227 + if (alarm_type != ANDROID_ALARM_SYSTEMTIME) {
81228 + getnstimeofday(&tmp_time);
81229 + if (alarm_type >= ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP)
81230 + tmp_time = timespec_sub(tmp_time,
81231 + elapsed_rtc_delta);
81232 + } else
81233 + ktime_get_ts(&tmp_time);
81234 + spin_unlock_irqrestore(&alarm_slock, flags);
81235 + mutex_unlock(&alarm_setrtc_mutex);
81236 + if (copy_to_user((void __user *)arg, &tmp_time,
81237 + sizeof(tmp_time))) {
81238 + rv = -EFAULT;
81239 + goto err1;
81240 + }
81241 + break;
81242 +
81243 + default:
81244 + rv = -EINVAL;
81245 + goto err1;
81246 + }
81247 +err1:
81248 + return rv;
81249 +}
81250 +
81251 +static int alarm_open(struct inode *inode, struct file *file)
81252 +{
81253 + file->private_data = NULL;
81254 + return 0;
81255 +}
81256 +
81257 +static int alarm_release(struct inode *inode, struct file *file)
81258 +{
81259 + int i;
81260 + unsigned long flags;
81261 +
81262 + spin_lock_irqsave(&alarm_slock, flags);
81263 + if (file->private_data != 0) {
81264 + for (i = 0; i < ANDROID_ALARM_TYPE_COUNT; i++) {
81265 + uint32_t alarm_type_mask = 1U << i;
81266 + if (alarm_enabled & alarm_type_mask) {
81267 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO,
81268 + "alarm_release: clear alarm, "
81269 + "pending %d\n",
81270 + !!(alarm_pending & alarm_type_mask));
81271 + alarm_enabled &= ~alarm_type_mask;
81272 + }
81273 + spin_unlock_irqrestore(&alarm_slock, flags);
81274 + hrtimer_cancel(&alarm_timer[i]);
81275 + spin_lock_irqsave(&alarm_slock, flags);
81276 + }
81277 + if (alarm_pending | wait_pending) {
81278 + if (alarm_pending)
81279 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO,
81280 + "alarm_release: clear pending alarms "
81281 + "%x\n", alarm_pending);
81282 + wake_unlock(&alarm_wake_lock);
81283 + wait_pending = 0;
81284 + alarm_pending = 0;
81285 + }
81286 + alarm_opened = 0;
81287 + }
81288 + spin_unlock_irqrestore(&alarm_slock, flags);
81289 + return 0;
81290 +}
81291 +
81292 +static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer)
81293 +{
81294 + unsigned long flags;
81295 + enum android_alarm_type alarm_type = (timer - alarm_timer);
81296 + uint32_t alarm_type_mask = 1U << alarm_type;
81297 +
81298 +
81299 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INT,
81300 + "alarm_timer_triggered type %d\n", alarm_type);
81301 + spin_lock_irqsave(&alarm_slock, flags);
81302 + if (alarm_enabled & alarm_type_mask) {
81303 + wake_lock_timeout(&alarm_wake_lock, 5 * HZ);
81304 + alarm_enabled &= ~alarm_type_mask;
81305 + alarm_pending |= alarm_type_mask;
81306 + wake_up(&alarm_wait_queue);
81307 + }
81308 + spin_unlock_irqrestore(&alarm_slock, flags);
81309 + return HRTIMER_NORESTART;
81310 +}
81311 +
81312 +static void alarm_triggered_func(void *p)
81313 +{
81314 + struct rtc_device *rtc = alarm_rtc_dev;
81315 + if (!(rtc->irq_data & RTC_AF))
81316 + return;
81317 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INT, "rtc alarm triggered\n");
81318 + wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
81319 +}
81320 +
81321 +int alarm_suspend(struct platform_device *pdev, pm_message_t state)
81322 +{
81323 + int err = 0;
81324 + unsigned long flags;
81325 + struct rtc_wkalrm rtc_alarm;
81326 + struct rtc_time rtc_current_rtc_time;
81327 + unsigned long rtc_current_time;
81328 + unsigned long rtc_alarm_time;
81329 + struct timespec rtc_current_timespec;
81330 + struct timespec rtc_delta;
81331 + struct timespec elapsed_realtime_alarm_time;
81332 +
81333 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_FLOW,
81334 + "alarm_suspend(%p, %d)\n", pdev, state.event);
81335 + spin_lock_irqsave(&alarm_slock, flags);
81336 + if (alarm_pending && !wake_lock_active(&alarm_wake_lock)) {
81337 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO,
81338 + "alarm pending\n");
81339 + err = -EBUSY;
81340 + goto err1;
81341 + }
81342 + if (alarm_enabled & ANDROID_ALARM_WAKEUP_MASK) {
81343 + spin_unlock_irqrestore(&alarm_slock, flags);
81344 + if (alarm_enabled & ANDROID_ALARM_RTC_WAKEUP_MASK)
81345 + hrtimer_cancel(&alarm_timer[ANDROID_ALARM_RTC_WAKEUP]);
81346 + if (alarm_enabled & ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
81347 + hrtimer_cancel(&alarm_timer[
81348 + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]);
81349 +
81350 + rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
81351 + rtc_current_timespec.tv_nsec = 0;
81352 + rtc_tm_to_time(&rtc_current_rtc_time,
81353 + &rtc_current_timespec.tv_sec);
81354 + save_time_delta(&rtc_delta, &rtc_current_timespec);
81355 + set_normalized_timespec(&elapsed_realtime_alarm_time,
81356 + alarm_time[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]
81357 + .tv_sec + elapsed_rtc_delta.tv_sec,
81358 + alarm_time[ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP]
81359 + .tv_nsec + elapsed_rtc_delta.tv_nsec);
81360 + if ((alarm_enabled & ANDROID_ALARM_RTC_WAKEUP_MASK) &&
81361 + (!(alarm_enabled &
81362 + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK) ||
81363 + timespec_compare(&alarm_time[ANDROID_ALARM_RTC_WAKEUP],
81364 + &elapsed_realtime_alarm_time) < 0))
81365 + rtc_alarm_time = timespec_sub(
81366 + alarm_time[ANDROID_ALARM_RTC_WAKEUP],
81367 + rtc_delta).tv_sec;
81368 + else
81369 + rtc_alarm_time = timespec_sub(
81370 + elapsed_realtime_alarm_time, rtc_delta).tv_sec;
81371 + rtc_time_to_tm(rtc_alarm_time, &rtc_alarm.time);
81372 + rtc_alarm.enabled = 1;
81373 + rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
81374 + rtc_read_time(alarm_rtc_dev, &rtc_current_rtc_time);
81375 + rtc_tm_to_time(&rtc_current_rtc_time, &rtc_current_time);
81376 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO,
81377 + "rtc alarm set at %ld, now %ld, rtc delta %ld.%09ld\n",
81378 + rtc_alarm_time, rtc_current_time,
81379 + rtc_delta.tv_sec, rtc_delta.tv_nsec);
81380 + if (rtc_current_time + 1 >= rtc_alarm_time) {
81381 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO,
81382 + "alarm about to go off\n");
81383 + memset(&rtc_alarm, 0, sizeof(rtc_alarm));
81384 + rtc_alarm.enabled = 0;
81385 + rtc_set_alarm(alarm_rtc_dev, &rtc_alarm);
81386 +
81387 + spin_lock_irqsave(&alarm_slock, flags);
81388 + wake_lock_timeout(&alarm_rtc_wake_lock, 2 * HZ);
81389 + alarm_start_hrtimer(ANDROID_ALARM_RTC_WAKEUP);
81390 + alarm_start_hrtimer(
81391 + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP);
81392 + err = -EBUSY;
81393 + spin_unlock_irqrestore(&alarm_slock, flags);
81394 + }
81395 + } else {
81396 +err1:
81397 + spin_unlock_irqrestore(&alarm_slock, flags);
81398 + }
81399 + return err;
81400 +}
81401 +
81402 +int alarm_resume(struct platform_device *pdev)
81403 +{
81404 + struct rtc_wkalrm alarm;
81405 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_FLOW,
81406 + "alarm_resume(%p)\n", pdev);
81407 + if (alarm_enabled & ANDROID_ALARM_WAKEUP_MASK) {
81408 + memset(&alarm, 0, sizeof(alarm));
81409 + alarm.enabled = 0;
81410 + rtc_set_alarm(alarm_rtc_dev, &alarm);
81411 + alarm_start_hrtimer(ANDROID_ALARM_RTC_WAKEUP);
81412 + alarm_start_hrtimer(ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP);
81413 + }
81414 + return 0;
81415 +}
81416 +
81417 +static struct rtc_task alarm_rtc_task = {
81418 + .func = alarm_triggered_func
81419 +};
81420 +
81421 +static struct file_operations alarm_fops = {
81422 + .owner = THIS_MODULE,
81423 + .unlocked_ioctl = alarm_ioctl,
81424 + .open = alarm_open,
81425 + .release = alarm_release,
81426 +};
81427 +
81428 +static struct miscdevice alarm_device = {
81429 + .minor = MISC_DYNAMIC_MINOR,
81430 + .name = "alarm",
81431 + .fops = &alarm_fops,
81432 +};
81433 +
81434 +static int rtc_alarm_add_device(struct device *dev,
81435 + struct class_interface *class_intf)
81436 +{
81437 + int err;
81438 + struct rtc_device *rtc = to_rtc_device(dev);
81439 +
81440 + mutex_lock(&alarm_setrtc_mutex);
81441 +
81442 + if (alarm_rtc_dev) {
81443 + err = -EBUSY;
81444 + goto err1;
81445 + }
81446 +
81447 + err = misc_register(&alarm_device);
81448 + if (err)
81449 + goto err1;
81450 + alarm_platform_dev =
81451 + platform_device_register_simple("alarm", -1, NULL, 0);
81452 + if (IS_ERR(alarm_platform_dev)) {
81453 + err = PTR_ERR(alarm_platform_dev);
81454 + goto err2;
81455 + }
81456 + err = rtc_irq_register(rtc, &alarm_rtc_task);
81457 + if (err)
81458 + goto err3;
81459 + alarm_rtc_dev = rtc;
81460 + mutex_unlock(&alarm_setrtc_mutex);
81461 +
81462 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO, "alarm: parent %p\n",
81463 + alarm_platform_dev->dev.power.pm_parent);
81464 + return 0;
81465 +
81466 +err3:
81467 + platform_device_unregister(alarm_platform_dev);
81468 +err2:
81469 + misc_deregister(&alarm_device);
81470 +err1:
81471 + mutex_unlock(&alarm_setrtc_mutex);
81472 + return err;
81473 +}
81474 +
81475 +static void rtc_alarm_remove_device(struct device *dev,
81476 + struct class_interface *class_intf)
81477 +{
81478 + if (dev == &alarm_rtc_dev->dev) {
81479 + rtc_irq_unregister(alarm_rtc_dev, &alarm_rtc_task);
81480 + platform_device_unregister(alarm_platform_dev);
81481 + misc_deregister(&alarm_device);
81482 + alarm_rtc_dev = NULL;
81483 + }
81484 +}
81485 +
81486 +static struct class_interface rtc_alarm_interface = {
81487 + .add_dev = &rtc_alarm_add_device,
81488 + .remove_dev = &rtc_alarm_remove_device,
81489 +};
81490 +
81491 +static struct platform_driver alarm_driver = {
81492 + .suspend = alarm_suspend,
81493 + .resume = alarm_resume,
81494 + .driver = {
81495 + .name = "alarm"
81496 + }
81497 +};
81498 +
81499 +static int __init alarm_late_init(void)
81500 +{
81501 + unsigned long flags;
81502 + struct timespec system_time;
81503 +
81504 + /* this needs to run after the rtc is read at boot */
81505 + spin_lock_irqsave(&alarm_slock, flags);
81506 + /* We read the current rtc and system time so we can later calulate
81507 + * elasped realtime to be (boot_systemtime + rtc - boot_rtc) ==
81508 + * (rtc - (boot_rtc - boot_systemtime))
81509 + */
81510 + getnstimeofday(&elapsed_rtc_delta);
81511 + ktime_get_ts(&system_time);
81512 + elapsed_rtc_delta = timespec_sub(elapsed_rtc_delta, system_time);
81513 + spin_unlock_irqrestore(&alarm_slock, flags);
81514 +
81515 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO,
81516 + "alarm_late_init: rtc to elapsed realtime delta %ld.%09ld\n",
81517 + elapsed_rtc_delta.tv_sec, elapsed_rtc_delta.tv_nsec);
81518 + return 0;
81519 +}
81520 +
81521 +static int __init alarm_init(void)
81522 +{
81523 + int err;
81524 + int i;
81525 +
81526 + for (i = 0; i < ANDROID_ALARM_SYSTEMTIME; i++) {
81527 + hrtimer_init(&alarm_timer[i], CLOCK_REALTIME, HRTIMER_MODE_ABS);
81528 + alarm_timer[i].function = alarm_timer_triggered;
81529 + }
81530 + hrtimer_init(&alarm_timer[ANDROID_ALARM_SYSTEMTIME],
81531 + CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
81532 + alarm_timer[ANDROID_ALARM_SYSTEMTIME].function = alarm_timer_triggered;
81533 + err = platform_driver_register(&alarm_driver);
81534 + if (err < 0)
81535 + goto err1;
81536 + wake_lock_init(&alarm_wake_lock, WAKE_LOCK_SUSPEND, "alarm");
81537 + wake_lock_init(&alarm_rtc_wake_lock, WAKE_LOCK_SUSPEND, "alarm_rtc");
81538 + rtc_alarm_interface.class = rtc_class;
81539 + err = class_interface_register(&rtc_alarm_interface);
81540 + if (err < 0)
81541 + goto err2;
81542 +
81543 + return 0;
81544 +
81545 +err2:
81546 + wake_lock_destroy(&alarm_rtc_wake_lock);
81547 + wake_lock_destroy(&alarm_wake_lock);
81548 + platform_driver_unregister(&alarm_driver);
81549 +err1:
81550 + return err;
81551 +}
81552 +
81553 +static void __exit alarm_exit(void)
81554 +{
81555 + class_interface_unregister(&rtc_alarm_interface);
81556 + wake_lock_destroy(&alarm_rtc_wake_lock);
81557 + wake_lock_destroy(&alarm_wake_lock);
81558 + platform_driver_unregister(&alarm_driver);
81559 +}
81560 +
81561 +late_initcall(alarm_late_init);
81562 +module_init(alarm_init);
81563 +module_exit(alarm_exit);
81564 +
81565 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/binder.c linux-2.6.29-rc3.owrt.om/drivers/staging/android/binder.c
81566 --- linux-2.6.29-rc3.owrt/drivers/staging/android/binder.c 2009-05-10 22:08:44.000000000 +0200
81567 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/binder.c 2009-05-10 22:28:00.000000000 +0200
81568 @@ -54,7 +54,7 @@
81569 #define SZ_4M 0x400000
81570 #endif
81571
81572 -#ifndef __i386__
81573 +#if !defined(__i386__) && !defined(__arm__)
81574 #define FORBIDDEN_MMAP_FLAGS (VM_WRITE | VM_EXEC)
81575 #else
81576 #define FORBIDDEN_MMAP_FLAGS (VM_WRITE)
81577 @@ -2649,14 +2649,14 @@
81578 {
81579 struct binder_proc *proc = vma->vm_private_data;
81580 if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
81581 - printk(KERN_INFO "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, vma->vm_page_prot.pgprot);
81582 + printk(KERN_INFO "binder: %d open vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, vma->vm_page_prot);
81583 dump_stack();
81584 }
81585 static void binder_vma_close(struct vm_area_struct *vma)
81586 {
81587 struct binder_proc *proc = vma->vm_private_data;
81588 if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
81589 - printk(KERN_INFO "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, vma->vm_page_prot.pgprot);
81590 + printk(KERN_INFO "binder: %d close vm area %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, vma->vm_page_prot);
81591 proc->vma = NULL;
81592 }
81593
81594 @@ -2677,7 +2677,7 @@
81595 vma->vm_end = vma->vm_start + SZ_4M;
81596
81597 if (binder_debug_mask & BINDER_DEBUG_OPEN_CLOSE)
81598 - printk(KERN_INFO "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, vma->vm_page_prot.pgprot);
81599 + printk(KERN_INFO "binder_mmap: %d %lx-%lx (%ld K) vma %lx pagep %lx\n", proc->pid, vma->vm_start, vma->vm_end, (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, vma->vm_page_prot);
81600
81601 if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
81602 ret = -EPERM;
81603 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/consoleearlysuspend.c linux-2.6.29-rc3.owrt.om/drivers/staging/android/consoleearlysuspend.c
81604 --- linux-2.6.29-rc3.owrt/drivers/staging/android/consoleearlysuspend.c 1970-01-01 01:00:00.000000000 +0100
81605 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/consoleearlysuspend.c 2009-05-10 22:28:00.000000000 +0200
81606 @@ -0,0 +1,78 @@
81607 +/* kernel/power/consoleearlysuspend.c
81608 + *
81609 + * Copyright (C) 2005-2008 Google, Inc.
81610 + *
81611 + * This software is licensed under the terms of the GNU General Public
81612 + * License version 2, as published by the Free Software Foundation, and
81613 + * may be copied, distributed, and modified under those terms.
81614 + *
81615 + * This program is distributed in the hope that it will be useful,
81616 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
81617 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81618 + * GNU General Public License for more details.
81619 + *
81620 + */
81621 +
81622 +#include <linux/console.h>
81623 +#include <linux/earlysuspend.h>
81624 +#include <linux/kbd_kern.h>
81625 +#include <linux/module.h>
81626 +#include <linux/vt_kern.h>
81627 +#include <linux/wait.h>
81628 +
81629 +#define EARLY_SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
81630 +
81631 +static int orig_fgconsole;
81632 +static void console_early_suspend(struct early_suspend *h)
81633 +{
81634 + acquire_console_sem();
81635 + orig_fgconsole = fg_console;
81636 + if (vc_allocate(EARLY_SUSPEND_CONSOLE))
81637 + goto err;
81638 + if (set_console(EARLY_SUSPEND_CONSOLE))
81639 + goto err;
81640 + release_console_sem();
81641 +
81642 + if (vt_waitactive(EARLY_SUSPEND_CONSOLE))
81643 + pr_warning("console_early_suspend: Can't switch VCs.\n");
81644 + return;
81645 +err:
81646 + pr_warning("console_early_suspend: Can't set console\n");
81647 + release_console_sem();
81648 +}
81649 +
81650 +static void console_late_resume(struct early_suspend *h)
81651 +{
81652 + int ret;
81653 + acquire_console_sem();
81654 + ret = set_console(orig_fgconsole);
81655 + release_console_sem();
81656 + if (ret) {
81657 + pr_warning("console_late_resume: Can't set console.\n");
81658 + return;
81659 + }
81660 +
81661 + if (vt_waitactive(orig_fgconsole))
81662 + pr_warning("console_late_resume: Can't switch VCs.\n");
81663 +}
81664 +
81665 +static struct early_suspend console_early_suspend_desc = {
81666 + .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
81667 + .suspend = console_early_suspend,
81668 + .resume = console_late_resume,
81669 +};
81670 +
81671 +static int __init console_early_suspend_init(void)
81672 +{
81673 + register_early_suspend(&console_early_suspend_desc);
81674 + return 0;
81675 +}
81676 +
81677 +static void __exit console_early_suspend_exit(void)
81678 +{
81679 + unregister_early_suspend(&console_early_suspend_desc);
81680 +}
81681 +
81682 +module_init(console_early_suspend_init);
81683 +module_exit(console_early_suspend_exit);
81684 +
81685 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/earlysuspend.c linux-2.6.29-rc3.owrt.om/drivers/staging/android/earlysuspend.c
81686 --- linux-2.6.29-rc3.owrt/drivers/staging/android/earlysuspend.c 1970-01-01 01:00:00.000000000 +0100
81687 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/earlysuspend.c 2009-05-10 22:28:00.000000000 +0200
81688 @@ -0,0 +1,178 @@
81689 +/* kernel/power/earlysuspend.c
81690 + *
81691 + * Copyright (C) 2005-2008 Google, Inc.
81692 + *
81693 + * This software is licensed under the terms of the GNU General Public
81694 + * License version 2, as published by the Free Software Foundation, and
81695 + * may be copied, distributed, and modified under those terms.
81696 + *
81697 + * This program is distributed in the hope that it will be useful,
81698 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
81699 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81700 + * GNU General Public License for more details.
81701 + *
81702 + */
81703 +
81704 +#include <linux/earlysuspend.h>
81705 +#include <linux/module.h>
81706 +#include <linux/mutex.h>
81707 +#include <linux/rtc.h>
81708 +#include <linux/syscalls.h> /* sys_sync */
81709 +#include <linux/wakelock.h>
81710 +#include <linux/workqueue.h>
81711 +
81712 +#include "power.h"
81713 +
81714 +enum {
81715 + DEBUG_USER_STATE = 1U << 0,
81716 + DEBUG_SUSPEND = 1U << 2,
81717 +};
81718 +static int debug_mask = DEBUG_USER_STATE;
81719 +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
81720 +
81721 +static DEFINE_MUTEX(early_suspend_lock);
81722 +static LIST_HEAD(early_suspend_handlers);
81723 +static void early_suspend(struct work_struct *work);
81724 +static void late_resume(struct work_struct *work);
81725 +static DECLARE_WORK(early_suspend_work, early_suspend);
81726 +static DECLARE_WORK(late_resume_work, late_resume);
81727 +static DEFINE_SPINLOCK(state_lock);
81728 +enum {
81729 + SUSPEND_REQUESTED = 0x1,
81730 + SUSPENDED = 0x2,
81731 + SUSPEND_REQUESTED_AND_SUSPENDED = SUSPEND_REQUESTED | SUSPENDED,
81732 +};
81733 +static int state;
81734 +
81735 +void register_early_suspend(struct early_suspend *handler)
81736 +{
81737 + struct list_head *pos;
81738 +
81739 + mutex_lock(&early_suspend_lock);
81740 + list_for_each(pos, &early_suspend_handlers) {
81741 + struct early_suspend *e;
81742 + e = list_entry(pos, struct early_suspend, link);
81743 + if (e->level > handler->level)
81744 + break;
81745 + }
81746 + list_add_tail(&handler->link, pos);
81747 + if ((state & SUSPENDED) && handler->suspend)
81748 + handler->suspend(handler);
81749 + mutex_unlock(&early_suspend_lock);
81750 +}
81751 +EXPORT_SYMBOL(register_early_suspend);
81752 +
81753 +void unregister_early_suspend(struct early_suspend *handler)
81754 +{
81755 + mutex_lock(&early_suspend_lock);
81756 + list_del(&handler->link);
81757 + mutex_unlock(&early_suspend_lock);
81758 +}
81759 +EXPORT_SYMBOL(unregister_early_suspend);
81760 +
81761 +static void early_suspend(struct work_struct *work)
81762 +{
81763 + struct early_suspend *pos;
81764 + unsigned long irqflags;
81765 + int abort = 0;
81766 +
81767 + mutex_lock(&early_suspend_lock);
81768 + spin_lock_irqsave(&state_lock, irqflags);
81769 + if (state == SUSPEND_REQUESTED)
81770 + state |= SUSPENDED;
81771 + else
81772 + abort = 1;
81773 + spin_unlock_irqrestore(&state_lock, irqflags);
81774 +
81775 + if (abort) {
81776 + if (debug_mask & DEBUG_SUSPEND)
81777 + pr_info("early_suspend: abort, state %d\n", state);
81778 + mutex_unlock(&early_suspend_lock);
81779 + goto abort;
81780 + }
81781 +
81782 + if (debug_mask & DEBUG_SUSPEND)
81783 + pr_info("early_suspend: call handlers\n");
81784 + list_for_each_entry(pos, &early_suspend_handlers, link) {
81785 + if (pos->suspend != NULL)
81786 + pos->suspend(pos);
81787 + }
81788 + mutex_unlock(&early_suspend_lock);
81789 +
81790 + if (debug_mask & DEBUG_SUSPEND)
81791 + pr_info("early_suspend: sync\n");
81792 +
81793 + sys_sync();
81794 +abort:
81795 + spin_lock_irqsave(&state_lock, irqflags);
81796 + if (state == SUSPEND_REQUESTED_AND_SUSPENDED)
81797 + wake_unlock(&main_wake_lock);
81798 + spin_unlock_irqrestore(&state_lock, irqflags);
81799 +}
81800 +
81801 +static void late_resume(struct work_struct *work)
81802 +{
81803 + struct early_suspend *pos;
81804 + unsigned long irqflags;
81805 + int abort = 0;
81806 +
81807 + mutex_lock(&early_suspend_lock);
81808 + spin_lock_irqsave(&state_lock, irqflags);
81809 + if (state == SUSPENDED)
81810 + state &= ~SUSPENDED;
81811 + else
81812 + abort = 1;
81813 + spin_unlock_irqrestore(&state_lock, irqflags);
81814 +
81815 + if (abort) {
81816 + if (debug_mask & DEBUG_SUSPEND)
81817 + pr_info("late_resume: abort, state %d\n", state);
81818 + goto abort;
81819 + }
81820 + if (debug_mask & DEBUG_SUSPEND)
81821 + pr_info("late_resume: call handlers\n");
81822 + list_for_each_entry_reverse(pos, &early_suspend_handlers, link)
81823 + if (pos->resume != NULL)
81824 + pos->resume(pos);
81825 + if (debug_mask & DEBUG_SUSPEND)
81826 + pr_info("late_resume: done\n");
81827 +abort:
81828 + mutex_unlock(&early_suspend_lock);
81829 +}
81830 +
81831 +void request_suspend_state(suspend_state_t new_state)
81832 +{
81833 + unsigned long irqflags;
81834 + int old_sleep;
81835 +
81836 + spin_lock_irqsave(&state_lock, irqflags);
81837 + old_sleep = state & SUSPEND_REQUESTED;
81838 + if (debug_mask & DEBUG_USER_STATE) {
81839 + struct timespec ts;
81840 + struct rtc_time tm;
81841 + getnstimeofday(&ts);
81842 + rtc_time_to_tm(ts.tv_sec, &tm);
81843 + pr_info("request_suspend_state: %s (%d->%d) at %lld "
81844 + "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n",
81845 + new_state != PM_SUSPEND_ON ? "sleep" : "wakeup",
81846 + requested_suspend_state, new_state,
81847 + ktime_to_ns(ktime_get()),
81848 + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
81849 + tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
81850 + }
81851 + if (!old_sleep && new_state != PM_SUSPEND_ON) {
81852 + state |= SUSPEND_REQUESTED;
81853 + queue_work(suspend_work_queue, &early_suspend_work);
81854 + } else if (old_sleep && new_state == PM_SUSPEND_ON) {
81855 + state &= ~SUSPEND_REQUESTED;
81856 + wake_lock(&main_wake_lock);
81857 + queue_work(suspend_work_queue, &late_resume_work);
81858 + }
81859 + requested_suspend_state = new_state;
81860 + spin_unlock_irqrestore(&state_lock, irqflags);
81861 +}
81862 +
81863 +suspend_state_t get_suspend_state(void)
81864 +{
81865 + return requested_suspend_state;
81866 +}
81867 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/fbearlysuspend.c linux-2.6.29-rc3.owrt.om/drivers/staging/android/fbearlysuspend.c
81868 --- linux-2.6.29-rc3.owrt/drivers/staging/android/fbearlysuspend.c 1970-01-01 01:00:00.000000000 +0100
81869 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/fbearlysuspend.c 2009-05-10 22:28:00.000000000 +0200
81870 @@ -0,0 +1,153 @@
81871 +/* kernel/power/fbearlysuspend.c
81872 + *
81873 + * Copyright (C) 2005-2008 Google, Inc.
81874 + *
81875 + * This software is licensed under the terms of the GNU General Public
81876 + * License version 2, as published by the Free Software Foundation, and
81877 + * may be copied, distributed, and modified under those terms.
81878 + *
81879 + * This program is distributed in the hope that it will be useful,
81880 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
81881 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
81882 + * GNU General Public License for more details.
81883 + *
81884 + */
81885 +
81886 +#include <linux/earlysuspend.h>
81887 +#include <linux/module.h>
81888 +#include <linux/wait.h>
81889 +
81890 +#include "power.h"
81891 +
81892 +static wait_queue_head_t fb_state_wq;
81893 +static DEFINE_SPINLOCK(fb_state_lock);
81894 +static enum {
81895 + FB_STATE_STOPPED_DRAWING,
81896 + FB_STATE_REQUEST_STOP_DRAWING,
81897 + FB_STATE_DRAWING_OK,
81898 +} fb_state;
81899 +
81900 +/* tell userspace to stop drawing, wait for it to stop */
81901 +static void stop_drawing_early_suspend(struct early_suspend *h)
81902 +{
81903 + int ret;
81904 + unsigned long irq_flags;
81905 +
81906 + spin_lock_irqsave(&fb_state_lock, irq_flags);
81907 + fb_state = FB_STATE_REQUEST_STOP_DRAWING;
81908 + spin_unlock_irqrestore(&fb_state_lock, irq_flags);
81909 +
81910 + wake_up_all(&fb_state_wq);
81911 + ret = wait_event_timeout(fb_state_wq,
81912 + fb_state == FB_STATE_STOPPED_DRAWING,
81913 + HZ);
81914 + if (unlikely(fb_state != FB_STATE_STOPPED_DRAWING))
81915 + pr_warning("stop_drawing_early_suspend: timeout waiting for "
81916 + "userspace to stop drawing\n");
81917 +}
81918 +
81919 +/* tell userspace to start drawing */
81920 +static void start_drawing_late_resume(struct early_suspend *h)
81921 +{
81922 + unsigned long irq_flags;
81923 +
81924 + spin_lock_irqsave(&fb_state_lock, irq_flags);
81925 + fb_state = FB_STATE_DRAWING_OK;
81926 + spin_unlock_irqrestore(&fb_state_lock, irq_flags);
81927 + wake_up(&fb_state_wq);
81928 +}
81929 +
81930 +static struct early_suspend stop_drawing_early_suspend_desc = {
81931 + .level = EARLY_SUSPEND_LEVEL_STOP_DRAWING,
81932 + .suspend = stop_drawing_early_suspend,
81933 + .resume = start_drawing_late_resume,
81934 +};
81935 +
81936 +static ssize_t wait_for_fb_sleep_show(struct kobject *kobj,
81937 + struct kobj_attribute *attr, char *buf)
81938 +{
81939 + char *s = buf;
81940 + int ret;
81941 +
81942 + ret = wait_event_interruptible(fb_state_wq,
81943 + fb_state != FB_STATE_DRAWING_OK);
81944 + if (ret && fb_state == FB_STATE_DRAWING_OK)
81945 + return ret;
81946 + else
81947 + s += sprintf(buf, "sleeping");
81948 + return s - buf;
81949 +}
81950 +
81951 +static ssize_t wait_for_fb_wake_show(struct kobject *kobj,
81952 + struct kobj_attribute *attr, char *buf)
81953 +{
81954 + char *s = buf;
81955 + int ret;
81956 + unsigned long irq_flags;
81957 +
81958 + spin_lock_irqsave(&fb_state_lock, irq_flags);
81959 + if (fb_state == FB_STATE_REQUEST_STOP_DRAWING) {
81960 + fb_state = FB_STATE_STOPPED_DRAWING;
81961 + wake_up(&fb_state_wq);
81962 + }
81963 + spin_unlock_irqrestore(&fb_state_lock, irq_flags);
81964 +
81965 + ret = wait_event_interruptible(fb_state_wq,
81966 + fb_state == FB_STATE_DRAWING_OK);
81967 + if (ret && fb_state != FB_STATE_DRAWING_OK)
81968 + return ret;
81969 + else
81970 + s += sprintf(buf, "awake");
81971 +
81972 + return s - buf;
81973 +}
81974 +
81975 +#define power_ro_attr(_name) \
81976 +static struct kobj_attribute _name##_attr = { \
81977 + .attr = { \
81978 + .name = __stringify(_name), \
81979 + .mode = 0444, \
81980 + }, \
81981 + .show = _name##_show, \
81982 + .store = NULL, \
81983 +}
81984 +
81985 +power_ro_attr(wait_for_fb_sleep);
81986 +power_ro_attr(wait_for_fb_wake);
81987 +
81988 +static struct attribute *g[] = {
81989 + &wait_for_fb_sleep_attr.attr,
81990 + &wait_for_fb_wake_attr.attr,
81991 + NULL,
81992 +};
81993 +
81994 +static struct attribute_group attr_group = {
81995 + .attrs = g,
81996 +};
81997 +
81998 +static int __init android_power_init(void)
81999 +{
82000 + int ret;
82001 +
82002 + init_waitqueue_head(&fb_state_wq);
82003 + fb_state = FB_STATE_DRAWING_OK;
82004 +
82005 + ret = sysfs_create_group(power_kobj, &attr_group);
82006 + if (ret) {
82007 + pr_err("android_power_init: sysfs_create_group failed\n");
82008 + return ret;
82009 + }
82010 +
82011 + register_early_suspend(&stop_drawing_early_suspend_desc);
82012 + return 0;
82013 +}
82014 +
82015 +static void __exit android_power_exit(void)
82016 +{
82017 + unregister_early_suspend(&stop_drawing_early_suspend_desc);
82018 + sysfs_remove_group(power_kobj, &attr_group);
82019 +}
82020 +
82021 +module_init(android_power_init);
82022 +module_exit(android_power_exit);
82023 +
82024 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/Kconfig linux-2.6.29-rc3.owrt.om/drivers/staging/android/Kconfig
82025 --- linux-2.6.29-rc3.owrt/drivers/staging/android/Kconfig 2009-05-10 22:08:44.000000000 +0200
82026 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/Kconfig 2009-05-10 22:28:00.000000000 +0200
82027 @@ -83,4 +83,80 @@
82028 ---help---
82029 Register processes to be killed when memory is low
82030
82031 +config ANDROID_HAS_WAKELOCK
82032 + bool
82033 +
82034 +config ANDROID_HAS_EARLYSUSPEND
82035 + bool
82036 +
82037 +config ANDROID_WAKELOCK
82038 + bool "Wake lock"
82039 + depends on PM && RTC_CLASS
82040 + default n
82041 + select ANDROID_HAS_WAKELOCK
82042 + ---help---
82043 + Enable wakelocks. When user space request a sleep state the
82044 + sleep request will be delayed until no wake locks are held.
82045 +
82046 +config ANDROID_WAKELOCK_STAT
82047 + bool "Wake lock stats"
82048 + depends on WAKELOCK
82049 + default y
82050 + ---help---
82051 + Report wake lock stats in /proc/wakelocks
82052 +
82053 +config ANDROID_USER_WAKELOCK
82054 + bool "Userspace wake locks"
82055 + depends on ANDROID_WAKELOCK
82056 + default y
82057 + ---help---
82058 + User-space wake lock api. Write "lockname" or "lockname timeout"
82059 + to /sys/power/wake_lock lock and if needed create a wake lock.
82060 + Write "lockname" to /sys/power/wake_unlock to unlock a user wake
82061 + lock.
82062 +
82063 +config ANDROID_EARLYSUSPEND
82064 + bool "Early suspend"
82065 + depends on ANDROID_WAKELOCK
82066 + default y
82067 + select ANDROID_HAS_EARLYSUSPEND
82068 + ---help---
82069 + Call early suspend handlers when the user requested sleep state
82070 + changes.
82071 +
82072 +choice
82073 + prompt "User-space screen access"
82074 + default ANDROID_FB_EARLYSUSPEND if !FRAMEBUFFER_CONSOLE
82075 + default ANDROID_CONSOLE_EARLYSUSPEND
82076 + depends on ANDROID_HAS_EARLYSUSPEND
82077 +
82078 + config NO_USER_SPACE_SCREEN_ACCESS_CONTROL
82079 + bool "None"
82080 +
82081 + config ANDROID_CONSOLE_EARLYSUSPEND
82082 + bool "Console switch on early-suspend"
82083 + depends on ANDROID_HAS_EARLYSUSPEND && VT
82084 + ---help---
82085 + Register early suspend handler to perform a console switch to
82086 + when user-space should stop drawing to the screen and a switch
82087 + back when it should resume.
82088 +
82089 + config ANDROID_FB_EARLYSUSPEND
82090 + bool "Sysfs interface"
82091 + depends on ANDROID_HAS_EARLYSUSPEND
82092 + ---help---
82093 + Register early suspend handler that notifies and waits for
82094 + user-space through sysfs when user-space should stop drawing
82095 + to the screen and notifies user-space when it should resume.
82096 +endchoice
82097 +
82098 +config ANDROID_POWER_ALARM
82099 + bool "Android alarm driver"
82100 + depends on ANDROID_WAKELOCK
82101 + default y
82102 +
82103 +config ANDROID_PARANOID_NETWORK
82104 + bool "Only allow certain groups to create sockets"
82105 + default y
82106 +
82107 endmenu
82108 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/Makefile linux-2.6.29-rc3.owrt.om/drivers/staging/android/Makefile
82109 --- linux-2.6.29-rc3.owrt/drivers/staging/android/Makefile 2009-05-10 22:04:48.000000000 +0200
82110 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/Makefile 2009-05-10 22:28:00.000000000 +0200
82111 @@ -3,3 +3,9 @@
82112 obj-$(CONFIG_ANDROID_RAM_CONSOLE) += ram_console.o
82113 obj-$(CONFIG_ANDROID_TIMED_GPIO) += timed_gpio.o
82114 obj-$(CONFIG_ANDROID_LOW_MEMORY_KILLER) += lowmemorykiller.o
82115 +obj-$(CONFIG_ANDROID_POWER_ALARM) += alarm.o
82116 +obj-$(CONFIG_ANDROID_WAKELOCK) += wakelock.o
82117 +obj-$(CONFIG_ANDROID_USER_WAKELOCK) += userwakelock.o
82118 +obj-$(CONFIG_ANDROID_EARLYSUSPEND) += earlysuspend.o
82119 +obj-$(CONFIG_ANDROID_CONSOLE_EARLYSUSPEND) += consoleearlysuspend.o
82120 +obj-$(CONFIG_ANDROID_FB_EARLYSUSPEND) += fbearlysuspend.o
82121 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/power.h linux-2.6.29-rc3.owrt.om/drivers/staging/android/power.h
82122 --- linux-2.6.29-rc3.owrt/drivers/staging/android/power.h 1970-01-01 01:00:00.000000000 +0100
82123 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/power.h 2009-05-10 22:28:00.000000000 +0200
82124 @@ -0,0 +1 @@
82125 +#include "../../../kernel/power/power.h"
82126 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/timed_gpio.c linux-2.6.29-rc3.owrt.om/drivers/staging/android/timed_gpio.c
82127 --- linux-2.6.29-rc3.owrt/drivers/staging/android/timed_gpio.c 2009-05-10 22:08:44.000000000 +0200
82128 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/timed_gpio.c 2009-05-10 22:28:00.000000000 +0200
82129 @@ -18,7 +18,7 @@
82130 #include <linux/platform_device.h>
82131 #include <linux/hrtimer.h>
82132 #include <linux/err.h>
82133 -#include <asm/arch/gpio.h>
82134 +#include <linux/gpio.h>
82135
82136 #include "timed_gpio.h"
82137
82138 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/userwakelock.c linux-2.6.29-rc3.owrt.om/drivers/staging/android/userwakelock.c
82139 --- linux-2.6.29-rc3.owrt/drivers/staging/android/userwakelock.c 1970-01-01 01:00:00.000000000 +0100
82140 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/userwakelock.c 2009-05-10 22:28:00.000000000 +0200
82141 @@ -0,0 +1,245 @@
82142 +/* kernel/power/userwakelock.c
82143 + *
82144 + * Copyright (C) 2005-2008 Google, Inc.
82145 + *
82146 + * This software is licensed under the terms of the GNU General Public
82147 + * License version 2, as published by the Free Software Foundation, and
82148 + * may be copied, distributed, and modified under those terms.
82149 + *
82150 + * This program is distributed in the hope that it will be useful,
82151 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
82152 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82153 + * GNU General Public License for more details.
82154 + *
82155 + */
82156 +
82157 +#include <linux/ctype.h>
82158 +#include <linux/module.h>
82159 +#include <linux/wakelock.h>
82160 +
82161 +#include "power.h"
82162 +
82163 +enum {
82164 + DEBUG_FAILURE = BIT(0),
82165 + DEBUG_ERROR = BIT(1),
82166 + DEBUG_NEW = BIT(2),
82167 + DEBUG_ACCESS = BIT(3),
82168 + DEBUG_LOOKUP = BIT(4),
82169 +};
82170 +static int debug_mask = DEBUG_FAILURE;
82171 +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
82172 +
82173 +static DEFINE_MUTEX(tree_lock);
82174 +
82175 +struct user_wake_lock {
82176 + struct rb_node node;
82177 + struct wake_lock wake_lock;
82178 + char name[0];
82179 +};
82180 +struct rb_root user_wake_locks;
82181 +
82182 +static struct user_wake_lock *lookup_wake_lock_name(
82183 + const char *buf, int allocate, long *timeoutptr)
82184 +{
82185 + struct rb_node **p = &user_wake_locks.rb_node;
82186 + struct rb_node *parent = NULL;
82187 + struct user_wake_lock *l;
82188 + int diff;
82189 + u64 timeout;
82190 + int name_len;
82191 + const char *arg;
82192 +
82193 + /* Find length of lock name and start of optional timeout string */
82194 + arg = buf;
82195 + while (*arg && !isspace(*arg))
82196 + arg++;
82197 + name_len = arg - buf;
82198 + if (!name_len)
82199 + goto bad_arg;
82200 + while (isspace(*arg))
82201 + arg++;
82202 +
82203 + /* Process timeout string */
82204 + if (timeoutptr && *arg) {
82205 + timeout = simple_strtoull(arg, (char **)&arg, 0);
82206 + while (isspace(*arg))
82207 + arg++;
82208 + if (*arg)
82209 + goto bad_arg;
82210 + /* convert timeout from nanoseconds to jiffies > 0 */
82211 + timeout += (NSEC_PER_SEC / HZ) - 1;
82212 + do_div(timeout, (NSEC_PER_SEC / HZ));
82213 + if (timeout <= 0)
82214 + timeout = 1;
82215 + *timeoutptr = timeout;
82216 + } else if (*arg)
82217 + goto bad_arg;
82218 + else if (timeoutptr)
82219 + *timeoutptr = 0;
82220 +
82221 + /* Lookup wake lock in rbtree */
82222 + while (*p) {
82223 + parent = *p;
82224 + l = rb_entry(parent, struct user_wake_lock, node);
82225 + diff = strncmp(buf, l->name, name_len);
82226 + if (!diff && l->name[name_len])
82227 + diff = -1;
82228 + if (debug_mask & DEBUG_ERROR)
82229 + pr_info("lookup_wake_lock_name: compare %.*s %s %d\n",
82230 + name_len, buf, l->name, diff);
82231 +
82232 + if (diff < 0)
82233 + p = &(*p)->rb_left;
82234 + else if (diff > 0)
82235 + p = &(*p)->rb_right;
82236 + else
82237 + return l;
82238 + }
82239 +
82240 + /* Allocate and add new wakelock to rbtree */
82241 + if (!allocate) {
82242 + if (debug_mask & DEBUG_ERROR)
82243 + pr_info("lookup_wake_lock_name: %.*s not found\n",
82244 + name_len, buf);
82245 + return ERR_PTR(-EINVAL);
82246 + }
82247 + l = kzalloc(sizeof(*l) + name_len + 1, GFP_KERNEL);
82248 + if (l == NULL) {
82249 + if (debug_mask & DEBUG_FAILURE)
82250 + pr_err("lookup_wake_lock_name: failed to allocate "
82251 + "memory for %.*s\n", name_len, buf);
82252 + return ERR_PTR(-ENOMEM);
82253 + }
82254 + memcpy(l->name, buf, name_len);
82255 + if (debug_mask & DEBUG_NEW)
82256 + pr_info("lookup_wake_lock_name: new wake lock %s\n", l->name);
82257 + wake_lock_init(&l->wake_lock, WAKE_LOCK_SUSPEND, l->name);
82258 + rb_link_node(&l->node, parent, p);
82259 + rb_insert_color(&l->node, &user_wake_locks);
82260 + return l;
82261 +
82262 +bad_arg:
82263 + if (debug_mask & DEBUG_ERROR)
82264 + pr_info("lookup_wake_lock_name: wake lock, %.*s, bad arg, %s\n",
82265 + name_len, buf, arg);
82266 + return ERR_PTR(-EINVAL);
82267 +}
82268 +
82269 +ssize_t wake_lock_show(
82270 + struct kobject *kobj, struct kobj_attribute *attr, char *buf)
82271 +{
82272 + char *s = buf;
82273 + char *end = buf + PAGE_SIZE;
82274 + struct rb_node *n;
82275 + struct user_wake_lock *l;
82276 +
82277 + mutex_lock(&tree_lock);
82278 +
82279 + for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
82280 + l = rb_entry(n, struct user_wake_lock, node);
82281 + if (wake_lock_active(&l->wake_lock))
82282 + s += scnprintf(s, end - s, "%s ", l->name);
82283 + }
82284 + s += scnprintf(s, end - s, "\n");
82285 +
82286 + mutex_unlock(&tree_lock);
82287 + return (s - buf);
82288 +}
82289 +
82290 +ssize_t wake_full_lock_store(
82291 + struct kobject *kobj, struct kobj_attribute *attr,
82292 + const char *buf, size_t n)
82293 +{
82294 + long timeout;
82295 + struct user_wake_lock *l;
82296 +
82297 + mutex_lock(&tree_lock);
82298 + l = lookup_wake_lock_name(buf, 1, &timeout);
82299 + if (IS_ERR(l)) {
82300 + n = PTR_ERR(l);
82301 + goto bad_name;
82302 + }
82303 +
82304 + if (debug_mask & DEBUG_ACCESS)
82305 + pr_info("wake_full_lock_store: %s, timeout %ld\n", l->name, timeout);
82306 +
82307 + if (timeout == 0)
82308 + timeout = INT_MAX;
82309 +
82310 + if (timeout)
82311 + wake_lock_timeout(&l->wake_lock, timeout);
82312 +bad_name:
82313 + mutex_unlock(&tree_lock);
82314 + return n;
82315 +}
82316 +
82317 +ssize_t wake_lock_store(
82318 + struct kobject *kobj, struct kobj_attribute *attr,
82319 + const char *buf, size_t n)
82320 +{
82321 + long timeout;
82322 + struct user_wake_lock *l;
82323 +
82324 + mutex_lock(&tree_lock);
82325 + l = lookup_wake_lock_name(buf, 1, &timeout);
82326 + if (IS_ERR(l)) {
82327 + n = PTR_ERR(l);
82328 + goto bad_name;
82329 + }
82330 +
82331 + if (debug_mask & DEBUG_ACCESS)
82332 + pr_info("wake_lock_store: %s, timeout %ld\n", l->name, timeout);
82333 +
82334 + if (timeout)
82335 + wake_lock_timeout(&l->wake_lock, timeout);
82336 + else
82337 + wake_lock(&l->wake_lock);
82338 +bad_name:
82339 + mutex_unlock(&tree_lock);
82340 + return n;
82341 +}
82342 +
82343 +
82344 +ssize_t wake_unlock_show(
82345 + struct kobject *kobj, struct kobj_attribute *attr, char *buf)
82346 +{
82347 + char *s = buf;
82348 + char *end = buf + PAGE_SIZE;
82349 + struct rb_node *n;
82350 + struct user_wake_lock *l;
82351 +
82352 + mutex_lock(&tree_lock);
82353 +
82354 + for (n = rb_first(&user_wake_locks); n != NULL; n = rb_next(n)) {
82355 + l = rb_entry(n, struct user_wake_lock, node);
82356 + if (!wake_lock_active(&l->wake_lock))
82357 + s += scnprintf(s, end - s, "%s ", l->name);
82358 + }
82359 + s += scnprintf(s, end - s, "\n");
82360 +
82361 + mutex_unlock(&tree_lock);
82362 + return (s - buf);
82363 +}
82364 +
82365 +ssize_t wake_unlock_store(
82366 + struct kobject *kobj, struct kobj_attribute *attr,
82367 + const char *buf, size_t n)
82368 +{
82369 + struct user_wake_lock *l;
82370 +
82371 + mutex_lock(&tree_lock);
82372 + l = lookup_wake_lock_name(buf, 0, NULL);
82373 + if (IS_ERR(l)) {
82374 + n = PTR_ERR(l);
82375 + goto not_found;
82376 + }
82377 +
82378 + if (debug_mask & DEBUG_ACCESS)
82379 + pr_info("wake_unlock_store: %s\n", l->name);
82380 +
82381 + wake_unlock(&l->wake_lock);
82382 +not_found:
82383 + mutex_unlock(&tree_lock);
82384 + return n;
82385 +}
82386 +
82387 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/staging/android/wakelock.c linux-2.6.29-rc3.owrt.om/drivers/staging/android/wakelock.c
82388 --- linux-2.6.29-rc3.owrt/drivers/staging/android/wakelock.c 1970-01-01 01:00:00.000000000 +0100
82389 +++ linux-2.6.29-rc3.owrt.om/drivers/staging/android/wakelock.c 2009-05-10 22:28:00.000000000 +0200
82390 @@ -0,0 +1,605 @@
82391 +/* kernel/power/wakelock.c
82392 + *
82393 + * Copyright (C) 2005-2008 Google, Inc.
82394 + *
82395 + * This software is licensed under the terms of the GNU General Public
82396 + * License version 2, as published by the Free Software Foundation, and
82397 + * may be copied, distributed, and modified under those terms.
82398 + *
82399 + * This program is distributed in the hope that it will be useful,
82400 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
82401 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
82402 + * GNU General Public License for more details.
82403 + *
82404 + */
82405 +
82406 +#include <linux/module.h>
82407 +#include <linux/platform_device.h>
82408 +#include <linux/rtc.h>
82409 +#include <linux/suspend.h>
82410 +#include <linux/syscalls.h> /* sys_sync */
82411 +#include <linux/wakelock.h>
82412 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82413 +#include <linux/proc_fs.h>
82414 +#endif
82415 +#include "power.h"
82416 +
82417 +enum {
82418 + DEBUG_EXIT_SUSPEND = 1U << 0,
82419 + DEBUG_WAKEUP = 1U << 1,
82420 + DEBUG_SUSPEND = 1U << 2,
82421 + DEBUG_EXPIRE = 1U << 3,
82422 + DEBUG_WAKE_LOCK = 1U << 4,
82423 +};
82424 +static int debug_mask = DEBUG_EXIT_SUSPEND | DEBUG_WAKEUP;
82425 +
82426 +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
82427 +
82428 +#define WAKE_LOCK_TYPE_MASK (0x0f)
82429 +#define WAKE_LOCK_INITIALIZED (1U << 8)
82430 +#define WAKE_LOCK_ACTIVE (1U << 9)
82431 +#define WAKE_LOCK_AUTO_EXPIRE (1U << 10)
82432 +#define WAKE_LOCK_PREVENTING_SUSPEND (1U << 11)
82433 +
82434 +static DEFINE_SPINLOCK(list_lock);
82435 +static LIST_HEAD(inactive_locks);
82436 +static struct list_head active_wake_locks[WAKE_LOCK_TYPE_COUNT];
82437 +static int current_event_num;
82438 +struct workqueue_struct *suspend_work_queue;
82439 +struct wake_lock main_wake_lock;
82440 +suspend_state_t requested_suspend_state = PM_SUSPEND_MEM;
82441 +static struct wake_lock unknown_wakeup;
82442 +
82443 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82444 +static struct wake_lock deleted_wake_locks;
82445 +static ktime_t last_sleep_time_update;
82446 +static int wait_for_wakeup;
82447 +
82448 +int get_expired_time(struct wake_lock *lock, ktime_t *expire_time)
82449 +{
82450 + struct timespec ts;
82451 + struct timespec kt;
82452 + struct timespec tomono;
82453 + struct timespec delta;
82454 + unsigned long seq;
82455 + long timeout;
82456 +
82457 + if (!(lock->flags & WAKE_LOCK_AUTO_EXPIRE))
82458 + return 0;
82459 + do {
82460 + seq = read_seqbegin(&xtime_lock);
82461 + timeout = lock->expires - jiffies;
82462 + if (timeout > 0)
82463 + return 0;
82464 + kt = current_kernel_time();
82465 + tomono = wall_to_monotonic;
82466 + } while (read_seqretry(&xtime_lock, seq));
82467 + jiffies_to_timespec(-timeout, &delta);
82468 + set_normalized_timespec(&ts, kt.tv_sec + tomono.tv_sec - delta.tv_sec,
82469 + kt.tv_nsec + tomono.tv_nsec - delta.tv_nsec);
82470 + *expire_time = timespec_to_ktime(ts);
82471 + return 1;
82472 +}
82473 +
82474 +
82475 +static int print_lock_stat(char *buf, struct wake_lock *lock)
82476 +{
82477 + int lock_count = lock->stat.count;
82478 + int expire_count = lock->stat.expire_count;
82479 + ktime_t active_time = ktime_set(0, 0);
82480 + ktime_t total_time = lock->stat.total_time;
82481 + ktime_t max_time = lock->stat.max_time;
82482 + ktime_t prevent_suspend_time = lock->stat.prevent_suspend_time;
82483 + if (lock->flags & WAKE_LOCK_ACTIVE) {
82484 + ktime_t now, add_time;
82485 + int expired = get_expired_time(lock, &now);
82486 + if (!expired)
82487 + now = ktime_get();
82488 + add_time = ktime_sub(now, lock->stat.last_time);
82489 + lock_count++;
82490 + if (!expired)
82491 + active_time = add_time;
82492 + else
82493 + expire_count++;
82494 + total_time = ktime_add(total_time, add_time);
82495 + if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND)
82496 + prevent_suspend_time = ktime_add(prevent_suspend_time,
82497 + ktime_sub(now, last_sleep_time_update));
82498 + if (add_time.tv64 > max_time.tv64)
82499 + max_time = add_time;
82500 + }
82501 +
82502 + return sprintf(buf, "\"%s\"\t%d\t%d\t%d\t%lld\t%lld\t%lld\t%lld\t"
82503 + "%lld\n", lock->name, lock_count, expire_count,
82504 + lock->stat.wakeup_count, ktime_to_ns(active_time),
82505 + ktime_to_ns(total_time),
82506 + ktime_to_ns(prevent_suspend_time), ktime_to_ns(max_time),
82507 + ktime_to_ns(lock->stat.last_time));
82508 +}
82509 +
82510 +
82511 +static int wakelocks_read_proc(char *page, char **start, off_t off,
82512 + int count, int *eof, void *data)
82513 +{
82514 + unsigned long irqflags;
82515 + struct wake_lock *lock;
82516 + int len = 0;
82517 + char *p = page;
82518 + int type;
82519 +
82520 + spin_lock_irqsave(&list_lock, irqflags);
82521 +
82522 + p += sprintf(p, "name\tcount\texpire_count\twake_count\tactive_since"
82523 + "\ttotal_time\tsleep_time\tmax_time\tlast_change\n");
82524 + list_for_each_entry(lock, &inactive_locks, link) {
82525 + p += print_lock_stat(p, lock);
82526 + }
82527 + for (type = 0; type < WAKE_LOCK_TYPE_COUNT; type++) {
82528 + list_for_each_entry(lock, &active_wake_locks[type], link)
82529 + p += print_lock_stat(p, lock);
82530 + }
82531 + spin_unlock_irqrestore(&list_lock, irqflags);
82532 +
82533 + *start = page + off;
82534 +
82535 + len = p - page;
82536 + if (len > off)
82537 + len -= off;
82538 + else
82539 + len = 0;
82540 +
82541 + return len < count ? len : count;
82542 +}
82543 +
82544 +static void wake_unlock_stat_locked(struct wake_lock *lock, int expired)
82545 +{
82546 + ktime_t duration;
82547 + ktime_t now;
82548 + if (!(lock->flags & WAKE_LOCK_ACTIVE))
82549 + return;
82550 + if (get_expired_time(lock, &now))
82551 + expired = 1;
82552 + else
82553 + now = ktime_get();
82554 + lock->stat.count++;
82555 + if (expired)
82556 + lock->stat.expire_count++;
82557 + duration = ktime_sub(now, lock->stat.last_time);
82558 + lock->stat.total_time = ktime_add(lock->stat.total_time, duration);
82559 + if (ktime_to_ns(duration) > ktime_to_ns(lock->stat.max_time))
82560 + lock->stat.max_time = duration;
82561 + lock->stat.last_time = ktime_get();
82562 + if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
82563 + duration = ktime_sub(now, last_sleep_time_update);
82564 + lock->stat.prevent_suspend_time = ktime_add(
82565 + lock->stat.prevent_suspend_time, duration);
82566 + lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
82567 + }
82568 +}
82569 +
82570 +static void update_sleep_wait_stats_locked(int done)
82571 +{
82572 + struct wake_lock *lock;
82573 + ktime_t now, etime, elapsed, add;
82574 + int expired;
82575 +
82576 + now = ktime_get();
82577 + elapsed = ktime_sub(now, last_sleep_time_update);
82578 + list_for_each_entry(lock, &active_wake_locks[WAKE_LOCK_SUSPEND], link) {
82579 + expired = get_expired_time(lock, &etime);
82580 + if (lock->flags & WAKE_LOCK_PREVENTING_SUSPEND) {
82581 + if (expired)
82582 + add = ktime_sub(etime, last_sleep_time_update);
82583 + else
82584 + add = elapsed;
82585 + lock->stat.prevent_suspend_time = ktime_add(
82586 + lock->stat.prevent_suspend_time, add);
82587 + }
82588 + if (done || expired)
82589 + lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
82590 + else
82591 + lock->flags |= WAKE_LOCK_PREVENTING_SUSPEND;
82592 + }
82593 + last_sleep_time_update = now;
82594 +}
82595 +#endif
82596 +
82597 +
82598 +static void expire_wake_lock(struct wake_lock *lock)
82599 +{
82600 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82601 + wake_unlock_stat_locked(lock, 1);
82602 +#endif
82603 + lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
82604 + list_del(&lock->link);
82605 + list_add(&lock->link, &inactive_locks);
82606 + if (debug_mask & (DEBUG_WAKE_LOCK | DEBUG_EXPIRE))
82607 + pr_info("expired wake lock %s\n", lock->name);
82608 +}
82609 +
82610 +static void print_active_locks(int type)
82611 +{
82612 + unsigned long irqflags;
82613 + struct wake_lock *lock;
82614 +
82615 + BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
82616 + spin_lock_irqsave(&list_lock, irqflags);
82617 + list_for_each_entry(lock, &active_wake_locks[type], link) {
82618 + if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
82619 + long timeout = lock->expires - jiffies;
82620 + if (timeout <= 0)
82621 + pr_info("wake lock %s, expired\n", lock->name);
82622 + else
82623 + pr_info("active wake lock %s, time left %ld\n",
82624 + lock->name, timeout);
82625 + } else
82626 + pr_info("active wake lock %s\n", lock->name);
82627 + }
82628 + spin_unlock_irqrestore(&list_lock, irqflags);
82629 +}
82630 +
82631 +static long has_wake_lock_locked(int type)
82632 +{
82633 + struct wake_lock *lock, *n;
82634 + long max_timeout = 0;
82635 +
82636 + BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
82637 + list_for_each_entry_safe(lock, n, &active_wake_locks[type], link) {
82638 + if (lock->flags & WAKE_LOCK_AUTO_EXPIRE) {
82639 + long timeout = lock->expires - jiffies;
82640 + if (timeout <= 0)
82641 + expire_wake_lock(lock);
82642 + else if (timeout > max_timeout)
82643 + max_timeout = timeout;
82644 + } else
82645 + return -1;
82646 + }
82647 + return max_timeout;
82648 +}
82649 +
82650 +long has_wake_lock(int type)
82651 +{
82652 + long ret;
82653 + unsigned long irqflags;
82654 + spin_lock_irqsave(&list_lock, irqflags);
82655 + ret = has_wake_lock_locked(type);
82656 + spin_unlock_irqrestore(&list_lock, irqflags);
82657 + return ret;
82658 +}
82659 +
82660 +static void suspend(struct work_struct *work)
82661 +{
82662 + int ret;
82663 + int entry_event_num;
82664 +
82665 + if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
82666 + if (debug_mask & DEBUG_SUSPEND)
82667 + pr_info("suspend: abort suspend\n");
82668 + return;
82669 + }
82670 +
82671 + entry_event_num = current_event_num;
82672 + sys_sync();
82673 + if (debug_mask & DEBUG_SUSPEND)
82674 + pr_info("suspend: enter suspend\n");
82675 + ret = pm_suspend(requested_suspend_state);
82676 + if (debug_mask & DEBUG_EXIT_SUSPEND) {
82677 + struct timespec ts;
82678 + struct rtc_time tm;
82679 + getnstimeofday(&ts);
82680 + rtc_time_to_tm(ts.tv_sec, &tm);
82681 + pr_info("suspend: exit suspend, ret = %d "
82682 + "(%d-%02d-%02d %02d:%02d:%02d.%09lu UTC)\n", ret,
82683 + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
82684 + tm.tm_hour, tm.tm_min, tm.tm_sec, ts.tv_nsec);
82685 + }
82686 + /* Openmoko needs more times to resume and a timeout is necessary
82687 + * in any case */
82688 + if (current_event_num == entry_event_num) {
82689 + if (debug_mask & DEBUG_SUSPEND)
82690 + pr_info("suspend: pm_suspend returned with no event\n");
82691 + wake_lock_timeout(&unknown_wakeup, HZ / 2);
82692 + } else {
82693 + /* create a temp lock to avoid autosuspend */
82694 + wake_lock_timeout(&unknown_wakeup, 5 * HZ);
82695 + }
82696 +}
82697 +
82698 +static DECLARE_WORK(suspend_work, suspend);
82699 +
82700 +static void expire_wake_locks(unsigned long data)
82701 +{
82702 + long has_lock;
82703 + unsigned long irqflags;
82704 + if (debug_mask & DEBUG_EXPIRE)
82705 + pr_info("expire_wake_locks: start\n");
82706 + if (debug_mask & DEBUG_SUSPEND)
82707 + print_active_locks(WAKE_LOCK_SUSPEND);
82708 + spin_lock_irqsave(&list_lock, irqflags);
82709 + has_lock = has_wake_lock_locked(WAKE_LOCK_SUSPEND);
82710 + if (debug_mask & DEBUG_EXPIRE)
82711 + pr_info("expire_wake_locks: done, has_lock %ld\n", has_lock);
82712 + if (has_lock == 0)
82713 + queue_work(suspend_work_queue, &suspend_work);
82714 + spin_unlock_irqrestore(&list_lock, irqflags);
82715 +}
82716 +static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);
82717 +
82718 +static int power_suspend_late(struct platform_device *pdev, pm_message_t state)
82719 +{
82720 + int ret = has_wake_lock(WAKE_LOCK_SUSPEND) ? -EAGAIN : 0;
82721 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82722 + wait_for_wakeup = 1;
82723 +#endif
82724 + if (debug_mask & DEBUG_SUSPEND)
82725 + pr_info("power_suspend_late return %d\n", ret);
82726 + return ret;
82727 +}
82728 +
82729 +static struct platform_driver power_driver = {
82730 + .driver.name = "power",
82731 + .suspend_late = power_suspend_late,
82732 +};
82733 +static struct platform_device power_device = {
82734 + .name = "power",
82735 +};
82736 +
82737 +void wake_lock_init(struct wake_lock *lock, int type, const char *name)
82738 +{
82739 + unsigned long irqflags = 0;
82740 +
82741 + if (name)
82742 + lock->name = name;
82743 + BUG_ON(!lock->name);
82744 +
82745 + if (debug_mask & DEBUG_WAKE_LOCK)
82746 + pr_info("wake_lock_init name=%s\n", lock->name);
82747 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82748 + lock->stat.count = 0;
82749 + lock->stat.expire_count = 0;
82750 + lock->stat.wakeup_count = 0;
82751 + lock->stat.total_time = ktime_set(0, 0);
82752 + lock->stat.prevent_suspend_time = ktime_set(0, 0);
82753 + lock->stat.max_time = ktime_set(0, 0);
82754 + lock->stat.last_time = ktime_set(0, 0);
82755 +#endif
82756 + lock->flags = (type & WAKE_LOCK_TYPE_MASK) | WAKE_LOCK_INITIALIZED;
82757 +
82758 + INIT_LIST_HEAD(&lock->link);
82759 + spin_lock_irqsave(&list_lock, irqflags);
82760 + list_add(&lock->link, &inactive_locks);
82761 + spin_unlock_irqrestore(&list_lock, irqflags);
82762 +}
82763 +EXPORT_SYMBOL(wake_lock_init);
82764 +
82765 +void wake_lock_destroy(struct wake_lock *lock)
82766 +{
82767 + unsigned long irqflags;
82768 + if (debug_mask & DEBUG_WAKE_LOCK)
82769 + pr_info("wake_lock_destroy name=%s\n", lock->name);
82770 + spin_lock_irqsave(&list_lock, irqflags);
82771 + lock->flags &= ~WAKE_LOCK_INITIALIZED;
82772 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82773 + if (lock->stat.count) {
82774 + deleted_wake_locks.stat.count += lock->stat.count;
82775 + deleted_wake_locks.stat.expire_count += lock->stat.expire_count;
82776 + deleted_wake_locks.stat.total_time =
82777 + ktime_add(deleted_wake_locks.stat.total_time,
82778 + lock->stat.total_time);
82779 + deleted_wake_locks.stat.prevent_suspend_time =
82780 + ktime_add(deleted_wake_locks.stat.prevent_suspend_time,
82781 + lock->stat.prevent_suspend_time);
82782 + deleted_wake_locks.stat.max_time =
82783 + ktime_add(deleted_wake_locks.stat.max_time,
82784 + lock->stat.max_time);
82785 + }
82786 +#endif
82787 + list_del(&lock->link);
82788 + spin_unlock_irqrestore(&list_lock, irqflags);
82789 +}
82790 +EXPORT_SYMBOL(wake_lock_destroy);
82791 +
82792 +static void wake_lock_internal(
82793 + struct wake_lock *lock, long timeout, int has_timeout)
82794 +{
82795 + int type;
82796 + unsigned long irqflags;
82797 + long expire_in;
82798 +
82799 + spin_lock_irqsave(&list_lock, irqflags);
82800 + type = lock->flags & WAKE_LOCK_TYPE_MASK;
82801 + BUG_ON(type >= WAKE_LOCK_TYPE_COUNT);
82802 + BUG_ON(!(lock->flags & WAKE_LOCK_INITIALIZED));
82803 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82804 + if (type == WAKE_LOCK_SUSPEND && wait_for_wakeup) {
82805 + if (debug_mask & DEBUG_WAKEUP)
82806 + pr_info("wakeup wake lock: %s\n", lock->name);
82807 + wait_for_wakeup = 0;
82808 + lock->stat.wakeup_count++;
82809 + }
82810 + if ((lock->flags & WAKE_LOCK_AUTO_EXPIRE) &&
82811 + (long)(lock->expires - jiffies) <= 0) {
82812 + wake_unlock_stat_locked(lock, 0);
82813 + lock->stat.last_time = ktime_get();
82814 + }
82815 +#endif
82816 + if (!(lock->flags & WAKE_LOCK_ACTIVE)) {
82817 + lock->flags |= WAKE_LOCK_ACTIVE;
82818 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82819 + lock->stat.last_time = ktime_get();
82820 +#endif
82821 + }
82822 + list_del(&lock->link);
82823 + if (has_timeout) {
82824 + if (debug_mask & DEBUG_WAKE_LOCK)
82825 + pr_info("wake_lock: %s, type %d, timeout %ld.%03lu\n",
82826 + lock->name, type, timeout / HZ,
82827 + (timeout % HZ) * MSEC_PER_SEC / HZ);
82828 + lock->expires = jiffies + timeout;
82829 + lock->flags |= WAKE_LOCK_AUTO_EXPIRE;
82830 + list_add_tail(&lock->link, &active_wake_locks[type]);
82831 + } else {
82832 + if (debug_mask & DEBUG_WAKE_LOCK)
82833 + pr_info("wake_lock: %s, type %d\n", lock->name, type);
82834 + lock->expires = LONG_MAX;
82835 + lock->flags &= ~WAKE_LOCK_AUTO_EXPIRE;
82836 + list_add(&lock->link, &active_wake_locks[type]);
82837 + }
82838 + if (type == WAKE_LOCK_SUSPEND) {
82839 + current_event_num++;
82840 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82841 + if (lock == &main_wake_lock)
82842 + update_sleep_wait_stats_locked(1);
82843 + else if (!wake_lock_active(&main_wake_lock))
82844 + update_sleep_wait_stats_locked(0);
82845 +#endif
82846 + if (has_timeout)
82847 + expire_in = has_wake_lock_locked(type);
82848 + else
82849 + expire_in = -1;
82850 + if (expire_in > 0) {
82851 + if (debug_mask & DEBUG_EXPIRE)
82852 + pr_info("wake_lock: %s, start expire timer, "
82853 + "%ld\n", lock->name, expire_in);
82854 + mod_timer(&expire_timer, jiffies + expire_in);
82855 + } else {
82856 + if (del_timer(&expire_timer))
82857 + if (debug_mask & DEBUG_EXPIRE)
82858 + pr_info("wake_lock: %s, stop expire timer\n",
82859 + lock->name);
82860 + if (expire_in == 0)
82861 + queue_work(suspend_work_queue, &suspend_work);
82862 + }
82863 + }
82864 + spin_unlock_irqrestore(&list_lock, irqflags);
82865 +}
82866 +
82867 +void wake_lock(struct wake_lock *lock)
82868 +{
82869 + wake_lock_internal(lock, 0, 0);
82870 +}
82871 +EXPORT_SYMBOL(wake_lock);
82872 +
82873 +void wake_lock_timeout(struct wake_lock *lock, long timeout)
82874 +{
82875 + wake_lock_internal(lock, timeout, 1);
82876 +}
82877 +EXPORT_SYMBOL(wake_lock_timeout);
82878 +
82879 +void wake_unlock(struct wake_lock *lock)
82880 +{
82881 + int type;
82882 + unsigned long irqflags;
82883 + spin_lock_irqsave(&list_lock, irqflags);
82884 + type = lock->flags & WAKE_LOCK_TYPE_MASK;
82885 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82886 + wake_unlock_stat_locked(lock, 0);
82887 +#endif
82888 + if (debug_mask & DEBUG_WAKE_LOCK)
82889 + pr_info("wake_unlock: %s\n", lock->name);
82890 + lock->flags &= ~(WAKE_LOCK_ACTIVE | WAKE_LOCK_AUTO_EXPIRE);
82891 + list_del(&lock->link);
82892 + list_add(&lock->link, &inactive_locks);
82893 + if (type == WAKE_LOCK_SUSPEND) {
82894 + long has_lock = has_wake_lock_locked(type);
82895 + if (has_lock > 0) {
82896 + if (debug_mask & DEBUG_EXPIRE)
82897 + pr_info("wake_unlock: %s, start expire timer, "
82898 + "%ld\n", lock->name, has_lock);
82899 + mod_timer(&expire_timer, jiffies + has_lock);
82900 + } else {
82901 + if (del_timer(&expire_timer))
82902 + if (debug_mask & DEBUG_EXPIRE)
82903 + pr_info("wake_unlock: %s, stop expire "
82904 + "timer\n", lock->name);
82905 + if (has_lock == 0)
82906 + queue_work(suspend_work_queue, &suspend_work);
82907 + }
82908 + if (lock == &main_wake_lock) {
82909 + if (debug_mask & DEBUG_SUSPEND)
82910 + print_active_locks(WAKE_LOCK_SUSPEND);
82911 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82912 + update_sleep_wait_stats_locked(0);
82913 +#endif
82914 + }
82915 + }
82916 + spin_unlock_irqrestore(&list_lock, irqflags);
82917 +}
82918 +EXPORT_SYMBOL(wake_unlock);
82919 +
82920 +int wake_lock_active(struct wake_lock *lock)
82921 +{
82922 + return !!(lock->flags & WAKE_LOCK_ACTIVE);
82923 +}
82924 +EXPORT_SYMBOL(wake_lock_active);
82925 +
82926 +static int __init wakelocks_init(void)
82927 +{
82928 + int ret;
82929 + int i;
82930 +
82931 + for (i = 0; i < ARRAY_SIZE(active_wake_locks); i++)
82932 + INIT_LIST_HEAD(&active_wake_locks[i]);
82933 +
82934 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82935 + wake_lock_init(&deleted_wake_locks, WAKE_LOCK_SUSPEND,
82936 + "deleted_wake_locks");
82937 +#endif
82938 + wake_lock_init(&main_wake_lock, WAKE_LOCK_SUSPEND, "main");
82939 + wake_lock(&main_wake_lock);
82940 + wake_lock_init(&unknown_wakeup, WAKE_LOCK_SUSPEND, "unknown_wakeups");
82941 +
82942 + ret = platform_device_register(&power_device);
82943 + if (ret) {
82944 + pr_err("wakelocks_init: platform_device_register failed\n");
82945 + goto err_platform_device_register;
82946 + }
82947 + ret = platform_driver_register(&power_driver);
82948 + if (ret) {
82949 + pr_err("wakelocks_init: platform_driver_register failed\n");
82950 + goto err_platform_driver_register;
82951 + }
82952 +
82953 + suspend_work_queue = create_singlethread_workqueue("suspend");
82954 + if (suspend_work_queue == NULL) {
82955 + ret = -ENOMEM;
82956 + goto err_suspend_work_queue;
82957 + }
82958 +
82959 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82960 + create_proc_read_entry("wakelocks", S_IRUGO, NULL,
82961 + wakelocks_read_proc, NULL);
82962 +#endif
82963 +
82964 + return 0;
82965 +
82966 +err_suspend_work_queue:
82967 + platform_driver_unregister(&power_driver);
82968 +err_platform_driver_register:
82969 + platform_device_unregister(&power_device);
82970 +err_platform_device_register:
82971 + wake_lock_destroy(&unknown_wakeup);
82972 + wake_lock_destroy(&main_wake_lock);
82973 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82974 + wake_lock_destroy(&deleted_wake_locks);
82975 +#endif
82976 + return ret;
82977 +}
82978 +
82979 +static void __exit wakelocks_exit(void)
82980 +{
82981 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82982 + remove_proc_entry("wakelocks", NULL);
82983 +#endif
82984 + destroy_workqueue(suspend_work_queue);
82985 + platform_driver_unregister(&power_driver);
82986 + platform_device_unregister(&power_device);
82987 + wake_lock_destroy(&unknown_wakeup);
82988 + wake_lock_destroy(&main_wake_lock);
82989 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82990 + wake_lock_destroy(&deleted_wake_locks);
82991 +#endif
82992 +}
82993 +
82994 +core_initcall(wakelocks_init);
82995 +module_exit(wakelocks_exit);
82996 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/composite.c linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/composite.c
82997 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/composite.c 2009-05-10 22:04:48.000000000 +0200
82998 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/composite.c 2009-05-10 22:28:00.000000000 +0200
82999 @@ -1046,7 +1046,11 @@
83000 /*-------------------------------------------------------------------------*/
83001
83002 static struct usb_gadget_driver composite_driver = {
83003 +#ifdef CONFIG_USB_GADGET_DUALSPEED
83004 .speed = USB_SPEED_HIGH,
83005 +#else
83006 + .speed = USB_SPEED_FULL,
83007 +#endif
83008
83009 .bind = composite_bind,
83010 .unbind = __exit_p(composite_unbind),
83011 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/epautoconf.c linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/epautoconf.c
83012 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/epautoconf.c 2009-05-10 22:04:48.000000000 +0200
83013 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/epautoconf.c 2009-05-10 22:28:00.000000000 +0200
83014 @@ -275,6 +275,18 @@
83015 ep = find_ep (gadget, "ep1-bulk");
83016 if (ep && ep_matches (gadget, ep, desc))
83017 return ep;
83018 + } else if (gadget_is_s3c64xx(gadget)) {
83019 + if (USB_ENDPOINT_XFER_INT == type) {
83020 + /* single buffering is enough */
83021 + ep = find_ep(gadget, "ep3-int");
83022 + if (ep && ep_matches(gadget, ep, desc))
83023 + return ep;
83024 + } else if (USB_ENDPOINT_XFER_BULK == type
83025 + && (USB_DIR_IN & desc->bEndpointAddress)) {
83026 + ep = find_ep(gadget, "ep2-bulk");
83027 + if (ep && ep_matches(gadget, ep, desc))
83028 + return ep;
83029 + }
83030 }
83031
83032 /* Second, look at endpoints until an unclaimed one looks usable */
83033 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/ether.c linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/ether.c
83034 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/ether.c 2009-05-10 22:04:48.000000000 +0200
83035 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/ether.c 2009-05-10 22:28:00.000000000 +0200
83036 @@ -122,11 +122,16 @@
83037 * Instead: allocate your own, using normal USB-IF procedures.
83038 */
83039
83040 +#if 0
83041 /* Thanks to NetChip Technologies for donating this product ID.
83042 * It's for devices with only CDC Ethernet configurations.
83043 */
83044 #define CDC_VENDOR_NUM 0x0525 /* NetChip */
83045 #define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */
83046 +#else
83047 +#define CDC_VENDOR_NUM 0x1457 /* First International Computer */
83048 +#define CDC_PRODUCT_NUM 0x5117 /* Linux-USB Ethernet Gadget */
83049 +#endif
83050
83051 /* For hardware that can't talk CDC, we use the same vendor ID that
83052 * ARM Linux has used for ethernet-over-usb, both with sa1100 and
83053 @@ -147,8 +152,8 @@
83054 * used with CDC Ethernet, Linux 2.4 hosts will need updates to choose
83055 * the non-RNDIS configuration.
83056 */
83057 -#define RNDIS_VENDOR_NUM 0x0525 /* NetChip */
83058 -#define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */
83059 +#define RNDIS_VENDOR_NUM 0x1457 /* NetChip */
83060 +#define RNDIS_PRODUCT_NUM 0x5122 /* Ethernet/RNDIS Gadget */
83061
83062 /*-------------------------------------------------------------------------*/
83063
83064 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/f_rndis.c linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/f_rndis.c
83065 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/f_rndis.c 2009-05-10 22:04:48.000000000 +0200
83066 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/f_rndis.c 2009-05-10 22:28:00.000000000 +0200
83067 @@ -437,7 +437,8 @@
83068 DBG(cdev, "rndis req%02x.%02x v%04x i%04x l%d\n",
83069 ctrl->bRequestType, ctrl->bRequest,
83070 w_value, w_index, w_length);
83071 - req->zero = 0;
83072 + req->zero = value < w_length
83073 + && (value % cdev->gadget->ep0->maxpacket) == 0;
83074 req->length = value;
83075 value = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC);
83076 if (value < 0)
83077 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/gadget_chips.h linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/gadget_chips.h
83078 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/gadget_chips.h 2009-05-10 22:04:48.000000000 +0200
83079 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/gadget_chips.h 2009-05-10 22:28:00.000000000 +0200
83080 @@ -104,6 +104,12 @@
83081 #define gadget_is_s3c2410(g) 0
83082 #endif
83083
83084 +#ifdef CONFIG_USB_GADGET_S3C_OTGD_HS
83085 +#define gadget_is_s3c64xx(g) !strcmp("s3c-otg-device", (g)->name)
83086 +#else
83087 +#define gadget_is_s3c64xx(g) 0
83088 +#endif
83089 +
83090 #ifdef CONFIG_USB_GADGET_AT91
83091 #define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
83092 #else
83093 @@ -231,6 +237,8 @@
83094 return 0x22;
83095 else if (gadget_is_ci13xxx(gadget))
83096 return 0x23;
83097 + else if (gadget_is_s3c64xx(gadget))
83098 + return 0x24;
83099 return -ENOENT;
83100 }
83101
83102 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/Kconfig linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/Kconfig
83103 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/Kconfig 2009-05-10 22:08:45.000000000 +0200
83104 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/Kconfig 2009-05-10 22:28:00.000000000 +0200
83105 @@ -291,6 +291,22 @@
83106 boolean "S3C2410 udc debug messages"
83107 depends on USB_GADGET_S3C2410
83108
83109 +config USB_GADGET_S3C_OTGD_HS
83110 + boolean "S3C high speed(2.0, dual-speed) USB OTG device"
83111 + depends on (CPU_S3C6400 || CPU_S3C6410)
83112 + select USB_GADGET_SELECTED
83113 + select USB_GADGET_DUALSPEED
83114 + help
83115 + Say "y" to link the driver statically, or "m" to build a
83116 + dynamically linked module called "s3c_udc_hs" and force all
83117 + gadget drivers to also be dynamically linked.
83118 +
83119 +config USB_S3C
83120 + tristate
83121 + depends on USB_GADGET_S3C_FS && USB_GADGET_S3C_HS && USB_GADGET_S3C_OTGD_HS
83122 + default USB_GADGET
83123 + select USB_GADGET_SELECTED
83124 +
83125 #
83126 # Controllers available in both integrated and discrete versions
83127 #
83128 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/Makefile linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/Makefile
83129 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/Makefile 2009-05-10 22:04:48.000000000 +0200
83130 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/Makefile 2009-05-10 22:28:00.000000000 +0200
83131 @@ -19,6 +19,7 @@
83132 obj-$(CONFIG_USB_ATMEL_USBA) += atmel_usba_udc.o
83133 obj-$(CONFIG_USB_FSL_USB2) += fsl_usb2_udc.o
83134 obj-$(CONFIG_USB_M66592) += m66592-udc.o
83135 +obj-$(CONFIG_USB_GADGET_S3C_OTGD_HS) += s3c_hs_otg.o
83136 obj-$(CONFIG_USB_FSL_QE) += fsl_qe_udc.o
83137 obj-$(CONFIG_USB_CI13XXX) += ci13xxx_udc.o
83138
83139 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/s3c2410_udc.c linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/s3c2410_udc.c
83140 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/s3c2410_udc.c 2009-05-10 22:04:48.000000000 +0200
83141 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/s3c2410_udc.c 2009-05-10 22:28:00.000000000 +0200
83142 @@ -134,6 +134,8 @@
83143 return 0;
83144 }
83145 #endif
83146 +
83147 +#ifdef CONFIG_USB_GADGET_DEBUG_FS
83148 static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
83149 {
83150 u32 addr_reg,pwr_reg,ep_int_reg,usb_int_reg;
83151 @@ -197,6 +199,7 @@
83152 .release = single_release,
83153 .owner = THIS_MODULE,
83154 };
83155 +#endif
83156
83157 /* io macros */
83158
83159 @@ -843,6 +846,7 @@
83160 u32 ep_csr1;
83161 u32 idx;
83162
83163 +handle_ep_again:
83164 if (likely (!list_empty(&ep->queue)))
83165 req = list_entry(ep->queue.next,
83166 struct s3c2410_request, queue);
83167 @@ -882,6 +886,8 @@
83168
83169 if ((ep_csr1 & S3C2410_UDC_OCSR1_PKTRDY) && req) {
83170 s3c2410_udc_read_fifo(ep,req);
83171 + if (s3c2410_udc_fifo_count_out())
83172 + goto handle_ep_again;
83173 }
83174 }
83175 }
83176 @@ -1707,6 +1713,7 @@
83177 if (driver->disconnect)
83178 driver->disconnect(&udc->gadget);
83179
83180 + driver->unbind(&udc->gadget);
83181 device_del(&udc->gadget.dev);
83182 udc->driver = NULL;
83183
83184 @@ -1897,6 +1904,7 @@
83185 udc->vbus = 1;
83186 }
83187
83188 +#ifdef CONFIG_USB_GADGET_DEBUG_FS
83189 if (s3c2410_udc_debugfs_root) {
83190 udc->regs_info = debugfs_create_file("registers", S_IRUGO,
83191 s3c2410_udc_debugfs_root,
83192 @@ -1904,6 +1912,7 @@
83193 if (!udc->regs_info)
83194 dev_warn(dev, "debugfs file creation failed\n");
83195 }
83196 +#endif
83197
83198 dev_dbg(dev, "probe ok\n");
83199
83200 @@ -2013,12 +2022,14 @@
83201
83202 dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
83203
83204 +#ifdef CONFIG_USB_GADGET_DEBUG_FS
83205 s3c2410_udc_debugfs_root = debugfs_create_dir(gadget_name, NULL);
83206 if (IS_ERR(s3c2410_udc_debugfs_root)) {
83207 printk(KERN_ERR "%s: debugfs dir creation failed %ld\n",
83208 gadget_name, PTR_ERR(s3c2410_udc_debugfs_root));
83209 s3c2410_udc_debugfs_root = NULL;
83210 }
83211 +#endif
83212
83213 retval = platform_driver_register(&udc_driver_2410);
83214 if (retval)
83215 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/s3c_hs_otg.c linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/s3c_hs_otg.c
83216 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/s3c_hs_otg.c 1970-01-01 01:00:00.000000000 +0100
83217 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/s3c_hs_otg.c 2009-05-10 22:28:00.000000000 +0200
83218 @@ -0,0 +1,1874 @@
83219 +/*
83220 + * drivers/usb/gadget/s3c_hs_otg.c
83221 + * Samsung S3C on-chip full/high speed USB OTG 2.0 device controllers
83222 + *
83223 + * Copyright (C) 2008 Samsung Electronics
83224 + * Minkyu Kang <mk7.kang@samsung.com>
83225 + *
83226 + * This program is free software; you can redistribute it and/or modify
83227 + * it under the terms of the GNU General Public License as published by
83228 + * the Free Software Foundation; either version 2 of the License, or
83229 + * (at your option) any later version.
83230 + *
83231 + * This program is distributed in the hope that it will be useful,
83232 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
83233 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
83234 + * GNU General Public License for more details.
83235 + *
83236 + * You should have received a copy of the GNU General Public License
83237 + * along with this program; if not, write to the Free Software
83238 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
83239 + *
83240 + */
83241 +
83242 +#include "s3c-udc.h"
83243 +#include <linux/platform_device.h>
83244 +#include <linux/clk.h>
83245 +#include <mach/map.h>
83246 +#include <plat/regs-clock.h>
83247 +#include <plat/regs-usb-hs-otg.h>
83248 +#include <plat/regs-sys.h>
83249 +#include <plat/devs.h>
83250 +
83251 +static char *state_names[] = {
83252 + "WAIT_FOR_SETUP",
83253 + "DATA_STATE_XMIT",
83254 + "DATA_STATE_NEED_ZLP",
83255 + "WAIT_FOR_OUT_STATUS",
83256 + "DATA_STATE_RECV"
83257 +};
83258 +
83259 +#define S3C_USB_DBG_LEVEL 0
83260 +
83261 +#define DBG(level, fmt, args...) do { \
83262 + if (level >= S3C_USB_DBG_LEVEL) { \
83263 + printk(KERN_INFO "[%s] " fmt, \
83264 + __func__, ##args); \
83265 + } } while (0)
83266 +
83267 +
83268 +#define DRIVER_DESC "Samsung Dual-speed USB 2.0 OTG Device Controller"
83269 +#define DRIVER_AUTHOR "Samsung Electronics"
83270 +#define DRIVER_VERSION "04 Dec 2008"
83271 +
83272 +
83273 +struct s3c_udc *the_controller;
83274 +
83275 +static const char driver_name[] = "s3c-otg-device";
83276 +static const char driver_desc[] = DRIVER_DESC;
83277 +static const char ep0name[] = "ep0-control";
83278 +
83279 +static u32 tx_ep_num = 2;
83280 +
83281 +static u32 ep0_fifo_size = EP0_FIFO_SIZE;
83282 +static u32 ep_fifo_size = EP_FIFO_SIZE;
83283 +static u32 ep_fifo_size2 = EP_FIFO_SIZE2;
83284 +
83285 +struct usb_ctrlrequest ctrl;
83286 +static int reset_available = 1;
83287 +
83288 +#ifdef CONFIG_USB_GADGET_DEBUG_FILES
83289 +
83290 +static const char proc_node_name[] = "driver/otg";
83291 +
83292 +static int
83293 +udc_proc_read(char *page, char **start, off_t off, int count,
83294 + int *eof, void *_dev)
83295 +{
83296 + char *buf = page;
83297 + struct s3c_udc *dev = _dev;
83298 + char *next = buf;
83299 + unsigned size = count;
83300 + unsigned long flags;
83301 + int t;
83302 +
83303 + if (off != 0)
83304 + return 0;
83305 +
83306 + local_irq_save(flags);
83307 +
83308 + /* basic device status */
83309 + t = scnprintf(next, size,
83310 + DRIVER_DESC "\n"
83311 + "%s version: %s\n"
83312 + "Gadget driver: %s\n"
83313 + "\n",
83314 + driver_name, DRIVER_VERSION,
83315 + dev->driver ? dev->driver->driver.name : "(none)");
83316 + size -= t;
83317 + next += t;
83318 +
83319 + local_irq_restore(flags);
83320 + *eof = 1;
83321 + return count - size;
83322 +}
83323 +
83324 +#define create_proc_files() \
83325 + create_proc_read_entry(proc_node_name, 0, NULL, udc_proc_read, dev)
83326 +#define remove_proc_files() \
83327 + remove_proc_entry(proc_node_name, NULL)
83328 +
83329 +#else /* !CONFIG_USB_GADGET_DEBUG_FILES */
83330 +
83331 +#define create_proc_files() do {} while (0)
83332 +#define remove_proc_files() do {} while (0)
83333 +
83334 +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
83335 +
83336 +
83337 +static u32 s3c_otg_readl(struct s3c_udc *dev, u32 reg)
83338 +{
83339 + return __raw_readl((u32)dev->reg_base + reg);
83340 +}
83341 +
83342 +static void s3c_otg_writel(struct s3c_udc *dev, u32 val, u32 reg)
83343 +{
83344 + __raw_writel(val, ((u32)dev->reg_base) + reg);
83345 +}
83346 +
83347 +static void s3c_otg_orl(struct s3c_udc *dev, u32 val, u32 reg)
83348 +{
83349 + u32 temp = __raw_readl(((u32)dev->reg_base) + reg);
83350 +
83351 + __raw_writel(val|temp, ((u32)dev->reg_base) + reg);
83352 +}
83353 +
83354 +/*
83355 + * retire a request
83356 + */
83357 +static void s3c_otg_done(struct s3c_ep *ep, struct s3c_request *req, int status)
83358 +{
83359 + unsigned int stopped = ep->stopped;
83360 +
83361 + DBG(1, "%s %p, stopped = %d\n", ep->ep.name, ep, stopped);
83362 + list_del_init(&req->queue);
83363 +
83364 + if (req->req.status == -EINPROGRESS)
83365 + req->req.status = status;
83366 + else
83367 + status = req->req.status;
83368 +
83369 + if (status && (status != -ESHUTDOWN))
83370 + DBG(2, "complete %s stat %d len %u/%u\n",
83371 + ep->ep.name, status, req->req.actual, req->req.length);
83372 +
83373 + /* don't modify queue heads during completion callback */
83374 + ep->stopped = 1;
83375 +
83376 + spin_unlock(&ep->dev->lock);
83377 + req->req.complete(&ep->ep, &req->req);
83378 + spin_lock(&ep->dev->lock);
83379 +
83380 + ep->stopped = stopped;
83381 +}
83382 +
83383 +/*
83384 + * dequeue ALL requests
83385 + */
83386 +void s3c_otg_nuke(struct s3c_ep *ep, int status)
83387 +{
83388 + struct s3c_request *req;
83389 +
83390 + DBG(1, "%s %p\n", ep->ep.name, ep);
83391 +
83392 + /* called with irqs blocked */
83393 + while (!list_empty(&ep->queue)) {
83394 + req = list_entry(ep->queue.next, struct s3c_request, queue);
83395 + s3c_otg_done(ep, req, status);
83396 + }
83397 +}
83398 +
83399 +static void s3c_otg_ep_control(int ep, int dir, u32 val, int update)
83400 +{
83401 + u32 epctrl;
83402 +
83403 + switch (ep) {
83404 + case 0:
83405 + if (dir)
83406 + epctrl = (u32)S3C_UDC_OTG_DIEPCTL0;
83407 + else
83408 + epctrl = (u32)S3C_UDC_OTG_DOEPCTL0;
83409 + break;
83410 + case 1:
83411 + if (dir)
83412 + epctrl = -EOPNOTSUPP;
83413 + else
83414 + epctrl = (u32)S3C_UDC_OTG_DOEPCTL1;
83415 + break;
83416 + case 2:
83417 + if (dir)
83418 + epctrl = (u32)S3C_UDC_OTG_DIEPCTL2;
83419 + else
83420 + epctrl = -EOPNOTSUPP;
83421 + break;
83422 + case 3:
83423 + if (dir)
83424 + epctrl = (u32)S3C_UDC_OTG_DIEPCTL3;
83425 + else
83426 + epctrl = -EOPNOTSUPP;
83427 + break;
83428 + default:
83429 + DBG(3, "ep%d is unused Endpoint", ep);
83430 + return;
83431 + }
83432 +
83433 + if (epctrl < 0) {
83434 + DBG(3, "ep%d - %s is invalid direction\n",
83435 + ep, dir ? "IN" : "OUT");
83436 + return;
83437 + }
83438 +
83439 + if (update)
83440 + s3c_otg_orl(the_controller, val, epctrl);
83441 + else
83442 + s3c_otg_writel(the_controller, val, epctrl);
83443 +}
83444 +
83445 +static int s3c_otg_write_packet(struct s3c_ep *ep,
83446 + struct s3c_request *req, int max)
83447 +{
83448 + u32 *buf;
83449 + int length;
83450 + int count;
83451 + u32 fifo = ep->fifo;
83452 + u32 epsize;
83453 +
83454 + buf = req->req.buf + req->req.actual;
83455 + prefetch(buf);
83456 +
83457 + length = req->req.length - req->req.actual;
83458 + length = min(length, max);
83459 + req->req.actual += length;
83460 +
83461 + DBG(1, "%s: %d/%d, fifo=0x%x\n", ep->ep.name, length, max, fifo);
83462 +
83463 + switch (ep_index(ep)) {
83464 + case 0:
83465 + epsize = (u32)S3C_UDC_OTG_DIEPTSIZ0;
83466 + break;
83467 + case 2:
83468 + epsize = (u32)S3C_UDC_OTG_DIEPTSIZ2;
83469 + break;
83470 + case 3:
83471 + epsize = (u32)S3C_UDC_OTG_DIEPTSIZ3;
83472 + break;
83473 + default:
83474 + DBG(3, "ep%d is unused Endpoint", ep_index(ep));
83475 + return 0;
83476 + }
83477 +
83478 + s3c_otg_writel(ep->dev, PKT_CNT(0x1)|XFERSIZE(length), epsize);
83479 + s3c_otg_ep_control(ep_index(ep), USB_DIR_IN,
83480 + DEPCTL_EPENA|DEPCTL_CNAK, 1);
83481 +
83482 + for (count = 0; count < length; count += 4)
83483 + s3c_otg_writel(ep->dev, *buf++, fifo);
83484 +
83485 + return length;
83486 +}
83487 +
83488 +static int s3c_otg_write_fifo_ep0(struct s3c_ep *ep, struct s3c_request *req)
83489 +{
83490 + u32 max;
83491 + unsigned count;
83492 + int is_last;
83493 +
83494 + max = ep_maxpacket(ep);
83495 + count = s3c_otg_write_packet(ep, req, max);
83496 +
83497 + /* last packet is usually short (or a zlp) */
83498 + if (count != max) {
83499 + is_last = 1;
83500 + } else {
83501 + if ((req->req.length != req->req.actual) || req->req.zero)
83502 + is_last = 0;
83503 + else
83504 + is_last = 1;
83505 + }
83506 +
83507 + DBG(2, "wrote %s %d bytes%s %d left %p\n",
83508 + ep->ep.name, count, is_last ? "/L" : "",
83509 + req->req.length - req->req.actual, req);
83510 +
83511 + /* requests complete when all IN data is in the FIFO */
83512 + return is_last;
83513 +}
83514 +
83515 +static int s3c_otg_read_fifo_ep0(struct s3c_ep *ep, struct s3c_request *req)
83516 +{
83517 + u32 csr;
83518 + u32 *buf;
83519 + unsigned bufferspace;
83520 + unsigned count;
83521 + unsigned is_short;
83522 + unsigned bytes;
83523 + u32 fifo = ep->fifo;
83524 +
83525 + csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GRXSTSP);
83526 + bytes = BYTE_COUNT(csr);
83527 +
83528 + buf = req->req.buf + req->req.actual;
83529 + prefetchw(buf);
83530 + bufferspace = req->req.length - req->req.actual;
83531 +
83532 + /* read all bytes from this packet */
83533 + if (EP_NUM(csr) == 0) {
83534 + count = bytes / 4 + (bytes % 4 ? 1 : 0);
83535 + req->req.actual += min(bytes, bufferspace);
83536 + } else {
83537 + count = 0;
83538 + bytes = 0;
83539 + }
83540 +
83541 + is_short = (bytes < ep->ep.maxpacket);
83542 +
83543 + DBG(2, "read %s %d bytes%s %d/%d\n",
83544 + ep->ep.name, bytes, is_short ? "/S" : "",
83545 + req->req.actual, req->req.length);
83546 +
83547 + while (count--) {
83548 + u32 byte = s3c_otg_readl(ep->dev, fifo);
83549 +
83550 + if (unlikely(bufferspace == 0)) {
83551 + /* this happens when the driver's buffer
83552 + * is smaller than what the host sent.
83553 + * discard the extra data.
83554 + */
83555 + if (req->req.status != -EOVERFLOW)
83556 + DBG(3, "%s overflow %d\n", ep->ep.name, count);
83557 + req->req.status = -EOVERFLOW;
83558 + } else {
83559 + *buf++ = byte;
83560 + bufferspace -= 4;
83561 + }
83562 + }
83563 +
83564 + /* completion */
83565 + if (is_short || req->req.actual == req->req.length)
83566 + return 1;
83567 +
83568 + return 0;
83569 +}
83570 +
83571 +static int s3c_otg_write_ep0(struct s3c_udc *dev)
83572 +{
83573 + struct s3c_request *req;
83574 + struct s3c_ep *ep = &dev->ep[0];
83575 + int ret;
83576 + int need_zlp = 0;
83577 +
83578 + if (list_empty(&ep->queue))
83579 + req = NULL;
83580 + else
83581 + req = list_entry(ep->queue.next, struct s3c_request, queue);
83582 +
83583 + if (!req) {
83584 + DBG(2, "NULL REQ\n");
83585 + return 0;
83586 + }
83587 +
83588 + DBG(2, "length = 0x%x, actual = 0x%x\n",
83589 + req->req.length, req->req.actual);
83590 +
83591 + if (req->req.length == 0) {
83592 + dev->ep0state = WAIT_FOR_SETUP;
83593 + s3c_otg_done(ep, req, 0);
83594 + return 1;
83595 + }
83596 +
83597 + /* Next write will end with the packet size, */
83598 + /* so we need Zero-length-packet */
83599 + if (req->req.length - req->req.actual == ep0_fifo_size)
83600 + need_zlp = 1;
83601 +
83602 + ret = s3c_otg_write_fifo_ep0(ep, req);
83603 +
83604 + if ((ret == 1) && !need_zlp) {
83605 + /* Last packet */
83606 + DBG(1, "finished, waiting for status\n");
83607 + dev->ep0state = WAIT_FOR_SETUP;
83608 + }
83609 +
83610 + if (need_zlp) {
83611 + DBG(1, "Need ZLP!\n");
83612 + dev->ep0state = DATA_STATE_NEED_ZLP;
83613 + }
83614 +
83615 + if (ret)
83616 + s3c_otg_done(ep, req, 0);
83617 +
83618 + return ret;
83619 +}
83620 +
83621 +static int first_time = 1;
83622 +
83623 +static int s3c_otg_read_ep0(struct s3c_udc *dev)
83624 +{
83625 + struct s3c_request *req;
83626 + struct s3c_ep *ep = &dev->ep[0];
83627 + int ret;
83628 +
83629 + if (!list_empty(&ep->queue))
83630 + req = list_entry(ep->queue.next, struct s3c_request, queue);
83631 + else {
83632 + DBG(3, "---> BUG\n");
83633 + BUG();
83634 + return 0;
83635 + }
83636 +
83637 + DBG(2, "length = 0x%x, actual = 0x%x\n",
83638 + req->req.length, req->req.actual);
83639 +
83640 + if (req->req.length == 0) {
83641 + dev->ep0state = WAIT_FOR_SETUP;
83642 + first_time = 1;
83643 + s3c_otg_done(ep, req, 0);
83644 + return 1;
83645 + }
83646 +
83647 + if (!req->req.actual && first_time) {
83648 + first_time = 0;
83649 + return 1;
83650 + }
83651 +
83652 + ret = s3c_otg_read_fifo_ep0(ep, req);
83653 +
83654 + if (ret)
83655 + s3c_otg_done(ep, req, 0);
83656 +
83657 + dev->ep0state = WAIT_FOR_SETUP;
83658 + first_time = 1;
83659 +
83660 + return ret;
83661 +}
83662 +
83663 +static void s3c_otg_kick_ep0(struct s3c_udc *dev, struct s3c_ep *ep)
83664 +{
83665 + int res = 0;
83666 +
83667 + DBG(1, "ep_is_in = %d\n", ep_is_in(ep));
83668 +
83669 + if (ep_is_in(ep)) {
83670 + dev->ep0state = DATA_STATE_XMIT;
83671 + while (!res)
83672 + res = s3c_otg_write_ep0(dev);
83673 + } else {
83674 + dev->ep0state = DATA_STATE_RECV;
83675 + s3c_otg_read_ep0(dev);
83676 + }
83677 +}
83678 +
83679 +/*
83680 + * Write request to FIFO
83681 + */
83682 +static int s3c_otg_write_fifo(struct s3c_ep *ep, struct s3c_request *req)
83683 +{
83684 + u32 max;
83685 + u32 gintmsk;
83686 + unsigned count;
83687 + int is_last = 0;
83688 + int is_short = 0;
83689 +
83690 + gintmsk = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GINTMSK);
83691 +
83692 + max = le16_to_cpu(ep->desc->wMaxPacketSize);
83693 + count = s3c_otg_write_packet(ep, req, max);
83694 +
83695 + /* last packet is usually short (or a zlp) */
83696 + if (count != max) {
83697 + is_last = 1;
83698 + is_short = 1;
83699 + } else {
83700 + if ((req->req.length != req->req.actual) || req->req.zero)
83701 + is_last = 0;
83702 + else
83703 + is_last = 1;
83704 +
83705 + /* interrupt/iso maxpacket may not fill the fifo */
83706 + is_short = (max < ep_maxpacket(ep));
83707 + }
83708 +
83709 + DBG(2, "wrote %s %d bytes%s%s %d/%d\n",
83710 + ep->ep.name, count,
83711 + is_last ? "/L" : "", is_short ? "/S" : "",
83712 + req->req.actual, req->req.length);
83713 +
83714 + /* requests complete when all IN data is in the FIFO */
83715 + if (is_last) {
83716 + if (ep_index(ep) == 0) {
83717 + DBG(3, "--> EP0 must not come here!\n");
83718 + BUG();
83719 + }
83720 +
83721 + s3c_otg_writel(ep->dev, gintmsk & (~INT_TX_FIFO_EMPTY),
83722 + (u32)S3C_UDC_OTG_GINTMSK);
83723 + s3c_otg_done(ep, req, 0);
83724 +
83725 + return 1;
83726 + }
83727 +
83728 + s3c_otg_writel(ep->dev, gintmsk|INT_TX_FIFO_EMPTY,
83729 + (u32)S3C_UDC_OTG_GINTMSK);
83730 +
83731 + return 0;
83732 +}
83733 +
83734 +/*
83735 + * Read to request from FIFO (max read == bytes in fifo)
83736 + */
83737 +static int s3c_otg_read_fifo(struct s3c_ep *ep, struct s3c_request *req)
83738 +{
83739 + u32 csr;
83740 + u32 gintmsk;
83741 + u32 *buf;
83742 + unsigned bufferspace;
83743 + unsigned count;
83744 + unsigned is_short = 0;
83745 + unsigned bytes;
83746 + u32 fifo = ep->fifo;
83747 +
83748 + csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GRXSTSP);
83749 + bytes = BYTE_COUNT(csr);
83750 + gintmsk = readl(S3C_UDC_OTG_GINTMSK);
83751 +
83752 + if (!bytes) {
83753 + DBG(2, "%d bytes\n", bytes);
83754 + s3c_otg_orl(ep->dev, INT_RX_FIFO_NOT_EMPTY,
83755 + (u32)S3C_UDC_OTG_GINTMSK);
83756 + return 0;
83757 + }
83758 +
83759 + buf = req->req.buf + req->req.actual;
83760 + prefetchw(buf);
83761 + bufferspace = req->req.length - req->req.actual;
83762 +
83763 + count = bytes / 4 + (bytes % 4 ? 1 : 0);
83764 + req->req.actual += min(bytes, bufferspace);
83765 +
83766 + is_short = (bytes < ep->ep.maxpacket);
83767 +
83768 + DBG(2, "read %s %d bytes%s %d/%d\n",
83769 + ep->ep.name, bytes, is_short ? "/S" : "",
83770 + req->req.actual, req->req.length);
83771 +
83772 + while (count--) {
83773 + u32 byte = s3c_otg_readl(ep->dev, fifo);
83774 +
83775 + if (unlikely(bufferspace == 0)) {
83776 + /* this happens when the driver's buffer
83777 + * is smaller than what the host sent.
83778 + * discard the extra data.
83779 + */
83780 + if (req->req.status != -EOVERFLOW)
83781 + DBG(3, "%s overflow %d\n", ep->ep.name, count);
83782 + req->req.status = -EOVERFLOW;
83783 + } else {
83784 + *buf++ = byte;
83785 + bufferspace -= 4;
83786 + }
83787 + }
83788 +
83789 + s3c_otg_writel(ep->dev, gintmsk|INT_RX_FIFO_NOT_EMPTY,
83790 + (u32)S3C_UDC_OTG_GINTMSK);
83791 +
83792 + /* completion */
83793 + if (is_short || req->req.actual == req->req.length) {
83794 + s3c_otg_done(ep, req, 0);
83795 + return 1;
83796 + }
83797 +
83798 + /* finished that packet. the next one may be waiting... */
83799 + return 0;
83800 +}
83801 +
83802 +static struct usb_request *s3c_otg_alloc_request(
83803 + struct usb_ep *ep, gfp_t gfp_flags)
83804 +{
83805 + struct s3c_request *req;
83806 +
83807 + if (!ep)
83808 + return NULL;
83809 +
83810 + DBG(1, "%s %p\n", ep->name, ep);
83811 +
83812 + req = kzalloc(sizeof *req, gfp_flags);
83813 + if (!req)
83814 + return NULL;
83815 +
83816 + INIT_LIST_HEAD(&req->queue);
83817 +
83818 + return &req->req;
83819 +}
83820 +
83821 +static void s3c_otg_free_request(struct usb_ep *ep, struct usb_request *_req)
83822 +{
83823 + struct s3c_request *req;
83824 +
83825 + if (!ep)
83826 + return;
83827 +
83828 + DBG(1, "%s %p\n", ep->name, ep);
83829 +
83830 + if (!_req)
83831 + return;
83832 +
83833 + req = container_of(_req, struct s3c_request, req);
83834 +
83835 + WARN_ON(!list_empty(&req->queue));
83836 + kfree(req);
83837 +}
83838 +
83839 +/*
83840 + * Queue one request
83841 + * Kickstart transfer if needed
83842 + */
83843 +static int s3c_otg_queue(struct usb_ep *_ep,
83844 + struct usb_request *_req, gfp_t gfp_flags)
83845 +{
83846 + struct s3c_request *req;
83847 + struct s3c_ep *ep;
83848 + struct s3c_udc *dev;
83849 + unsigned long flags;
83850 + u32 csr;
83851 +
83852 + req = container_of(_req, struct s3c_request, req);
83853 + if (!_req || !_req->complete || !_req->buf
83854 + || !list_empty(&req->queue)) {
83855 + DBG(3, "bad params\n");
83856 + return -EINVAL;
83857 + }
83858 +
83859 + ep = container_of(_ep, struct s3c_ep, ep);
83860 + if (!_ep || (!ep->desc && ep->ep.name != ep0name)) {
83861 + DBG(3, "bad ep\n");
83862 + return -EINVAL;
83863 + }
83864 +
83865 + dev = ep->dev;
83866 + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
83867 + DBG(3, "bogus device state %p\n", dev->driver);
83868 + return -ESHUTDOWN;
83869 + }
83870 +
83871 + DBG(2, "%s queue req %p, len %d buf %p\n",
83872 + _ep->name, _req, _req->length, _req->buf);
83873 +
83874 + spin_lock_irqsave(&dev->lock, flags);
83875 +
83876 + _req->status = -EINPROGRESS;
83877 + _req->actual = 0;
83878 +
83879 + DBG(2, "ep=%d, Q empty=%d, stopped=%d\n",
83880 + ep_index(ep), list_empty(&ep->queue), ep->stopped);
83881 +
83882 + /* kickstart this i/o queue? */
83883 + if (list_empty(&ep->queue) && !ep->stopped) {
83884 + if (ep_index(ep) == 0) {
83885 + list_add_tail(&req->queue, &ep->queue);
83886 + s3c_otg_kick_ep0(dev, ep);
83887 + req = NULL;
83888 + } else if (ep_is_in(ep)) {
83889 + csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GINTSTS);
83890 +
83891 + if ((csr & INT_TX_FIFO_EMPTY) &&
83892 + (s3c_otg_write_fifo(ep, req) == 1))
83893 + req = NULL;
83894 + else
83895 + tx_ep_num = ep_index(ep);
83896 + } else {
83897 + csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GINTSTS);
83898 +
83899 + if ((csr & INT_RX_FIFO_NOT_EMPTY) &&
83900 + (s3c_otg_read_fifo(ep, req) == 1))
83901 + req = NULL;
83902 + }
83903 + }
83904 +
83905 + /* pio or dma irq handler advances the queue. */
83906 + if (req)
83907 + list_add_tail(&req->queue, &ep->queue);
83908 +
83909 + spin_unlock_irqrestore(&dev->lock, flags);
83910 +
83911 + return 0;
83912 +}
83913 +
83914 +/*
83915 + * dequeue JUST ONE request
83916 + */
83917 +static int s3c_otg_dequeue(struct usb_ep *_ep, struct usb_request *_req)
83918 +{
83919 + struct s3c_ep *ep;
83920 + struct s3c_request *req;
83921 + unsigned long flags;
83922 +
83923 + ep = container_of(_ep, struct s3c_ep, ep);
83924 + if (!_ep || ep->ep.name == ep0name)
83925 + return -EINVAL;
83926 +
83927 + spin_lock_irqsave(&ep->dev->lock, flags);
83928 +
83929 + /* make sure it's actually queued on this endpoint */
83930 + list_for_each_entry(req, &ep->queue, queue) {
83931 + if (&req->req == _req)
83932 + break;
83933 + }
83934 +
83935 + if (&req->req != _req) {
83936 + spin_unlock_irqrestore(&ep->dev->lock, flags);
83937 + return -EINVAL;
83938 + }
83939 +
83940 + s3c_otg_done(ep, req, -ECONNRESET);
83941 +
83942 + spin_unlock_irqrestore(&ep->dev->lock, flags);
83943 +
83944 + return 0;
83945 +}
83946 +
83947 +static int s3c_otg_set_halt(struct usb_ep *_ep, int value)
83948 +{
83949 + return 0;
83950 +}
83951 +
83952 +static int s3c_otg_fifo_status(struct usb_ep *_ep)
83953 +{
83954 + int count = 0;
83955 + struct s3c_ep *ep;
83956 +
83957 + ep = container_of(_ep, struct s3c_ep, ep);
83958 + if (!_ep) {
83959 + DBG(3, "bad ep\n");
83960 + return -ENODEV;
83961 + }
83962 +
83963 + /* LPD can't report unclaimed bytes from IN fifos */
83964 + if (ep_is_in(ep))
83965 + return -EOPNOTSUPP;
83966 +
83967 + return count;
83968 +}
83969 +
83970 +static void s3c_otg_fifo_flush(struct usb_ep *_ep)
83971 +{
83972 + struct s3c_ep *ep;
83973 +
83974 + ep = container_of(_ep, struct s3c_ep, ep);
83975 + if (unlikely(!_ep || (!ep->desc && ep->ep.name != ep0name))) {
83976 + DBG(3, "bad ep\n");
83977 + return;
83978 + }
83979 +}
83980 +
83981 +static int s3c_otg_ep_enable(struct usb_ep *_ep,
83982 + const struct usb_endpoint_descriptor *desc)
83983 +{
83984 + struct s3c_ep *ep;
83985 + struct s3c_udc *dev;
83986 + unsigned long flags;
83987 +
83988 + ep = container_of(_ep, struct s3c_ep, ep);
83989 + if (!_ep || !desc || ep->desc || _ep->name == ep0name
83990 + || desc->bDescriptorType != USB_DT_ENDPOINT
83991 + || ep->bEndpointAddress != desc->bEndpointAddress
83992 + || ep_maxpacket(ep) < le16_to_cpu(desc->wMaxPacketSize)) {
83993 + DBG(3, "bad ep or descriptor\n");
83994 + return -EINVAL;
83995 + }
83996 +
83997 + /* xfer types must match, except that interrupt ~= bulk */
83998 + if (ep->bmAttributes != desc->bmAttributes
83999 + && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
84000 + && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
84001 + DBG(3, "%s type mismatch\n", _ep->name);
84002 + return -EINVAL;
84003 + }
84004 +
84005 + /* hardware _could_ do smaller, but driver doesn't */
84006 + if ((desc->bmAttributes == USB_ENDPOINT_XFER_BULK
84007 + && le16_to_cpu(desc->wMaxPacketSize)
84008 + != ep_maxpacket(ep))
84009 + || !desc->wMaxPacketSize) {
84010 + DBG(3, "bad %s maxpacket\n", _ep->name);
84011 + return -ERANGE;
84012 + }
84013 +
84014 + dev = ep->dev;
84015 + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
84016 + DBG(3, "bogus device state\n");
84017 + return -ESHUTDOWN;
84018 + }
84019 +
84020 + spin_lock_irqsave(&ep->dev->lock, flags);
84021 +
84022 + ep->stopped = 0;
84023 + ep->desc = desc;
84024 + ep->pio_irqs = 0;
84025 + ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
84026 +
84027 + /* Reset halt state */
84028 + s3c_otg_set_halt(_ep, 0);
84029 +
84030 + spin_unlock_irqrestore(&ep->dev->lock, flags);
84031 +
84032 + DBG(2, "enabled %s, stopped = %d, maxpacket = %d\n",
84033 + _ep->name, ep->stopped, ep->ep.maxpacket);
84034 + return 0;
84035 +}
84036 +
84037 +static int s3c_otg_ep_disable(struct usb_ep *_ep)
84038 +{
84039 + struct s3c_ep *ep;
84040 + unsigned long flags;
84041 +
84042 + ep = container_of(_ep, struct s3c_ep, ep);
84043 + if (!_ep || !ep->desc) {
84044 + DBG(3, "%s not enabled\n", _ep ? ep->ep.name : NULL);
84045 + return -EINVAL;
84046 + }
84047 +
84048 + spin_lock_irqsave(&ep->dev->lock, flags);
84049 +
84050 + /* Nuke all pending requests */
84051 + s3c_otg_nuke(ep, -ESHUTDOWN);
84052 +
84053 + ep->desc = 0;
84054 + ep->stopped = 1;
84055 +
84056 + spin_unlock_irqrestore(&ep->dev->lock, flags);
84057 +
84058 + DBG(2, "disabled %s\n", _ep->name);
84059 + return 0;
84060 +}
84061 +
84062 +static struct usb_ep_ops s3c_ep_ops = {
84063 + .enable = s3c_otg_ep_enable,
84064 + .disable = s3c_otg_ep_disable,
84065 +
84066 + .alloc_request = s3c_otg_alloc_request,
84067 + .free_request = s3c_otg_free_request,
84068 +
84069 + .queue = s3c_otg_queue,
84070 + .dequeue = s3c_otg_dequeue,
84071 +
84072 + .set_halt = s3c_otg_set_halt,
84073 + .fifo_status = s3c_otg_fifo_status,
84074 + .fifo_flush = s3c_otg_fifo_flush,
84075 +};
84076 +
84077 +void s3c_otg_set_ep(struct s3c_udc *dev, enum usb_device_speed speed)
84078 +{
84079 + u32 ep0_mps = DEPCTL0_MPS_64;
84080 +
84081 + if (speed == USB_SPEED_FULL) {
84082 + ep0_fifo_size = 8;
84083 + ep_fifo_size = 64;
84084 + ep_fifo_size2 = 64;
84085 +
84086 + ep0_mps = DEPCTL0_MPS_8;
84087 + }
84088 +
84089 + dev->gadget.speed = speed;
84090 +
84091 + dev->ep[0].ep.maxpacket = ep0_fifo_size;
84092 + dev->ep[1].ep.maxpacket = ep_fifo_size;
84093 + dev->ep[2].ep.maxpacket = ep_fifo_size;
84094 + dev->ep[3].ep.maxpacket = ep_fifo_size;
84095 + dev->ep[4].ep.maxpacket = ep_fifo_size;
84096 + dev->ep[5].ep.maxpacket = ep_fifo_size2;
84097 + dev->ep[6].ep.maxpacket = ep_fifo_size2;
84098 + dev->ep[7].ep.maxpacket = ep_fifo_size2;
84099 + dev->ep[8].ep.maxpacket = ep_fifo_size2;
84100 +
84101 + /* EP0 - Control */
84102 + s3c_otg_ep_control(0, USB_DIR_OUT, ep0_mps, 1);
84103 + s3c_otg_ep_control(0, USB_DIR_IN, ep0_mps, 1);
84104 +
84105 + /* EP1 - Bulk Data OUT */
84106 + s3c_otg_ep_control(1, USB_DIR_OUT, ep_fifo_size, 1);
84107 +
84108 + /* EP2 - Bulk Data IN */
84109 + s3c_otg_ep_control(2, USB_DIR_IN, ep_fifo_size, 1);
84110 +
84111 + /* EP3 - INTR Data IN */
84112 + s3c_otg_ep_control(3, USB_DIR_IN, ep_fifo_size, 1);
84113 +
84114 + DBG(2, "%s Speed Detection\n",
84115 + speed == USB_SPEED_HIGH ? "High" : "Full");
84116 +}
84117 +
84118 +/*
84119 + * set the USB address for this device
84120 + *
84121 + * Called from control endpoint function
84122 + * after it decodes a set address setup packet.
84123 + */
84124 +static void s3c_otg_set_address(struct s3c_udc *dev, unsigned char addr)
84125 +{
84126 + s3c_otg_orl(dev, DEVICE_ADDR(addr), S3C_UDC_OTG_DCFG);
84127 + s3c_otg_ep_control(0, USB_DIR_IN, DEPCTL_EPENA|DEPCTL_CNAK, 1);
84128 +
84129 + DBG(2, "USB OTG 2.0 Device Address=%d\n", addr);
84130 +
84131 + dev->usb_address = addr;
84132 +}
84133 +
84134 +static inline int s3c_otg_read_setup(struct s3c_ep *ep, u32 *ctrl, int max)
84135 +{
84136 + int bytes;
84137 + int count;
84138 + u32 csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GRXSTSP);
84139 +
84140 + bytes = BYTE_COUNT(csr);
84141 +
84142 + /* 32 bits interface */
84143 + count = bytes / 4;
84144 +
84145 + while (count--)
84146 + *ctrl++ = s3c_otg_readl(ep->dev, S3C_UDC_OTG_EP0_FIFO);
84147 +
84148 + return bytes;
84149 +}
84150 +
84151 +static void s3c_otg_setup(struct s3c_udc *dev)
84152 +{
84153 + struct s3c_ep *ep = &dev->ep[0];
84154 + int bytes;
84155 + int is_in;
84156 + int ret;
84157 +
84158 + /* Nuke all previous transfers */
84159 + s3c_otg_nuke(ep, -EPROTO);
84160 +
84161 + /* read control req from fifo (8 bytes) */
84162 + bytes = s3c_otg_read_setup(ep, (u32 *)&ctrl, 8);
84163 +
84164 + DBG(2, "SETUP REQ %02x %02x %04x %04x %d\n",
84165 + ctrl.bRequestType, ctrl.bRequest,
84166 + ctrl.wValue, ctrl.wIndex, ctrl.wLength);
84167 +
84168 + /* Set direction of EP0 */
84169 + if (ctrl.bRequestType & USB_DIR_IN) {
84170 + ep->bEndpointAddress |= USB_DIR_IN;
84171 + is_in = 1;
84172 + } else {
84173 + ep->bEndpointAddress &= ~USB_DIR_IN;
84174 + is_in = 0;
84175 + }
84176 +
84177 + dev->req_pending = 1;
84178 +
84179 + /* Handle some SETUP packets ourselves */
84180 + switch (ctrl.bRequest) {
84181 + case USB_REQ_SET_ADDRESS:
84182 + if (ctrl.bRequestType != (USB_TYPE_STANDARD|USB_RECIP_DEVICE))
84183 + break;
84184 +
84185 + s3c_otg_set_address(dev, ctrl.wValue);
84186 + return;
84187 +
84188 + case USB_REQ_SET_INTERFACE:
84189 + DBG(2, "USB_REQ_SET_INTERFACE (%d)\n", ctrl.wValue);
84190 + /* FALLTHROUGH */
84191 +
84192 + case USB_REQ_SET_CONFIGURATION:
84193 + DBG(2, "USB_REQ_SET_CONFIGURATION (%d)\n", ctrl.wValue);
84194 +
84195 + s3c_otg_ep_control(0, USB_DIR_IN,
84196 + DEPCTL_EPENA|DEPCTL_CNAK, 1);
84197 + s3c_otg_ep_control(1, USB_DIR_OUT,
84198 + DEPCTL_EPDIS|DEPCTL_CNAK|
84199 + DEPCTL_BULK_TYPE|DEPCTL_USBACTEP, 1);
84200 + s3c_otg_ep_control(2, USB_DIR_IN,
84201 + DEPCTL_BULK_TYPE|DEPCTL_USBACTEP, 1);
84202 + s3c_otg_ep_control(3, USB_DIR_IN,
84203 + DEPCTL_BULK_TYPE|DEPCTL_USBACTEP, 1);
84204 +
84205 + reset_available = 1;
84206 + dev->req_config = 1;
84207 + break;
84208 +
84209 + case USB_REQ_GET_DESCRIPTOR:
84210 + DBG(2, "USB_REQ_GET_DESCRIPTOR\n");
84211 + break;
84212 +
84213 + case USB_REQ_GET_CONFIGURATION:
84214 + DBG(2, "USB_REQ_GET_CONFIGURATION\n");
84215 + break;
84216 +
84217 + case USB_REQ_GET_STATUS:
84218 + DBG(2, "USB_REQ_GET_STATUS\n");
84219 + s3c_otg_ep_control(0, USB_DIR_IN, DEPCTL_EPENA|DEPCTL_CNAK, 1);
84220 + break;
84221 +
84222 + case USB_REQ_CLEAR_FEATURE:
84223 + DBG(2, "USB_REQ_CLEAR_FEATURE\n");
84224 + break;
84225 +
84226 + case USB_REQ_SET_FEATURE:
84227 + DBG(2, "USB_REQ_SET_FEATURE\n");
84228 + break;
84229 +
84230 + default:
84231 + DBG(3, "Default of ctrl.bRequest=0x%x\n", ctrl.bRequest);
84232 + break;
84233 + }
84234 +
84235 + if (dev->driver) {
84236 + /* device-2-host (IN) or no data setup command,
84237 + * process immediately */
84238 + spin_unlock(&dev->lock);
84239 +
84240 + DBG(1, "usb_ctrlrequest will be passed to fsg_setup()\n");
84241 +
84242 + ret = dev->driver->setup(&dev->gadget, &ctrl);
84243 + spin_lock(&dev->lock);
84244 +
84245 + if (ret < 0) {
84246 + /* setup processing failed, force stall */
84247 + DBG(3, "gadget setup FAILED (stalling) - %d\n", ret);
84248 + dev->ep0state = WAIT_FOR_SETUP;
84249 + }
84250 + }
84251 +}
84252 +
84253 +/*
84254 + * handle ep0 interrupt
84255 + */
84256 +static void s3c_otg_handle_ep0(struct s3c_udc *dev)
84257 +{
84258 + if (dev->ep0state == WAIT_FOR_SETUP)
84259 + s3c_otg_setup(dev);
84260 + else
84261 + DBG(3, "strange state!! - %s\n", state_names[dev->ep0state]);
84262 +}
84263 +
84264 +static void s3c_otg_handle_ep_out(struct s3c_udc *dev, u32 ep_num)
84265 +{
84266 + struct s3c_ep *ep = &dev->ep[ep_num];
84267 + struct s3c_request *req;
84268 +
84269 + if (unlikely(!(ep->desc))) {
84270 + /* Throw packet away.. */
84271 + DBG(3, "No descriptor?!?\n");
84272 + return;
84273 + }
84274 +
84275 + if (list_empty(&ep->queue))
84276 + req = 0;
84277 + else
84278 + req = list_entry(ep->queue.next, struct s3c_request, queue);
84279 +
84280 + if (unlikely(!req))
84281 + DBG(2, "NULL REQ on OUT EP-%d\n", ep_num);
84282 + else
84283 + s3c_otg_read_fifo(ep, req);
84284 +}
84285 +
84286 +static void s3c_otg_handle_ep_in(struct s3c_udc *dev, u32 ep_num)
84287 +{
84288 + struct s3c_ep *ep = &dev->ep[ep_num];
84289 + struct s3c_request *req;
84290 +
84291 + if (list_empty(&ep->queue))
84292 + req = 0;
84293 + else
84294 + req = list_entry(ep->queue.next, struct s3c_request, queue);
84295 +
84296 + if (unlikely(!req)) {
84297 + DBG(2, "NULL REQ on IN EP-%d\n", ep_num);
84298 + return;
84299 + } else
84300 + s3c_otg_write_fifo(ep, req);
84301 +}
84302 +
84303 +static void s3c_otg_handle_ep(struct s3c_udc *dev, u32 gintmsk)
84304 +{
84305 + u32 csr;
84306 + u32 packet_status;
84307 + u32 ep_num;
84308 + u32 bytes = 0;
84309 +
84310 + gintmsk &= ~INT_RX_FIFO_NOT_EMPTY;
84311 + s3c_otg_writel(dev, gintmsk, S3C_UDC_OTG_GINTMSK);
84312 +
84313 + csr = s3c_otg_readl(dev, S3C_UDC_OTG_GRXSTSR);
84314 +
84315 + packet_status = PKT_STS(csr);
84316 + bytes = BYTE_COUNT(csr);
84317 + ep_num = EP_NUM(csr);
84318 +
84319 + switch (packet_status) {
84320 + case SETUP_PKT_RECEIVED:
84321 + DBG(2, "SETUP received : %d bytes\n", bytes);
84322 + if (!bytes)
84323 + break;
84324 +
84325 + s3c_otg_handle_ep0(dev);
84326 + gintmsk |= INT_RX_FIFO_NOT_EMPTY;
84327 + break;
84328 +
84329 + case OUT_PKT_RECEIVED:
84330 + if (!bytes)
84331 + break;
84332 +
84333 + if (ep_num == 0) {
84334 + DBG(2, "CONTROL OUT received : %d bytes\n", bytes);
84335 +
84336 + dev->ep0state = DATA_STATE_RECV;
84337 + s3c_otg_read_ep0(dev);
84338 +
84339 + gintmsk |= INT_RX_FIFO_NOT_EMPTY;
84340 + } else if (ep_num == 1) {
84341 + DBG(2, " Bulk OUT received : %d bytes\n", bytes);
84342 +
84343 + s3c_otg_handle_ep_out(dev, 1);
84344 + gintmsk = s3c_otg_readl(dev,S3C_UDC_OTG_GINTMSK);
84345 +
84346 + s3c_otg_ep_control(1, USB_DIR_OUT, DEPCTL_CNAK, 1);
84347 + } else
84348 + DBG(2, "Unused EP%d: %d bytes\n", ep_num, bytes);
84349 + break;
84350 +
84351 + case SETUP_COMPLETED:
84352 + DBG(2, "SETUP_COMPLETED\n");
84353 + s3c_otg_ep_control(0, USB_DIR_OUT, DEPCTL_CNAK, 1);
84354 + break;
84355 +
84356 + case OUT_COMPLELTED:
84357 + DBG(2, "OUT_COMPLELTED - ep%d\n", ep_num);
84358 + s3c_otg_ep_control(ep_num, USB_DIR_OUT, DEPCTL_CNAK, 1);
84359 + break;
84360 +
84361 + default:
84362 + gintmsk |= INT_RX_FIFO_NOT_EMPTY;
84363 + s3c_otg_ep_control(0, USB_DIR_OUT, DEPCTL_CNAK, 1);
84364 + DBG(1, "reserved packet received : scr=0x%08X bytes\n", csr);
84365 + break;
84366 + }
84367 +
84368 + if (!bytes) {
84369 + csr = s3c_otg_readl(dev, S3C_UDC_OTG_GRXSTSP);
84370 + gintmsk |= INT_RX_FIFO_NOT_EMPTY;
84371 + }
84372 +
84373 + s3c_otg_writel(dev, gintmsk, S3C_UDC_OTG_GINTMSK);
84374 +}
84375 +
84376 +/*
84377 + * disable USB device controller
84378 + */
84379 +static void s3c_otg_disable(struct s3c_udc *dev)
84380 +{
84381 + s3c_otg_set_address(dev, 0);
84382 +
84383 + dev->ep0state = WAIT_FOR_SETUP;
84384 + dev->gadget.speed = USB_SPEED_UNKNOWN;
84385 + dev->usb_address = 0;
84386 +
84387 + s3c_otg_orl(dev, ANALOG_PWR_DOWN, S3C_USBOTG_PHYPWR);
84388 +}
84389 +
84390 +/*
84391 + * initialize software state
84392 + */
84393 +static void s3c_otg_reinit(struct s3c_udc *dev)
84394 +{
84395 + u32 i;
84396 +
84397 + /* device/ep0 records init */
84398 + INIT_LIST_HEAD(&dev->gadget.ep_list);
84399 + INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
84400 + dev->ep0state = WAIT_FOR_SETUP;
84401 +
84402 + /* basic endpoint records init */
84403 + for (i = 0; i < S3C_MAX_ENDPOINTS; i++) {
84404 + struct s3c_ep *ep = &dev->ep[i];
84405 +
84406 + if (i != 0)
84407 + list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
84408 +
84409 + ep->desc = 0;
84410 + ep->stopped = 0;
84411 + INIT_LIST_HEAD(&ep->queue);
84412 + ep->pio_irqs = 0;
84413 + }
84414 +}
84415 +
84416 +#define GUSBCFG_INIT (PHY_CLK_480M|TXFIFO_RE_EN| \
84417 + TURN_AROUND|HNP_DISABLE|SRP_DISABLE|ULPI_DDR| \
84418 + HS_UTMI|INTERF_UTMI|PHY_INTERF_16|TIME_OUT_CAL)
84419 +
84420 +#define GINTMSK_INIT (INT_RESUME|INT_ENUMDONE| \
84421 + INT_RESET|INT_SUSPEND|INT_RX_FIFO_NOT_EMPTY)
84422 +
84423 +#define DOEPMSK_INIT (AHB_ERROR)
84424 +
84425 +#define DIEPMSK_INIT (IN_EP_TIMEOUT|AHB_ERROR)
84426 +
84427 +#define GAHBCFG_INIT (PTXFE_HALF|NPTXFE_HALF| \
84428 + MODE_SLAVE|BURST_INCR16|GBL_INT_UNMASK)
84429 +
84430 +static void s3c_otg_config(struct s3c_udc *dev)
84431 +{
84432 + u32 reg;
84433 +
84434 + /* OTG USB configuration */
84435 + s3c_otg_writel(dev, GUSBCFG_INIT, S3C_UDC_OTG_GUSBCFG);
84436 +
84437 + /* Soft-reset OTG Core and then unreset again */
84438 + s3c_otg_writel(dev, CORE_SOFT_RESET, S3C_UDC_OTG_GRSTCTL);
84439 +
84440 + /* Put the OTG device core in the disconnected state */
84441 + s3c_otg_orl(dev, SOFT_DISCONNECT, S3C_UDC_OTG_DCTL);
84442 +
84443 + udelay(20);
84444 +
84445 + /* Make the OTG device core exit from the disconnected state */
84446 + reg = s3c_otg_readl(dev, S3C_UDC_OTG_DCTL);
84447 + s3c_otg_writel(dev, reg & ~SOFT_DISCONNECT, S3C_UDC_OTG_DCTL);
84448 +
84449 + /* Configure OTG Core to initial settings of device mode */
84450 + s3c_otg_orl(dev, EP_MIS_CNT(0x1)|SPEED_2_HIGH, S3C_UDC_OTG_DCFG);
84451 +
84452 + udelay(1000);
84453 +
84454 + /* Unmask the core interrupts */
84455 + s3c_otg_writel(dev, GINTMSK_INIT, S3C_UDC_OTG_GINTMSK);
84456 +
84457 + /* Set NAK bit of EP0, EP1, EP2 */
84458 + s3c_otg_ep_control(0, USB_DIR_OUT,
84459 + DEPCTL_EPDIS|DEPCTL_SNAK|DEPCTL0_MPS_64, 0);
84460 + s3c_otg_ep_control(0, USB_DIR_IN,
84461 + DEPCTL_EPDIS|DEPCTL_SNAK|DEPCTL0_MPS_64, 0);
84462 + s3c_otg_ep_control(1, USB_DIR_OUT,
84463 + DEPCTL_EPDIS|DEPCTL_SNAK|DEPCTL_BULK_TYPE, 0);
84464 + s3c_otg_ep_control(2, USB_DIR_IN,
84465 + DEPCTL_EPDIS|DEPCTL_SNAK|DEPCTL_BULK_TYPE, 0);
84466 + s3c_otg_ep_control(3, USB_DIR_IN,
84467 + DEPCTL_EPDIS|DEPCTL_SNAK|DEPCTL_BULK_TYPE, 0);
84468 +
84469 + /* Unmask EP interrupts */
84470 + s3c_otg_writel(dev, S3C_UDC_INT_IN_EP0
84471 + |S3C_UDC_INT_IN_EP2
84472 + |S3C_UDC_INT_IN_EP3
84473 + |S3C_UDC_INT_OUT_EP0
84474 + |S3C_UDC_INT_OUT_EP1,
84475 + S3C_UDC_OTG_DAINTMSK);
84476 +
84477 + /* Unmask device OUT EP common interrupts */
84478 + s3c_otg_writel(dev, DOEPMSK_INIT, S3C_UDC_OTG_DOEPMSK);
84479 +
84480 + /* Unmask device IN EP common interrupts */
84481 + s3c_otg_writel(dev, DIEPMSK_INIT, S3C_UDC_OTG_DIEPMSK);
84482 +
84483 + /* Set Rx FIFO Size */
84484 + s3c_otg_writel(dev, RX_FIFO_SIZE, S3C_UDC_OTG_GRXFSIZ);
84485 +
84486 + /* Set Non Periodic Tx FIFO Size */
84487 + s3c_otg_writel(dev, NPTX_FIFO_SIZE|NPTX_FIFO_START_ADDR,
84488 + (u32)S3C_UDC_OTG_GNPTXFSIZ);
84489 +
84490 + /* Clear NAK bit of EP0 For Slave mode */
84491 + s3c_otg_ep_control(0, USB_DIR_OUT, DEPCTL_EPDIS|DEPCTL_CNAK, 0);
84492 +
84493 + /* Initialize OTG Link Core */
84494 + s3c_otg_writel(dev, GAHBCFG_INIT, S3C_UDC_OTG_GAHBCFG);
84495 +}
84496 +
84497 +static int s3c_otg_enable(struct s3c_udc *dev)
84498 +{
84499 + /* USB_SIG_MASK */
84500 + __raw_writel(S3C64XX_OTHERS_USBMASK | __raw_readl(S3C64XX_OTHERS),
84501 + S3C64XX_OTHERS);
84502 +
84503 + /* Initializes OTG Phy. */
84504 + s3c_otg_writel(dev, SUSPEND_DISABLE, S3C_USBOTG_PHYPWR);
84505 +
84506 + s3c_otg_writel(dev, dev->phyclk, S3C_USBOTG_PHYCLK);
84507 +
84508 + s3c_otg_writel(dev, SW_RST_ON, S3C_USBOTG_RSTCON);
84509 + udelay(50);
84510 +
84511 + s3c_otg_writel(dev, SW_RST_OFF, S3C_USBOTG_RSTCON);
84512 + udelay(50);
84513 +
84514 + s3c_otg_config(dev);
84515 +
84516 + DBG(2, "S3C USB 2.0 OTG Controller Core Initialized\n");
84517 +
84518 + dev->gadget.speed = USB_SPEED_UNKNOWN;
84519 +
84520 + return 0;
84521 +}
84522 +
84523 +/*
84524 + * usb client interrupt handler.
84525 + */
84526 +static irqreturn_t s3c_otg_irq(int irq, void *_dev)
84527 +{
84528 + struct s3c_udc *dev = _dev;
84529 + u32 intr_status;
84530 + u32 usb_status;
84531 + u32 gintmsk;
84532 +
84533 + spin_lock(&dev->lock);
84534 +
84535 + intr_status = s3c_otg_readl(dev, S3C_UDC_OTG_GINTSTS);
84536 + gintmsk = s3c_otg_readl(dev, S3C_UDC_OTG_GINTMSK);
84537 +
84538 + DBG(1, "GINTSTS=0x%x(on state %s), GINTMSK : 0x%x\n",
84539 + intr_status, state_names[dev->ep0state], gintmsk);
84540 +
84541 + if (!intr_status) {
84542 + spin_unlock(&dev->lock);
84543 + return IRQ_HANDLED;
84544 + }
84545 +
84546 + if (intr_status & INT_ENUMDONE) {
84547 + DBG(2, "Speed Detection interrupt\n");
84548 + s3c_otg_writel(dev, INT_ENUMDONE, S3C_UDC_OTG_GINTSTS);
84549 +
84550 + usb_status = ENUM_SPEED(s3c_otg_readl(dev, S3C_UDC_OTG_DSTS));
84551 +
84552 + if (usb_status & (USB_FULL_30_60MHZ | USB_FULL_48MHZ))
84553 + s3c_otg_set_ep(dev, USB_SPEED_FULL);
84554 + else
84555 + s3c_otg_set_ep(dev, USB_SPEED_HIGH);
84556 + }
84557 +
84558 + if (intr_status & INT_EARLY_SUSPEND) {
84559 + DBG(2, "Early suspend interrupt\n");
84560 + s3c_otg_writel(dev, INT_EARLY_SUSPEND, S3C_UDC_OTG_GINTSTS);
84561 + }
84562 +
84563 + if (intr_status & INT_SUSPEND) {
84564 + DBG(2, "Suspend interrupt\n");
84565 + s3c_otg_writel(dev, INT_SUSPEND, S3C_UDC_OTG_GINTSTS);
84566 +
84567 + if (dev->gadget.speed != USB_SPEED_UNKNOWN
84568 + && dev->driver
84569 + && dev->driver->suspend) {
84570 + dev->driver->suspend(&dev->gadget);
84571 + }
84572 + }
84573 +
84574 + if (intr_status & INT_RESUME) {
84575 + DBG(2, "Resume interrupt\n");
84576 + s3c_otg_writel(dev, INT_RESUME, S3C_UDC_OTG_GINTSTS);
84577 +
84578 + if (dev->gadget.speed != USB_SPEED_UNKNOWN
84579 + && dev->driver
84580 + && dev->driver->resume) {
84581 + dev->driver->resume(&dev->gadget);
84582 + }
84583 + }
84584 +
84585 + if (intr_status & INT_RESET) {
84586 + DBG(2, "Reset interrupt\n");
84587 + s3c_otg_writel(dev, INT_RESET, S3C_UDC_OTG_GINTSTS);
84588 +
84589 + usb_status = s3c_otg_readl(dev, S3C_UDC_OTG_GOTGCTL);
84590 +
84591 + if (usb_status | (A_SESSION_VALID|B_SESSION_VALID)) {
84592 + if (reset_available) {
84593 + s3c_otg_config(dev);
84594 + dev->ep0state = WAIT_FOR_SETUP;
84595 + reset_available = 0;
84596 + }
84597 + } else {
84598 + reset_available = 1;
84599 + DBG(2, "RESET handling skipped\n");
84600 + }
84601 + }
84602 +
84603 + if (intr_status & INT_RX_FIFO_NOT_EMPTY) {
84604 + s3c_otg_handle_ep(dev, gintmsk);
84605 + spin_unlock(&dev->lock);
84606 +
84607 + return IRQ_HANDLED;
84608 + }
84609 +
84610 +
84611 + if (intr_status & INT_TX_FIFO_EMPTY) {
84612 + DBG(2, "INT_TX_FIFO_EMPTY ep_num=%d\n", tx_ep_num);
84613 + s3c_otg_handle_ep_in(dev, tx_ep_num);
84614 + }
84615 +
84616 + spin_unlock(&dev->lock);
84617 +
84618 + return IRQ_HANDLED;
84619 +}
84620 +
84621 +static void s3c_otg_stop_activity(struct s3c_udc *dev,
84622 + struct usb_gadget_driver *driver)
84623 +{
84624 + int i;
84625 +
84626 + /* don't disconnect drivers more than once */
84627 + if (dev->gadget.speed == USB_SPEED_UNKNOWN)
84628 + driver = 0;
84629 + dev->gadget.speed = USB_SPEED_UNKNOWN;
84630 +
84631 + /* prevent new request submissions, kill any outstanding requests */
84632 + for (i = 0; i < S3C_MAX_ENDPOINTS; i++) {
84633 + struct s3c_ep *ep = &dev->ep[i];
84634 + ep->stopped = 1;
84635 + s3c_otg_nuke(ep, -ESHUTDOWN);
84636 + }
84637 +
84638 + /* report disconnect; the driver is already quiesced */
84639 + if (driver) {
84640 + spin_unlock(&dev->lock);
84641 + driver->disconnect(&dev->gadget);
84642 + spin_lock(&dev->lock);
84643 + }
84644 +
84645 + /* re-init driver-visible data structures */
84646 + s3c_otg_reinit(dev);
84647 +}
84648 +
84649 +/*
84650 + * Register the gadget driver. Used by gadget drivers when
84651 + * registering themselves with the controller.
84652 + */
84653 +int usb_gadget_register_driver(struct usb_gadget_driver *driver)
84654 +{
84655 + struct s3c_udc *dev = the_controller;
84656 + int retval;
84657 +
84658 + if (!driver
84659 + || driver->speed != USB_SPEED_HIGH
84660 + || !driver->bind
84661 + || !driver->setup)
84662 + return -EINVAL;
84663 +
84664 + if (!dev) {
84665 + DBG(3, "No device\n");
84666 + return -ENODEV;
84667 + }
84668 +
84669 + if (dev->driver) {
84670 + DBG(3, "Already bound to %s\n", driver->driver.name);
84671 + return -EBUSY;
84672 + }
84673 +
84674 + /* first hook up the driver ... */
84675 + dev->driver = driver;
84676 + dev->gadget.dev.driver = &driver->driver;
84677 + retval = device_add(&dev->gadget.dev);
84678 +
84679 + if (retval) { /* TODO */
84680 + DBG(3, "target device_add failed, error %d\n", retval);
84681 + return retval;
84682 + }
84683 +
84684 + retval = driver->bind(&dev->gadget);
84685 + if (retval) {
84686 + DBG(3, "%s: bind to driver %s --> error %d\n",
84687 + dev->gadget.name, driver->driver.name, retval);
84688 + device_del(&dev->gadget.dev);
84689 +
84690 + dev->driver = 0;
84691 + dev->gadget.dev.driver = 0;
84692 + return retval;
84693 + }
84694 +
84695 + dev_info(&dev->gadget.dev, "Registered gadget driver '%s'\n",
84696 + driver->driver.name);
84697 + s3c_otg_enable(dev);
84698 +
84699 + enable_irq(IRQ_OTG);
84700 +
84701 + return 0;
84702 +}
84703 +EXPORT_SYMBOL(usb_gadget_register_driver);
84704 +
84705 +/*
84706 + Unregister entry point for the peripheral controller driver.
84707 +*/
84708 +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
84709 +{
84710 + struct s3c_udc *dev = the_controller;
84711 + unsigned long flags;
84712 +
84713 + if (!dev)
84714 + return -ENODEV;
84715 +
84716 + if (!driver || driver != dev->driver)
84717 + return -EINVAL;
84718 +
84719 + spin_lock_irqsave(&dev->lock, flags);
84720 +
84721 + dev->driver = 0;
84722 + s3c_otg_stop_activity(dev, driver);
84723 +
84724 + spin_unlock_irqrestore(&dev->lock, flags);
84725 +
84726 + if (driver->unbind)
84727 + driver->unbind(&dev->gadget);
84728 +
84729 + device_del(&dev->gadget.dev);
84730 +
84731 + disable_irq(IRQ_OTG);
84732 +
84733 + dev_info(&dev->gadget.dev, "Unregistered gadget driver '%s'\n",
84734 + driver->driver.name);
84735 +
84736 + s3c_otg_disable(dev);
84737 +
84738 + return 0;
84739 +}
84740 +EXPORT_SYMBOL(usb_gadget_unregister_driver);
84741 +
84742 +/*
84743 + * device-scoped parts of the api to the usb controller hardware
84744 + */
84745 +static int s3c_otg_get_frame(struct usb_gadget *gadget)
84746 +{
84747 + u32 frame = s3c_otg_readl(the_controller, S3C_UDC_OTG_DSTS);
84748 + return FRAME_CNT(frame);
84749 +}
84750 +
84751 +static int s3c_otg_wakeup(struct usb_gadget *gadget)
84752 +{
84753 + return -EOPNOTSUPP;
84754 +}
84755 +
84756 +static int s3c_otg_set_selfpowered(
84757 + struct usb_gadget *gadget, int is_selfpowered)
84758 +{
84759 + return -EOPNOTSUPP;
84760 +}
84761 +
84762 +static int s3c_otg_pullup(struct usb_gadget *gadget, int is_on)
84763 +{
84764 + return -EOPNOTSUPP;
84765 +}
84766 +
84767 +static int s3c_otg_vbus_session(struct usb_gadget *gadget, int is_active)
84768 +{
84769 + return -EOPNOTSUPP;
84770 +}
84771 +
84772 +static int s3c_otg_vbus_draw(struct usb_gadget *gadget, unsigned mA)
84773 +{
84774 + return -EOPNOTSUPP;
84775 +}
84776 +
84777 +static const struct usb_gadget_ops s3c_udc_ops = {
84778 + .get_frame = s3c_otg_get_frame,
84779 + .wakeup = s3c_otg_wakeup,
84780 + .set_selfpowered = s3c_otg_set_selfpowered,
84781 + .vbus_session = s3c_otg_vbus_session,
84782 + .vbus_draw = s3c_otg_vbus_draw,
84783 + .pullup = s3c_otg_pullup,
84784 +};
84785 +
84786 +static void nop_release(struct device *dev)
84787 +{
84788 + DBG(2, "%s\n", dev->bus_id);
84789 +}
84790 +
84791 +static struct s3c_udc memory = {
84792 + .usb_address = 0,
84793 + .gadget = {
84794 + .ops = &s3c_udc_ops,
84795 + .ep0 = &memory.ep[0].ep,
84796 + .name = driver_name,
84797 + .dev = {
84798 + .bus_id = "gadget",
84799 + .release = nop_release,
84800 + },
84801 + },
84802 + .ep[0] = {
84803 + .ep = {
84804 + .name = ep0name,
84805 + .ops = &s3c_ep_ops,
84806 + .maxpacket = EP0_FIFO_SIZE,
84807 + },
84808 + .dev = &memory,
84809 +
84810 + .bEndpointAddress = 0,
84811 + .bmAttributes = 0,
84812 +
84813 + .ep_type = ep_control,
84814 + .fifo = (u32) S3C_UDC_OTG_EP0_FIFO,
84815 + },
84816 + .ep[1] = {
84817 + .ep = {
84818 + .name = "ep1-bulk",
84819 + .ops = &s3c_ep_ops,
84820 + .maxpacket = EP_FIFO_SIZE,
84821 + },
84822 + .dev = &memory,
84823 +
84824 + .bEndpointAddress = 1,
84825 + .bmAttributes = USB_ENDPOINT_XFER_BULK,
84826 +
84827 + .ep_type = ep_bulk_out,
84828 + .fifo = (u32) S3C_UDC_OTG_EP1_FIFO,
84829 + },
84830 + .ep[2] = {
84831 + .ep = {
84832 + .name = "ep2-bulk",
84833 + .ops = &s3c_ep_ops,
84834 + .maxpacket = EP_FIFO_SIZE,
84835 + },
84836 + .dev = &memory,
84837 +
84838 + .bEndpointAddress = USB_DIR_IN | 2,
84839 + .bmAttributes = USB_ENDPOINT_XFER_BULK,
84840 +
84841 + .ep_type = ep_bulk_in,
84842 + .fifo = (u32) S3C_UDC_OTG_EP2_FIFO,
84843 + },
84844 +
84845 + .ep[3] = {
84846 + .ep = {
84847 + .name = "ep3-int",
84848 + .ops = &s3c_ep_ops,
84849 + .maxpacket = EP_FIFO_SIZE,
84850 + },
84851 + .dev = &memory,
84852 +
84853 + .bEndpointAddress = USB_DIR_IN | 3,
84854 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84855 +
84856 + .ep_type = ep_interrupt,
84857 + .fifo = (u32) S3C_UDC_OTG_EP3_FIFO,
84858 + },
84859 + .ep[4] = {
84860 + .ep = {
84861 + .name = "ep4-int",
84862 + .ops = &s3c_ep_ops,
84863 + .maxpacket = EP_FIFO_SIZE,
84864 + },
84865 + .dev = &memory,
84866 +
84867 + .bEndpointAddress = USB_DIR_IN | 4,
84868 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84869 +
84870 + .ep_type = ep_interrupt,
84871 + .fifo = (u32) S3C_UDC_OTG_EP4_FIFO,
84872 + },
84873 + .ep[5] = {
84874 + .ep = {
84875 + .name = "ep5-int",
84876 + .ops = &s3c_ep_ops,
84877 + .maxpacket = EP_FIFO_SIZE2,
84878 + },
84879 + .dev = &memory,
84880 +
84881 + .bEndpointAddress = USB_DIR_IN | 5,
84882 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84883 +
84884 + .ep_type = ep_interrupt,
84885 + .fifo = (u32) S3C_UDC_OTG_EP5_FIFO,
84886 + },
84887 + .ep[6] = {
84888 + .ep = {
84889 + .name = "ep6-int",
84890 + .ops = &s3c_ep_ops,
84891 + .maxpacket = EP_FIFO_SIZE2,
84892 + },
84893 + .dev = &memory,
84894 +
84895 + .bEndpointAddress = USB_DIR_IN | 6,
84896 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84897 +
84898 + .ep_type = ep_interrupt,
84899 + .fifo = (u32) S3C_UDC_OTG_EP6_FIFO,
84900 + },
84901 + .ep[7] = {
84902 + .ep = {
84903 + .name = "ep7-int",
84904 + .ops = &s3c_ep_ops,
84905 + .maxpacket = EP_FIFO_SIZE2,
84906 + },
84907 + .dev = &memory,
84908 +
84909 + .bEndpointAddress = USB_DIR_IN | 7,
84910 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84911 +
84912 + .ep_type = ep_interrupt,
84913 + .fifo = (u32) S3C_UDC_OTG_EP7_FIFO,
84914 + },
84915 + .ep[8] = {
84916 + .ep = {
84917 + .name = "ep8-int",
84918 + .ops = &s3c_ep_ops,
84919 + .maxpacket = EP_FIFO_SIZE2,
84920 + },
84921 + .dev = &memory,
84922 +
84923 + .bEndpointAddress = USB_DIR_IN | 8,
84924 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84925 +
84926 + .ep_type = ep_interrupt,
84927 + .fifo = (u32) S3C_UDC_OTG_EP8_FIFO,
84928 + },
84929 +};
84930 +
84931 +static struct clk *otg_clock;
84932 +
84933 +/*
84934 + * binds to the platform device
84935 + */
84936 +static int s3c_otg_probe(struct platform_device *pdev)
84937 +{
84938 + struct s3c_udc *dev = &memory;
84939 + struct s3c_plat_otg_data *pdata = pdev->dev.platform_data;
84940 + int retval;
84941 +
84942 + dev->reg_base = ioremap(pdev->resource[0].start,
84943 + pdev->resource[0].end - pdev->resource[0].start);
84944 + if (dev->reg_base == NULL) {
84945 + dev_err(&pdev->dev, "Unable to map USB OTG physical regs\n");
84946 + return -ENOMEM;
84947 + }
84948 +
84949 +
84950 + DBG(2, "%p\n", pdev);
84951 +
84952 + spin_lock_init(&dev->lock);
84953 + dev->dev = pdev;
84954 +
84955 + device_initialize(&dev->gadget.dev);
84956 + dev->gadget.dev.parent = &pdev->dev;
84957 +
84958 + dev->gadget.is_dualspeed = 1;
84959 + dev->gadget.is_otg = 0;
84960 + dev->gadget.is_a_peripheral = 0;
84961 + dev->gadget.b_hnp_enable = 0;
84962 + dev->gadget.a_hnp_support = 0;
84963 + dev->gadget.a_alt_hnp_support = 0;
84964 +
84965 + dev->phyclk = pdata->phyclk;
84966 +
84967 + the_controller = dev;
84968 + platform_set_drvdata(pdev, dev);
84969 +
84970 + otg_clock = clk_get(&pdev->dev, "otg");
84971 + if (otg_clock == NULL) {
84972 + DBG(3, "failed to find otg clock source\n");
84973 + return -ENOENT;
84974 + }
84975 + clk_enable(otg_clock);
84976 +
84977 + s3c_otg_reinit(dev);
84978 +
84979 + local_irq_disable();
84980 +
84981 + /* irq setup after old hardware state is cleaned up */
84982 + retval = request_irq(pdev->resource[1].start, s3c_otg_irq,
84983 + IRQF_DISABLED, driver_name, dev);
84984 +
84985 + if (retval != 0) {
84986 + DBG(3, "%s: can't get irq %i - %d\n",
84987 + driver_name, IRQ_OTG, retval);
84988 + return -EBUSY;
84989 + }
84990 +
84991 + disable_irq(IRQ_OTG);
84992 + local_irq_enable();
84993 + create_proc_files();
84994 +
84995 + return retval;
84996 +}
84997 +
84998 +static int s3c_otg_remove(struct platform_device *pdev)
84999 +{
85000 + struct s3c_udc *dev = platform_get_drvdata(pdev);
85001 +
85002 + if (otg_clock != NULL) {
85003 + clk_disable(otg_clock);
85004 + clk_put(otg_clock);
85005 + otg_clock = NULL;
85006 + }
85007 +
85008 + remove_proc_files();
85009 + usb_gadget_unregister_driver(dev->driver);
85010 +
85011 + free_irq(IRQ_OTG, dev);
85012 +
85013 + platform_set_drvdata(pdev, 0);
85014 +
85015 + the_controller = 0;
85016 +
85017 + if (dev->reg_base)
85018 + iounmap(dev->reg_base);
85019 +
85020 + return 0;
85021 +}
85022 +
85023 +#ifdef CONFIG_PM
85024 +static int s3c_otg_suspend(struct platform_device *pdev, pm_message_t state)
85025 +{
85026 + struct s3c_udc *dev = the_controller;
85027 +
85028 + if (dev->driver) {
85029 + disable_irq(IRQ_OTG);
85030 + s3c_otg_disable(dev);
85031 + clk_disable(otg_clock);
85032 + }
85033 +
85034 + return 0;
85035 +}
85036 +
85037 +static int s3c_otg_resume(struct platform_device *pdev)
85038 +{
85039 + struct s3c_udc *dev = the_controller;
85040 +
85041 + if (dev->driver) {
85042 + clk_enable(otg_clock);
85043 + s3c_otg_enable(dev);
85044 + s3c_otg_reinit(dev);
85045 + enable_irq(IRQ_OTG);
85046 + }
85047 +
85048 + return 0;
85049 +}
85050 +#else
85051 +#define s3c_otg_suspend NULL
85052 +#define s3c_otg_resume NULL
85053 +#endif
85054 +
85055 +/*-------------------------------------------------------------------------*/
85056 +static struct platform_driver s3c_otg_driver = {
85057 + .probe = s3c_otg_probe,
85058 + .remove = s3c_otg_remove,
85059 + .suspend = s3c_otg_suspend,
85060 + .resume = s3c_otg_resume,
85061 + .driver = {
85062 + .owner = THIS_MODULE,
85063 + .name = "s3c-otg-usbgadget",
85064 + },
85065 +};
85066 +
85067 +static int __init otg_init(void)
85068 +{
85069 + int ret;
85070 +
85071 + ret = platform_driver_register(&s3c_otg_driver);
85072 + if (!ret)
85073 + printk(KERN_INFO "Loaded %s version %s %s\n",
85074 + driver_name, DRIVER_VERSION, "(Slave Mode)");
85075 +
85076 + return ret;
85077 +}
85078 +
85079 +static void __exit otg_exit(void)
85080 +{
85081 + platform_driver_unregister(&s3c_otg_driver);
85082 + printk(KERN_INFO "Unloaded %s version %s\n",
85083 + driver_name, DRIVER_VERSION);
85084 +}
85085 +
85086 +module_init(otg_init);
85087 +module_exit(otg_exit);
85088 +
85089 +MODULE_AUTHOR(DRIVER_AUTHOR);
85090 +MODULE_DESCRIPTION(DRIVER_DESC);
85091 +MODULE_VERSION(DRIVER_VERSION);
85092 +MODULE_LICENSE("GPL");
85093 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/gadget/s3c-udc.h linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/s3c-udc.h
85094 --- linux-2.6.29-rc3.owrt/drivers/usb/gadget/s3c-udc.h 1970-01-01 01:00:00.000000000 +0100
85095 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/gadget/s3c-udc.h 2009-05-10 22:28:00.000000000 +0200
85096 @@ -0,0 +1,132 @@
85097 +/*
85098 + * drivers/usb/gadget/s3c-udc.h
85099 + * Samsung S3C on-chip full/high speed USB device controllers
85100 + *
85101 + * Copyright (C) 2008 Samsung Electronics
85102 + * Minkyu Kang <mk7.kang@samsung.com>
85103 + *
85104 + * This program is free software; you can redistribute it and/or modify
85105 + * it under the terms of the GNU General Public License as published by
85106 + * the Free Software Foundation; either version 2 of the License, or
85107 + * (at your option) any later version.
85108 + *
85109 + * This program is distributed in the hope that it will be useful,
85110 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
85111 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85112 + * GNU General Public License for more details.
85113 + *
85114 + * You should have received a copy of the GNU General Public License
85115 + * along with this program; if not, write to the Free Software
85116 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
85117 + *
85118 + */
85119 +
85120 +#ifndef __S3C_UDC_H
85121 +#define __S3C_UDC_H
85122 +
85123 +#include <linux/module.h>
85124 +#include <linux/kernel.h>
85125 +#include <linux/ioport.h>
85126 +#include <linux/types.h>
85127 +#include <linux/version.h>
85128 +#include <linux/errno.h>
85129 +#include <linux/delay.h>
85130 +#include <linux/sched.h>
85131 +#include <linux/slab.h>
85132 +#include <linux/init.h>
85133 +#include <linux/timer.h>
85134 +#include <linux/list.h>
85135 +#include <linux/interrupt.h>
85136 +#include <linux/proc_fs.h>
85137 +#include <linux/mm.h>
85138 +#include <linux/device.h>
85139 +#include <linux/dma-mapping.h>
85140 +#include <asm/byteorder.h>
85141 +#include <linux/io.h>
85142 +#include <asm/dma.h>
85143 +#include <asm/irq.h>
85144 +#include <asm/system.h>
85145 +#include <asm/unaligned.h>
85146 +#include <mach/hardware.h>
85147 +
85148 +#include <linux/usb/ch9.h>
85149 +#include <linux/usb/gadget.h>
85150 +
85151 +/* Max packet size */
85152 +#if defined(CONFIG_USB_GADGET_S3C_FS)
85153 +#define EP0_FIFO_SIZE 8
85154 +#define EP_FIFO_SIZE 64
85155 +#define S3C_MAX_ENDPOINTS 5
85156 +#elif defined(CONFIG_USB_GADGET_S3C_HS)
85157 +#define EP0_FIFO_SIZE 64
85158 +#define EP_FIFO_SIZE 512
85159 +#define EP_FIFO_SIZE2 1024
85160 +#define S3C_MAX_ENDPOINTS 9
85161 +#else
85162 +#define EP0_FIFO_SIZE 64
85163 +#define EP_FIFO_SIZE 512
85164 +#define EP_FIFO_SIZE2 1024
85165 +#define S3C_MAX_ENDPOINTS 16
85166 +#endif
85167 +
85168 +#define WAIT_FOR_SETUP 0
85169 +#define DATA_STATE_XMIT 1
85170 +#define DATA_STATE_NEED_ZLP 2
85171 +#define WAIT_FOR_OUT_STATUS 3
85172 +#define DATA_STATE_RECV 4
85173 +
85174 +enum ep_type {
85175 + ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt
85176 +};
85177 +
85178 +struct s3c_ep {
85179 + struct usb_ep ep;
85180 + struct s3c_udc *dev;
85181 +
85182 + const struct usb_endpoint_descriptor *desc;
85183 + struct list_head queue;
85184 + unsigned long pio_irqs;
85185 +
85186 + u8 stopped;
85187 + u8 bEndpointAddress;
85188 + u8 bmAttributes;
85189 +
85190 + u32 ep_type;
85191 + u32 fifo;
85192 +#ifdef CONFIG_USB_GADGET_S3C_FS
85193 + u32 csr1;
85194 + u32 csr2;
85195 +#endif
85196 +};
85197 +
85198 +struct s3c_request {
85199 + struct usb_request req;
85200 + struct list_head queue;
85201 +};
85202 +
85203 +struct s3c_udc {
85204 + struct usb_gadget gadget;
85205 + struct usb_gadget_driver *driver;
85206 + struct platform_device *dev;
85207 + spinlock_t lock;
85208 + u32 * reg_base;
85209 +
85210 + int phyclk;
85211 + int ep0state;
85212 + struct s3c_ep ep[S3C_MAX_ENDPOINTS];
85213 +
85214 + unsigned char usb_address;
85215 +
85216 + unsigned req_pending:1;
85217 + unsigned req_std:1;
85218 + unsigned req_config:1;
85219 +};
85220 +
85221 +extern struct s3c_udc *the_controller;
85222 +
85223 +#define ep_is_in(EP) (((EP)->bEndpointAddress & USB_DIR_IN) \
85224 + == USB_DIR_IN)
85225 +#define ep_index(EP) ((EP)->bEndpointAddress & 0xF)
85226 +#define ep_maxpacket(EP) ((EP)->ep.maxpacket)
85227 +
85228 +#endif
85229 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/host/ohci-hcd.c linux-2.6.29-rc3.owrt.om/drivers/usb/host/ohci-hcd.c
85230 --- linux-2.6.29-rc3.owrt/drivers/usb/host/ohci-hcd.c 2009-05-10 22:04:48.000000000 +0200
85231 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/host/ohci-hcd.c 2009-05-10 22:28:00.000000000 +0200
85232 @@ -997,7 +997,7 @@
85233 #define SA1111_DRIVER ohci_hcd_sa1111_driver
85234 #endif
85235
85236 -#ifdef CONFIG_ARCH_S3C2410
85237 +#ifdef CONFIG_PLAT_S3C
85238 #include "ohci-s3c2410.c"
85239 #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver
85240 #endif
85241 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/host/ohci-s3c2410.c linux-2.6.29-rc3.owrt.om/drivers/usb/host/ohci-s3c2410.c
85242 --- linux-2.6.29-rc3.owrt/drivers/usb/host/ohci-s3c2410.c 2009-05-10 22:04:48.000000000 +0200
85243 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/host/ohci-s3c2410.c 2009-05-10 22:28:00.000000000 +0200
85244 @@ -21,9 +21,9 @@
85245
85246 #include <linux/platform_device.h>
85247 #include <linux/clk.h>
85248 -
85249 #include <mach/hardware.h>
85250 -#include <mach/usb-control.h>
85251 +#include <mach/regs-gpio.h>
85252 +#include <plat/usb-control.h>
85253
85254 #define valid_port(idx) ((idx) == 1 || (idx) == 2)
85255
85256 @@ -58,9 +58,8 @@
85257 info->hcd = hcd;
85258 info->report_oc = s3c2410_hcd_oc;
85259
85260 - if (info->enable_oc != NULL) {
85261 + if (info->enable_oc != NULL)
85262 (info->enable_oc)(info, 1);
85263 - }
85264 }
85265 }
85266
85267 @@ -74,9 +73,8 @@
85268 info->report_oc = NULL;
85269 info->hcd = NULL;
85270
85271 - if (info->enable_oc != NULL) {
85272 + if (info->enable_oc != NULL)
85273 (info->enable_oc)(info, 0);
85274 - }
85275 }
85276
85277 clk_disable(clk);
85278 @@ -90,14 +88,14 @@
85279 */
85280
85281 static int
85282 -ohci_s3c2410_hub_status_data (struct usb_hcd *hcd, char *buf)
85283 +ohci_s3c2410_hub_status_data(struct usb_hcd *hcd, char *buf)
85284 {
85285 struct s3c2410_hcd_info *info = to_s3c2410_info(hcd);
85286 struct s3c2410_hcd_port *port;
85287 int orig;
85288 int portno;
85289
85290 - orig = ohci_hub_status_data (hcd, buf);
85291 + orig = ohci_hub_status_data(hcd, buf);
85292
85293 if (info == NULL)
85294 return orig;
85295 @@ -147,7 +145,7 @@
85296 * request.
85297 */
85298
85299 -static int ohci_s3c2410_hub_control (
85300 +static int ohci_s3c2410_hub_control(
85301 struct usb_hcd *hcd,
85302 u16 typeReq,
85303 u16 wValue,
85304 @@ -201,9 +199,8 @@
85305 dev_dbg(hcd->self.controller,
85306 "ClearPortFeature: OVER_CURRENT\n");
85307
85308 - if (valid_port(wIndex)) {
85309 + if (valid_port(wIndex))
85310 info->port[wIndex-1].oc_status = 0;
85311 - }
85312
85313 goto out;
85314
85315 @@ -244,28 +241,28 @@
85316 desc->wHubCharacteristics |= cpu_to_le16(0x0001);
85317
85318 if (info->enable_oc) {
85319 - desc->wHubCharacteristics &= ~cpu_to_le16(HUB_CHAR_OCPM);
85320 - desc->wHubCharacteristics |= cpu_to_le16(0x0008|0x0001);
85321 + desc->wHubCharacteristics &=
85322 + ~cpu_to_le16(HUB_CHAR_OCPM);
85323 + desc->wHubCharacteristics |=
85324 + cpu_to_le16(0x0008|0x0001);
85325 }
85326
85327 - dev_dbg(hcd->self.controller, "wHubCharacteristics after 0x%04x\n",
85328 + dev_dbg(hcd->self.controller,
85329 + "wHubCharacteristics after 0x%04x\n",
85330 desc->wHubCharacteristics);
85331
85332 return ret;
85333
85334 case GetPortStatus:
85335 /* check port status */
85336 -
85337 dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex);
85338
85339 if (valid_port(wIndex)) {
85340 - if (info->port[wIndex-1].oc_changed) {
85341 + if (info->port[wIndex-1].oc_changed)
85342 *data |= cpu_to_le32(RH_PS_OCIC);
85343 - }
85344
85345 - if (info->port[wIndex-1].oc_status) {
85346 + if (info->port[wIndex-1].oc_status)
85347 *data |= cpu_to_le32(RH_PS_POCI);
85348 - }
85349 }
85350 }
85351
85352 @@ -308,6 +305,42 @@
85353 local_irq_restore(flags);
85354 }
85355
85356 +/* switching of USB pads */
85357 +static ssize_t show_usb_mode(struct device *dev, struct device_attribute *attr,
85358 + char *buf)
85359 +{
85360 + if (__raw_readl(S3C24XX_MISCCR) & S3C2410_MISCCR_USBHOST)
85361 + return sprintf(buf, "host\n");
85362 +
85363 + return sprintf(buf, "device\n");
85364 +}
85365 +
85366 +static ssize_t set_usb_mode(struct device *dev, struct device_attribute *attr,
85367 + const char *buf, size_t count)
85368 +{
85369 + if (!strncmp(buf, "host", 4)) {
85370 + printk(KERN_WARNING "s3c2410: changing usb to host\n");
85371 + s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST,
85372 + S3C2410_MISCCR_USBHOST);
85373 + /* FIXME:
85374 + * - call machine-specific disable-pullup function i
85375 + * - enable +Vbus (if hardware supports it)
85376 + */
85377 + s3c2410_gpio_setpin(S3C2410_GPB9, 0);
85378 + } else if (!strncmp(buf, "device", 6)) {
85379 + printk(KERN_WARNING "s3c2410: changing usb to device\n");
85380 + s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST, 0);
85381 + s3c2410_gpio_setpin(S3C2410_GPB9, 1);
85382 + } else {
85383 + printk(KERN_WARNING "s3c2410: unknown mode\n");
85384 + return -EINVAL;
85385 + }
85386 +
85387 + return count;
85388 +}
85389 +
85390 +static DEVICE_ATTR(usb_mode, S_IRUGO | S_IWUSR, show_usb_mode, set_usb_mode);
85391 +
85392 /* may be called without controller electrically present */
85393 /* may be called with controller, bus, and devices active */
85394
85395 @@ -323,8 +356,9 @@
85396 */
85397
85398 static void
85399 -usb_hcd_s3c2410_remove (struct usb_hcd *hcd, struct platform_device *dev)
85400 +usb_hcd_s3c2410_remove(struct usb_hcd *hcd, struct platform_device *dev)
85401 {
85402 + device_remove_file(&dev->dev, &dev_attr_usb_mode);
85403 usb_remove_hcd(hcd);
85404 s3c2410_stop_hc(dev);
85405 iounmap(hcd->regs);
85406 @@ -341,8 +375,8 @@
85407 * through the hotplug entry's driver_data.
85408 *
85409 */
85410 -static int usb_hcd_s3c2410_probe (const struct hc_driver *driver,
85411 - struct platform_device *dev)
85412 +static int usb_hcd_s3c2410_probe(const struct hc_driver *driver,
85413 + struct platform_device *dev)
85414 {
85415 struct usb_hcd *hcd = NULL;
85416 int retval;
85417 @@ -392,9 +426,16 @@
85418 if (retval != 0)
85419 goto err_ioremap;
85420
85421 + retval = device_create_file(&dev->dev, &dev_attr_usb_mode);
85422 + if (retval != 0)
85423 + goto err_hcd;
85424 +
85425 return 0;
85426
85427 - err_ioremap:
85428 +err_hcd:
85429 + usb_remove_hcd(hcd);
85430 +
85431 +err_ioremap:
85432 s3c2410_stop_hc(dev);
85433 iounmap(hcd->regs);
85434 clk_put(usb_clk);
85435 @@ -413,17 +454,19 @@
85436 /*-------------------------------------------------------------------------*/
85437
85438 static int
85439 -ohci_s3c2410_start (struct usb_hcd *hcd)
85440 +ohci_s3c2410_start(struct usb_hcd *hcd)
85441 {
85442 - struct ohci_hcd *ohci = hcd_to_ohci (hcd);
85443 + struct ohci_hcd *ohci = hcd_to_ohci(hcd);
85444 int ret;
85445
85446 - if ((ret = ohci_init(ohci)) < 0)
85447 + ret = ohci_init(ohci);
85448 + if (ret < 0)
85449 return ret;
85450
85451 - if ((ret = ohci_run (ohci)) < 0) {
85452 - err ("can't start %s", hcd->self.bus_name);
85453 - ohci_stop (hcd);
85454 + ret = ohci_run(ohci);
85455 + if (ret < 0) {
85456 + err("can't start %s", hcd->self.bus_name);
85457 + ohci_stop(hcd);
85458 return ret;
85459 }
85460
85461 @@ -488,15 +531,23 @@
85462 return 0;
85463 }
85464
85465 +static int ohci_hcd_s3c2410_drv_resume(struct platform_device *pdev)
85466 +{
85467 + struct usb_hcd *hcd = platform_get_drvdata(pdev);
85468 +
85469 + ohci_finish_controller_resume(hcd);
85470 + return 0;
85471 +}
85472 +
85473 static struct platform_driver ohci_hcd_s3c2410_driver = {
85474 .probe = ohci_hcd_s3c2410_drv_probe,
85475 .remove = ohci_hcd_s3c2410_drv_remove,
85476 .shutdown = usb_hcd_platform_shutdown,
85477 /*.suspend = ohci_hcd_s3c2410_drv_suspend, */
85478 - /*.resume = ohci_hcd_s3c2410_drv_resume, */
85479 + .resume = ohci_hcd_s3c2410_drv_resume,
85480 .driver = {
85481 .owner = THIS_MODULE,
85482 - .name = "s3c2410-ohci",
85483 + .name = "s3c-ohci",
85484 },
85485 };
85486
85487 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/usb/Kconfig linux-2.6.29-rc3.owrt.om/drivers/usb/Kconfig
85488 --- linux-2.6.29-rc3.owrt/drivers/usb/Kconfig 2009-05-10 22:04:48.000000000 +0200
85489 +++ linux-2.6.29-rc3.owrt.om/drivers/usb/Kconfig 2009-05-10 22:28:00.000000000 +0200
85490 @@ -31,7 +31,7 @@
85491 default y if SA1111
85492 default y if ARCH_OMAP
85493 default y if ARCH_LH7A404
85494 - default y if ARCH_S3C2410
85495 + default y if PLAT_S3C
85496 default y if PXA27x
85497 default y if PXA3xx
85498 default y if ARCH_EP93XX
85499 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/backlight/gta01_bl.c linux-2.6.29-rc3.owrt.om/drivers/video/backlight/gta01_bl.c
85500 --- linux-2.6.29-rc3.owrt/drivers/video/backlight/gta01_bl.c 1970-01-01 01:00:00.000000000 +0100
85501 +++ linux-2.6.29-rc3.owrt.om/drivers/video/backlight/gta01_bl.c 2009-05-10 22:28:00.000000000 +0200
85502 @@ -0,0 +1,269 @@
85503 +/*
85504 + * Backlight Driver for FIC GTA01 (Neo1973) GSM Phone
85505 + *
85506 + * Copyright (C) 2006-2007 by Openmoko, Inc.
85507 + * Author: Harald Welte <laforge@openmoko.org>
85508 + * All rights reserved.
85509 + *
85510 + * based on corgi_cl.c, Copyright (c) 2004-2006 Richard Purdie
85511 + *
85512 + * This program is free software; you can redistribute it and/or
85513 + * modify it under the terms of the GNU General Public License as
85514 + * published by the Free Software Foundation, version 2.
85515 + *
85516 + * This program is distributed in the hope that it will be useful,
85517 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
85518 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85519 + * GNU General Public License for more details.
85520 + *
85521 + * You should have received a copy of the GNU General Public License
85522 + * along with this program; if not, write to the Free Software
85523 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
85524 + * MA 02111-1307 USA
85525 + *
85526 + * Javi Roman <javiroman@kernel-labs.org>:
85527 + * implement PWM, instead of simple on/off switching
85528 + *
85529 + */
85530 +
85531 +#include <linux/module.h>
85532 +#include <linux/kernel.h>
85533 +#include <linux/init.h>
85534 +#include <linux/platform_device.h>
85535 +#include <linux/mutex.h>
85536 +#include <linux/fb.h>
85537 +#include <linux/backlight.h>
85538 +#include <linux/clk.h>
85539 +
85540 +#include <mach/hardware.h>
85541 +#include <mach/gta01.h>
85542 +#include <plat/pwm.h>
85543 +
85544 +#include <plat/regs-timer.h>
85545 +#include <asm/plat-s3c24xx/neo1973.h>
85546 +
85547 +static struct backlight_properties gta01bl_prop;
85548 +static struct backlight_device *gta01_backlight_device;
85549 +static struct gta01bl_machinfo *bl_machinfo;
85550 +
85551 +static unsigned long gta01bl_flags;
85552 +
85553 +struct gta01bl_data {
85554 + int intensity;
85555 + struct mutex mutex;
85556 + struct clk *clk;
85557 + struct s3c2410_pwm pwm;
85558 +};
85559 +
85560 +static struct gta01bl_data gta01bl;
85561 +
85562 +static int gta01bl_defer_resume_backlight;
85563 +
85564 +#define GTA01BL_SUSPENDED 0x01
85565 +#define GTA01BL_BATTLOW 0x02
85566 +
85567 +/* On the GTA01 / Neo1973, we use a 50 or 66MHz PCLK, which gives
85568 + * us a 6.25..8.25MHz DIV8 clock, which is further divided by a
85569 + * prescaler of 4, resulting in a 1.56..2.06MHz tick. This results in a
85570 + * minimum frequency of 24..31Hz. At 400Hz, we need to set the count
85571 + * to something like 3906..5156, providing us a way sufficient resolution
85572 + * for display brightness adjustment. */
85573 +#define GTA01BL_COUNTER 5156
85574 +
85575 +static int gta01bl_send_intensity(struct backlight_device *bd)
85576 +{
85577 + int intensity = bd->props.brightness;
85578 +
85579 + if (bd->props.power != FB_BLANK_UNBLANK)
85580 + intensity = 0;
85581 + if (bd->props.fb_blank != FB_BLANK_UNBLANK)
85582 + intensity = 0;
85583 + if (gta01bl_flags & GTA01BL_SUSPENDED)
85584 + intensity = 0;
85585 + if (gta01bl_flags & GTA01BL_BATTLOW)
85586 + intensity &= bl_machinfo->limit_mask;
85587 +
85588 + mutex_lock(&gta01bl.mutex);
85589 +#ifdef GTA01_BACKLIGHT_ONOFF_ONLY
85590 + if (intensity)
85591 + neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 1);
85592 + else
85593 + neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 0);
85594 +#else
85595 + if (intensity == bd->props.max_brightness) {
85596 + neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 1);
85597 + s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
85598 + } else {
85599 + s3c2410_pwm_duty_cycle(intensity & 0xffff, &gta01bl.pwm);
85600 + s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPB0_TOUT0);
85601 + }
85602 +#endif
85603 + mutex_unlock(&gta01bl.mutex);
85604 +
85605 + gta01bl.intensity = intensity;
85606 + return 0;
85607 +}
85608 +
85609 +static int gta01bl_init_hw(void)
85610 +{
85611 + int rc;
85612 +
85613 + rc = s3c2410_pwm_init(&gta01bl.pwm);
85614 + if (rc)
85615 + return rc;
85616 +
85617 + gta01bl.pwm.timerid = PWM0;
85618 + gta01bl.pwm.prescaler = (4 - 1);
85619 + gta01bl.pwm.divider = S3C2410_TCFG1_MUX0_DIV8;
85620 + gta01bl.pwm.counter = GTA01BL_COUNTER;
85621 + gta01bl.pwm.comparer = gta01bl.pwm.counter;
85622 +
85623 + rc = s3c2410_pwm_enable(&gta01bl.pwm);
85624 + if (rc)
85625 + return rc;
85626 +
85627 + s3c2410_pwm_start(&gta01bl.pwm);
85628 +
85629 + gta01bl_prop.max_brightness = gta01bl.pwm.counter;
85630 +
85631 + return 0;
85632 +}
85633 +
85634 +#ifdef CONFIG_PM
85635 +static int gta01bl_suspend(struct platform_device *dev, pm_message_t state)
85636 +{
85637 + gta01bl_flags |= GTA01BL_SUSPENDED;
85638 + gta01bl_send_intensity(gta01_backlight_device);
85639 + neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 0);
85640 + s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
85641 + return 0;
85642 +}
85643 +
85644 +void gta01bl_deferred_resume(void)
85645 +{
85646 + mutex_lock(&gta01bl.mutex);
85647 + gta01bl_init_hw();
85648 + mutex_unlock(&gta01bl.mutex);
85649 +
85650 + gta01bl_flags &= ~GTA01BL_SUSPENDED;
85651 + gta01bl_send_intensity(gta01_backlight_device);
85652 +}
85653 +EXPORT_SYMBOL_GPL(gta01bl_deferred_resume);
85654 +
85655 +static int gta01bl_resume(struct platform_device *dev)
85656 +{
85657 + if (!gta01bl_defer_resume_backlight)
85658 + gta01bl_deferred_resume();
85659 + return 0;
85660 +}
85661 +#else
85662 +#define gta01bl_suspend NULL
85663 +#define gta01bl_resume NULL
85664 +#endif
85665 +
85666 +static int gta01bl_get_intensity(struct backlight_device *bd)
85667 +{
85668 + return gta01bl.intensity;
85669 +}
85670 +
85671 +static int gta01bl_set_intensity(struct backlight_device *bd)
85672 +{
85673 + gta01bl_send_intensity(gta01_backlight_device);
85674 + return 0;
85675 +}
85676 +
85677 +/*
85678 + * Called when the battery is low to limit the backlight intensity.
85679 + * If limit==0 clear any limit, otherwise limit the intensity
85680 + */
85681 +void gta01bl_limit_intensity(int limit)
85682 +{
85683 + if (limit)
85684 + gta01bl_flags |= GTA01BL_BATTLOW;
85685 + else
85686 + gta01bl_flags &= ~GTA01BL_BATTLOW;
85687 + gta01bl_send_intensity(gta01_backlight_device);
85688 +}
85689 +EXPORT_SYMBOL_GPL(gta01bl_limit_intensity);
85690 +
85691 +
85692 +static struct backlight_ops gta01bl_ops = {
85693 + .get_brightness = gta01bl_get_intensity,
85694 + .update_status = gta01bl_set_intensity,
85695 +};
85696 +
85697 +static int __init gta01bl_probe(struct platform_device *pdev)
85698 +{
85699 + struct gta01bl_machinfo *machinfo = pdev->dev.platform_data;
85700 + int rc;
85701 +
85702 +#ifdef GTA01_BACKLIGHT_ONOFF_ONLY
85703 + s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
85704 + gta01bl_prop.max_brightness = 1;
85705 +#else
85706 + rc = gta01bl_init_hw();
85707 + if (rc < 0)
85708 + return rc;
85709 +#endif
85710 + mutex_init(&gta01bl.mutex);
85711 +
85712 + if (!machinfo->limit_mask)
85713 + machinfo->limit_mask = -1;
85714 +
85715 + gta01bl_defer_resume_backlight = machinfo->defer_resume_backlight;
85716 +
85717 + gta01_backlight_device = backlight_device_register("gta01-bl",
85718 + &pdev->dev, NULL,
85719 + &gta01bl_ops);
85720 + if (IS_ERR(gta01_backlight_device))
85721 + return PTR_ERR(gta01_backlight_device);
85722 +
85723 + gta01bl_prop.power = FB_BLANK_UNBLANK;
85724 + gta01bl_prop.brightness = gta01bl_prop.max_brightness;
85725 + memcpy(&gta01_backlight_device->props,
85726 + &gta01bl_prop, sizeof(gta01bl_prop));
85727 + gta01bl_send_intensity(gta01_backlight_device);
85728 +
85729 + return 0;
85730 +}
85731 +
85732 +static int gta01bl_remove(struct platform_device *dev)
85733 +{
85734 +#ifndef GTA01_BACKLIGHT_ONOFF_ONLY
85735 + s3c2410_pwm_disable(&gta01bl.pwm);
85736 +#endif
85737 + backlight_device_unregister(gta01_backlight_device);
85738 + mutex_destroy(&gta01bl.mutex);
85739 +
85740 + s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
85741 + neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 1);
85742 +
85743 + return 0;
85744 +}
85745 +
85746 +static struct platform_driver gta01bl_driver = {
85747 + .probe = gta01bl_probe,
85748 + .remove = gta01bl_remove,
85749 + .suspend = gta01bl_suspend,
85750 + .resume = gta01bl_resume,
85751 + .driver = {
85752 + .name = "gta01-bl",
85753 + },
85754 +};
85755 +
85756 +static int __init gta01bl_init(void)
85757 +{
85758 + return platform_driver_register(&gta01bl_driver);
85759 +}
85760 +
85761 +static void __exit gta01bl_exit(void)
85762 +{
85763 + platform_driver_unregister(&gta01bl_driver);
85764 +}
85765 +
85766 +module_init(gta01bl_init);
85767 +module_exit(gta01bl_exit);
85768 +
85769 +MODULE_DESCRIPTION("FIC GTA01 (Neo1973) Backlight Driver");
85770 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
85771 +MODULE_LICENSE("GPL");
85772 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/backlight/Kconfig linux-2.6.29-rc3.owrt.om/drivers/video/backlight/Kconfig
85773 --- linux-2.6.29-rc3.owrt/drivers/video/backlight/Kconfig 2009-05-10 22:04:48.000000000 +0200
85774 +++ linux-2.6.29-rc3.owrt.om/drivers/video/backlight/Kconfig 2009-05-10 22:28:00.000000000 +0200
85775 @@ -149,6 +149,13 @@
85776 the PWL module of OMAP1 processors. Say Y if your board
85777 uses this hardware.
85778
85779 +config BACKLIGHT_GTA01
85780 + tristate "FIC Neo1973 GTA01 Backlight Driver"
85781 + depends on BACKLIGHT_CLASS_DEVICE && MACH_NEO1973_GTA01
85782 + default y
85783 + help
85784 + If you have a FIC Neo1973 GTA01, say y to enable the backlight driver.
85785 +
85786 config BACKLIGHT_HP680
85787 tristate "HP Jornada 680 Backlight Driver"
85788 depends on BACKLIGHT_CLASS_DEVICE && SH_HP6XX
85789 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/backlight/Makefile linux-2.6.29-rc3.owrt.om/drivers/video/backlight/Makefile
85790 --- linux-2.6.29-rc3.owrt/drivers/video/backlight/Makefile 2009-05-10 22:08:45.000000000 +0200
85791 +++ linux-2.6.29-rc3.owrt.om/drivers/video/backlight/Makefile 2009-05-10 22:28:00.000000000 +0200
85792 @@ -12,6 +12,8 @@
85793 obj-$(CONFIG_BACKLIGHT_CLASS_DEVICE) += backlight.o
85794 obj-$(CONFIG_BACKLIGHT_ATMEL_PWM) += atmel-pwm-bl.o
85795 obj-$(CONFIG_BACKLIGHT_GENERIC) += generic_bl.o
85796 +obj-$(CONFIG_BACKLIGHT_CORGI) += corgi_bl.o
85797 +obj-$(CONFIG_BACKLIGHT_GTA01) += gta01_bl.o
85798 obj-$(CONFIG_BACKLIGHT_HP680) += hp680_bl.o
85799 obj-$(CONFIG_BACKLIGHT_LOCOMO) += locomolcd.o
85800 obj-$(CONFIG_BACKLIGHT_OMAP1) += omap1_bl.o
85801 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/console/fbcon.c linux-2.6.29-rc3.owrt.om/drivers/video/console/fbcon.c
85802 --- linux-2.6.29-rc3.owrt/drivers/video/console/fbcon.c 2009-05-10 22:04:48.000000000 +0200
85803 +++ linux-2.6.29-rc3.owrt.om/drivers/video/console/fbcon.c 2009-05-10 22:28:00.000000000 +0200
85804 @@ -373,6 +373,9 @@
85805 int c;
85806 int mode;
85807
85808 + if (info->state != FBINFO_STATE_RUNNING)
85809 + return;
85810 +
85811 acquire_console_sem();
85812 if (ops && ops->currcon != -1)
85813 vc = vc_cons[ops->currcon].d;
85814 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/display/jbt6k74.c linux-2.6.29-rc3.owrt.om/drivers/video/display/jbt6k74.c
85815 --- linux-2.6.29-rc3.owrt/drivers/video/display/jbt6k74.c 1970-01-01 01:00:00.000000000 +0100
85816 +++ linux-2.6.29-rc3.owrt.om/drivers/video/display/jbt6k74.c 2009-05-10 22:28:00.000000000 +0200
85817 @@ -0,0 +1,768 @@
85818 +/* Linux kernel driver for the tpo JBT6K74-AS LCM ASIC
85819 + *
85820 + * Copyright (C) 2006-2007 by Openmoko, Inc.
85821 + * Author: Harald Welte <laforge@openmoko.org>,
85822 + * Stefan Schmidt <stefan@openmoko.org>
85823 + * Copyright (C) 2008 by Harald Welte <laforge@openmoko.org>
85824 + * All rights reserved.
85825 + *
85826 + * This program is free software; you can redistribute it and/or
85827 + * modify it under the terms of the GNU General Public License as
85828 + * published by the Free Software Foundation; either version 2 of
85829 + * the License, or (at your option) any later version.
85830 + *
85831 + * This program is distributed in the hope that it will be useful,
85832 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
85833 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
85834 + * GNU General Public License for more details.
85835 + *
85836 + * You should have received a copy of the GNU General Public License
85837 + * along with this program; if not, write to the Free Software
85838 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
85839 + * MA 02111-1307 USA
85840 + *
85841 + */
85842 +
85843 +#include <linux/kernel.h>
85844 +#include <linux/types.h>
85845 +#include <linux/module.h>
85846 +#include <linux/device.h>
85847 +#include <linux/platform_device.h>
85848 +#include <linux/delay.h>
85849 +#include <linux/jbt6k74.h>
85850 +#include <linux/fb.h>
85851 +#include <linux/time.h>
85852 +
85853 +enum jbt_register {
85854 + JBT_REG_SLEEP_IN = 0x10,
85855 + JBT_REG_SLEEP_OUT = 0x11,
85856 +
85857 + JBT_REG_DISPLAY_OFF = 0x28,
85858 + JBT_REG_DISPLAY_ON = 0x29,
85859 +
85860 + JBT_REG_RGB_FORMAT = 0x3a,
85861 + JBT_REG_QUAD_RATE = 0x3b,
85862 +
85863 + JBT_REG_POWER_ON_OFF = 0xb0,
85864 + JBT_REG_BOOSTER_OP = 0xb1,
85865 + JBT_REG_BOOSTER_MODE = 0xb2,
85866 + JBT_REG_BOOSTER_FREQ = 0xb3,
85867 + JBT_REG_OPAMP_SYSCLK = 0xb4,
85868 + JBT_REG_VSC_VOLTAGE = 0xb5,
85869 + JBT_REG_VCOM_VOLTAGE = 0xb6,
85870 + JBT_REG_EXT_DISPL = 0xb7,
85871 + JBT_REG_OUTPUT_CONTROL = 0xb8,
85872 + JBT_REG_DCCLK_DCEV = 0xb9,
85873 + JBT_REG_DISPLAY_MODE1 = 0xba,
85874 + JBT_REG_DISPLAY_MODE2 = 0xbb,
85875 + JBT_REG_DISPLAY_MODE = 0xbc,
85876 + JBT_REG_ASW_SLEW = 0xbd,
85877 + JBT_REG_DUMMY_DISPLAY = 0xbe,
85878 + JBT_REG_DRIVE_SYSTEM = 0xbf,
85879 +
85880 + JBT_REG_SLEEP_OUT_FR_A = 0xc0,
85881 + JBT_REG_SLEEP_OUT_FR_B = 0xc1,
85882 + JBT_REG_SLEEP_OUT_FR_C = 0xc2,
85883 + JBT_REG_SLEEP_IN_LCCNT_D = 0xc3,
85884 + JBT_REG_SLEEP_IN_LCCNT_E = 0xc4,
85885 + JBT_REG_SLEEP_IN_LCCNT_F = 0xc5,
85886 + JBT_REG_SLEEP_IN_LCCNT_G = 0xc6,
85887 +
85888 + JBT_REG_GAMMA1_FINE_1 = 0xc7,
85889 + JBT_REG_GAMMA1_FINE_2 = 0xc8,
85890 + JBT_REG_GAMMA1_INCLINATION = 0xc9,
85891 + JBT_REG_GAMMA1_BLUE_OFFSET = 0xca,
85892 +
85893 + /* VGA */
85894 + JBT_REG_BLANK_CONTROL = 0xcf,
85895 + JBT_REG_BLANK_TH_TV = 0xd0,
85896 + JBT_REG_CKV_ON_OFF = 0xd1,
85897 + JBT_REG_CKV_1_2 = 0xd2,
85898 + JBT_REG_OEV_TIMING = 0xd3,
85899 + JBT_REG_ASW_TIMING_1 = 0xd4,
85900 + JBT_REG_ASW_TIMING_2 = 0xd5,
85901 +
85902 + /* QVGA */
85903 + JBT_REG_BLANK_CONTROL_QVGA = 0xd6,
85904 + JBT_REG_BLANK_TH_TV_QVGA = 0xd7,
85905 + JBT_REG_CKV_ON_OFF_QVGA = 0xd8,
85906 + JBT_REG_CKV_1_2_QVGA = 0xd9,
85907 + JBT_REG_OEV_TIMING_QVGA = 0xde,
85908 + JBT_REG_ASW_TIMING_1_QVGA = 0xdf,
85909 + JBT_REG_ASW_TIMING_2_QVGA = 0xe0,
85910 +
85911 +
85912 + JBT_REG_HCLOCK_VGA = 0xec,
85913 + JBT_REG_HCLOCK_QVGA = 0xed,
85914 +
85915 +};
85916 +
85917 +enum jbt_state {
85918 + JBT_STATE_DEEP_STANDBY,
85919 + JBT_STATE_SLEEP,
85920 + JBT_STATE_NORMAL,
85921 + JBT_STATE_QVGA_NORMAL,
85922 +};
85923 +
85924 +static const char *jbt_state_names[] = {
85925 + [JBT_STATE_DEEP_STANDBY] = "deep-standby",
85926 + [JBT_STATE_SLEEP] = "sleep",
85927 + [JBT_STATE_NORMAL] = "normal",
85928 + [JBT_STATE_QVGA_NORMAL] = "qvga-normal",
85929 +};
85930 +
85931 +struct jbt_info {
85932 + enum jbt_state state, normal_state;
85933 + struct spi_device *spi_dev;
85934 + struct mutex lock; /* protects tx_buf and reg_cache */
85935 + struct notifier_block fb_notif;
85936 + u16 tx_buf[8];
85937 + u16 reg_cache[0xEE];
85938 + struct timespec last_sleep;
85939 +};
85940 +
85941 +#define JBT_COMMAND 0x000
85942 +#define JBT_DATA 0x100
85943 +
85944 +static inline unsigned int timespec_sub_ms(struct timespec lhs,
85945 + struct timespec rhs)
85946 +{
85947 + struct timespec ts = timespec_sub(lhs, rhs);
85948 + return (ts.tv_sec * MSEC_PER_SEC) + (ts.tv_nsec / NSEC_PER_MSEC);
85949 +}
85950 +
85951 +static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
85952 +{
85953 + int rc;
85954 +
85955 + jbt->tx_buf[0] = JBT_COMMAND | reg;
85956 + rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
85957 + 1*sizeof(u16));
85958 + if (rc == 0)
85959 + jbt->reg_cache[reg] = 0;
85960 + else
85961 + printk(KERN_ERR"jbt_reg_write_nodata spi_write ret %d\n",
85962 + rc);
85963 +
85964 + return rc;
85965 +}
85966 +
85967 +
85968 +static int jbt_reg_write(struct jbt_info *jbt, u8 reg, u8 data)
85969 +{
85970 + int rc;
85971 +
85972 + jbt->tx_buf[0] = JBT_COMMAND | reg;
85973 + jbt->tx_buf[1] = JBT_DATA | data;
85974 + rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
85975 + 2*sizeof(u16));
85976 + if (rc == 0)
85977 + jbt->reg_cache[reg] = data;
85978 + else
85979 + printk(KERN_ERR"jbt_reg_write spi_write ret %d\n", rc);
85980 +
85981 + return rc;
85982 +}
85983 +
85984 +static int jbt_reg_write16(struct jbt_info *jbt, u8 reg, u16 data)
85985 +{
85986 + int rc;
85987 +
85988 + jbt->tx_buf[0] = JBT_COMMAND | reg;
85989 + jbt->tx_buf[1] = JBT_DATA | (data >> 8);
85990 + jbt->tx_buf[2] = JBT_DATA | (data & 0xff);
85991 +
85992 + rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
85993 + 3*sizeof(u16));
85994 + if (rc == 0)
85995 + jbt->reg_cache[reg] = data;
85996 + else
85997 + printk(KERN_ERR"jbt_reg_write16 spi_write ret %d\n", rc);
85998 +
85999 + return rc;
86000 +}
86001 +
86002 +static int jbt_init_regs(struct jbt_info *jbt)
86003 +{
86004 + int rc;
86005 +
86006 + dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n",
86007 + jbt->normal_state == JBT_STATE_QVGA_NORMAL ? 'Q' : ' ');
86008 +
86009 + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE1, 0x01);
86010 + rc |= jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE2, 0x00);
86011 + rc |= jbt_reg_write(jbt, JBT_REG_RGB_FORMAT, 0x60);
86012 + rc |= jbt_reg_write(jbt, JBT_REG_DRIVE_SYSTEM, 0x10);
86013 + rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_OP, 0x56);
86014 + rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_MODE, 0x33);
86015 + rc |= jbt_reg_write(jbt, JBT_REG_BOOSTER_FREQ, 0x11);
86016 + rc |= jbt_reg_write(jbt, JBT_REG_OPAMP_SYSCLK, 0x02);
86017 + rc |= jbt_reg_write(jbt, JBT_REG_VSC_VOLTAGE, 0x2b);
86018 + rc |= jbt_reg_write(jbt, JBT_REG_VCOM_VOLTAGE, 0x40);
86019 + rc |= jbt_reg_write(jbt, JBT_REG_EXT_DISPL, 0x03);
86020 + rc |= jbt_reg_write(jbt, JBT_REG_DCCLK_DCEV, 0x04);
86021 + /*
86022 + * default of 0x02 in JBT_REG_ASW_SLEW responsible for 72Hz requirement
86023 + * to avoid red / blue flicker
86024 + */
86025 + rc |= jbt_reg_write(jbt, JBT_REG_ASW_SLEW, 0x04);
86026 + rc |= jbt_reg_write(jbt, JBT_REG_DUMMY_DISPLAY, 0x00);
86027 +
86028 + rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_A, 0x11);
86029 + rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_B, 0x11);
86030 + rc |= jbt_reg_write(jbt, JBT_REG_SLEEP_OUT_FR_C, 0x11);
86031 + rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_D, 0x2040);
86032 + rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_E, 0x60c0);
86033 + rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_F, 0x1020);
86034 + rc |= jbt_reg_write16(jbt, JBT_REG_SLEEP_IN_LCCNT_G, 0x60c0);
86035 +
86036 + rc |= jbt_reg_write16(jbt, JBT_REG_GAMMA1_FINE_1, 0x5533);
86037 + rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_FINE_2, 0x00);
86038 + rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_INCLINATION, 0x00);
86039 + rc |= jbt_reg_write(jbt, JBT_REG_GAMMA1_BLUE_OFFSET, 0x00);
86040 +
86041 + if (jbt->normal_state != JBT_STATE_QVGA_NORMAL) {
86042 + rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_VGA, 0x1f0);
86043 + rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL, 0x02);
86044 + rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV, 0x0804);
86045 +
86046 + rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF, 0x01);
86047 + rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2, 0x0000);
86048 +
86049 + rc |= jbt_reg_write16(jbt, JBT_REG_OEV_TIMING, 0x0d0e);
86050 + rc |= jbt_reg_write16(jbt, JBT_REG_ASW_TIMING_1, 0x11a4);
86051 + rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2, 0x0e);
86052 + } else {
86053 + rc |= jbt_reg_write16(jbt, JBT_REG_HCLOCK_QVGA, 0x00ff);
86054 + rc |= jbt_reg_write(jbt, JBT_REG_BLANK_CONTROL_QVGA, 0x02);
86055 + rc |= jbt_reg_write16(jbt, JBT_REG_BLANK_TH_TV_QVGA, 0x0804);
86056 +
86057 + rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF_QVGA, 0x01);
86058 + rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2_QVGA, 0x0008);
86059 +
86060 + rc |= jbt_reg_write16(jbt, JBT_REG_OEV_TIMING_QVGA, 0x050a);
86061 + rc |= jbt_reg_write16(jbt, JBT_REG_ASW_TIMING_1_QVGA, 0x0a19);
86062 + rc |= jbt_reg_write(jbt, JBT_REG_ASW_TIMING_2_QVGA, 0x0a);
86063 + }
86064 +
86065 + return rc ? -EIO : 0;
86066 +}
86067 +
86068 +static int standby_to_sleep(struct jbt_info *jbt)
86069 +{
86070 + int rc;
86071 +
86072 + /* three times command zero */
86073 + rc = jbt_reg_write_nodata(jbt, 0x00);
86074 + mdelay(1);
86075 + rc |= jbt_reg_write_nodata(jbt, 0x00);
86076 + mdelay(1);
86077 + rc |= jbt_reg_write_nodata(jbt, 0x00);
86078 + mdelay(1);
86079 +
86080 + /* deep standby out */
86081 + rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x11);
86082 + mdelay(1);
86083 + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x28);
86084 +
86085 + /* (re)initialize register set */
86086 + rc |= jbt_init_regs(jbt);
86087 +
86088 + return rc ? -EIO : 0;
86089 +}
86090 +
86091 +static int sleep_to_normal(struct jbt_info *jbt)
86092 +{
86093 + int rc;
86094 +
86095 + /* Make sure we are 120 ms after SLEEP_OUT */
86096 + unsigned int sleep_time = timespec_sub_ms(current_kernel_time(),
86097 + jbt->last_sleep);
86098 + if (sleep_time < 120)
86099 + mdelay(120 - sleep_time);
86100 +
86101 + if (jbt->normal_state == JBT_STATE_NORMAL) {
86102 + /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */
86103 + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x80);
86104 +
86105 + /* Quad mode off */
86106 + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00);
86107 + } else {
86108 + /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */
86109 + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81);
86110 +
86111 + /* Quad mode on */
86112 + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22);
86113 + }
86114 +
86115 + /* AVDD on, XVDD on */
86116 + rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16);
86117 +
86118 + /* Output control */
86119 + rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9);
86120 +
86121 + /* Turn on display */
86122 + rc |= jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON);
86123 +
86124 + /* Sleep mode off */
86125 + rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
86126 + jbt->last_sleep = current_kernel_time();
86127 +
86128 + /* Allow the booster and display controller to restart stably */
86129 + mdelay(5);
86130 +
86131 + return rc ? -EIO : 0;
86132 +}
86133 +
86134 +static int normal_to_sleep(struct jbt_info *jbt)
86135 +{
86136 + int rc;
86137 +
86138 + /* Make sure we are 120 ms after SLEEP_OUT */
86139 + unsigned int sleep_time = timespec_sub_ms(current_kernel_time(),
86140 + jbt->last_sleep);
86141 + if (sleep_time < 120)
86142 + mdelay(120 - sleep_time);
86143 +
86144 + rc = jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_OFF);
86145 + rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0x8002);
86146 + rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_IN);
86147 + jbt->last_sleep = current_kernel_time();
86148 +
86149 + /* Allow the internal circuits to stop automatically */
86150 + mdelay(5);
86151 +
86152 + return rc ? -EIO : 0;
86153 +}
86154 +
86155 +static int sleep_to_standby(struct jbt_info *jbt)
86156 +{
86157 + return jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x00);
86158 +}
86159 +
86160 +/* frontend function */
86161 +int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state)
86162 +{
86163 + int rc = -EINVAL;
86164 +
86165 + dev_dbg(&jbt->spi_dev->dev, "entering (old_state=%s, new_state=%s)\n",
86166 + jbt_state_names[jbt->state],
86167 + jbt_state_names[new_state]);
86168 +
86169 + mutex_lock(&jbt->lock);
86170 +
86171 + if (new_state == JBT_STATE_NORMAL ||
86172 + new_state == JBT_STATE_QVGA_NORMAL)
86173 + jbt->normal_state = new_state;
86174 +
86175 + switch (jbt->state) {
86176 + case JBT_STATE_DEEP_STANDBY:
86177 + switch (new_state) {
86178 + case JBT_STATE_DEEP_STANDBY:
86179 + rc = 0;
86180 + break;
86181 + case JBT_STATE_SLEEP:
86182 + rc = standby_to_sleep(jbt);
86183 + break;
86184 + case JBT_STATE_NORMAL:
86185 + /* first transition into sleep */
86186 + rc = standby_to_sleep(jbt);
86187 + /* then transition into normal */
86188 + rc |= sleep_to_normal(jbt);
86189 + break;
86190 + case JBT_STATE_QVGA_NORMAL:
86191 + /* first transition into sleep */
86192 + rc = standby_to_sleep(jbt);
86193 + /* then transition into normal */
86194 + rc |= sleep_to_normal(jbt);
86195 + break;
86196 + }
86197 + break;
86198 + case JBT_STATE_SLEEP:
86199 + switch (new_state) {
86200 + case JBT_STATE_SLEEP:
86201 + rc = 0;
86202 + break;
86203 + case JBT_STATE_DEEP_STANDBY:
86204 + rc = sleep_to_standby(jbt);
86205 + break;
86206 + case JBT_STATE_NORMAL:
86207 + case JBT_STATE_QVGA_NORMAL:
86208 + rc = sleep_to_normal(jbt);
86209 + break;
86210 + }
86211 + break;
86212 + case JBT_STATE_NORMAL:
86213 + switch (new_state) {
86214 + case JBT_STATE_NORMAL:
86215 + rc = 0;
86216 + break;
86217 + case JBT_STATE_DEEP_STANDBY:
86218 + /* first transition into sleep */
86219 + rc = normal_to_sleep(jbt);
86220 + /* then transition into deep standby */
86221 + rc |= sleep_to_standby(jbt);
86222 + break;
86223 + case JBT_STATE_SLEEP:
86224 + rc = normal_to_sleep(jbt);
86225 + break;
86226 + case JBT_STATE_QVGA_NORMAL:
86227 + /* first transition into sleep */
86228 + rc = normal_to_sleep(jbt);
86229 + /* second transition into deep standby */
86230 + rc |= sleep_to_standby(jbt);
86231 + /* third transition into sleep */
86232 + rc |= standby_to_sleep(jbt);
86233 + /* fourth transition into normal */
86234 + rc |= sleep_to_normal(jbt);
86235 + break;
86236 + }
86237 + break;
86238 + case JBT_STATE_QVGA_NORMAL:
86239 + switch (new_state) {
86240 + case JBT_STATE_QVGA_NORMAL:
86241 + rc = 0;
86242 + break;
86243 + case JBT_STATE_DEEP_STANDBY:
86244 + /* first transition into sleep */
86245 + rc = normal_to_sleep(jbt);
86246 + /* then transition into deep standby */
86247 + rc |= sleep_to_standby(jbt);
86248 + break;
86249 + case JBT_STATE_SLEEP:
86250 + rc = normal_to_sleep(jbt);
86251 + break;
86252 + case JBT_STATE_NORMAL:
86253 + /* first transition into sleep */
86254 + rc = normal_to_sleep(jbt);
86255 + /* second transition into deep standby */
86256 + rc |= sleep_to_standby(jbt);
86257 + /* third transition into sleep */
86258 + rc |= standby_to_sleep(jbt);
86259 + /* fourth transition into normal */
86260 + rc |= sleep_to_normal(jbt);
86261 + break;
86262 + }
86263 + break;
86264 + }
86265 +
86266 + if (rc == 0)
86267 + jbt->state = new_state;
86268 + else
86269 + dev_err(&jbt->spi_dev->dev, "Failed enter state '%s')\n",
86270 + jbt_state_names[new_state]);
86271 +
86272 + mutex_unlock(&jbt->lock);
86273 +
86274 + return rc;
86275 +}
86276 +EXPORT_SYMBOL_GPL(jbt6k74_enter_state);
86277 +
86278 +static ssize_t state_read(struct device *dev, struct device_attribute *attr,
86279 + char *buf)
86280 +{
86281 + struct jbt_info *jbt = dev_get_drvdata(dev);
86282 +
86283 + if (jbt->state >= ARRAY_SIZE(jbt_state_names))
86284 + return -EIO;
86285 +
86286 + return sprintf(buf, "%s\n", jbt_state_names[jbt->state]);
86287 +}
86288 +
86289 +static ssize_t state_write(struct device *dev, struct device_attribute *attr,
86290 + const char *buf, size_t count)
86291 +{
86292 + struct jbt_info *jbt = dev_get_drvdata(dev);
86293 + int i, rc;
86294 +
86295 + for (i = 0; i < ARRAY_SIZE(jbt_state_names); i++) {
86296 + if (!strncmp(buf, jbt_state_names[i],
86297 + strlen(jbt_state_names[i]))) {
86298 + rc = jbt6k74_enter_state(jbt, i);
86299 + if (rc)
86300 + return rc;
86301 + return count;
86302 + }
86303 + }
86304 +
86305 + return -EINVAL;
86306 +}
86307 +
86308 +static DEVICE_ATTR(state, 0644, state_read, state_write);
86309 +
86310 +static int reg_by_string(const char *name)
86311 +{
86312 + if (!strcmp(name, "gamma_fine1"))
86313 + return JBT_REG_GAMMA1_FINE_1;
86314 + else if (!strcmp(name, "gamma_fine2"))
86315 + return JBT_REG_GAMMA1_FINE_2;
86316 + else if (!strcmp(name, "gamma_inclination"))
86317 + return JBT_REG_GAMMA1_INCLINATION;
86318 + else
86319 + return JBT_REG_GAMMA1_BLUE_OFFSET;
86320 +}
86321 +
86322 +static ssize_t gamma_read(struct device *dev, struct device_attribute *attr,
86323 + char *buf)
86324 +{
86325 + struct jbt_info *jbt = dev_get_drvdata(dev);
86326 + int reg = reg_by_string(attr->attr.name);
86327 + u16 val;
86328 +
86329 + mutex_lock(&jbt->lock);
86330 + val = jbt->reg_cache[reg];
86331 + mutex_unlock(&jbt->lock);
86332 +
86333 + return sprintf(buf, "0x%04x\n", val);
86334 +}
86335 +
86336 +static ssize_t gamma_write(struct device *dev, struct device_attribute *attr,
86337 + const char *buf, size_t count)
86338 +{
86339 + struct jbt_info *jbt = dev_get_drvdata(dev);
86340 + int reg = reg_by_string(attr->attr.name);
86341 + unsigned long val = simple_strtoul(buf, NULL, 10);
86342 +
86343 + dev_info(dev, "writing gama %lu\n", val & 0xff);
86344 +
86345 + mutex_lock(&jbt->lock);
86346 + jbt_reg_write(jbt, reg, val & 0xff);
86347 + mutex_unlock(&jbt->lock);
86348 +
86349 + return count;
86350 +}
86351 +
86352 +static ssize_t reset_write(struct device *dev, struct device_attribute *attr,
86353 + const char *buf, size_t count)
86354 +{
86355 + int rc;
86356 + struct jbt_info *jbt = dev_get_drvdata(dev);
86357 + struct jbt6k74_platform_data *pdata = jbt->spi_dev->dev.platform_data;
86358 +
86359 + dev_info(dev, "reset\n");
86360 +
86361 + mutex_lock(&jbt->lock);
86362 +
86363 + jbt->state = JBT_STATE_DEEP_STANDBY;
86364 +
86365 + /* hard reset the jbt6k74 */
86366 + (pdata->reset)(0, 0);
86367 + mdelay(1);
86368 + (pdata->reset)(0, 1);
86369 + mdelay(120);
86370 +
86371 + rc = jbt_reg_write_nodata(jbt, 0x01);
86372 + if (rc < 0)
86373 + dev_err(&jbt->spi_dev->dev, "cannot soft reset\n");
86374 + mdelay(120);
86375 +
86376 + mutex_unlock(&jbt->lock);
86377 +
86378 + jbt6k74_enter_state(jbt, jbt->normal_state);
86379 +
86380 + return count;
86381 +}
86382 +
86383 +static DEVICE_ATTR(gamma_fine1, 0644, gamma_read, gamma_write);
86384 +static DEVICE_ATTR(gamma_fine2, 0644, gamma_read, gamma_write);
86385 +static DEVICE_ATTR(gamma_inclination, 0644, gamma_read, gamma_write);
86386 +static DEVICE_ATTR(gamma_blue_offset, 0644, gamma_read, gamma_write);
86387 +static DEVICE_ATTR(reset, 0600, NULL, reset_write);
86388 +
86389 +static struct attribute *jbt_sysfs_entries[] = {
86390 + &dev_attr_state.attr,
86391 + &dev_attr_gamma_fine1.attr,
86392 + &dev_attr_gamma_fine2.attr,
86393 + &dev_attr_gamma_inclination.attr,
86394 + &dev_attr_gamma_blue_offset.attr,
86395 + &dev_attr_reset.attr,
86396 + NULL,
86397 +};
86398 +
86399 +static struct attribute_group jbt_attr_group = {
86400 + .name = NULL,
86401 + .attrs = jbt_sysfs_entries,
86402 +};
86403 +
86404 +static int fb_notifier_callback(struct notifier_block *self,
86405 + unsigned long event, void *data)
86406 +{
86407 + struct jbt_info *jbt;
86408 + struct fb_event *evdata = data;
86409 + int fb_blank;
86410 +
86411 + jbt = container_of(self, struct jbt_info, fb_notif);
86412 +
86413 + dev_dbg(&jbt->spi_dev->dev, "event=%lu\n", event);
86414 +
86415 + if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK)
86416 + return 0;
86417 +
86418 + fb_blank = *(int *)evdata->data;
86419 + switch (fb_blank) {
86420 + case FB_BLANK_UNBLANK:
86421 + dev_dbg(&jbt->spi_dev->dev, "unblank\n");
86422 + jbt6k74_enter_state(jbt, jbt->normal_state);
86423 + break;
86424 + case FB_BLANK_NORMAL:
86425 + dev_dbg(&jbt->spi_dev->dev, "blank\n");
86426 + break;
86427 + case FB_BLANK_VSYNC_SUSPEND:
86428 + dev_dbg(&jbt->spi_dev->dev, "vsync suspend\n");
86429 + break;
86430 + case FB_BLANK_HSYNC_SUSPEND:
86431 + dev_dbg(&jbt->spi_dev->dev, "hsync suspend\n");
86432 + break;
86433 + case FB_BLANK_POWERDOWN:
86434 + dev_dbg(&jbt->spi_dev->dev, "powerdown\n");
86435 + jbt6k74_enter_state(jbt, JBT_STATE_SLEEP);
86436 + break;
86437 + }
86438 +
86439 + return 0;
86440 +}
86441 +
86442 +/* linux device model infrastructure */
86443 +
86444 +static int __devinit jbt_probe(struct spi_device *spi)
86445 +{
86446 + int rc;
86447 + struct jbt_info *jbt;
86448 + struct jbt6k74_platform_data *pdata = spi->dev.platform_data;
86449 +
86450 + /* the controller doesn't have a MISO pin; we can't do detection */
86451 +
86452 + spi->mode = SPI_CPOL | SPI_CPHA;
86453 + spi->bits_per_word = 9;
86454 +
86455 + rc = spi_setup(spi);
86456 + if (rc < 0) {
86457 + dev_err(&spi->dev,
86458 + "error during spi_setup of jbt6k74 driver\n");
86459 + return rc;
86460 + }
86461 +
86462 + jbt = kzalloc(sizeof(*jbt), GFP_KERNEL);
86463 + if (!jbt)
86464 + return -ENOMEM;
86465 +
86466 + jbt->spi_dev = spi;
86467 + jbt->normal_state = JBT_STATE_NORMAL;
86468 + jbt->state = JBT_STATE_DEEP_STANDBY;
86469 + jbt->last_sleep = current_kernel_time();
86470 + mutex_init(&jbt->lock);
86471 +
86472 + dev_set_drvdata(&spi->dev, jbt);
86473 +
86474 + rc = jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
86475 + if (rc < 0) {
86476 + dev_err(&spi->dev, "cannot enter NORMAL state\n");
86477 + goto err_free_drvdata;
86478 + }
86479 +
86480 + rc = sysfs_create_group(&spi->dev.kobj, &jbt_attr_group);
86481 + if (rc < 0) {
86482 + dev_err(&spi->dev, "cannot create sysfs group\n");
86483 + goto err_standby;
86484 + }
86485 +
86486 + jbt->fb_notif.notifier_call = fb_notifier_callback;
86487 + rc = fb_register_client(&jbt->fb_notif);
86488 + if (rc < 0) {
86489 + dev_err(&spi->dev, "cannot register notifier\n");
86490 + goto err_sysfs;
86491 + }
86492 +
86493 + if (pdata->probe_completed)
86494 + (pdata->probe_completed)(&spi->dev);
86495 +
86496 + return 0;
86497 +
86498 +err_sysfs:
86499 + sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group);
86500 +err_standby:
86501 + jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
86502 +err_free_drvdata:
86503 + dev_set_drvdata(&spi->dev, NULL);
86504 + kfree(jbt);
86505 +
86506 + return rc;
86507 +}
86508 +
86509 +static int __devexit jbt_remove(struct spi_device *spi)
86510 +{
86511 + struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
86512 +
86513 + /* We don't want to switch off the display in case the user
86514 + * accidentially onloads the module (whose use count normally is 0) */
86515 + jbt6k74_enter_state(jbt, jbt->normal_state);
86516 +
86517 + fb_unregister_client(&jbt->fb_notif);
86518 + sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group);
86519 + dev_set_drvdata(&spi->dev, NULL);
86520 + kfree(jbt);
86521 +
86522 + return 0;
86523 +}
86524 +
86525 +#ifdef CONFIG_PM
86526 +static int jbt_suspend(struct spi_device *spi, pm_message_t state)
86527 +{
86528 + struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
86529 +
86530 + jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
86531 +
86532 + dev_info(&spi->dev, "suspended\n");
86533 +
86534 + return 0;
86535 +}
86536 +
86537 +int jbt6k74_resume(struct spi_device *spi)
86538 +{
86539 + struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
86540 + struct jbt6k74_platform_data *pdata = spi->dev.platform_data;
86541 +
86542 + jbt6k74_enter_state(jbt, jbt->normal_state);
86543 +
86544 + if (pdata->resuming)
86545 + (pdata->resuming)(0);
86546 +
86547 + dev_info(&spi->dev, "resumed\n");
86548 +
86549 + return 0;
86550 +}
86551 +EXPORT_SYMBOL_GPL(jbt6k74_resume);
86552 +
86553 +#else
86554 +#define jbt_suspend NULL
86555 +#define jbt6k74_resume NULL
86556 +#endif
86557 +
86558 +static struct spi_driver jbt6k74_driver = {
86559 + .driver = {
86560 + .name = "jbt6k74",
86561 + .owner = THIS_MODULE,
86562 + },
86563 +
86564 + .probe = jbt_probe,
86565 + .remove = __devexit_p(jbt_remove),
86566 + .suspend = jbt_suspend,
86567 + .resume = jbt6k74_resume,
86568 +};
86569 +
86570 +static int __init jbt_init(void)
86571 +{
86572 + return spi_register_driver(&jbt6k74_driver);
86573 +}
86574 +
86575 +static void __exit jbt_exit(void)
86576 +{
86577 + spi_unregister_driver(&jbt6k74_driver);
86578 +}
86579 +
86580 +MODULE_DESCRIPTION("SPI driver for tpo JBT6K74-AS LCM control interface");
86581 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
86582 +MODULE_LICENSE("GPL");
86583 +
86584 +module_init(jbt_init);
86585 +module_exit(jbt_exit);
86586 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/display/Kconfig linux-2.6.29-rc3.owrt.om/drivers/video/display/Kconfig
86587 --- linux-2.6.29-rc3.owrt/drivers/video/display/Kconfig 2009-05-10 22:04:48.000000000 +0200
86588 +++ linux-2.6.29-rc3.owrt.om/drivers/video/display/Kconfig 2009-05-10 22:28:00.000000000 +0200
86589 @@ -21,4 +21,23 @@
86590 comment "Display hardware drivers"
86591 depends on DISPLAY_SUPPORT
86592
86593 +config DISPLAY_JBT6K74
86594 + tristate "TPO JBT6K74-AS TFT display ASIC control interface"
86595 + depends on SPI_MASTER && SYSFS
86596 + help
86597 + SPI driver for the control interface of TFT panels containing
86598 + the TPO JBT6K74-AS controller ASIC, such as the TPO TD028TTEC1
86599 + TFT diplay module used in the FIC/Openmoko Neo1973 GSM phones.
86600 +
86601 + The control interface is required for display operation, as it
86602 + controls power management, display timing and gamma calibration.
86603 +
86604 +config DISPLAY_L1K002
86605 + tristate "TP0 L1K0-02 TFT ASIC control interface"
86606 + depends on SPI_MASTER && SYSFS
86607 + help
86608 + The control interface of this LTPS TFT panel is based on SPI bitbang driver.
86609 + It controls display timing and gamma calibration. TP0 LPJ028T007A LCM uses this IC
86610 + as its controller in the Openmoko GTA03 GSM phone.
86611 +
86612 endmenu
86613 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/display/l1k002.c linux-2.6.29-rc3.owrt.om/drivers/video/display/l1k002.c
86614 --- linux-2.6.29-rc3.owrt/drivers/video/display/l1k002.c 1970-01-01 01:00:00.000000000 +0100
86615 +++ linux-2.6.29-rc3.owrt.om/drivers/video/display/l1k002.c 2009-05-10 22:28:00.000000000 +0200
86616 @@ -0,0 +1,278 @@
86617 +/*
86618 + * Copyright (C) 2009 Openmoko, Inc.
86619 + *
86620 + * Author: Matt Hsu <matt_hsu@openmoko.org>
86621 + *
86622 + * This program is free software; you can redistribute it and/or modify
86623 + * it under the terms of the GNU General Public License as published by
86624 + * the Free Software Foundation; either version 2 of the License, or (at
86625 + * your option) any later version.
86626 + *
86627 + * This program is distributed in the hope that it will be useful, but
86628 + * WITHOUT ANY WARRANTY; without even the implied warranty of
86629 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
86630 + * General Public License for more details.
86631 + *
86632 + * You should have received a copy of the GNU General Public License along
86633 + * with this program; if not, write to the Free Software Foundation, Inc.,
86634 + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
86635 + *
86636 +*/
86637 +
86638 +#include <linux/kernel.h>
86639 +#include <linux/device.h>
86640 +#include <linux/module.h>
86641 +#include <linux/platform_device.h>
86642 +#include <linux/spi/spi.h>
86643 +
86644 +#include <linux/l1k002.h>
86645 +
86646 +struct l1k002_data {
86647 + struct spi_device *spi;
86648 + struct mutex lock;
86649 + u8 mosi_buf[2];
86650 + u8 reg_cache[0x40];
86651 +};
86652 +
86653 +enum l1k002_regs_table {
86654 +
86655 + L1K002_REG_SYNCP_SEL = 0x02,
86656 + L1K002_REG_VSTS = 0x03,
86657 + L1K002_REG_HSTS = 0x04,
86658 + L1K002_REG_MISC = 0x07,
86659 + L1K002_REG_CMDR = 0x08,
86660 + L1K002_REG_IN_DATA_TIMING = 0x09,
86661 + L1K002_REG_ENGR_OTP = 0x0b,
86662 + L1K002_REG_VGLS = 0x0c,
86663 + L1K002_REG_DISP_8_9 = 0x0d,
86664 + L1K002_REG_DISP_0_7 = 0x0e,
86665 + L1K002_REG_HTOTAL_8_10 = 0x0f,
86666 + L1K002_REG_HTOTAL_0_7 = 0x10,
86667 + L1K002_REG_WCKH = 0x20,
86668 + L1K002_REG_GCKH = 0x21,
86669 + L1K002_REG_DCKH = 0x22,
86670 + L1K002_REG_WENBV = 0x23,
86671 + L1K002_REG_DCKV = 0x25,
86672 + L1K002_REG_WCKV = 0x27,
86673 + L1K002_REG_DA_VCOM = 0x2a,
86674 + L1K002_REG_PVH = 0x2b,
86675 + L1K002_REG_NVH_NVL = 0x2c,
86676 + L1K002_REG_GC1 = 0x2d,
86677 + L1K002_REG_GC2 = 0x2e,
86678 + L1K002_REG_GC3 = 0x2f,
86679 + L1K002_REG_GC4 = 0x30,
86680 + L1K002_REG_GC5 = 0x31,
86681 + L1K002_REG_GC6 = 0x32,
86682 + L1K002_REG_GC7 = 0x33,
86683 + L1K002_REG_GC8 = 0x34,
86684 + L1K002_REG_GC9 = 0x35,
86685 + L1K002_REG_GC10 = 0x36,
86686 + L1K002_REG_GC11 = 0x37,
86687 + L1K002_REG_GC12 = 0x38,
86688 + L1K002_REG_GC13 = 0x39,
86689 + L1K002_REG_GC14 = 0x3a,
86690 + L1K002_REG_GC15 = 0x3b,
86691 +};
86692 +
86693 +static int l1k002_reg_write(struct l1k002_data *l1k002, u8 reg, u8 data)
86694 +{
86695 + int ret;
86696 +
86697 + mutex_lock(&l1k002->lock);
86698 +
86699 + l1k002->mosi_buf[0] = reg;
86700 + l1k002->mosi_buf[1] = data;
86701 +
86702 + ret = spi_write(l1k002->spi, (u8 *)l1k002->mosi_buf, 2*sizeof(u8));
86703 + if (ret == 0)
86704 + l1k002->reg_cache[reg] = data;
86705 + else
86706 + dev_err(&l1k002->spi->dev, "reg spi_write ret: %d\n", ret);
86707 +
86708 + mutex_unlock(&l1k002->lock);
86709 + return ret;
86710 +}
86711 +
86712 +static int l1k002_init_reg(struct l1k002_data *l1k002)
86713 +{
86714 + int ret;
86715 +
86716 + /* software reset */
86717 + ret = l1k002_reg_write(l1k002, L1K002_REG_CMDR, 0x01);
86718 + ret |= l1k002_reg_write(l1k002, L1K002_REG_CMDR, 0x00);
86719 +
86720 + /* setup color mode and direction */
86721 + ret |= l1k002_reg_write(l1k002, L1K002_REG_MISC, 0xd9);
86722 +
86723 + /* dclk initial */
86724 + ret |= l1k002_reg_write(l1k002, L1K002_REG_SYNCP_SEL, 0x00);
86725 +
86726 + /* start vertical data */
86727 + ret |= l1k002_reg_write(l1k002, L1K002_REG_VSTS, 0x04);
86728 +
86729 + /* start horizonal data */
86730 + ret |= l1k002_reg_write(l1k002, L1K002_REG_HSTS, 0x14);
86731 +
86732 + /* setup hsnc, vsnc, data_enable */
86733 + ret |= l1k002_reg_write(l1k002, L1K002_REG_IN_DATA_TIMING, 0x03);
86734 + /* enable engineering mode and OTP */
86735 + ret |= l1k002_reg_write(l1k002, L1K002_REG_ENGR_OTP, 0x18);
86736 +
86737 + /* display area */
86738 + ret |= l1k002_reg_write(l1k002, L1K002_REG_VGLS, 0x41);
86739 + ret |= l1k002_reg_write(l1k002, L1K002_REG_DISP_8_9, 0x02);
86740 + ret |= l1k002_reg_write(l1k002, L1K002_REG_DISP_0_7, 0x80);
86741 + ret |= l1k002_reg_write(l1k002, L1K002_REG_HTOTAL_8_10, 0x02);
86742 + ret |= l1k002_reg_write(l1k002, L1K002_REG_HTOTAL_0_7, 0x08);
86743 +
86744 + /* CKH pulse config */
86745 + ret |= l1k002_reg_write(l1k002, L1K002_REG_WCKH, 0x3c);
86746 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GCKH, 0x0c);
86747 + ret |= l1k002_reg_write(l1k002, L1K002_REG_DCKH, 0x10);
86748 +
86749 + /* ENBV config */
86750 + ret |= l1k002_reg_write(l1k002, L1K002_REG_WENBV, 0x38);
86751 + ret |= l1k002_reg_write(l1k002, L1K002_REG_DCKV, 0x3c);
86752 + ret |= l1k002_reg_write(l1k002, L1K002_REG_WCKV, 0xdb);
86753 +
86754 + /* driving voltage */
86755 + ret |= l1k002_reg_write(l1k002, L1K002_REG_DA_VCOM, 0x66);
86756 +
86757 + /* gamma output voltage level */
86758 + ret |= l1k002_reg_write(l1k002, L1K002_REG_PVH, 0x70);
86759 + ret |= l1k002_reg_write(l1k002, L1K002_REG_NVH_NVL, 0x70);
86760 +
86761 + /* gamma correction */
86762 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC1, 0x15);
86763 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC2, 0xaa);
86764 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC3, 0xbf);
86765 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC4, 0x86);
86766 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC5, 0x11);
86767 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC6, 0x5e);
86768 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC7, 0xb6);
86769 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC8, 0x16);
86770 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC9, 0x4e);
86771 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC10, 0x78);
86772 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC11, 0xbf);
86773 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC12, 0xec);
86774 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC13, 0x10);
86775 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC14, 0x30);
86776 + ret |= l1k002_reg_write(l1k002, L1K002_REG_GC15, 0xff);
86777 +
86778 + ret |= l1k002_reg_write(l1k002, 0x07, 0xc9);
86779 +
86780 + if (ret == 0)
86781 + dev_info(&l1k002->spi->dev, "initialize OK \n");
86782 + else
86783 + dev_err(&l1k002->spi->dev, "initialize failed ret: %d\n", ret);
86784 + return ret;
86785 +}
86786 +
86787 +static int l1k002_probe(struct spi_device *spi)
86788 +{
86789 + int ret;
86790 + struct l1k002_data *l1k002;
86791 + struct l1k002_platform_data *l1k002_pdata = spi->dev.platform_data;
86792 +
86793 + if (l1k002_pdata == NULL) {
86794 + dev_err(&spi->dev,
86795 + "no platform data available \n");
86796 + return -EINVAL;
86797 + }
86798 +
86799 + spi->mode = SPI_CPOL | SPI_CPHA;
86800 + spi->bits_per_word = 8;
86801 +
86802 + ret = spi_setup(spi);
86803 + if (ret < 0) {
86804 + dev_err(&spi->dev,
86805 + "error during spi_setup of l1k002 driver\n");
86806 + return ret;
86807 + }
86808 +
86809 + l1k002 = kzalloc(sizeof(*l1k002), GFP_KERNEL);
86810 + if (!l1k002)
86811 + return -ENOMEM;
86812 +
86813 + l1k002->spi = spi;
86814 + dev_set_drvdata(&spi->dev, l1k002);
86815 +
86816 + mutex_init(&l1k002->lock);
86817 +
86818 + /* hard reset l1k002 */
86819 + (l1k002_pdata->pwr_onoff)(1);
86820 +
86821 + ret = l1k002_init_reg(l1k002);
86822 + if (ret)
86823 + goto err_free;
86824 +
86825 + /* FIXME: sysfs should be added here */
86826 +
86827 + return 0;
86828 +
86829 +err_free:
86830 + kfree(l1k002);
86831 + return ret;
86832 +}
86833 +
86834 +static int __devexit l1k002_remove(struct spi_device *spi)
86835 +{
86836 + struct l1k002 *l1k002 = dev_get_drvdata(&spi->dev);
86837 +
86838 + dev_set_drvdata(&spi->dev, NULL);
86839 + kfree(l1k002);
86840 + return 0;
86841 +}
86842 +
86843 +#ifdef CONFIG_PM
86844 +static int l1k002_suspend(struct spi_device *spi, pm_message_t state)
86845 +{
86846 + struct l1k002_platform_data *l1k002_pdata = spi->dev.platform_data;
86847 +
86848 + /* l1k002 doesn't have sleep mode
86849 + * it should be powered down as entering suspend state
86850 + */
86851 + (l1k002_pdata->pwr_onoff)(0);
86852 + return 0;
86853 +}
86854 +
86855 +static int l1k002_resume(struct spi_device *spi)
86856 +{
86857 + struct l1k002_platform_data *l1k002_pdata = spi->dev.platform_data;
86858 + struct l1k002_data *l1k002 = dev_get_drvdata(&spi->dev);
86859 +
86860 + (l1k002_pdata->pwr_onoff)(1);
86861 + return l1k002_init_reg(l1k002);
86862 +}
86863 +#else
86864 +#define l1k002_suspend NULL
86865 +#define l1k002_resume NULL
86866 +#endif
86867 +
86868 +static struct spi_driver l1k002_driver = {
86869 + .driver = {
86870 + .name = "l1k002",
86871 + .owner = THIS_MODULE,
86872 + },
86873 +
86874 + .probe = l1k002_probe,
86875 + .remove = __devexit_p(l1k002_remove),
86876 + .suspend = l1k002_suspend,
86877 + .resume = l1k002_resume,
86878 +};
86879 +
86880 +static int __init l1k002_init(void)
86881 +{
86882 + return spi_register_driver(&l1k002_driver);
86883 +}
86884 +
86885 +static void __exit l1k002_exit(void)
86886 +{
86887 + spi_unregister_driver(&l1k002_driver);
86888 +}
86889 +
86890 +MODULE_AUTHOR("Matt Hsu <matt_hsu@openmoko.org>");
86891 +MODULE_LICENSE("GPL v2");
86892 +
86893 +module_init(l1k002_init);
86894 +module_exit(l1k002_exit);
86895 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/display/Makefile linux-2.6.29-rc3.owrt.om/drivers/video/display/Makefile
86896 --- linux-2.6.29-rc3.owrt/drivers/video/display/Makefile 2009-05-10 22:04:48.000000000 +0200
86897 +++ linux-2.6.29-rc3.owrt.om/drivers/video/display/Makefile 2009-05-10 22:28:00.000000000 +0200
86898 @@ -3,4 +3,6 @@
86899 display-objs := display-sysfs.o
86900
86901 obj-$(CONFIG_DISPLAY_SUPPORT) += display.o
86902 +obj-$(CONFIG_DISPLAY_JBT6K74) += jbt6k74.o
86903 +obj-$(CONFIG_DISPLAY_L1K002) += l1k002.o
86904
86905 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/Kconfig linux-2.6.29-rc3.owrt.om/drivers/video/Kconfig
86906 --- linux-2.6.29-rc3.owrt/drivers/video/Kconfig 2009-05-10 22:08:45.000000000 +0200
86907 +++ linux-2.6.29-rc3.owrt.om/drivers/video/Kconfig 2009-05-10 22:28:00.000000000 +0200
86908 @@ -1924,6 +1924,30 @@
86909 depends on FB_TMIO
86910 default y
86911
86912 +config FB_S3C
86913 + tristate "Samsung S3C framebuffer support"
86914 + depends on FB && ARCH_S3C64XX
86915 + select FB_CFB_FILLRECT
86916 + select FB_CFB_COPYAREA
86917 + select FB_CFB_IMAGEBLIT
86918 + ---help---
86919 + Frame buffer driver for the built-in FB controller in the Samsung
86920 + SoC line from the S3C2443 onwards, including the S3C2416, S3C2450,
86921 + and the S3C64XX series such as the S3C6400 and S3C6410.
86922 +
86923 + These chips all have the same basic framebuffer design with the
86924 + actual capabilities depending on the chip. For instance the S3C6400
86925 + and S3C6410 support 4 hardware windows whereas the S3C24XX series
86926 + currently only have two.
86927 +
86928 + Currently the support is only for the S3C6400 and S3C6410 SoCs.
86929 +
86930 +config FB_S3C_DEBUG_REGWRITE
86931 + bool "Debug register writes"
86932 + depends on FB_S3C
86933 + ---help---
86934 + Show all register writes via printk(KERN_DEBUG)
86935 +
86936 config FB_S3C2410
86937 tristate "S3C2410 LCD framebuffer support"
86938 depends on FB && ARCH_S3C2410
86939 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/Makefile linux-2.6.29-rc3.owrt.om/drivers/video/Makefile
86940 --- linux-2.6.29-rc3.owrt/drivers/video/Makefile 2009-05-10 22:04:48.000000000 +0200
86941 +++ linux-2.6.29-rc3.owrt.om/drivers/video/Makefile 2009-05-10 22:28:00.000000000 +0200
86942 @@ -109,6 +109,7 @@
86943 obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o
86944 obj-$(CONFIG_FB_SH7760) += sh7760fb.o
86945 obj-$(CONFIG_FB_IMX) += imxfb.o
86946 +obj-$(CONFIG_FB_S3C) += s3c-fb.o
86947 obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o
86948 obj-$(CONFIG_FB_FSL_DIU) += fsl-diu-fb.o
86949 obj-$(CONFIG_FB_COBALT) += cobalt_lcdfb.o
86950 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/s3c2410fb.c linux-2.6.29-rc3.owrt.om/drivers/video/s3c2410fb.c
86951 --- linux-2.6.29-rc3.owrt/drivers/video/s3c2410fb.c 2009-05-10 22:04:48.000000000 +0200
86952 +++ linux-2.6.29-rc3.owrt.om/drivers/video/s3c2410fb.c 2009-05-10 22:28:00.000000000 +0200
86953 @@ -1017,6 +1017,8 @@
86954
86955 s3c2410fb_init_registers(fbinfo);
86956
86957 + s3c2410fb_set_par(fbinfo);
86958 +
86959 return 0;
86960 }
86961
86962 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/video/s3c-fb.c linux-2.6.29-rc3.owrt.om/drivers/video/s3c-fb.c
86963 --- linux-2.6.29-rc3.owrt/drivers/video/s3c-fb.c 1970-01-01 01:00:00.000000000 +0100
86964 +++ linux-2.6.29-rc3.owrt.om/drivers/video/s3c-fb.c 2009-05-10 22:28:00.000000000 +0200
86965 @@ -0,0 +1,1036 @@
86966 +/* linux/drivers/video/s3c-fb.c
86967 + *
86968 + * Copyright 2008 Openmoko Inc.
86969 + * Copyright 2008 Simtec Electronics
86970 + * Ben Dooks <ben@simtec.co.uk>
86971 + * http://armlinux.simtec.co.uk/
86972 + *
86973 + * Samsung SoC Framebuffer driver
86974 + *
86975 + * This program is free software; you can redistribute it and/or modify
86976 + * it under the terms of the GNU General Public License version 2 as
86977 + * published by the Free Software Foundation.
86978 +*/
86979 +
86980 +#include <linux/kernel.h>
86981 +#include <linux/module.h>
86982 +#include <linux/platform_device.h>
86983 +#include <linux/dma-mapping.h>
86984 +#include <linux/init.h>
86985 +#include <linux/gfp.h>
86986 +#include <linux/clk.h>
86987 +#include <linux/fb.h>
86988 +#include <linux/io.h>
86989 +
86990 +#include <mach/map.h>
86991 +#include <mach/regs-fb.h>
86992 +#include <plat/fb.h>
86993 +
86994 +/* This driver will export a number of framebuffer interfaces depending
86995 + * on the configuration passed in via the platform data. Each fb instance
86996 + * maps to a hardware window. Currently there is no support for runtime
86997 + * setting of the alpha-blending functions that each window has, so only
86998 + * window 0 is actually useful.
86999 + *
87000 + * Window 0 is treated specially, it is used for the basis of the LCD
87001 + * output timings and as the control for the output power-down state.
87002 +*/
87003 +
87004 +/* note, some of the functions that get called are derived from including
87005 + * <mach/regs-fb.h> as they are specific to the architecture that the code
87006 + * is being built for.
87007 +*/
87008 +
87009 +#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
87010 +#undef writel
87011 +#define writel(v, r) do { \
87012 + printk(KERN_DEBUG "%s: %08x => %p\n", __func__, (unsigned int)v, r); \
87013 + __raw_writel(v, r); } while(0)
87014 +#endif /* FB_S3C_DEBUG_REGWRITE */
87015 +
87016 +struct s3c_fb;
87017 +
87018 +/**
87019 + * struct s3c_fb_win - per window private data for each framebuffer.
87020 + * @windata: The platform data supplied for the window configuration.
87021 + * @parent: The hardware that this window is part of.
87022 + * @fbinfo: Pointer pack to the framebuffer info for this window.
87023 + * @palette_buffer: Buffer/cache to hold palette entries.
87024 + * @pseudo_palette: For use in TRUECOLOUR modes for entries 0..15/
87025 + * @index: The window number of this window.
87026 + * @palette: The bitfields for changing r/g/b into a hardware palette entry.
87027 + */
87028 +struct s3c_fb_win {
87029 + struct s3c_fb_pd_win *windata;
87030 + struct s3c_fb *parent;
87031 + struct fb_info *fbinfo;
87032 + struct s3c_fb_palette palette;
87033 +
87034 + u32 *palette_buffer;
87035 + u32 pseudo_palette[16];
87036 + unsigned int index;
87037 +};
87038 +
87039 +/**
87040 + * struct s3c_fb - overall hardware state of the hardware
87041 + * @dev: The device that we bound to, for printing, etc.
87042 + * @regs_res: The resource we claimed for the IO registers.
87043 + * @bus_clk: The clk (hclk) feeding our interface and possibly pixclk.
87044 + * @regs: The mapped hardware registers.
87045 + * @enabled: A bitmask of enabled hardware windows.
87046 + * @pdata: The platform configuration data passed with the device.
87047 + * @windows: The hardware windows that have been claimed.
87048 + */
87049 +struct s3c_fb {
87050 + struct device *dev;
87051 + struct resource *regs_res;
87052 + struct clk *bus_clk;
87053 + void __iomem *regs;
87054 +
87055 + unsigned char enabled;
87056 +
87057 + struct s3c_fb_platdata *pdata;
87058 + struct s3c_fb_win *windows[S3C_FB_MAX_WIN];
87059 +};
87060 +
87061 +/**
87062 + * s3c_fb_win_has_palette() - determine if a mode has a palette
87063 + * @win: The window number being queried.
87064 + * @bpp: The number of bits per pixel to test.
87065 + *
87066 + * Work out if the given window supports palletised data at the specified bpp.
87067 + */
87068 +static int s3c_fb_win_has_palette(unsigned int win, unsigned int bpp)
87069 +{
87070 + return s3c_fb_win_pal_size(win) <= (1 << bpp);
87071 +}
87072 +
87073 +/**
87074 + * s3c_fb_check_var() - framebuffer layer request to verify a given mode.
87075 + * @var: The screen information to verify.
87076 + * @info: The framebuffer device.
87077 + *
87078 + * Framebuffer layer call to verify the given information and allow us to
87079 + * update various information depending on the hardware capabilities.
87080 + */
87081 +static int s3c_fb_check_var(struct fb_var_screeninfo *var,
87082 + struct fb_info *info)
87083 +{
87084 + struct s3c_fb_win *win = info->par;
87085 + struct s3c_fb_pd_win *windata = win->windata;
87086 + struct s3c_fb *sfb = win->parent;
87087 +
87088 + dev_dbg(sfb->dev, "checking parameters\n");
87089 +
87090 + var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres);
87091 + var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres);
87092 +
87093 + if (!s3c_fb_validate_win_bpp(win->index, var->bits_per_pixel)) {
87094 + dev_dbg(sfb->dev, "win %d: unsupported bpp %d\n",
87095 + win->index, var->bits_per_pixel);
87096 + return -EINVAL;
87097 + }
87098 +
87099 + /* always ensure these are zero, for drop through cases below */
87100 + var->transp.offset = 0;
87101 + var->transp.length = 0;
87102 +
87103 + switch (var->bits_per_pixel) {
87104 + case 1:
87105 + case 2:
87106 + case 4:
87107 + case 8:
87108 + if (!s3c_fb_win_has_palette(win->index, var->bits_per_pixel)) {
87109 + /* non palletised, A:1,R:2,G:3,B:2 mode */
87110 + var->red.offset = 4;
87111 + var->green.offset = 2;
87112 + var->blue.offset = 0;
87113 + var->red.length = 5;
87114 + var->green.length = 3;
87115 + var->blue.length = 2;
87116 + var->transp.offset = 7;
87117 + var->transp.length = 1;
87118 + } else {
87119 + var->red.offset = 0;
87120 + var->red.length = var->bits_per_pixel;
87121 + var->green = var->red;
87122 + var->blue = var->red;
87123 + }
87124 + break;
87125 +
87126 + case 19:
87127 + /* 666 with one bit alpha/transparency */
87128 + var->transp.offset = 18;
87129 + var->transp.length = 1;
87130 + case 18:
87131 + var->bits_per_pixel = 32;
87132 +
87133 + /* 666 format */
87134 + var->red.offset = 12;
87135 + var->green.offset = 6;
87136 + var->blue.offset = 0;
87137 + var->red.length = 6;
87138 + var->green.length = 6;
87139 + var->blue.length = 6;
87140 + break;
87141 +
87142 + case 16:
87143 + /* 16 bpp, 565 format */
87144 + var->red.offset = 11;
87145 + var->green.offset = 5;
87146 + var->blue.offset = 0;
87147 + var->red.length = 5;
87148 + var->green.length = 6;
87149 + var->blue.length = 5;
87150 + break;
87151 +
87152 + case 28:
87153 + case 25:
87154 + var->transp.length = var->bits_per_pixel - 24;
87155 + var->transp.offset = 24;
87156 + /* drop through */
87157 + case 24:
87158 + /* our 24bpp is unpacked, so 32bpp */
87159 + var->bits_per_pixel = 32;
87160 + case 32:
87161 + var->red.offset = 16;
87162 + var->red.length = 8;
87163 + var->green.offset = 8;
87164 + var->green.length = 8;
87165 + var->blue.offset = 0;
87166 + var->blue.length = 8;
87167 + break;
87168 +
87169 + default:
87170 + dev_err(sfb->dev, "invalid bpp\n");
87171 + }
87172 +
87173 + dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
87174 + return 0;
87175 +}
87176 +
87177 +/**
87178 + * s3c_fb_calc_pixclk() - calculate the divider to create the pixel clock.
87179 + * @sfb: The hardware state.
87180 + * @pixclock: The pixel clock wanted, in picoseconds.
87181 + *
87182 + * Given the specified pixel clock, work out the necessary divider to get
87183 + * close to the output frequency.
87184 + */
87185 +static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
87186 +{
87187 + unsigned long clk = clk_get_rate(sfb->bus_clk);
87188 + unsigned long long tmp;
87189 + unsigned int result;
87190 +
87191 + tmp = (unsigned long long)clk;
87192 + tmp *= pixclk;
87193 +
87194 + do_div(tmp, 1000000000UL);
87195 + result = (unsigned int)tmp / 1000;
87196 +
87197 + dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
87198 + pixclk, clk, result, clk / result);
87199 +
87200 + return result;
87201 +}
87202 +
87203 +/**
87204 + * s3c_fb_align_word() - align pixel count to word boundary
87205 + * @bpp: The number of bits per pixel
87206 + * @pix: The value to be aligned.
87207 + *
87208 + * Align the given pixel count so that it will start on an 32bit word
87209 + * boundary.
87210 + */
87211 +static int s3c_fb_align_word(unsigned int bpp, unsigned int pix)
87212 +{
87213 + int pix_per_word;
87214 +
87215 + if (bpp > 16)
87216 + return pix;
87217 +
87218 + pix_per_word = (8 * 32) / bpp;
87219 + return ALIGN(pix, pix_per_word);
87220 +}
87221 +
87222 +/**
87223 + * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
87224 + * @info: The framebuffer to change.
87225 + *
87226 + * Framebuffer layer request to set a new mode for the specified framebuffer
87227 + */
87228 +static int s3c_fb_set_par(struct fb_info *info)
87229 +{
87230 + struct fb_var_screeninfo *var = &info->var;
87231 + struct s3c_fb_win *win = info->par;
87232 + struct s3c_fb *sfb = win->parent;
87233 + void __iomem *regs = sfb->regs;
87234 + int win_no = win->index;
87235 + u32 data;
87236 + u32 pagewidth;
87237 + int clkdiv;
87238 +
87239 + dev_dbg(sfb->dev, "setting framebuffer parameters\n");
87240 +
87241 + switch (var->bits_per_pixel) {
87242 + case 32:
87243 + case 24:
87244 + case 16:
87245 + case 12:
87246 + info->fix.visual = FB_VISUAL_TRUECOLOR;
87247 + break;
87248 + case 8:
87249 + if (s3c_fb_win_has_palette(win_no, 8))
87250 + info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
87251 + else
87252 + info->fix.visual = FB_VISUAL_TRUECOLOR;
87253 + break;
87254 + case 1:
87255 + info->fix.visual = FB_VISUAL_MONO01;
87256 + break;
87257 + default:
87258 + info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
87259 + break;
87260 + }
87261 +
87262 + info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
87263 +
87264 + /* disable the window whilst we update it */
87265 + writel(0, regs + WINCON(win_no));
87266 +
87267 + /* use window 0 as the basis for the lcd output timings */
87268 +
87269 + if (win_no == 0) {
87270 + clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
87271 +
87272 + data = sfb->pdata->vidcon0;
87273 + data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
87274 +
87275 + if (clkdiv > 1)
87276 + data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
87277 + else
87278 + data &= ~VIDCON0_CLKDIR; /* 1:1 clock */
87279 +
87280 + /* write the timing data to the panel */
87281 +
87282 + data |= VIDCON0_ENVID | VIDCON0_ENVID_F;
87283 + writel(data, regs + VIDCON0);
87284 +
87285 + data = VIDTCON0_VBPD(var->upper_margin - 1) |
87286 + VIDTCON0_VFPD(var->lower_margin - 1) |
87287 + VIDTCON0_VSPW(var->vsync_len - 1);
87288 +
87289 + writel(data, regs + VIDTCON0);
87290 +
87291 + data = VIDTCON1_HBPD(var->left_margin - 1) |
87292 + VIDTCON1_HFPD(var->right_margin - 1) |
87293 + VIDTCON1_HSPW(var->hsync_len - 1);
87294 +
87295 + writel(data, regs + VIDTCON1);
87296 +
87297 + data = VIDTCON2_LINEVAL(var->yres - 1) |
87298 + VIDTCON2_HOZVAL(var->xres - 1);
87299 + writel(data, regs + VIDTCON2);
87300 + }
87301 +
87302 + /* write the buffer address */
87303 +
87304 + writel(info->fix.smem_start, regs + VIDW_BUF_START(win_no));
87305 +
87306 + data = info->fix.smem_start + info->fix.line_length * var->yres;
87307 + writel(data, regs + VIDW_BUF_END(win_no));
87308 +
87309 + pagewidth = (var->xres * var->bits_per_pixel) >> 3;
87310 + data = VIDW_BUF_SIZE_OFFSET(info->fix.line_length - pagewidth) |
87311 + VIDW_BUF_SIZE_PAGEWIDTH(pagewidth);
87312 + writel(data, regs + VIDW_BUF_SIZE(win_no));
87313 +
87314 + /* write 'OSD' registers to control position of framebuffer */
87315 +
87316 + data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0);
87317 + writel(data, regs + VIDOSD_A(win_no));
87318 +
87319 + data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
87320 + var->xres - 1)) |
87321 + VIDOSDxB_BOTRIGHT_Y(var->yres - 1);
87322 +
87323 + writel(data, regs + VIDOSD_B(win_no));
87324 +
87325 + data = var->xres * var->yres;
87326 + if (s3c_fb_has_osd_d(win_no)) {
87327 + writel(data, regs + VIDOSD_D(win_no));
87328 + writel(0, regs + VIDOSD_C(win_no));
87329 + } else
87330 + writel(data, regs + VIDOSD_C(win_no));
87331 +
87332 + data = WINCONx_ENWIN;
87333 +
87334 + /* note, since we have to round up the bits-per-pixel, we end up
87335 + * relying on the bitfield information for r/g/b/a to work out
87336 + * exactly which mode of operation is intended. */
87337 +
87338 + switch (var->bits_per_pixel) {
87339 + case 1:
87340 + data |= WINCON0_BPPMODE_1BPP;
87341 + data |= WINCONx_BITSWP;
87342 + data |= WINCONx_BURSTLEN_4WORD;
87343 + break;
87344 + case 2:
87345 + data |= WINCON0_BPPMODE_2BPP;
87346 + data |= WINCONx_BITSWP;
87347 + data |= WINCONx_BURSTLEN_8WORD;
87348 + break;
87349 + case 4:
87350 + data |= WINCON0_BPPMODE_4BPP;
87351 + data |= WINCONx_BITSWP;
87352 + data |= WINCONx_BURSTLEN_8WORD;
87353 + break;
87354 + case 8:
87355 + if (var->transp.length != 0)
87356 + data |= WINCON1_BPPMODE_8BPP_1232;
87357 + else
87358 + data |= WINCON0_BPPMODE_8BPP_PALETTE;
87359 + data |= WINCONx_BURSTLEN_8WORD;
87360 + data |= WINCONx_BYTSWP;
87361 + break;
87362 + case 16:
87363 + if (var->transp.length != 0)
87364 + data |= WINCON1_BPPMODE_16BPP_A1555;
87365 + else
87366 + data |= WINCON0_BPPMODE_16BPP_565;
87367 + data |= WINCONx_HAWSWP;
87368 + data |= WINCONx_BURSTLEN_16WORD;
87369 + break;
87370 + case 24:
87371 + case 32:
87372 + if (var->red.length == 6) {
87373 + if (var->transp.length != 0)
87374 + data |= WINCON1_BPPMODE_19BPP_A1666;
87375 + else
87376 + data |= WINCON1_BPPMODE_18BPP_666;
87377 + } else if (var->transp.length != 0)
87378 + data |= WINCON1_BPPMODE_25BPP_A1888;
87379 + else
87380 + data |= WINCON0_BPPMODE_24BPP_888;
87381 +
87382 + data |= WINCONx_BURSTLEN_16WORD;
87383 + break;
87384 + }
87385 +
87386 + writel(data, regs + WINCON(win_no));
87387 + writel(0x0, regs + WINxMAP(win_no));
87388 +
87389 + return 0;
87390 +}
87391 +
87392 +/**
87393 + * s3c_fb_update_palette() - set or schedule a palette update.
87394 + * @sfb: The hardware information.
87395 + * @win: The window being updated.
87396 + * @reg: The palette index being changed.
87397 + * @value: The computed palette value.
87398 + *
87399 + * Change the value of a palette register, either by directly writing to
87400 + * the palette (this requires the palette RAM to be disconnected from the
87401 + * hardware whilst this is in progress) or schedule the update for later.
87402 + *
87403 + * At the moment, since we have no VSYNC interrupt support, we simply set
87404 + * the palette entry directly.
87405 + */
87406 +static void s3c_fb_update_palette(struct s3c_fb *sfb,
87407 + struct s3c_fb_win *win,
87408 + unsigned int reg,
87409 + u32 value)
87410 +{
87411 + void __iomem *palreg;
87412 + u32 palcon;
87413 +
87414 + palreg = sfb->regs + s3c_fb_pal_reg(win->index, reg);
87415 +
87416 + dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n",
87417 + __func__, win->index, reg, palreg, value);
87418 +
87419 + win->palette_buffer[reg] = value;
87420 +
87421 + palcon = readl(sfb->regs + WPALCON);
87422 + writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON);
87423 +
87424 + if (s3c_fb_pal_is16(win->index))
87425 + writew(value, palreg);
87426 + else
87427 + writel(value, palreg);
87428 +
87429 + writel(palcon, sfb->regs + WPALCON);
87430 +}
87431 +
87432 +static inline unsigned int chan_to_field(unsigned int chan,
87433 + struct fb_bitfield *bf)
87434 +{
87435 + chan &= 0xffff;
87436 + chan >>= 16 - bf->length;
87437 + return chan << bf->offset;
87438 +}
87439 +
87440 +/**
87441 + * s3c_fb_setcolreg() - framebuffer layer request to change palette.
87442 + * @regno: The palette index to change.
87443 + * @red: The red field for the palette data.
87444 + * @green: The green field for the palette data.
87445 + * @blue: The blue field for the palette data.
87446 + * @trans: The transparency (alpha) field for the palette data.
87447 + * @info: The framebuffer being changed.
87448 + */
87449 +static int s3c_fb_setcolreg(unsigned regno,
87450 + unsigned red, unsigned green, unsigned blue,
87451 + unsigned transp, struct fb_info *info)
87452 +{
87453 + struct s3c_fb_win *win = info->par;
87454 + struct s3c_fb *sfb = win->parent;
87455 + unsigned int val;
87456 +
87457 + dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
87458 + __func__, win->index, regno, red, green, blue);
87459 +
87460 + switch (info->fix.visual) {
87461 + case FB_VISUAL_TRUECOLOR:
87462 + /* true-colour, use pseudo-palette */
87463 +
87464 + if (regno < 16) {
87465 + u32 *pal = info->pseudo_palette;
87466 +
87467 + val = chan_to_field(red, &info->var.red);
87468 + val |= chan_to_field(green, &info->var.green);
87469 + val |= chan_to_field(blue, &info->var.blue);
87470 +
87471 + pal[regno] = val;
87472 + }
87473 + break;
87474 +
87475 + case FB_VISUAL_PSEUDOCOLOR:
87476 + if (regno < s3c_fb_win_pal_size(win->index)) {
87477 + val = chan_to_field(red, &win->palette.r);
87478 + val |= chan_to_field(green, &win->palette.g);
87479 + val |= chan_to_field(blue, &win->palette.b);
87480 +
87481 + s3c_fb_update_palette(sfb, win, regno, val);
87482 + }
87483 +
87484 + break;
87485 +
87486 + default:
87487 + return 1; /* unknown type */
87488 + }
87489 +
87490 + return 0;
87491 +}
87492 +
87493 +/**
87494 + * s3c_fb_enable() - Set the state of the main LCD output
87495 + * @sfb: The main framebuffer state.
87496 + * @enable: The state to set.
87497 + */
87498 +static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
87499 +{
87500 + u32 vidcon0 = readl(sfb->regs + VIDCON0);
87501 +
87502 + if (enable)
87503 + vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
87504 + else {
87505 + /* see the note in the framebuffer datasheet about
87506 + * why you cannot take both of these bits down at the
87507 + * same time. */
87508 +
87509 + if (!(vidcon0 & VIDCON0_ENVID))
87510 + return;
87511 +
87512 + vidcon0 |= VIDCON0_ENVID;
87513 + vidcon0 &= ~VIDCON0_ENVID_F;
87514 + }
87515 +
87516 + writel(vidcon0, sfb->regs + VIDCON0);
87517 +}
87518 +
87519 +/**
87520 + * s3c_fb_blank() - blank or unblank the given window
87521 + * @blank_mode: The blank state from FB_BLANK_*
87522 + * @info: The framebuffer to blank.
87523 + *
87524 + * Framebuffer layer request to change the power state.
87525 + */
87526 +static int s3c_fb_blank(int blank_mode, struct fb_info *info)
87527 +{
87528 + struct s3c_fb_win *win = info->par;
87529 + struct s3c_fb *sfb = win->parent;
87530 + unsigned int index = win->index;
87531 + u32 wincon;
87532 +
87533 + dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
87534 +
87535 + wincon = readl(sfb->regs + WINCON(index));
87536 +
87537 + switch (blank_mode) {
87538 + case FB_BLANK_POWERDOWN:
87539 + wincon &= ~WINCONx_ENWIN;
87540 + sfb->enabled &= ~(1 << index);
87541 + /* fall through to FB_BLANK_NORMAL */
87542 +
87543 + case FB_BLANK_NORMAL:
87544 + /* disable the DMA and display 0x0 (black) */
87545 + writel(WINxMAP_MAP | WINxMAP_MAP_COLOUR(0x0),
87546 + sfb->regs + WINxMAP(index));
87547 + break;
87548 +
87549 + case FB_BLANK_UNBLANK:
87550 + writel(0x0, sfb->regs + WINxMAP(index));
87551 + wincon |= WINCONx_ENWIN;
87552 + sfb->enabled |= (1 << index);
87553 + break;
87554 +
87555 + case FB_BLANK_VSYNC_SUSPEND:
87556 + case FB_BLANK_HSYNC_SUSPEND:
87557 + default:
87558 + return 1;
87559 + }
87560 +
87561 + writel(wincon, sfb->regs + WINCON(index));
87562 +
87563 + /* Check the enabled state to see if we need to be running the
87564 + * main LCD interface, as if there are no active windows then
87565 + * it is highly likely that we also do not need to output
87566 + * anything.
87567 + */
87568 +
87569 + /* We could do something like the following code, but the current
87570 + * system of using framebuffer events means that we cannot make
87571 + * the distinction between just window 0 being inactive and all
87572 + * the windows being down.
87573 + *
87574 + * s3c_fb_enable(sfb, sfb->enabled ? 1 : 0);
87575 + */
87576 +
87577 + /* we're stuck with this until we can do something about overriding
87578 + * the power control using the blanking event for a single fb.
87579 + */
87580 + if (index == 0)
87581 + s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
87582 +
87583 + return 0;
87584 +}
87585 +
87586 +static struct fb_ops s3c_fb_ops = {
87587 + .owner = THIS_MODULE,
87588 + .fb_check_var = s3c_fb_check_var,
87589 + .fb_set_par = s3c_fb_set_par,
87590 + .fb_blank = s3c_fb_blank,
87591 + .fb_setcolreg = s3c_fb_setcolreg,
87592 + .fb_fillrect = cfb_fillrect,
87593 + .fb_copyarea = cfb_copyarea,
87594 + .fb_imageblit = cfb_imageblit,
87595 +};
87596 +
87597 +/**
87598 + * s3c_fb_alloc_memory() - allocate display memory for framebuffer window
87599 + * @sfb: The base resources for the hardware.
87600 + * @win: The window to initialise memory for.
87601 + *
87602 + * Allocate memory for the given framebuffer.
87603 + */
87604 +static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb,
87605 + struct s3c_fb_win *win)
87606 +{
87607 + struct s3c_fb_pd_win *windata = win->windata;
87608 + unsigned int real_size, virt_size, size;
87609 + struct fb_info *fbi = win->fbinfo;
87610 + dma_addr_t map_dma;
87611 +
87612 + dev_dbg(sfb->dev, "allocating memory for display\n");
87613 +
87614 + real_size = windata->win_mode.xres * windata->win_mode.yres;
87615 + virt_size = windata->virtual_x * windata->virtual_y;
87616 +
87617 + dev_dbg(sfb->dev, "real_size=%u (%u.%u), virt_size=%u (%u.%u)\n",
87618 + real_size, windata->win_mode.xres, windata->win_mode.yres,
87619 + virt_size, windata->virtual_x, windata->virtual_y);
87620 +
87621 + size = (real_size > virt_size) ? real_size : virt_size;
87622 + size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp;
87623 + size /= 8;
87624 +
87625 + fbi->fix.smem_len = size;
87626 + size = PAGE_ALIGN(size);
87627 +
87628 + dev_dbg(sfb->dev, "want %u bytes for window\n", size);
87629 +
87630 + fbi->screen_base = dma_alloc_writecombine(sfb->dev, size,
87631 + &map_dma, GFP_KERNEL);
87632 + if (!fbi->screen_base)
87633 + return -ENOMEM;
87634 +
87635 + dev_dbg(sfb->dev, "mapped %x to %p\n",
87636 + (unsigned int)map_dma, fbi->screen_base);
87637 +
87638 + memset(fbi->screen_base, 0x0, size);
87639 + fbi->fix.smem_start = map_dma;
87640 +
87641 + return 0;
87642 +}
87643 +
87644 +/**
87645 + * s3c_fb_free_memory() - free the display memory for the given window
87646 + * @sfb: The base resources for the hardware.
87647 + * @win: The window to free the display memory for.
87648 + *
87649 + * Free the display memory allocated by s3c_fb_alloc_memory().
87650 + */
87651 +static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
87652 +{
87653 + struct fb_info *fbi = win->fbinfo;
87654 +
87655 + dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
87656 + fbi->screen_base, fbi->fix.smem_start);
87657 +}
87658 +
87659 +/**
87660 + * s3c_fb_release_win() - release resources for a framebuffer window.
87661 + * @win: The window to cleanup the resources for.
87662 + *
87663 + * Release the resources that where claimed for the hardware window,
87664 + * such as the framebuffer instance and any memory claimed for it.
87665 + */
87666 +static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
87667 +{
87668 + fb_dealloc_cmap(&win->fbinfo->cmap);
87669 + unregister_framebuffer(win->fbinfo);
87670 + s3c_fb_free_memory(sfb, win);
87671 +}
87672 +
87673 +/**
87674 + * s3c_fb_probe_win() - register an hardware window
87675 + * @sfb: The base resources for the hardware
87676 + * @res: Pointer to where to place the resultant window.
87677 + *
87678 + * Allocate and do the basic initialisation for one of the hardware's graphics
87679 + * windows.
87680 + */
87681 +static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
87682 + struct s3c_fb_win **res)
87683 +{
87684 + struct fb_var_screeninfo *var;
87685 + struct fb_videomode *initmode;
87686 + struct s3c_fb_pd_win *windata;
87687 + struct s3c_fb_win *win;
87688 + struct fb_info *fbinfo;
87689 + int palette_size;
87690 + int ret;
87691 +
87692 + dev_dbg(sfb->dev, "probing window %d\n", win_no);
87693 +
87694 + palette_size = s3c_fb_win_pal_size(win_no);
87695 +
87696 + fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
87697 + palette_size * sizeof(u32), sfb->dev);
87698 + if (!fbinfo) {
87699 + dev_err(sfb->dev, "failed to allocate framebuffer\n");
87700 + return -ENOENT;
87701 + }
87702 +
87703 + windata = sfb->pdata->win[win_no];
87704 + initmode = &windata->win_mode;
87705 +
87706 + WARN_ON(windata->max_bpp == 0);
87707 + WARN_ON(windata->win_mode.xres == 0);
87708 + WARN_ON(windata->win_mode.yres == 0);
87709 +
87710 + win = fbinfo->par;
87711 + var = &fbinfo->var;
87712 + win->fbinfo = fbinfo;
87713 + win->parent = sfb;
87714 + win->windata = windata;
87715 + win->index = win_no;
87716 + win->palette_buffer = (u32 *)(win + 1);
87717 +
87718 + ret = s3c_fb_alloc_memory(sfb, win);
87719 + if (ret) {
87720 + dev_err(sfb->dev, "failed to allocate display memory\n");
87721 + goto err_framebuffer;
87722 + }
87723 +
87724 + /* setup the r/b/g positions for the window's palette */
87725 + s3c_fb_init_palette(win_no, &win->palette);
87726 +
87727 + /* setup the initial video mode from the window */
87728 + fb_videomode_to_var(&fbinfo->var, initmode);
87729 +
87730 + fbinfo->fix.type = FB_TYPE_PACKED_PIXELS;
87731 + fbinfo->fix.accel = FB_ACCEL_NONE;
87732 + fbinfo->var.activate = FB_ACTIVATE_NOW;
87733 + fbinfo->var.vmode = FB_VMODE_NONINTERLACED;
87734 + fbinfo->var.bits_per_pixel = windata->default_bpp;
87735 + fbinfo->fbops = &s3c_fb_ops;
87736 + fbinfo->flags = FBINFO_FLAG_DEFAULT;
87737 + fbinfo->pseudo_palette = &win->pseudo_palette;
87738 +
87739 + /* prepare to actually start the framebuffer */
87740 +
87741 + ret = s3c_fb_check_var(&fbinfo->var, fbinfo);
87742 + if (ret < 0) {
87743 + dev_err(sfb->dev, "check_var failed on initial video params\n");
87744 + goto err_alloc_mem;
87745 + }
87746 +
87747 + /* create initial colour map */
87748 +
87749 + ret = fb_alloc_cmap(&fbinfo->cmap, s3c_fb_win_pal_size(win_no), 1);
87750 + if (ret == 0)
87751 + fb_set_cmap(&fbinfo->cmap, fbinfo);
87752 + else
87753 + dev_err(sfb->dev, "failed to allocate fb cmap\n");
87754 +
87755 + s3c_fb_set_par(fbinfo);
87756 +
87757 + dev_dbg(sfb->dev, "about to register framebuffer\n");
87758 +
87759 + /* run the check_var and set_par on our configuration. */
87760 +
87761 + ret = register_framebuffer(fbinfo);
87762 + if (ret < 0) {
87763 + dev_err(sfb->dev, "failed to register framebuffer\n");
87764 + goto err_alloc_mem;
87765 + }
87766 +
87767 + *res = win;
87768 + dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id);
87769 +
87770 + return 0;
87771 +
87772 +err_alloc_mem:
87773 + s3c_fb_free_memory(sfb, win);
87774 +
87775 +err_framebuffer:
87776 + unregister_framebuffer(fbinfo);
87777 + return ret;
87778 +}
87779 +
87780 +/**
87781 + * s3c_fb_clear_win() - clear hardware window registers.
87782 + * @sfb: The base resources for the hardware.
87783 + * @win: The window to process.
87784 + *
87785 + * Reset the specific window registers to a known state.
87786 + */
87787 +static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
87788 +{
87789 + void __iomem *regs = sfb->regs;
87790 +
87791 + writel(0, regs + WINCON(win));
87792 + writel(0xffffff, regs + WxKEYCONy(win, 0));
87793 + writel(0xffffff, regs + WxKEYCONy(win, 1));
87794 +
87795 + writel(0, regs + VIDOSD_A(win));
87796 + writel(0, regs + VIDOSD_B(win));
87797 + writel(0, regs + VIDOSD_C(win));
87798 +}
87799 +
87800 +static int __devinit s3c_fb_probe(struct platform_device *pdev)
87801 +{
87802 + struct device *dev = &pdev->dev;
87803 + struct s3c_fb_platdata *pd;
87804 + struct s3c_fb *sfb;
87805 + struct resource *res;
87806 + int win;
87807 + int ret = 0;
87808 +
87809 + pd = pdev->dev.platform_data;
87810 + if (!pd) {
87811 + dev_err(dev, "no platform data specified\n");
87812 + return -EINVAL;
87813 + }
87814 +
87815 + sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL);
87816 + if (!sfb) {
87817 + dev_err(dev, "no memory for framebuffers\n");
87818 + return -ENOMEM;
87819 + }
87820 +
87821 + sfb->dev = dev;
87822 + sfb->pdata = pd;
87823 +
87824 + sfb->bus_clk = clk_get(dev, "lcd");
87825 + if (IS_ERR(sfb->bus_clk)) {
87826 + dev_err(dev, "failed to get bus clock\n");
87827 + goto err_sfb;
87828 + }
87829 +
87830 + clk_enable(sfb->bus_clk);
87831 +
87832 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
87833 + if (!res) {
87834 + dev_err(dev, "failed to find registers\n");
87835 + ret = -ENOENT;
87836 + goto err_clk;
87837 + }
87838 +
87839 + sfb->regs_res = request_mem_region(res->start, resource_size(res),
87840 + dev_name(dev));
87841 + if (!sfb->regs_res) {
87842 + dev_err(dev, "failed to claim register region\n");
87843 + ret = -ENOENT;
87844 + goto err_clk;
87845 + }
87846 +
87847 + sfb->regs = ioremap(res->start, resource_size(res));
87848 + if (!sfb->regs) {
87849 + dev_err(dev, "failed to map registers\n");
87850 + ret = -ENXIO;
87851 + goto err_req_region;
87852 + }
87853 +
87854 + dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
87855 +
87856 + /* setup gpio and output polarity controls */
87857 +
87858 + pd->setup_gpio();
87859 +
87860 + writel(pd->vidcon1, sfb->regs + VIDCON1);
87861 +
87862 + /* zero all windows before we do anything */
87863 +
87864 + for (win = 0; win < S3C_FB_MAX_WIN; win++)
87865 + s3c_fb_clear_win(sfb, win);
87866 +
87867 + /* we have the register setup, start allocating framebuffers */
87868 +
87869 + for (win = 0; win < S3C_FB_MAX_WIN; win++) {
87870 + if (!pd->win[win])
87871 + continue;
87872 +
87873 + ret = s3c_fb_probe_win(sfb, win, &sfb->windows[win]);
87874 + if (ret < 0) {
87875 + dev_err(dev, "failed to create window %d\n", win);
87876 + for (; win >= 0; win--)
87877 + s3c_fb_release_win(sfb, sfb->windows[win]);
87878 + goto err_ioremap;
87879 + }
87880 + }
87881 +
87882 + platform_set_drvdata(pdev, sfb);
87883 +
87884 + return 0;
87885 +
87886 +err_ioremap:
87887 + iounmap(sfb->regs);
87888 +
87889 +err_req_region:
87890 + release_resource(sfb->regs_res);
87891 + kfree(sfb->regs_res);
87892 +
87893 +err_clk:
87894 + clk_disable(sfb->bus_clk);
87895 + clk_put(sfb->bus_clk);
87896 +
87897 +err_sfb:
87898 + kfree(sfb);
87899 + return ret;
87900 +}
87901 +
87902 +/**
87903 + * s3c_fb_remove() - Cleanup on module finalisation
87904 + * @pdev: The platform device we are bound to.
87905 + *
87906 + * Shutdown and then release all the resources that the driver allocated
87907 + * on initialisation.
87908 + */
87909 +static int __devexit s3c_fb_remove(struct platform_device *pdev)
87910 +{
87911 + struct s3c_fb *sfb = platform_get_drvdata(pdev);
87912 + int win;
87913 +
87914 + for (win = 0; win <= S3C_FB_MAX_WIN; win++)
87915 + s3c_fb_release_win(sfb, sfb->windows[win]);
87916 +
87917 + iounmap(sfb->regs);
87918 +
87919 + clk_disable(sfb->bus_clk);
87920 + clk_put(sfb->bus_clk);
87921 +
87922 + release_resource(sfb->regs_res);
87923 + kfree(sfb->regs_res);
87924 +
87925 + kfree(sfb);
87926 +
87927 + return 0;
87928 +}
87929 +
87930 +#ifdef CONFIG_PM
87931 +static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
87932 +{
87933 + struct s3c_fb *sfb = platform_get_drvdata(pdev);
87934 + struct s3c_fb_win *win;
87935 + int win_no;
87936 +
87937 + for (win_no = S3C_FB_MAX_WIN; win_no >= 0; win_no--) {
87938 + win = sfb->windows[win_no];
87939 + if (!win)
87940 + continue;
87941 +
87942 + /* use the blank function to push into power-down */
87943 + s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
87944 + }
87945 +
87946 + clk_disable(sfb->bus_clk);
87947 + return 0;
87948 +}
87949 +
87950 +static int s3c_fb_resume(struct platform_device *pdev)
87951 +{
87952 + struct s3c_fb *sfb = platform_get_drvdata(pdev);
87953 + struct s3c_fb_win *win;
87954 + int win_no;
87955 +
87956 + clk_enable(sfb->bus_clk);
87957 +
87958 + for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
87959 + win = sfb->windows[win_no];
87960 + if (!win)
87961 + continue;
87962 +
87963 + dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
87964 + s3c_fb_set_par(win->fbinfo);
87965 + }
87966 +
87967 + return 0;
87968 +}
87969 +#else
87970 +#define s3c_fb_suspend NULL
87971 +#define s3c_fb_resume NULL
87972 +#endif
87973 +
87974 +static struct platform_driver s3c_fb_driver = {
87975 + .probe = s3c_fb_probe,
87976 + .remove = s3c_fb_remove,
87977 + .suspend = s3c_fb_suspend,
87978 + .resume = s3c_fb_resume,
87979 + .driver = {
87980 + .name = "s3c-fb",
87981 + .owner = THIS_MODULE,
87982 + },
87983 +};
87984 +
87985 +static int __init s3c_fb_init(void)
87986 +{
87987 + return platform_driver_register(&s3c_fb_driver);
87988 +}
87989 +
87990 +static void __exit s3c_fb_cleanup(void)
87991 +{
87992 + platform_driver_unregister(&s3c_fb_driver);
87993 +}
87994 +
87995 +module_init(s3c_fb_init);
87996 +module_exit(s3c_fb_cleanup);
87997 +
87998 +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
87999 +MODULE_DESCRIPTION("Samsung S3C SoC Framebuffer driver");
88000 +MODULE_LICENSE("GPL");
88001 +MODULE_ALIAS("platform:s3c-fb");
88002 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/watchdog/Kconfig linux-2.6.29-rc3.owrt.om/drivers/watchdog/Kconfig
88003 --- linux-2.6.29-rc3.owrt/drivers/watchdog/Kconfig 2009-05-10 22:08:45.000000000 +0200
88004 +++ linux-2.6.29-rc3.owrt.om/drivers/watchdog/Kconfig 2009-05-10 22:28:00.000000000 +0200
88005 @@ -154,6 +154,13 @@
88006 The driver can be built as a module by choosing M, and will
88007 be called s3c2410_wdt
88008
88009 +config PCF50606_WATCHDOG
88010 + depends on MFD_PCF50606
88011 + tristate "Philips PCF50606 watchdog"
88012 + help
88013 + If you say yes here you get support for the Philips PCF50606
88014 + PMU's watchdog.
88015 +
88016 config SA1100_WATCHDOG
88017 tristate "SA1100/PXA2xx watchdog"
88018 depends on ARCH_SA1100 || ARCH_PXA
88019 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/watchdog/Makefile linux-2.6.29-rc3.owrt.om/drivers/watchdog/Makefile
88020 --- linux-2.6.29-rc3.owrt/drivers/watchdog/Makefile 2009-05-10 22:04:48.000000000 +0200
88021 +++ linux-2.6.29-rc3.owrt.om/drivers/watchdog/Makefile 2009-05-10 22:28:00.000000000 +0200
88022 @@ -34,6 +34,7 @@
88023 obj-$(CONFIG_IXP4XX_WATCHDOG) += ixp4xx_wdt.o
88024 obj-$(CONFIG_KS8695_WATCHDOG) += ks8695_wdt.o
88025 obj-$(CONFIG_S3C2410_WATCHDOG) += s3c2410_wdt.o
88026 +obj-$(CONFIG_PCF50606_WATCHDOG) += pcf50606_wdt.o
88027 obj-$(CONFIG_SA1100_WATCHDOG) += sa1100_wdt.o
88028 obj-$(CONFIG_MPCORE_WATCHDOG) += mpcore_wdt.o
88029 obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o
88030 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/drivers/watchdog/pcf50606_wdt.c linux-2.6.29-rc3.owrt.om/drivers/watchdog/pcf50606_wdt.c
88031 --- linux-2.6.29-rc3.owrt/drivers/watchdog/pcf50606_wdt.c 1970-01-01 01:00:00.000000000 +0100
88032 +++ linux-2.6.29-rc3.owrt.om/drivers/watchdog/pcf50606_wdt.c 2009-05-10 22:28:00.000000000 +0200
88033 @@ -0,0 +1,223 @@
88034 +/* Philips PCF50606 Watchdog Timer Driver
88035 + *
88036 + * (C) 2006-2008 by Openmoko, Inc.
88037 + * Author: Balaji Rao <balajirrao@openmoko.org>
88038 + * All rights reserved.
88039 + *
88040 + * Broken down from monstrous PCF50606 driver mainly by
88041 + * Harald Welte, Matt Hsu, Andy Green and Werner Almesberger
88042 + *
88043 + * This program is free software; you can redistribute it and/or
88044 + * modify it under the terms of the GNU General Public License as
88045 + * published by the Free Software Foundation; either version 2 of
88046 + * the License, or (at your option) any later version.
88047 + */
88048 +
88049 +#include <linux/kernel.h>
88050 +#include <linux/module.h>
88051 +#include <linux/init.h>
88052 +#include <linux/device.h>
88053 +#include <linux/rtc.h>
88054 +#include <linux/bcd.h>
88055 +#include <linux/err.h>
88056 +#include <linux/miscdevice.h>
88057 +#include <linux/watchdog.h>
88058 +#include <linux/platform_device.h>
88059 +
88060 +#include <linux/mfd/pcf50606/core.h>
88061 +
88062 +static struct pcf50606 *pcf = NULL;
88063 +static unsigned long wdt_status;
88064 +
88065 +#define WDT_IN_USE 0
88066 +#define WDT_OK_TO_CLOSE 1
88067 +#define WDT_REGION_INITED 2
88068 +#define WDT_DEVICE_INITED 3
88069 +
88070 +static int allow_close;
88071 +#define CLOSE_STATE_NOT 0x0000
88072 +#define CLOSE_STATE_ALLOW 0x2342
88073 +
88074 +#define PCF50606_REG_OOCC1 0x08
88075 +#define PCF50606_REG_OOCS 0x01
88076 +
88077 +#define PCF50606_OOCS_WDTEXP 0x80
88078 +#define PCF50606_OOCC1_WDTRST 0x08
88079 +
88080 +static void pcf50606_wdt_start(void)
88081 +{
88082 + pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_OOCC1, PCF50606_OOCC1_WDTRST,
88083 + PCF50606_OOCC1_WDTRST);
88084 +}
88085 +
88086 +static void pcf50606_wdt_stop(void)
88087 +{
88088 + pcf50606_reg_clear_bits(pcf, PCF50606_REG_OOCS, PCF50606_OOCS_WDTEXP);
88089 +}
88090 +
88091 +static void pcf50606_wdt_keepalive(void)
88092 +{
88093 + pcf50606_wdt_start();
88094 +}
88095 +
88096 +static int pcf50606_wdt_open(struct inode *inode, struct file *file)
88097 +{
88098 + if (test_and_set_bit(WDT_IN_USE, &wdt_status))
88099 + return -EBUSY;
88100 +
88101 + pcf50606_wdt_start();
88102 +
88103 + return nonseekable_open(inode, file);
88104 +}
88105 +
88106 +static int pcf50606_wdt_release(struct inode *inode, struct file *file)
88107 +{
88108 + if (allow_close == CLOSE_STATE_ALLOW)
88109 + pcf50606_wdt_stop();
88110 + else {
88111 + printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
88112 + pcf50606_wdt_keepalive();
88113 + }
88114 +
88115 + allow_close = CLOSE_STATE_NOT;
88116 + clear_bit(WDT_IN_USE, &wdt_status);
88117 +
88118 + return 0;
88119 +}
88120 +
88121 +static ssize_t pcf50606_wdt_write(struct file *file, const char __user *data,
88122 + size_t len, loff_t *ppos)
88123 +{
88124 + if (len) {
88125 + size_t i;
88126 +
88127 + for (i = 0; i != len; i++) {
88128 + char c;
88129 + if (get_user(c, data + i))
88130 + return -EFAULT;
88131 + if (c == 'V')
88132 + allow_close = CLOSE_STATE_ALLOW;
88133 + }
88134 + pcf50606_wdt_keepalive();
88135 + }
88136 +
88137 + return len;
88138 +}
88139 +
88140 +static struct watchdog_info pcf50606_wdt_ident = {
88141 + .options = WDIOF_MAGICCLOSE,
88142 + .firmware_version = 0,
88143 + .identity = "PCF50606 Watchdog",
88144 +};
88145 +
88146 +static int pcf50606_wdt_ioctl(struct inode *inode, struct file *file,
88147 + unsigned int cmd, unsigned long arg)
88148 +{
88149 + void __user *argp = (void __user *)arg;
88150 + int __user *p = argp;
88151 +
88152 + switch (cmd) {
88153 + case WDIOC_GETSUPPORT:
88154 + return copy_to_user(argp, &pcf50606_wdt_ident,
88155 + sizeof(pcf50606_wdt_ident)) ? -EFAULT : 0;
88156 + break;
88157 + case WDIOC_GETSTATUS:
88158 + case WDIOC_GETBOOTSTATUS:
88159 + return put_user(0, p);
88160 + case WDIOC_KEEPALIVE:
88161 + pcf50606_wdt_keepalive();
88162 + return 0;
88163 + case WDIOC_GETTIMEOUT:
88164 + return put_user(8, p);
88165 + default:
88166 + return -ENOIOCTLCMD;
88167 + }
88168 +}
88169 +
88170 +static struct file_operations pcf50606_wdt_fops = {
88171 + .owner = THIS_MODULE,
88172 + .llseek = no_llseek,
88173 + .write = &pcf50606_wdt_write,
88174 + .ioctl = &pcf50606_wdt_ioctl,
88175 + .open = &pcf50606_wdt_open,
88176 + .release = &pcf50606_wdt_release,
88177 +};
88178 +
88179 +static struct miscdevice pcf50606_wdt_miscdev = {
88180 + .minor = WATCHDOG_MINOR,
88181 + .name = "watchdog",
88182 + .fops = &pcf50606_wdt_fops,
88183 +};
88184 +
88185 +static void pcf50606_wdt_irq(int irq, void *unused)
88186 +{
88187 + pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_OOCC1,
88188 + PCF50606_OOCC1_WDTRST,
88189 + PCF50606_OOCC1_WDTRST);
88190 +}
88191 +
88192 +int __init pcf50606_wdt_probe(struct platform_device *pdev)
88193 +{
88194 + struct pcf50606_subdev_pdata *pdata;
88195 + int err;
88196 +
88197 + if (pcf) {
88198 + dev_err(pcf->dev, "Only one instance of WDT supported\n");
88199 + return -ENODEV;
88200 + }
88201 +
88202 + pdata = pdev->dev.platform_data;
88203 + if (!pdata) {
88204 + dev_err(&pdev->dev, "No platform data available\n");
88205 + return -EINVAL;
88206 + }
88207 +
88208 + pcf = pdata->pcf;
88209 +
88210 + err = misc_register(&pcf50606_wdt_miscdev);
88211 + if (err) {
88212 + dev_err(&pdev->dev, "cannot register miscdev on "
88213 + "minor=%d (%d)\n", WATCHDOG_MINOR, err);
88214 + return err;
88215 + }
88216 + set_bit(WDT_DEVICE_INITED, &wdt_status);
88217 +
88218 + pcf50606_register_irq(pcf, PCF50606_IRQ_CHGWD10S, pcf50606_wdt_irq, NULL);
88219 +
88220 + return 0;
88221 +}
88222 +
88223 +static int __devexit pcf50606_wdt_remove(struct platform_device *pdev)
88224 +{
88225 + pcf50606_free_irq(pcf, PCF50606_IRQ_CHGWD10S);
88226 + misc_deregister(&pcf50606_wdt_miscdev);
88227 + pcf = NULL;
88228 +
88229 + return 0;
88230 +}
88231 +
88232 +struct platform_driver pcf50606_wdt_driver = {
88233 + .driver = {
88234 + .name = "pcf50606-wdt",
88235 + },
88236 + .probe = pcf50606_wdt_probe,
88237 + .remove = __devexit_p(pcf50606_wdt_remove),
88238 +};
88239 +
88240 +static int __init pcf50606_wdt_init(void)
88241 +{
88242 + return platform_driver_register(&pcf50606_wdt_driver);
88243 +}
88244 +module_init(pcf50606_wdt_init);
88245 +
88246 +static void __exit pcf50606_wdt_exit(void)
88247 +{
88248 + platform_driver_unregister(&pcf50606_wdt_driver);
88249 +}
88250 +module_exit(pcf50606_wdt_exit);
88251 +
88252 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
88253 +MODULE_DESCRIPTION("PCF50606 wdt driver");
88254 +MODULE_LICENSE("GPL");
88255 +MODULE_ALIAS("platform:pcf50606-wdt");
88256 +
88257 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/fs/jffs2/background.c linux-2.6.29-rc3.owrt.om/fs/jffs2/background.c
88258 --- linux-2.6.29-rc3.owrt/fs/jffs2/background.c 2009-05-10 22:08:58.000000000 +0200
88259 +++ linux-2.6.29-rc3.owrt.om/fs/jffs2/background.c 2009-05-10 22:28:00.000000000 +0200
88260 @@ -95,13 +95,17 @@
88261 spin_unlock(&c->erase_completion_lock);
88262
88263
88264 - /* This thread is purely an optimisation. But if it runs when
88265 - other things could be running, it actually makes things a
88266 - lot worse. Use yield() and put it at the back of the runqueue
88267 - every time. Especially during boot, pulling an inode in
88268 - with read_inode() is much preferable to having the GC thread
88269 - get there first. */
88270 - yield();
88271 + /* Problem - immediately after bootup, the GCD spends a lot
88272 + * of time in places like jffs2_kill_fragtree(); so much so
88273 + * that userspace processes (like gdm and X) are starved
88274 + * despite plenty of cond_resched()s and renicing. Yield()
88275 + * doesn't help, either (presumably because userspace and GCD
88276 + * are generally competing for a higher latency resource -
88277 + * disk).
88278 + * This forces the GCD to slow the hell down. Pulling an
88279 + * inode in with read_inode() is much preferable to having
88280 + * the GC thread get there first. */
88281 + schedule_timeout_interruptible(msecs_to_jiffies(50));
88282
88283 /* Put_super will send a SIGKILL and then wait on the sem.
88284 */
88285 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/asm-arm/plat-s3c24xx/neo1973.h linux-2.6.29-rc3.owrt.om/include/asm-arm/plat-s3c24xx/neo1973.h
88286 --- linux-2.6.29-rc3.owrt/include/asm-arm/plat-s3c24xx/neo1973.h 1970-01-01 01:00:00.000000000 +0100
88287 +++ linux-2.6.29-rc3.owrt.om/include/asm-arm/plat-s3c24xx/neo1973.h 2009-05-10 22:28:00.000000000 +0200
88288 @@ -0,0 +1,33 @@
88289 +/*
88290 + * include/asm-arm/plat-s3c24xx/neo1973.h
88291 + *
88292 + * Common utility code for GTA01 and GTA02
88293 + *
88294 + * Copyright (C) 2008 by Openmoko, Inc.
88295 + * Author: Holger Hans Peter Freyther <freyther@openmoko.org>
88296 + * All rights reserved.
88297 + *
88298 + * This program is free software; you can redistribute it and/or
88299 + * modify it under the terms of the GNU General Public License as
88300 + * published by the Free Software Foundation; either version 2 of
88301 + * the License, or (at your option) any later version.
88302 + *
88303 + * This program is distributed in the hope that it will be useful,
88304 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
88305 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88306 + * GNU General Public License for more details.
88307 + *
88308 + * You should have received a copy of the GNU General Public License
88309 + * along with this program; if not, write to the Free Software
88310 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
88311 + * MA 02111-1307 USA
88312 + *
88313 + */
88314 +
88315 +#ifndef NEO1973_H
88316 +#define NEO1973_H
88317 +
88318 +void neo1973_gpb_add_shadow_gpio(unsigned int gpio);
88319 +void neo1973_gpb_setpin(unsigned int pin, unsigned to);
88320 +
88321 +#endif
88322 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/asm-arm/plat-s3c24xx/regs-iis.h linux-2.6.29-rc3.owrt.om/include/asm-arm/plat-s3c24xx/regs-iis.h
88323 --- linux-2.6.29-rc3.owrt/include/asm-arm/plat-s3c24xx/regs-iis.h 2009-05-10 22:04:48.000000000 +0200
88324 +++ linux-2.6.29-rc3.owrt.om/include/asm-arm/plat-s3c24xx/regs-iis.h 1970-01-01 01:00:00.000000000 +0100
88325 @@ -1,77 +0,0 @@
88326 -/* arch/arm/mach-s3c2410/include/mach/regs-iis.h
88327 - *
88328 - * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
88329 - * http://www.simtec.co.uk/products/SWLINUX/
88330 - *
88331 - * This program is free software; you can redistribute it and/or modify
88332 - * it under the terms of the GNU General Public License version 2 as
88333 - * published by the Free Software Foundation.
88334 - *
88335 - * S3C2410 IIS register definition
88336 -*/
88337 -
88338 -#ifndef __ASM_ARCH_REGS_IIS_H
88339 -#define __ASM_ARCH_REGS_IIS_H
88340 -
88341 -#define S3C2410_IISCON (0x00)
88342 -
88343 -#define S3C2410_IISCON_LRINDEX (1<<8)
88344 -#define S3C2410_IISCON_TXFIFORDY (1<<7)
88345 -#define S3C2410_IISCON_RXFIFORDY (1<<6)
88346 -#define S3C2410_IISCON_TXDMAEN (1<<5)
88347 -#define S3C2410_IISCON_RXDMAEN (1<<4)
88348 -#define S3C2410_IISCON_TXIDLE (1<<3)
88349 -#define S3C2410_IISCON_RXIDLE (1<<2)
88350 -#define S3C2410_IISCON_PSCEN (1<<1)
88351 -#define S3C2410_IISCON_IISEN (1<<0)
88352 -
88353 -#define S3C2410_IISMOD (0x04)
88354 -
88355 -#define S3C2440_IISMOD_MPLL (1<<9)
88356 -#define S3C2410_IISMOD_SLAVE (1<<8)
88357 -#define S3C2410_IISMOD_NOXFER (0<<6)
88358 -#define S3C2410_IISMOD_RXMODE (1<<6)
88359 -#define S3C2410_IISMOD_TXMODE (2<<6)
88360 -#define S3C2410_IISMOD_TXRXMODE (3<<6)
88361 -#define S3C2410_IISMOD_LR_LLOW (0<<5)
88362 -#define S3C2410_IISMOD_LR_RLOW (1<<5)
88363 -#define S3C2410_IISMOD_IIS (0<<4)
88364 -#define S3C2410_IISMOD_MSB (1<<4)
88365 -#define S3C2410_IISMOD_8BIT (0<<3)
88366 -#define S3C2410_IISMOD_16BIT (1<<3)
88367 -#define S3C2410_IISMOD_BITMASK (1<<3)
88368 -#define S3C2410_IISMOD_256FS (0<<2)
88369 -#define S3C2410_IISMOD_384FS (1<<2)
88370 -#define S3C2410_IISMOD_16FS (0<<0)
88371 -#define S3C2410_IISMOD_32FS (1<<0)
88372 -#define S3C2410_IISMOD_48FS (2<<0)
88373 -#define S3C2410_IISMOD_FS_MASK (3<<0)
88374 -
88375 -#define S3C2410_IISPSR (0x08)
88376 -#define S3C2410_IISPSR_INTMASK (31<<5)
88377 -#define S3C2410_IISPSR_INTSHIFT (5)
88378 -#define S3C2410_IISPSR_EXTMASK (31<<0)
88379 -#define S3C2410_IISPSR_EXTSHFIT (0)
88380 -
88381 -#define S3C2410_IISFCON (0x0c)
88382 -
88383 -#define S3C2410_IISFCON_TXDMA (1<<15)
88384 -#define S3C2410_IISFCON_RXDMA (1<<14)
88385 -#define S3C2410_IISFCON_TXENABLE (1<<13)
88386 -#define S3C2410_IISFCON_RXENABLE (1<<12)
88387 -#define S3C2410_IISFCON_TXMASK (0x3f << 6)
88388 -#define S3C2410_IISFCON_TXSHIFT (6)
88389 -#define S3C2410_IISFCON_RXMASK (0x3f)
88390 -#define S3C2410_IISFCON_RXSHIFT (0)
88391 -
88392 -#define S3C2400_IISFCON_TXDMA (1<<11)
88393 -#define S3C2400_IISFCON_RXDMA (1<<10)
88394 -#define S3C2400_IISFCON_TXENABLE (1<<9)
88395 -#define S3C2400_IISFCON_RXENABLE (1<<8)
88396 -#define S3C2400_IISFCON_TXMASK (0x07 << 4)
88397 -#define S3C2400_IISFCON_TXSHIFT (4)
88398 -#define S3C2400_IISFCON_RXMASK (0x07)
88399 -#define S3C2400_IISFCON_RXSHIFT (0)
88400 -
88401 -#define S3C2410_IISFIFO (0x10)
88402 -#endif /* __ASM_ARCH_REGS_IIS_H */
88403 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h linux-2.6.29-rc3.owrt.om/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h
88404 --- linux-2.6.29-rc3.owrt/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h 2009-05-10 22:04:48.000000000 +0200
88405 +++ linux-2.6.29-rc3.owrt.om/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h 1970-01-01 01:00:00.000000000 +0100
88406 @@ -1,72 +0,0 @@
88407 -/* linux/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h
88408 - *
88409 - * Copyright 2007 Simtec Electronics <linux@simtec.co.uk>
88410 - * http://armlinux.simtec.co.uk/
88411 - *
88412 - * This program is free software; you can redistribute it and/or modify
88413 - * it under the terms of the GNU General Public License version 2 as
88414 - * published by the Free Software Foundation.
88415 - *
88416 - * S3C2412 IIS register definition
88417 -*/
88418 -
88419 -#ifndef __ASM_ARCH_REGS_S3C2412_IIS_H
88420 -#define __ASM_ARCH_REGS_S3C2412_IIS_H
88421 -
88422 -#define S3C2412_IISCON (0x00)
88423 -#define S3C2412_IISMOD (0x04)
88424 -#define S3C2412_IISFIC (0x08)
88425 -#define S3C2412_IISPSR (0x0C)
88426 -#define S3C2412_IISTXD (0x10)
88427 -#define S3C2412_IISRXD (0x14)
88428 -
88429 -#define S3C2412_IISCON_LRINDEX (1 << 11)
88430 -#define S3C2412_IISCON_TXFIFO_EMPTY (1 << 10)
88431 -#define S3C2412_IISCON_RXFIFO_EMPTY (1 << 9)
88432 -#define S3C2412_IISCON_TXFIFO_FULL (1 << 8)
88433 -#define S3C2412_IISCON_RXFIFO_FULL (1 << 7)
88434 -#define S3C2412_IISCON_TXDMA_PAUSE (1 << 6)
88435 -#define S3C2412_IISCON_RXDMA_PAUSE (1 << 5)
88436 -#define S3C2412_IISCON_TXCH_PAUSE (1 << 4)
88437 -#define S3C2412_IISCON_RXCH_PAUSE (1 << 3)
88438 -#define S3C2412_IISCON_TXDMA_ACTIVE (1 << 2)
88439 -#define S3C2412_IISCON_RXDMA_ACTIVE (1 << 1)
88440 -#define S3C2412_IISCON_IIS_ACTIVE (1 << 0)
88441 -
88442 -#define S3C2412_IISMOD_MASTER_INTERNAL (0 << 10)
88443 -#define S3C2412_IISMOD_MASTER_EXTERNAL (1 << 10)
88444 -#define S3C2412_IISMOD_SLAVE (2 << 10)
88445 -#define S3C2412_IISMOD_MASTER_MASK (3 << 10)
88446 -#define S3C2412_IISMOD_MODE_TXONLY (0 << 8)
88447 -#define S3C2412_IISMOD_MODE_RXONLY (1 << 8)
88448 -#define S3C2412_IISMOD_MODE_TXRX (2 << 8)
88449 -#define S3C2412_IISMOD_MODE_MASK (3 << 8)
88450 -#define S3C2412_IISMOD_LR_LLOW (0 << 7)
88451 -#define S3C2412_IISMOD_LR_RLOW (1 << 7)
88452 -#define S3C2412_IISMOD_SDF_IIS (0 << 5)
88453 -#define S3C2412_IISMOD_SDF_MSB (0 << 5)
88454 -#define S3C2412_IISMOD_SDF_LSB (0 << 5)
88455 -#define S3C2412_IISMOD_SDF_MASK (3 << 5)
88456 -#define S3C2412_IISMOD_RCLK_256FS (0 << 3)
88457 -#define S3C2412_IISMOD_RCLK_512FS (1 << 3)
88458 -#define S3C2412_IISMOD_RCLK_384FS (2 << 3)
88459 -#define S3C2412_IISMOD_RCLK_768FS (3 << 3)
88460 -#define S3C2412_IISMOD_RCLK_MASK (3 << 3)
88461 -#define S3C2412_IISMOD_BCLK_32FS (0 << 1)
88462 -#define S3C2412_IISMOD_BCLK_48FS (1 << 1)
88463 -#define S3C2412_IISMOD_BCLK_16FS (2 << 1)
88464 -#define S3C2412_IISMOD_BCLK_24FS (3 << 1)
88465 -#define S3C2412_IISMOD_BCLK_MASK (3 << 1)
88466 -#define S3C2412_IISMOD_8BIT (1 << 0)
88467 -
88468 -#define S3C2412_IISPSR_PSREN (1 << 15)
88469 -
88470 -#define S3C2412_IISFIC_TXFLUSH (1 << 15)
88471 -#define S3C2412_IISFIC_RXFLUSH (1 << 7)
88472 -#define S3C2412_IISFIC_TXCOUNT(x) (((x) >> 8) & 0xf)
88473 -#define S3C2412_IISFIC_RXCOUNT(x) (((x) >> 0) & 0xf)
88474 -
88475 -
88476 -
88477 -#endif /* __ASM_ARCH_REGS_S3C2412_IIS_H */
88478 -
88479 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/android_aid.h linux-2.6.29-rc3.owrt.om/include/linux/android_aid.h
88480 --- linux-2.6.29-rc3.owrt/include/linux/android_aid.h 1970-01-01 01:00:00.000000000 +0100
88481 +++ linux-2.6.29-rc3.owrt.om/include/linux/android_aid.h 2009-05-10 22:28:00.000000000 +0200
88482 @@ -0,0 +1,25 @@
88483 +/* include/linux/android_aid.h
88484 + *
88485 + * Copyright (C) 2008 Google, Inc.
88486 + *
88487 + * This software is licensed under the terms of the GNU General Public
88488 + * License version 2, as published by the Free Software Foundation, and
88489 + * may be copied, distributed, and modified under those terms.
88490 + *
88491 + * This program is distributed in the hope that it will be useful,
88492 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
88493 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88494 + * GNU General Public License for more details.
88495 + *
88496 + */
88497 +
88498 +#ifndef _LINUX_ANDROID_AID_H
88499 +#define _LINUX_ANDROID_AID_H
88500 +
88501 +/* AIDs that the kernel treats differently */
88502 +#define AID_NET_BT_ADMIN 3001
88503 +#define AID_NET_BT 3002
88504 +#define AID_INET 3003
88505 +#define AID_NET_RAW 3004
88506 +
88507 +#endif
88508 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/android_alarm.h linux-2.6.29-rc3.owrt.om/include/linux/android_alarm.h
88509 --- linux-2.6.29-rc3.owrt/include/linux/android_alarm.h 1970-01-01 01:00:00.000000000 +0100
88510 +++ linux-2.6.29-rc3.owrt.om/include/linux/android_alarm.h 2009-05-10 22:28:00.000000000 +0200
88511 @@ -0,0 +1,62 @@
88512 +/* include/linux/android_alarm.h
88513 + *
88514 + * Copyright (C) 2006-2007 Google, Inc.
88515 + *
88516 + * This software is licensed under the terms of the GNU General Public
88517 + * License version 2, as published by the Free Software Foundation, and
88518 + * may be copied, distributed, and modified under those terms.
88519 + *
88520 + * This program is distributed in the hope that it will be useful,
88521 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
88522 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88523 + * GNU General Public License for more details.
88524 + *
88525 + */
88526 +
88527 +#ifndef _LINUX_ANDROID_ALARM_H
88528 +#define _LINUX_ANDROID_ALARM_H
88529 +
88530 +#include <linux/ioctl.h>
88531 +#include <linux/time.h>
88532 +
88533 +enum android_alarm_type {
88534 + /* return code bit numbers or set alarm arg */
88535 + ANDROID_ALARM_RTC_WAKEUP,
88536 + ANDROID_ALARM_RTC,
88537 + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
88538 + ANDROID_ALARM_ELAPSED_REALTIME,
88539 + ANDROID_ALARM_SYSTEMTIME,
88540 +
88541 + ANDROID_ALARM_TYPE_COUNT,
88542 +
88543 + /* return code bit numbers */
88544 + /* ANDROID_ALARM_TIME_CHANGE = 16 */
88545 +};
88546 +
88547 +enum android_alarm_return_flags {
88548 + ANDROID_ALARM_RTC_WAKEUP_MASK = 1U << ANDROID_ALARM_RTC_WAKEUP,
88549 + ANDROID_ALARM_RTC_MASK = 1U << ANDROID_ALARM_RTC,
88550 + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK =
88551 + 1U << ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
88552 + ANDROID_ALARM_ELAPSED_REALTIME_MASK =
88553 + 1U << ANDROID_ALARM_ELAPSED_REALTIME,
88554 + ANDROID_ALARM_SYSTEMTIME_MASK = 1U << ANDROID_ALARM_SYSTEMTIME,
88555 + ANDROID_ALARM_TIME_CHANGE_MASK = 1U << 16
88556 +};
88557 +
88558 +/* Disable alarm */
88559 +#define ANDROID_ALARM_CLEAR(type) _IO('a', 0 | ((type) << 4))
88560 +
88561 +/* Ack last alarm and wait for next */
88562 +#define ANDROID_ALARM_WAIT _IO('a', 1)
88563 +
88564 +#define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size)
88565 +/* Set alarm */
88566 +#define ANDROID_ALARM_SET(type) ALARM_IOW(2, type, struct timespec)
88567 +#define ANDROID_ALARM_SET_AND_WAIT(type) ALARM_IOW(3, type, struct timespec)
88568 +#define ANDROID_ALARM_GET_TIME(type) ALARM_IOW(4, type, struct timespec)
88569 +#define ANDROID_ALARM_SET_RTC _IOW('a', 5, struct timespec)
88570 +#define ANDROID_ALARM_BASE_CMD(cmd) (cmd & ~(_IOC(0, 0, 0xf0, 0)))
88571 +#define ANDROID_ALARM_IOCTL_TO_TYPE(cmd) (_IOC_NR(cmd) >> 4)
88572 +
88573 +#endif
88574 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/ashmem.h linux-2.6.29-rc3.owrt.om/include/linux/ashmem.h
88575 --- linux-2.6.29-rc3.owrt/include/linux/ashmem.h 1970-01-01 01:00:00.000000000 +0100
88576 +++ linux-2.6.29-rc3.owrt.om/include/linux/ashmem.h 2009-05-10 22:28:00.000000000 +0200
88577 @@ -0,0 +1,48 @@
88578 +/*
88579 + * include/linux/ashmem.h
88580 + *
88581 + * Copyright 2008 Google Inc.
88582 + * Author: Robert Love
88583 + *
88584 + * This file is dual licensed. It may be redistributed and/or modified
88585 + * under the terms of the Apache 2.0 License OR version 2 of the GNU
88586 + * General Public License.
88587 + */
88588 +
88589 +#ifndef _LINUX_ASHMEM_H
88590 +#define _LINUX_ASHMEM_H
88591 +
88592 +#include <linux/limits.h>
88593 +#include <linux/ioctl.h>
88594 +
88595 +#define ASHMEM_NAME_LEN 256
88596 +
88597 +#define ASHMEM_NAME_DEF "dev/ashmem"
88598 +
88599 +/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
88600 +#define ASHMEM_NOT_PURGED 0
88601 +#define ASHMEM_WAS_PURGED 1
88602 +
88603 +/* Return values from ASHMEM_GET_PIN_STATUS: Is the mapping pinned? */
88604 +#define ASHMEM_IS_UNPINNED 0
88605 +#define ASHMEM_IS_PINNED 1
88606 +
88607 +struct ashmem_pin {
88608 + __u32 offset; /* offset into region, in bytes, page-aligned */
88609 + __u32 len; /* length forward from offset, in bytes, page-aligned */
88610 +};
88611 +
88612 +#define __ASHMEMIOC 0x77
88613 +
88614 +#define ASHMEM_SET_NAME _IOW(__ASHMEMIOC, 1, char[ASHMEM_NAME_LEN])
88615 +#define ASHMEM_GET_NAME _IOR(__ASHMEMIOC, 2, char[ASHMEM_NAME_LEN])
88616 +#define ASHMEM_SET_SIZE _IOW(__ASHMEMIOC, 3, size_t)
88617 +#define ASHMEM_GET_SIZE _IO(__ASHMEMIOC, 4)
88618 +#define ASHMEM_SET_PROT_MASK _IOW(__ASHMEMIOC, 5, unsigned long)
88619 +#define ASHMEM_GET_PROT_MASK _IO(__ASHMEMIOC, 6)
88620 +#define ASHMEM_PIN _IOW(__ASHMEMIOC, 7, struct ashmem_pin)
88621 +#define ASHMEM_UNPIN _IOW(__ASHMEMIOC, 8, struct ashmem_pin)
88622 +#define ASHMEM_GET_PIN_STATUS _IO(__ASHMEMIOC, 9)
88623 +#define ASHMEM_PURGE_ALL_CACHES _IO(__ASHMEMIOC, 10)
88624 +
88625 +#endif /* _LINUX_ASHMEM_H */
88626 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/bq27000_battery.h linux-2.6.29-rc3.owrt.om/include/linux/bq27000_battery.h
88627 --- linux-2.6.29-rc3.owrt/include/linux/bq27000_battery.h 1970-01-01 01:00:00.000000000 +0100
88628 +++ linux-2.6.29-rc3.owrt.om/include/linux/bq27000_battery.h 2009-05-10 22:28:00.000000000 +0200
88629 @@ -0,0 +1,16 @@
88630 +#ifndef __BQ27000_BATTERY_H__
88631 +#define __BQ27000_BATTERY_H__
88632 +
88633 +void bq27000_charging_state_change(struct platform_device *pdev);
88634 +
88635 +struct bq27000_platform_data {
88636 + const char *name;
88637 + int rsense_mohms;
88638 + int (*hdq_read)(int);
88639 + int (*hdq_write)(int, u8);
88640 + int (*hdq_initialized)(void);
88641 + int (*get_charger_online_status)(void);
88642 + int (*get_charger_active_status)(void);
88643 +};
88644 +
88645 +#endif
88646 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/device.h linux-2.6.29-rc3.owrt.om/include/linux/device.h
88647 --- linux-2.6.29-rc3.owrt/include/linux/device.h 2009-05-10 22:09:07.000000000 +0200
88648 +++ linux-2.6.29-rc3.owrt.om/include/linux/device.h 2009-05-10 22:28:00.000000000 +0200
88649 @@ -48,6 +48,11 @@
88650 struct bus_attribute *);
88651 extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
88652
88653 +extern int __must_check bus_create_device_link(struct bus_type *bus,
88654 + struct kobject *target,
88655 + const char *name);
88656 +extern void bus_remove_device_link(struct bus_type *bus, const char *name);
88657 +
88658 struct bus_type {
88659 const char *name;
88660 struct bus_attribute *bus_attrs;
88661 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/earlysuspend.h linux-2.6.29-rc3.owrt.om/include/linux/earlysuspend.h
88662 --- linux-2.6.29-rc3.owrt/include/linux/earlysuspend.h 1970-01-01 01:00:00.000000000 +0100
88663 +++ linux-2.6.29-rc3.owrt.om/include/linux/earlysuspend.h 2009-05-10 22:28:00.000000000 +0200
88664 @@ -0,0 +1,56 @@
88665 +/* include/linux/earlysuspend.h
88666 + *
88667 + * Copyright (C) 2007-2008 Google, Inc.
88668 + *
88669 + * This software is licensed under the terms of the GNU General Public
88670 + * License version 2, as published by the Free Software Foundation, and
88671 + * may be copied, distributed, and modified under those terms.
88672 + *
88673 + * This program is distributed in the hope that it will be useful,
88674 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
88675 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
88676 + * GNU General Public License for more details.
88677 + *
88678 + */
88679 +
88680 +#ifndef _LINUX_EARLYSUSPEND_H
88681 +#define _LINUX_EARLYSUSPEND_H
88682 +
88683 +#ifdef CONFIG_ANDROID_HAS_EARLYSUSPEND
88684 +#include <linux/list.h>
88685 +#endif
88686 +
88687 +/* The early_suspend structure defines suspend and resume hooks to be called
88688 + * when the user visible sleep state of the system changes, and a level to
88689 + * control the order. They can be used to turn off the screen and input
88690 + * devices that are not used for wakeup.
88691 + * Suspend handlers are called in low to high level order, resume handlers are
88692 + * called in the opposite order. If, when calling register_early_suspend,
88693 + * the suspend handlers have already been called without a matching call to the
88694 + * resume handlers, the suspend handler will be called directly from
88695 + * register_early_suspend. This direct call can violate the normal level order.
88696 + */
88697 +enum {
88698 + EARLY_SUSPEND_LEVEL_BLANK_SCREEN = 50,
88699 + EARLY_SUSPEND_LEVEL_STOP_DRAWING = 100,
88700 + EARLY_SUSPEND_LEVEL_DISABLE_FB = 150,
88701 +};
88702 +struct early_suspend {
88703 +#ifdef CONFIG_ANDROID_HAS_EARLYSUSPEND
88704 + struct list_head link;
88705 + int level;
88706 + void (*suspend)(struct early_suspend *h);
88707 + void (*resume)(struct early_suspend *h);
88708 +#endif
88709 +};
88710 +
88711 +#ifdef CONFIG_ANDROID_HAS_EARLYSUSPEND
88712 +void register_early_suspend(struct early_suspend *handler);
88713 +void unregister_early_suspend(struct early_suspend *handler);
88714 +#else
88715 +#define register_early_suspend(handler) do { } while (0)
88716 +#define unregister_early_suspend(handler) do { } while (0)
88717 +#endif
88718 +
88719 +#endif
88720 +
88721 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/fb.h linux-2.6.29-rc3.owrt.om/include/linux/fb.h
88722 --- linux-2.6.29-rc3.owrt/include/linux/fb.h 2009-05-10 22:09:07.000000000 +0200
88723 +++ linux-2.6.29-rc3.owrt.om/include/linux/fb.h 2009-05-10 22:28:00.000000000 +0200
88724 @@ -123,6 +123,7 @@
88725 #define FB_ACCEL_TRIDENT_3DIMAGE 51 /* Trident 3DImage */
88726 #define FB_ACCEL_TRIDENT_BLADE3D 52 /* Trident Blade3D */
88727 #define FB_ACCEL_TRIDENT_BLADEXP 53 /* Trident BladeXP */
88728 +#define FB_ACCEL_GLAMO 50 /* SMedia Glamo */
88729 #define FB_ACCEL_NEOMAGIC_NM2070 90 /* NeoMagic NM2070 */
88730 #define FB_ACCEL_NEOMAGIC_NM2090 91 /* NeoMagic NM2090 */
88731 #define FB_ACCEL_NEOMAGIC_NM2093 92 /* NeoMagic NM2093 */
88732 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/glamofb.h linux-2.6.29-rc3.owrt.om/include/linux/glamofb.h
88733 --- linux-2.6.29-rc3.owrt/include/linux/glamofb.h 1970-01-01 01:00:00.000000000 +0100
88734 +++ linux-2.6.29-rc3.owrt.om/include/linux/glamofb.h 2009-05-10 22:28:00.000000000 +0200
88735 @@ -0,0 +1,50 @@
88736 +#ifndef _LINUX_GLAMOFB_H
88737 +#define _LINUX_GLAMOFB_H
88738 +
88739 +#include <linux/spi/glamo.h>
88740 +
88741 +struct glamofb_val {
88742 + unsigned int defval;
88743 + unsigned int min;
88744 + unsigned int max;
88745 +};
88746 +
88747 +struct glamo_core;
88748 +
88749 +struct glamofb_platform_data {
88750 + int width, height;
88751 + int pixclock;
88752 + int left_margin, right_margin;
88753 + int upper_margin, lower_margin;
88754 + int hsync_len, vsync_len;
88755 + int fb_mem_size;
88756 +
88757 + struct glamofb_val xres;
88758 + struct glamofb_val yres;
88759 + struct glamofb_val bpp;
88760 +
88761 + struct glamo_spi_info *spi_info;
88762 + struct glamo_spigpio_info *spigpio_info;
88763 + struct glamo_core *glamo;
88764 +
88765 + struct platform_device *mmc_dev;
88766 +
88767 + /* glamo mmc platform specific info */
88768 + int (*glamo_can_set_mci_power)(void);
88769 +
88770 + /* glamo-mci asking if it should use the slow clock to card */
88771 + int (*glamo_mci_use_slow)(void);
88772 + int (*glamo_irq_is_wired)(void);
88773 + void (*glamo_external_reset)(int);
88774 +};
88775 +
88776 +int glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
88777 +int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val);
88778 +
88779 +#ifdef CONFIG_MFD_GLAMO
88780 +void glamo_lcm_reset(int level);
88781 +#else
88782 +#define glamo_lcm_reset(...) do {} while (0)
88783 +#endif
88784 +
88785 +#endif
88786 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/glamo-gpio.h linux-2.6.29-rc3.owrt.om/include/linux/glamo-gpio.h
88787 --- linux-2.6.29-rc3.owrt/include/linux/glamo-gpio.h 1970-01-01 01:00:00.000000000 +0100
88788 +++ linux-2.6.29-rc3.owrt.om/include/linux/glamo-gpio.h 2009-05-10 22:28:00.000000000 +0200
88789 @@ -0,0 +1,99 @@
88790 +#ifndef __GLAMO_GPIO_H
88791 +#define __GLAMO_GPIO_H
88792 +
88793 +struct glamo_core;
88794 +
88795 +#define GLAMO_GPIO_BANKA 0x0000
88796 +#define GLAMO_GPIO_BANKB 0x1000
88797 +#define GLAMO_GPIO_BANKC 0x2000
88798 +#define GLAMO_GPIO_BANKD 0x3000
88799 +
88800 +#define GLAMO_GPIONO(bank, pin) ((bank & 0xf000) | ((pin & 0xf) << 8))
88801 +
88802 +#define GLAMO_GPIO_F_IN 0x0010
88803 +#define GLAMO_GPIO_F_OUT 0x0020
88804 +#define GLAMO_GPIO_F_FUNC 0x0030
88805 +
88806 +#define GLAMO_GPIO0 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 0)
88807 +#define GLAMO_GPIO0_INPUT (GLAMO_GPIO0 | GLAMO_GPIO_F_IN)
88808 +#define GLAMO_GPIO0_OUTPUT (GLAMO_GPIO0 | GLAMO_GPIO_F_OUT)
88809 +#define GLAMO_GPIO0_HA20 (GLAMO_GPIO0 | GLAMO_GPIO_F_FUNC)
88810 +
88811 +#define GLAMO_GPIO1 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 1)
88812 +#define GLAMO_GPIO1_INPUT (GLAMO_GPIO1 | GLAMO_GPIO_F_IN)
88813 +#define GLAMO_GPIO1_OUTPUT (GLAMO_GPIO1 | GLAMO_GPIO_F_OUT)
88814 +#define GLAMO_GPIO1_HA21 (GLAMO_GPIO1 | GLAMO_GPIO_F_FUNC)
88815 +
88816 +#define GLAMO_GPIO2 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 2)
88817 +#define GLAMO_GPIO2_INPUT (GLAMO_GPIO2 | GLAMO_GPIO_F_IN)
88818 +#define GLAMO_GPIO2_OUTPUT (GLAMO_GPIO2 | GLAMO_GPIO_F_OUT)
88819 +#define GLAMO_GPIO2_HA22 (GLAMO_GPIO2 | GLAMO_GPIO_F_FUNC)
88820 +
88821 +#define GLAMO_GPIO3 GLAMO_GPIONO(GLAMO_GPIO_BANKA, 3)
88822 +#define GLAMO_GPIO3_INPUT (GLAMO_GPIO3 | GLAMO_GPIO_F_IN)
88823 +#define GLAMO_GPIO3_OUTPUT (GLAMO_GPIO3 | GLAMO_GPIO_F_OUT)
88824 +#define GLAMO_GPIO3_HA23 (GLAMO_GPIO3 | GLAMO_GPIO_F_FUNC)
88825 +
88826 +#define GLAMO_GPIO4 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 0)
88827 +#define GLAMO_GPIO4_INPUT (GLAMO_GPIO4 | GLAMO_GPIO_F_IN)
88828 +#define GLAMO_GPIO4_OUTPUT (GLAMO_GPIO4 | GLAMO_GPIO_F_OUT)
88829 +#define GLAMO_GPIO4_nLCS0 (GLAMO_GPIO4 | GLAMO_GPIO_F_FUNC)
88830 +
88831 +#define GLAMO_GPIO5 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 1)
88832 +#define GLAMO_GPIO5_INPUT (GLAMO_GPIO5 | GLAMO_GPIO_F_IN)
88833 +#define GLAMO_GPIO5_OUTPUT (GLAMO_GPIO5 | GLAMO_GPIO_F_OUT)
88834 +#define GLAMO_GPIO5_nLCS1 (GLAMO_GPIO5 | GLAMO_GPIO_F_FUNC)
88835 +
88836 +#define GLAMO_GPIO6 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 2)
88837 +#define GLAMO_GPIO6_INPUT (GLAMO_GPIO6 | GLAMO_GPIO_F_IN)
88838 +#define GLAMO_GPIO6_OUTPUT (GLAMO_GPIO6 | GLAMO_GPIO_F_OUT)
88839 +#define GLAMO_GPIO6_LDCLK (GLAMO_GPIO6 | GLAMO_GPIO_F_FUNC)
88840 +
88841 +#define GLAMO_GPIO7 GLAMO_GPIONO(GLAMO_GPIO_BANKB, 3)
88842 +#define GLAMO_GPIO7_INPUT (GLAMO_GPIO7 | GLAMO_GPIO_F_IN)
88843 +#define GLAMO_GPIO7_OUTPUT (GLAMO_GPIO7 | GLAMO_GPIO_F_OUT)
88844 +#define GLAMO_GPIO7_nLDE (GLAMO_GPIO7 | GLAMO_GPIO_F_FUNC)
88845 +
88846 +#define GLAMO_GPIO8 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 0)
88847 +#define GLAMO_GPIO8_INPUT (GLAMO_GPIO8 | GLAMO_GPIO_F_IN)
88848 +#define GLAMO_GPIO8_OUTPUT (GLAMO_GPIO8 | GLAMO_GPIO_F_OUT)
88849 +#define GLAMO_GPIO8_LD16 (GLAMO_GPIO8 | GLAMO_GPIO_F_FUNC)
88850 +
88851 +#define GLAMO_GPIO9 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 1)
88852 +#define GLAMO_GPIO9_INPUT (GLAMO_GPIO9 | GLAMO_GPIO_F_IN)
88853 +#define GLAMO_GPIO9_OUTPUT (GLAMO_GPIO9 | GLAMO_GPIO_F_OUT)
88854 +#define GLAMO_GPIO9_LD17 (GLAMO_GPIO9 | GLAMO_GPIO_F_FUNC)
88855 +
88856 +#define GLAMO_GPIO10 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 2)
88857 +#define GLAMO_GPIO10_INPUT (GLAMO_GPIO10 | GLAMO_GPIO_F_IN)
88858 +#define GLAMO_GPIO10_OUTPUT (GLAMO_GPIO10 | GLAMO_GPIO_F_OUT)
88859 +#define GLAMO_GPIO10_LSCK (GLAMO_GPIO10 | GLAMO_GPIO_F_FUNC)
88860 +
88861 +#define GLAMO_GPIO11 GLAMO_GPIONO(GLAMO_GPIO_BANKC, 3)
88862 +#define GLAMO_GPIO11_INPUT (GLAMO_GPIO11 | GLAMO_GPIO_F_IN)
88863 +#define GLAMO_GPIO11_OUTPUT (GLAMO_GPIO11 | GLAMO_GPIO_F_OUT)
88864 +#define GLAMO_GPIO11_LSDA (GLAMO_GPIO11 | GLAMO_GPIO_F_FUNC)
88865 +
88866 +#define GLAMO_GPIO12 GLAMO_GPIONO(GLAMO_GPIO_BANKD, 0)
88867 +#define GLAMO_GPIO12_INPUT (GLAMO_GPIO12 | GLAMO_GPIO_F_IN)
88868 +#define GLAMO_GPIO12_OUTPUT (GLAMO_GPIO12 | GLAMO_GPIO_F_OUT)
88869 +#define GLAMO_GPIO12_LSA0 (GLAMO_GPIO12 | GLAMO_GPIO_F_FUNC)
88870 +
88871 +
88872 +#define REG_OF_GPIO(gpio) (((gpio & 0xf000) >> 12)*2 \
88873 + + GLAMO_REG_GPIO_GEN1)
88874 +#define NUM_OF_GPIO(gpio) ((gpio & 0x0f00) >> 8)
88875 +#define GPIO_OUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 0))
88876 +#define OUTPUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 4))
88877 +#define INPUT_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 8))
88878 +#define FUNC_BIT(gpio) (1 << (NUM_OF_GPIO(gpio) + 12))
88879 +
88880 +void glamo_gpio_setpin(struct glamo_core *glamo, unsigned int pin,
88881 + unsigned int value);
88882 +
88883 +int glamo_gpio_getpin(struct glamo_core *glamo, unsigned int pin);
88884 +
88885 +void glamo_gpio_cfgpin(struct glamo_core *glamo, unsigned int pinfunc);
88886 +
88887 +
88888 +#endif /* _GLAMO_GPIO */
88889 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/gta01_battery.h linux-2.6.29-rc3.owrt.om/include/linux/gta01_battery.h
88890 --- linux-2.6.29-rc3.owrt/include/linux/gta01_battery.h 1970-01-01 01:00:00.000000000 +0100
88891 +++ linux-2.6.29-rc3.owrt.om/include/linux/gta01_battery.h 2009-05-10 22:28:00.000000000 +0200
88892 @@ -0,0 +1,10 @@
88893 +#ifndef __GTA01_BATTERY_H__
88894 +#define __GTA01_BATTERY_H__
88895 +
88896 +struct gta01_bat_platform_data {
88897 + int (*get_charging_status)(void);
88898 + int (*get_voltage)(void);
88899 + int (*get_current)(void);
88900 +};
88901 +
88902 +#endif
88903 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/gta02_hdq.h linux-2.6.29-rc3.owrt.om/include/linux/gta02_hdq.h
88904 --- linux-2.6.29-rc3.owrt/include/linux/gta02_hdq.h 1970-01-01 01:00:00.000000000 +0100
88905 +++ linux-2.6.29-rc3.owrt.om/include/linux/gta02_hdq.h 2009-05-10 22:28:00.000000000 +0200
88906 @@ -0,0 +1,18 @@
88907 +#ifndef __GTA02HDQ_H__
88908 +#define __GTA02HDQ_H__
88909 +
88910 +/* platform data */
88911 +
88912 +struct gta02_hdq_platform_data {
88913 + /*
88914 + * give an opportunity to use us as parent for
88915 + * devices that depend on us
88916 + */
88917 + void (*attach_child_devices)(struct device *parent_device);
88918 +};
88919 +
88920 +int gta02hdq_read(int address);
88921 +int gta02hdq_write(int address, u8 data);
88922 +int gta02hdq_initialized(void);
88923 +
88924 +#endif
88925 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/hdq.h linux-2.6.29-rc3.owrt.om/include/linux/hdq.h
88926 --- linux-2.6.29-rc3.owrt/include/linux/hdq.h 1970-01-01 01:00:00.000000000 +0100
88927 +++ linux-2.6.29-rc3.owrt.om/include/linux/hdq.h 2009-05-10 22:28:00.000000000 +0200
88928 @@ -0,0 +1,32 @@
88929 +#ifndef __LINUX_HDQ_H__
88930 +#define __LINUX_HDQ_H__
88931 +
88932 +#include <linux/device.h>
88933 +
88934 +#define HDQ_SAMPLE_PERIOD_US 10
88935 +
88936 +/* platform data */
88937 +
88938 +struct hdq_platform_data {
88939 + /*
88940 + * give an opportunity to use us as parent for
88941 + * devices that depend on us
88942 + */
88943 + void (*attach_child_devices)(struct device *parent_device);
88944 +
88945 + void (*gpio_dir_out)(void);
88946 + void (*gpio_dir_in)(void);
88947 + void (*gpio_set)(int);
88948 + int (*gpio_get)(void);
88949 +
88950 + int (*enable_fiq)(void);
88951 + void (*disable_fiq)(void);
88952 + void (*kick_fiq)(void);
88953 +
88954 +};
88955 +
88956 +int hdq_read(int address);
88957 +int hdq_write(int address, u8 data);
88958 +int hdq_initialized(void);
88959 +
88960 +#endif
88961 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/i2c-id.h linux-2.6.29-rc3.owrt.om/include/linux/i2c-id.h
88962 --- linux-2.6.29-rc3.owrt/include/linux/i2c-id.h 2009-05-10 22:04:47.000000000 +0200
88963 +++ linux-2.6.29-rc3.owrt.om/include/linux/i2c-id.h 2009-05-10 22:28:00.000000000 +0200
88964 @@ -73,6 +73,15 @@
88965 #define I2C_DRIVERID_CS5345 96 /* cs5345 audio processor */
88966
88967 #define I2C_DRIVERID_OV7670 1048 /* Omnivision 7670 camera */
88968 +#define I2C_DRIVERID_PCF50606 1049
88969 +#define I2C_DRIVERID_PCF50633 1051
88970 +#define I2C_DRIVERID_PCA9632 1052
88971 +
88972 +#define I2C_DRIVERID_S5K_3XA 1500 /* Samsung MobileAP I2C adapter */
88973 +#define I2C_DRIVERID_S5K_53BEA 1501 /* Samsung MobileAP I2C adapter */
88974 +#define I2C_DRIVERID_S5K_532 1502 /* Samsung MobileAP I2C adapter */
88975 +#define I2C_DRIVERID_S5K_3BA 1503 /* Samsung MobileAP I2C adapter */
88976 +#define I2C_DRIVERID_S5K_4XA 1504 /* Samsung MobileAP I2C adapter */
88977
88978 /*
88979 * ---- Adapter types ----------------------------------------------------
88980 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/jbt6k74.h linux-2.6.29-rc3.owrt.om/include/linux/jbt6k74.h
88981 --- linux-2.6.29-rc3.owrt/include/linux/jbt6k74.h 1970-01-01 01:00:00.000000000 +0100
88982 +++ linux-2.6.29-rc3.owrt.om/include/linux/jbt6k74.h 2009-05-10 22:28:00.000000000 +0200
88983 @@ -0,0 +1,12 @@
88984 +#ifndef __JBT6K74_H__
88985 +#define __JBT6K74_H__
88986 +
88987 +#include <linux/spi/spi.h>
88988 +
88989 +struct jbt6k74_platform_data {
88990 + void (*reset)(int devindex, int level);
88991 + void (*resuming)(int devindex); /* called when LCM is resumed */
88992 + void (*probe_completed)(struct device *dev);
88993 +};
88994 +
88995 +#endif
88996 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/kernel.h linux-2.6.29-rc3.owrt.om/include/linux/kernel.h
88997 --- linux-2.6.29-rc3.owrt/include/linux/kernel.h 2009-05-10 22:09:07.000000000 +0200
88998 +++ linux-2.6.29-rc3.owrt.om/include/linux/kernel.h 2009-05-10 22:28:00.000000000 +0200
88999 @@ -242,6 +242,8 @@
89000 extern int printk_ratelimit(void);
89001 extern bool printk_timed_ratelimit(unsigned long *caller_jiffies,
89002 unsigned int interval_msec);
89003 +extern void (*printk_emergency_debug_spew_init)(void);
89004 +extern void (*printk_emergency_debug_spew_send_string)(const char *);
89005 #else
89006 static inline int vprintk(const char *s, va_list args)
89007 __attribute__ ((format (printf, 1, 0)));
89008 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/kexec.h linux-2.6.29-rc3.owrt.om/include/linux/kexec.h
89009 --- linux-2.6.29-rc3.owrt/include/linux/kexec.h 2009-05-10 22:04:47.000000000 +0200
89010 +++ linux-2.6.29-rc3.owrt.om/include/linux/kexec.h 2009-05-10 22:28:00.000000000 +0200
89011 @@ -1,7 +1,6 @@
89012 #ifndef LINUX_KEXEC_H
89013 #define LINUX_KEXEC_H
89014
89015 -#ifdef CONFIG_KEXEC
89016 #include <linux/types.h>
89017 #include <linux/list.h>
89018 #include <linux/linkage.h>
89019 @@ -11,6 +10,8 @@
89020 #include <linux/elf.h>
89021 #include <asm/kexec.h>
89022
89023 +#ifdef CONFIG_KEXEC
89024 +
89025 /* Verify architecture specific macros are defined */
89026
89027 #ifndef KEXEC_SOURCE_MEMORY_LIMIT
89028 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/l1k002.h linux-2.6.29-rc3.owrt.om/include/linux/l1k002.h
89029 --- linux-2.6.29-rc3.owrt/include/linux/l1k002.h 1970-01-01 01:00:00.000000000 +0100
89030 +++ linux-2.6.29-rc3.owrt.om/include/linux/l1k002.h 2009-05-10 22:28:00.000000000 +0200
89031 @@ -0,0 +1,8 @@
89032 +#ifndef __LINUX_L1K002_H_
89033 +#define __LINUX_L1K002_H_
89034 +
89035 +struct l1k002_platform_data {
89036 + void (*pwr_onoff)(int level);
89037 +};
89038 +
89039 +#endif /* __LINUX_L1K002_H_ */
89040 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/lis302dl.h linux-2.6.29-rc3.owrt.om/include/linux/lis302dl.h
89041 --- linux-2.6.29-rc3.owrt/include/linux/lis302dl.h 1970-01-01 01:00:00.000000000 +0100
89042 +++ linux-2.6.29-rc3.owrt.om/include/linux/lis302dl.h 2009-05-10 22:28:00.000000000 +0200
89043 @@ -0,0 +1,152 @@
89044 +#ifndef _LINUX_LIS302DL_H
89045 +#define _LINUX_LIS302DL_H
89046 +
89047 +#include <linux/types.h>
89048 +#include <linux/spi/spi.h>
89049 +#include <linux/input.h>
89050 +#include <linux/workqueue.h>
89051 +
89052 +struct lis302dl_info;
89053 +
89054 +struct lis302dl_platform_data {
89055 + char *name;
89056 + unsigned long pin_chip_select;
89057 + unsigned long pin_clk;
89058 + unsigned long pin_mosi;
89059 + unsigned long pin_miso;
89060 + int open_drain;
89061 + int interrupt;
89062 + void (*lis302dl_suspend_io)(struct lis302dl_info *, int resuming);
89063 +};
89064 +
89065 +struct lis302dl_info {
89066 + struct lis302dl_platform_data *pdata;
89067 + struct device *dev;
89068 + struct input_dev *input_dev;
89069 + unsigned int flags;
89070 + unsigned int threshold;
89071 + unsigned int duration;
89072 + u32 overruns;
89073 + struct {
89074 + unsigned int threshold; /* mg */
89075 + unsigned int duration; /* ms */
89076 + } wakeup;
89077 +
89078 + struct spi_device *spi;
89079 + u_int8_t regs[0x40];
89080 +};
89081 +
89082 +enum lis302dl_reg {
89083 + LIS302DL_REG_WHO_AM_I = 0x0f,
89084 + LIS302DL_REG_CTRL1 = 0x20,
89085 + LIS302DL_REG_CTRL2 = 0x21,
89086 + LIS302DL_REG_CTRL3 = 0x22,
89087 + LIS302DL_REG_HP_FILTER_RESET = 0x23,
89088 + LIS302DL_REG_STATUS = 0x27,
89089 + LIS302DL_REG_OUT_X = 0x29,
89090 + LIS302DL_REG_OUT_Y = 0x2b,
89091 + LIS302DL_REG_OUT_Z = 0x2d,
89092 + LIS302DL_REG_FF_WU_CFG_1 = 0x30,
89093 + LIS302DL_REG_FF_WU_SRC_1 = 0x31,
89094 + LIS302DL_REG_FF_WU_THS_1 = 0x32,
89095 + LIS302DL_REG_FF_WU_DURATION_1 = 0x33,
89096 + LIS302DL_REG_FF_WU_CFG_2 = 0x34,
89097 + LIS302DL_REG_FF_WU_SRC_2 = 0x35,
89098 + LIS302DL_REG_FF_WU_THS_2 = 0x36,
89099 + LIS302DL_REG_FF_WU_DURATION_2 = 0x37,
89100 + LIS302DL_REG_CLICK_CFG = 0x38,
89101 + LIS302DL_REG_CLICK_SRC = 0x39,
89102 + LIS302DL_REG_CLICK_THSY_X = 0x3b,
89103 + LIS302DL_REG_CLICK_THSZ = 0x3c,
89104 + LIS302DL_REG_CLICK_TIME_LIMIT = 0x3d,
89105 + LIS302DL_REG_CLICK_LATENCY = 0x3e,
89106 + LIS302DL_REG_CLICK_WINDOW = 0x3f,
89107 +};
89108 +
89109 +enum lis302dl_reg_ctrl1 {
89110 + LIS302DL_CTRL1_Xen = 0x01,
89111 + LIS302DL_CTRL1_Yen = 0x02,
89112 + LIS302DL_CTRL1_Zen = 0x04,
89113 + LIS302DL_CTRL1_STM = 0x08,
89114 + LIS302DL_CTRL1_STP = 0x10,
89115 + LIS302DL_CTRL1_FS = 0x20,
89116 + LIS302DL_CTRL1_PD = 0x40,
89117 + LIS302DL_CTRL1_DR = 0x80,
89118 +};
89119 +
89120 +enum lis302dl_reg_ctrl2 {
89121 + LIS302DL_CTRL2_HPC1 = 0x01,
89122 + LIS302DL_CTRL2_HPC2 = 0x02,
89123 + LIS302DL_CTRL2_HPFF1 = 0x04,
89124 + LIS302DL_CTRL2_HPFF2 = 0x08,
89125 + LIS302DL_CTRL2_FDS = 0x10,
89126 + LIS302DL_CTRL2_BOOT = 0x40,
89127 + LIS302DL_CTRL2_SIM = 0x80,
89128 +};
89129 +enum lis302dl_reg_ctrl3 {
89130 + LIS302DL_CTRL3_PP_OD = 0x40,
89131 + LIS302DL_CTRL3_IHL = 0x80,
89132 +};
89133 +
89134 +enum lis302dl_reg_status {
89135 + LIS302DL_STATUS_XDA = 0x01,
89136 + LIS302DL_STATUS_YDA = 0x02,
89137 + LIS302DL_STATUS_ZDA = 0x04,
89138 + LIS302DL_STATUS_XYZDA = 0x08,
89139 + LIS302DL_STATUS_XOR = 0x10,
89140 + LIS302DL_STATUS_YOR = 0x20,
89141 + LIS302DL_STATUS_ZOR = 0x40,
89142 + LIS302DL_STATUS_XYZOR = 0x80,
89143 +};
89144 +
89145 +/* Wakeup/freefall interrupt defs */
89146 +enum lis302dl_reg_ffwucfg {
89147 + LIS302DL_FFWUCFG_XLIE = 0x01,
89148 + LIS302DL_FFWUCFG_XHIE = 0x02,
89149 + LIS302DL_FFWUCFG_YLIE = 0x04,
89150 + LIS302DL_FFWUCFG_YHIE = 0x08,
89151 + LIS302DL_FFWUCFG_ZLIE = 0x10,
89152 + LIS302DL_FFWUCFG_ZHIE = 0x20,
89153 + LIS302DL_FFWUCFG_LIR = 0x40,
89154 + LIS302DL_FFWUCFG_AOI = 0x80,
89155 +};
89156 +
89157 +enum lis302dl_reg_ffwuths {
89158 + LIS302DL_FFWUTHS_DCRM = 0x80,
89159 +};
89160 +
89161 +enum lis302dl_reg_ffwusrc {
89162 + LIS302DL_FFWUSRC_XL = 0x01,
89163 + LIS302DL_FFWUSRC_XH = 0x02,
89164 + LIS302DL_FFWUSRC_YL = 0x04,
89165 + LIS302DL_FFWUSRC_YH = 0x08,
89166 + LIS302DL_FFWUSRC_ZL = 0x10,
89167 + LIS302DL_FFWUSRC_ZH = 0x20,
89168 + LIS302DL_FFWUSRC_IA = 0x40,
89169 +};
89170 +
89171 +enum lis302dl_reg_cloik_src {
89172 + LIS302DL_CLICKSRC_SINGLE_X = 0x01,
89173 + LIS302DL_CLICKSRC_DOUBLE_X = 0x02,
89174 + LIS302DL_CLICKSRC_SINGLE_Y = 0x04,
89175 + LIS302DL_CLICKSRC_DOUBLE_Y = 0x08,
89176 + LIS302DL_CLICKSRC_SINGLE_Z = 0x10,
89177 + LIS302DL_CLICKSRC_DOUBLE_Z = 0x20,
89178 + LIS302DL_CLICKSRC_IA = 0x40,
89179 +};
89180 +
89181 +#define LIS302DL_WHO_AM_I_MAGIC 0x3b
89182 +
89183 +#define LIS302DL_F_WUP_FF_1 0x0001 /* wake up from free fall */
89184 +#define LIS302DL_F_WUP_FF_2 0x0002
89185 +#define LIS302DL_F_WUP_FF 0x0003
89186 +#define LIS302DL_F_WUP_CLICK 0x0004
89187 +#define LIS302DL_F_POWER 0x0010
89188 +#define LIS302DL_F_FS 0x0020 /* ADC full scale */
89189 +#define LIS302DL_F_INPUT_OPEN 0x0040 /* Set if input device is opened */
89190 +#define LIS302DL_F_IRQ_WAKE 0x0080 /* IRQ is setup in wake mode */
89191 +#define LIS302DL_F_DR 0x0100 /* Data rate, 400Hz/100Hz */
89192 +
89193 +
89194 +#endif /* _LINUX_LIS302DL_H */
89195 +
89196 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/lp5521.h linux-2.6.29-rc3.owrt.om/include/linux/lp5521.h
89197 --- linux-2.6.29-rc3.owrt/include/linux/lp5521.h 1970-01-01 01:00:00.000000000 +0100
89198 +++ linux-2.6.29-rc3.owrt.om/include/linux/lp5521.h 2009-05-10 22:28:00.000000000 +0200
89199 @@ -0,0 +1,75 @@
89200 +#ifndef _LINUX_LP5521_H_
89201 +#define _LINUX_LP5521_H_
89202 +
89203 +#define LP5521_REG_ENABLE 0x00
89204 +#define LP5521_REG_OP_MODE 0x01
89205 +
89206 +#define LP5521_REG_R_PWM 0x02
89207 +#define LP5521_REG_G_PWM 0x03
89208 +#define LP5521_REG_B_PWM 0x04
89209 +
89210 +#define LP5521_REG_R_CUR 0x05
89211 +#define LP5521_REG_G_CUR 0x06
89212 +#define LP5521_REG_B_CUR 0x07
89213 +
89214 +#define LP5521_REG_CONFIG 0x08
89215 +
89216 +#define LP5521_REG_R_PC 0x09
89217 +#define LP5521_REG_G_PC 0x0a
89218 +#define LP5521_REG_B_PC 0x0b
89219 +
89220 +#define LP5521_REG_STATUS 0x0c
89221 +#define LP5521_REG_RESET 0x0d
89222 +#define LP5521_REG_GPO 0x0e
89223 +
89224 +enum {
89225 + LP5521_NC,
89226 + LP5521_CONNECTED,
89227 +};
89228 +
89229 +enum {
89230 + LP5521_BLUE,
89231 + LP5521_GREEN,
89232 + LP5521_RED,
89233 + LP5521_NUM_CH,
89234 +};
89235 +
89236 +enum {
89237 + LP5521_MODE_DISABLE,
89238 + LP5521_MODE_LOAD,
89239 + LP5521_MODE_RUN,
89240 + LP5521_MODE_DIRECT,
89241 +};
89242 +
89243 +enum CP_MODE {
89244 + LP5521_CPM_OFF,
89245 + LP5521_CPM_BY_PASS,
89246 + LP5521_CPM_1_5X,
89247 + LP5521_CPM_AUTO,
89248 +};
89249 +
89250 +enum CLK_SRC {
89251 + LP5521_EXT_CLK,
89252 + LP5521_INT_CLK,
89253 + LP5521_AUTO_CLK,
89254 +};
89255 +
89256 +#define LP5521_FEAT_TRIG 0x00000001
89257 +#define LP5521_FEAT_GPO 0x00000002
89258 +
89259 +
89260 +struct lp5521_platform_data {
89261 + int channels[LP5521_NUM_CH];
89262 + /* chip enable */
89263 + void (*ext_enable)(int level);
89264 +};
89265 +
89266 +struct lp5521 {
89267 + struct device *dev;
89268 + struct i2c_client *client;
89269 + struct mutex lock;
89270 + int irq;
89271 +
89272 + struct lp5521_platform_data *pdata;
89273 +};
89274 +#endif /* LINUX_LP5521_H */
89275 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/adc.h linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/adc.h
89276 --- linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/adc.h 1970-01-01 01:00:00.000000000 +0100
89277 +++ linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/adc.h 2009-05-10 22:28:00.000000000 +0200
89278 @@ -0,0 +1,72 @@
89279 +/*
89280 + * adc.h -- Driver for NXP PCF50606 ADC
89281 + *
89282 + * (C) 2006-2008 by Openmoko, Inc.
89283 + * All rights reserved.
89284 + *
89285 + * This program is free software; you can redistribute it and/or modify it
89286 + * under the terms of the GNU General Public License as published by the
89287 + * Free Software Foundation; either version 2 of the License, or (at your
89288 + * option) any later version.
89289 + */
89290 +
89291 +#ifndef __LINUX_MFD_PCF50606_ADC_H
89292 +#define __LINUX_MFD_PCF50606_ADC_H
89293 +
89294 +#include <linux/mfd/pcf50633/core.h>
89295 +#include <linux/platform_device.h>
89296 +
89297 +/* ADC Registers */
89298 +#define PCF50606_REG_ADCC1 0x2e
89299 +#define PCF50606_REG_ADCC2 0x2f
89300 +#define PCF50606_REG_ADCS1 0x30
89301 +#define PCF50606_REG_ADCS2 0x31
89302 +#define PCF50606_REG_ADCS3 0x32
89303 +
89304 +#define PCF50606_ADCC1_TSCMODACT 0x01
89305 +#define PCF50606_ADCC1_TSCMODSTB 0x02
89306 +#define PCF50606_ADCC1_TRATSET 0x04
89307 +#define PCF50606_ADCC1_NTCSWAPE 0x08
89308 +#define PCF50606_ADCC1_NTCSWAOFF 0x10
89309 +#define PCF50606_ADCC1_EXTSYNCBREAK 0x20
89310 + /* reserved */
89311 +#define PCF50606_ADCC1_TSCINT 0x80
89312 +
89313 +#define PCF50606_ADCC2_ADCSTART 0x01
89314 + /* see enum pcf50606_adcc2_adcmux */
89315 +#define PCF50606_ADCC2_SYNC_NONE 0x00
89316 +#define PCF50606_ADCC2_SYNC_TXON 0x20
89317 +#define PCF50606_ADCC2_SYNC_PWREN1 0x40
89318 +#define PCF50606_ADCC2_SYNC_PWREN2 0x60
89319 +#define PCF50606_ADCC2_RES_10BIT 0x00
89320 +#define PCF50606_ADCC2_RES_8BIT 0x80
89321 +
89322 +#define PCF50606_ADCC2_ADCMUX_MASK (0xf << 1)
89323 +
89324 +#define ADCMUX_SHIFT 1
89325 +#define PCF50606_ADCMUX_BATVOLT_RES (0x0 << ADCMUX_SHIFT)
89326 +#define PCF50606_ADCMUX_BATVOLT_SUBTR (0x1 << ADCMUX_SHIFT)
89327 +#define PCF50606_ADCMUX_ADCIN1_RES (0x2 << ADCMUX_SHIFT)
89328 +#define PCF50606_ADCMUX_ADCIN1_SUBTR (0x3 << ADCMUX_SHIFT)
89329 +#define PCF50606_ADCMUX_BATTEMP (0x4 << ADCMUX_SHIFT)
89330 +#define PCF50606_ADCMUX_ADCIN2 (0x5 << ADCMUX_SHIFT)
89331 +#define PCF50606_ADCMUX_ADCIN3 (0x6 << ADCMUX_SHIFT)
89332 +#define PCF50606_ADCMUX_ADCIN3_RATIO (0x7 << ADCMUX_SHIFT)
89333 +#define PCF50606_ADCMUX_XPOS (0x8 << ADCMUX_SHIFT)
89334 +#define PCF50606_ADCMUX_YPOS (0x9 << ADCMUX_SHIFT)
89335 +#define PCF50606_ADCMUX_P1 (0xa << ADCMUX_SHIFT)
89336 +#define PCF50606_ADCMUX_P2 (0xb << ADCMUX_SHIFT)
89337 +#define PCF50606_ADCMUX_BATVOLT_ADCIN1 (0xc << ADCMUX_SHIFT)
89338 +#define PCF50606_ADCMUX_XY_SEQUENCE (0xe << ADCMUX_SHIFT)
89339 +#define PCF50606_P1_P2_RESISTANCE (0xf << ADCMUX_SHIFT)
89340 +
89341 +#define PCF50606_ADCS2_ADCRDY 0x80
89342 +
89343 +extern int
89344 +pcf50606_adc_async_read(struct pcf50606 *pcf, int mux,
89345 + void (*callback)(struct pcf50606 *, void *, int),
89346 + void *callback_param);
89347 +extern int
89348 +pcf50606_adc_sync_read(struct pcf50606 *pcf, int mux);
89349 +
89350 +#endif /* __LINUX_PCF50606_ADC_H */
89351 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/core.h linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/core.h
89352 --- linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/core.h 1970-01-01 01:00:00.000000000 +0100
89353 +++ linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/core.h 2009-05-10 22:28:00.000000000 +0200
89354 @@ -0,0 +1,170 @@
89355 +/*
89356 + * core.h -- Core driver for NXP PCF50606
89357 + *
89358 + * (C) 2006-2008 by Openmoko, Inc.
89359 + * All rights reserved.
89360 + *
89361 + * This program is free software; you can redistribute it and/or modify it
89362 + * under the terms of the GNU General Public License as published by the
89363 + * Free Software Foundation; either version 2 of the License, or (at your
89364 + * option) any later version.
89365 + */
89366 +
89367 +#ifndef __LINUX_MFD_PCF50606_CORE_H
89368 +#define __LINUX_MFD_PCF50606_CORE_H
89369 +
89370 +#include <linux/i2c.h>
89371 +#include <linux/workqueue.h>
89372 +#include <linux/regulator/driver.h>
89373 +#include <linux/regulator/machine.h>
89374 +#include <linux/power_supply.h>
89375 +
89376 +struct pcf50606;
89377 +
89378 +#define PCF50606_NUM_REGULATORS 8
89379 +
89380 +struct pcf50606_platform_data {
89381 + struct regulator_init_data reg_init_data[PCF50606_NUM_REGULATORS];
89382 +
89383 + char **batteries;
89384 + int num_batteries;
89385 +
89386 + /* Callbacks */
89387 + void (*probe_done)(struct pcf50606 *);
89388 + void (*mbc_event_callback)(struct pcf50606 *, int);
89389 + void (*regulator_registered)(struct pcf50606 *, int);
89390 + void (*force_shutdown)(struct pcf50606 *);
89391 +
89392 + u8 resumers[3];
89393 +};
89394 +
89395 +struct pcf50606_subdev_pdata {
89396 + struct pcf50606 *pcf;
89397 +};
89398 +
89399 +struct pcf50606_irq {
89400 + void (*handler)(int, void *);
89401 + void *data;
89402 +};
89403 +
89404 +int pcf50606_register_irq(struct pcf50606 *pcf, int irq,
89405 + void (*handler) (int, void *), void *data);
89406 +int pcf50606_free_irq(struct pcf50606 *pcf, int irq);
89407 +
89408 +int pcf50606_irq_mask(struct pcf50606 *pcf, int irq);
89409 +int pcf50606_irq_unmask(struct pcf50606 *pcf, int irq);
89410 +int pcf50606_irq_mask_get(struct pcf50606 *pcf, int irq);
89411 +
89412 +int pcf50606_read_block(struct pcf50606 *, u8 reg,
89413 + int nr_regs, u8 *data);
89414 +int pcf50606_write_block(struct pcf50606 *pcf, u8 reg,
89415 + int nr_regs, u8 *data);
89416 +u8 pcf50606_reg_read(struct pcf50606 *, u8 reg);
89417 +int pcf50606_reg_write(struct pcf50606 *pcf, u8 reg, u8 val);
89418 +
89419 +int pcf50606_reg_set_bit_mask(struct pcf50606 *pcf, u8 reg, u8 mask, u8 val);
89420 +int pcf50606_reg_clear_bits(struct pcf50606 *pcf, u8 reg, u8 bits);
89421 +
89422 +/* Interrupt registers */
89423 +
89424 +#define PCF50606_REG_INT1 0x02
89425 +#define PCF50606_REG_INT2 0x03
89426 +#define PCF50606_REG_INT3 0x04
89427 +
89428 +#define PCF50606_REG_INT1M 0x05
89429 +#define PCF50606_REG_INT2M 0x06
89430 +#define PCF50606_REG_INT3M 0x07
89431 +
89432 +enum {
89433 + /* Chip IRQs */
89434 + PCF50606_IRQ_ONKEYR,
89435 + PCF50606_IRQ_ONKEYF,
89436 + PCF50606_IRQ_ONKEY1S,
89437 + PCF50606_IRQ_EXTONR,
89438 + PCF50606_IRQ_EXTONF,
89439 + PCF50606_IRQ_RESERVED_1,
89440 + PCF50606_IRQ_SECOND,
89441 + PCF50606_IRQ_ALARM,
89442 + PCF50606_IRQ_CHGINS,
89443 + PCF50606_IRQ_CHGRM,
89444 + PCF50606_IRQ_CHGFOK,
89445 + PCF50606_IRQ_CHGERR,
89446 + PCF50606_IRQ_CHGFRDY,
89447 + PCF50606_IRQ_CHGPROT,
89448 + PCF50606_IRQ_CHGWD10S,
89449 + PCF50606_IRQ_CHGWDEXP,
89450 + PCF50606_IRQ_ADCRDY,
89451 + PCF50606_IRQ_ACDINS,
89452 + PCF50606_IRQ_ACDREM,
89453 + PCF50606_IRQ_TSCPRES,
89454 + PCF50606_IRQ_RESERVED_2,
89455 + PCF50606_IRQ_RESERVED_3,
89456 + PCF50606_IRQ_LOWBAT,
89457 + PCF50606_IRQ_HIGHTMP,
89458 +
89459 + /* Always last */
89460 + PCF50606_NUM_IRQ,
89461 +};
89462 +
89463 +struct pcf50606 {
89464 + struct device *dev;
89465 + struct i2c_client *i2c_client;
89466 +
89467 + struct pcf50606_platform_data *pdata;
89468 + int irq;
89469 + struct pcf50606_irq irq_handler[PCF50606_NUM_IRQ];
89470 + struct work_struct irq_work;
89471 + struct mutex lock;
89472 +
89473 + u8 mask_regs[3];
89474 +
89475 + u8 suspend_irq_masks[3];
89476 + u8 resume_reason[3];
89477 + int is_suspended;
89478 +
89479 + int onkey1s_held;
89480 +
89481 + struct platform_device *rtc_pdev;
89482 + struct platform_device *mbc_pdev;
89483 + struct platform_device *adc_pdev;
89484 + struct platform_device *input_pdev;
89485 + struct platform_device *wdt_pdev;
89486 + struct platform_device *regulator_pdev[PCF50606_NUM_REGULATORS];
89487 +};
89488 +
89489 +enum pcf50606_reg_int1 {
89490 + PCF50606_INT1_ONKEYR = 0x01, /* ONKEY rising edge */
89491 + PCF50606_INT1_ONKEYF = 0x02, /* ONKEY falling edge */
89492 + PCF50606_INT1_ONKEY1S = 0x04, /* OMKEY at least 1sec low */
89493 + PCF50606_INT1_EXTONR = 0x08, /* EXTON rising edge */
89494 + PCF50606_INT1_EXTONF = 0x10, /* EXTON falling edge */
89495 + PCF50606_INT1_SECOND = 0x40, /* RTC periodic second interrupt */
89496 + PCF50606_INT1_ALARM = 0x80, /* RTC alarm time is reached */
89497 +};
89498 +
89499 +enum pcf50606_reg_int2 {
89500 + PCF50606_INT2_CHGINS = 0x01, /* Charger inserted */
89501 + PCF50606_INT2_CHGRM = 0x02, /* Charger removed */
89502 + PCF50606_INT2_CHGFOK = 0x04, /* Fast charging OK */
89503 + PCF50606_INT2_CHGERR = 0x08, /* Error in charging mode */
89504 + PCF50606_INT2_CHGFRDY = 0x10, /* Fast charge completed */
89505 + PCF50606_INT2_CHGPROT = 0x20, /* Charging protection interrupt */
89506 + PCF50606_INT2_CHGWD10S = 0x40, /* Charger watchdig expires in 10s */
89507 + PCF50606_INT2_CHGWDEXP = 0x80, /* Charger watchdog expires */
89508 +};
89509 +
89510 +enum pcf50606_reg_int3 {
89511 + PCF50606_INT3_ADCRDY = 0x01, /* ADC conversion finished */
89512 + PCF50606_INT3_ACDINS = 0x02, /* Accessory inserted */
89513 + PCF50606_INT3_ACDREM = 0x04, /* Accessory removed */
89514 + PCF50606_INT3_TSCPRES = 0x08, /* Touch screen pressed */
89515 + PCF50606_INT3_LOWBAT = 0x40, /* Low battery voltage */
89516 + PCF50606_INT3_HIGHTMP = 0x80, /* High temperature */
89517 +};
89518 +
89519 +/* Misc regs */
89520 +
89521 +#define PCF50606_REG_OOCC1 0x08
89522 +#define PCF50606_OOCC1_GOSTDBY 0x01
89523 +#endif
89524 +
89525 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/gpo.h linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/gpo.h
89526 --- linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/gpo.h 1970-01-01 01:00:00.000000000 +0100
89527 +++ linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/gpo.h 2009-05-10 22:28:00.000000000 +0200
89528 @@ -0,0 +1,42 @@
89529 +/*
89530 + * gpo.h -- GPO driver for NXP PCF50606
89531 + *
89532 + * (C) 2006-2008 by Openmoko, Inc.
89533 + * All rights reserved.
89534 + *
89535 + * This program is free software; you can redistribute it and/or modify it
89536 + * under the terms of the GNU General Public License as published by the
89537 + * Free Software Foundation; either version 2 of the License, or (at your
89538 + * option) any later version.
89539 + */
89540 +
89541 +#ifndef __LINUX_MFD_PCF50606_GPO_H
89542 +#define __LINUX_MFD_PCF50606_GPO_H
89543 +
89544 +#include <linux/mfd/pcf50633/core.h>
89545 +
89546 +#define PCF50606_REG_GPOC1 0x38
89547 +#define PCF50606_REG_GPOC2 0x39
89548 +#define PCF50606_REG_GPOC3 0x3a
89549 +#define PCF50606_REG_GPOC4 0x3b
89550 +#define PCF50606_REG_GPOC5 0x3c
89551 +
89552 +#define PCF50606_GPO1 PCF50606_REG_GPOC1
89553 +#define PCF50606_GPO2 PCF50606_REG_GPOC1
89554 +#define PCF50606_GPOOD1 PCF50606_REG_GPOC2
89555 +#define PCF50606_GPOOD2 PCF50606_REG_GPOC3
89556 +#define PCF50606_GPOOD3 PCF50606_REG_GPOC4
89557 +#define PCF50606_GPOOD4 PCF50606_REG_GPOC5
89558 +
89559 +#define PCF50606_GPOCFG_GPOSEL_MASK 0x07
89560 +
89561 +void pcf50606_gpo_set_active(struct pcf50606 *pcf, int gpo, int value);
89562 +int pcf50606_gpo_get_active(struct pcf50606 *pcf, int gpo);
89563 +void pcf50606_gpo_set_standby(struct pcf50606 *pcf, int gpo, int value);
89564 +int pcf50606_gpo_get_standby(struct pcf50606 *pcf, int gpo);
89565 +
89566 +void pcf50606_gpo_invert_set(struct pcf50606 *, int gpo, int invert);
89567 +int pcf50606_gpo_invert_get(struct pcf50606 *pcf, int gpo);
89568 +
89569 +#endif /* __LINUX_MFD_PCF50606_GPIO_H */
89570 +
89571 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/mbc.h linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/mbc.h
89572 --- linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/mbc.h 1970-01-01 01:00:00.000000000 +0100
89573 +++ linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/mbc.h 2009-05-10 22:28:00.000000000 +0200
89574 @@ -0,0 +1,52 @@
89575 +/*
89576 + * mbc.h -- Driver for NXP PCF50606 Main Battery Charger
89577 + *
89578 + * (C) 2006-2008 by Openmoko, Inc.
89579 + * All rights reserved.
89580 + *
89581 + * This program is free software; you can redistribute it and/or modify it
89582 + * under the terms of the GNU General Public License as published by the
89583 + * Free Software Foundation; either version 2 of the License, or (at your
89584 + * option) any later version.
89585 + */
89586 +
89587 +#ifndef __LINUX_MFD_PCF50606_MBC_H
89588 +#define __LINUX_MFD_PCF50606_MBC_H
89589 +
89590 +#include <linux/mfd/pcf50606/core.h>
89591 +#include <linux/platform_device.h>
89592 +
89593 +#define PCF50606_REG_OOCS 0x01
89594 +
89595 +/* Charger OK */
89596 +#define PCF50606_OOCS_CHGOK 0x20
89597 +
89598 +#define PCF50606_REG_MBCC1 0x29
89599 +#define PCF50606_REG_MBCC2 0x2a
89600 +#define PCF50606_REG_MBCC3 0x2b
89601 +#define PCF50606_REG_MBCS1 0x2c
89602 +
89603 +#define PCF50606_MBCC1_CHGAPE 0x01
89604 +#define PCF50606_MBCC1_AUTOFST 0x02
89605 +#define PCF50606_MBCC1_CHGMOD_MASK 0x1c
89606 +#define PCF50606_MBCC1_CHGMOD_QUAL 0x00
89607 +#define PCF50606_MBCC1_CHGMOD_PRE 0x04
89608 +#define PCF50606_MBCC1_CHGMOD_TRICKLE 0x08
89609 +#define PCF50606_MBCC1_CHGMOD_FAST_CCCV 0x0c
89610 +#define PCF50606_MBCC1_CHGMOD_FAST_NOCC 0x10
89611 +#define PCF50606_MBCC1_CHGMOD_FAST_NOCV 0x14
89612 +#define PCF50606_MBCC1_CHGMOD_FAST_SW 0x18
89613 +#define PCF50606_MBCC1_CHGMOD_IDLE 0x1c
89614 +#define PCF50606_MBCC1_DETMOD_LOWCHG 0x20
89615 +#define PCF50606_MBCC1_DETMOD_WDRST 0x40
89616 +
89617 +#define PCF50606_MBCC1_CHGMOD_SHIFT 2
89618 +
89619 +/* Charger status */
89620 +#define PCF50606_MBC_CHARGER_ONLINE 0x01
89621 +#define PCF50606_MBC_CHARGER_ACTIVE 0x02
89622 +
89623 +void pcf50606_charge_fast(struct pcf50606 *pcf, int on);
89624 +
89625 +#endif
89626 +
89627 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/pmic.h linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/pmic.h
89628 --- linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50606/pmic.h 1970-01-01 01:00:00.000000000 +0100
89629 +++ linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50606/pmic.h 2009-05-10 22:28:00.000000000 +0200
89630 @@ -0,0 +1,73 @@
89631 +#ifndef __LINUX_MFD_PCF50606_PMIC_H
89632 +#define __LINUX_MFD_PCF50606_PMIC_H
89633 +
89634 +#define PCF50606_REG_DCDC1 0x1b
89635 +#define PCF50606_REG_DCDC2 0x1c
89636 +#define PCF50606_REG_DCDC3 0x1d
89637 +#define PCF50606_REG_DCDC4 0x1e
89638 +#define PCF50606_REG_DCDEC1 0x1f
89639 +#define PCF50606_REG_DCDEC2 0x20
89640 +#define PCF50606_REG_DCUDC1 0x21
89641 +#define PCF50606_REG_DCUDC2 0x22
89642 +#define PCF50606_REG_IOREGC 0x23
89643 +#define PCF50606_REG_D1REGC1 0x24
89644 +#define PCF50606_REG_D2REGC1 0x25
89645 +#define PCF50606_REG_D3REGC1 0x26
89646 +#define PCF50606_REG_LPREGC1 0x27
89647 +#define PCF50606_REG_LPREGC2 0x28
89648 +
89649 +/* used by PSSC, PWROKM, PWROKS, */
89650 +enum pcf50606_regu {
89651 + PCF50606_REGU_DCD = 0x01, /* DCD in phase 2 */
89652 + PCF50606_REGU_DCDE = 0x02, /* DCDE in phase 2 */
89653 + PCF50606_REGU_DCUD = 0x04, /* DCDU in phase 2 */
89654 + PCF50606_REGU_IO = 0x08, /* IO in phase 2 */
89655 + PCF50606_REGU_D1 = 0x10, /* D1 in phase 2 */
89656 + PCF50606_REGU_D2 = 0x20, /* D2 in phase 2 */
89657 + PCF50606_REGU_D3 = 0x40, /* D3 in phase 2 */
89658 + PCF50606_REGU_LP = 0x80, /* LP in phase 2 */
89659 +};
89660 +
89661 +enum pcf50606_reg_dcdc4 {
89662 + PCF50606_DCDC4_MODE_AUTO = 0x00,
89663 + PCF50606_DCDC4_MODE_PWM = 0x01,
89664 + PCF50606_DCDC4_MODE_PCF = 0x02,
89665 + PCF50606_DCDC4_OFF_FLOAT = 0x00,
89666 + PCF50606_DCDC4_OFF_BYPASS = 0x04,
89667 + PCF50606_DCDC4_OFF_PULLDOWN = 0x08,
89668 + PCF50606_DCDC4_CURLIM_500mA = 0x00,
89669 + PCF50606_DCDC4_CURLIM_750mA = 0x10,
89670 + PCF50606_DCDC4_CURLIM_1000mA = 0x20,
89671 + PCF50606_DCDC4_CURLIM_1250mA = 0x30,
89672 + PCF50606_DCDC4_TOGGLE = 0x40,
89673 + PCF50606_DCDC4_REGSEL_DCDC2 = 0x80,
89674 +};
89675 +
89676 +enum pcf50606_reg_dcdec2 {
89677 + PCF50606_DCDEC2_MODE_AUTO = 0x00,
89678 + PCF50606_DCDEC2_MODE_PWM = 0x01,
89679 + PCF50606_DCDEC2_MODE_PCF = 0x02,
89680 + PCF50606_DCDEC2_OFF_FLOAT = 0x00,
89681 + PCF50606_DCDEC2_OFF_BYPASS = 0x04,
89682 +};
89683 +
89684 +enum pcf50606_reg_dcudc2 {
89685 + PCF50606_DCUDC2_MODE_AUTO = 0x00,
89686 + PCF50606_DCUDC2_MODE_PWM = 0x01,
89687 + PCF50606_DCUDC2_MODE_PCF = 0x02,
89688 + PCF50606_DCUDC2_OFF_FLOAT = 0x00,
89689 + PCF50606_DCUDC2_OFF_BYPASS = 0x04,
89690 +};
89691 +
89692 +enum pcf50606_regulator_id {
89693 + PCF50606_REGULATOR_DCD,
89694 + PCF50606_REGULATOR_DCDE,
89695 + PCF50606_REGULATOR_DCUD,
89696 + PCF50606_REGULATOR_D1REG,
89697 + PCF50606_REGULATOR_D2REG,
89698 + PCF50606_REGULATOR_D3REG,
89699 + PCF50606_REGULATOR_LPREG,
89700 + PCF50606_REGULATOR_IOREG,
89701 +};
89702 +
89703 +#endif
89704 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50633/core.h linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50633/core.h
89705 --- linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50633/core.h 2009-05-10 22:04:47.000000000 +0200
89706 +++ linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50633/core.h 2009-05-10 22:28:00.000000000 +0200
89707 @@ -29,6 +29,10 @@
89708 char **batteries;
89709 int num_batteries;
89710
89711 + int charging_restart_interval;
89712 +
89713 + int chg_ref_current_ma;
89714 +
89715 /* Callbacks */
89716 void (*probe_done)(struct pcf50633 *);
89717 void (*mbc_event_callback)(struct pcf50633 *, int);
89718 @@ -206,7 +210,8 @@
89719 };
89720
89721 /* misc. registers */
89722 -#define PCF50633_REG_OOCSHDWN 0x0c
89723 +#define PCF50633_REG_OOCSHDWN 0x0c
89724 +#define PCF50633_OOCSHDWN_GOSTDBY 0x01
89725
89726 /* LED registers */
89727 #define PCF50633_REG_LEDOUT 0x28
89728 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50633/mbc.h linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50633/mbc.h
89729 --- linux-2.6.29-rc3.owrt/include/linux/mfd/pcf50633/mbc.h 2009-05-10 22:04:47.000000000 +0200
89730 +++ linux-2.6.29-rc3.owrt.om/include/linux/mfd/pcf50633/mbc.h 2009-05-10 22:28:00.000000000 +0200
89731 @@ -128,7 +128,5 @@
89732 int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma);
89733
89734 int pcf50633_mbc_get_status(struct pcf50633 *);
89735 -void pcf50633_mbc_set_status(struct pcf50633 *, int what, int status);
89736 -
89737 #endif
89738
89739 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mmc/core.h linux-2.6.29-rc3.owrt.om/include/linux/mmc/core.h
89740 --- linux-2.6.29-rc3.owrt/include/linux/mmc/core.h 2009-05-10 22:04:47.000000000 +0200
89741 +++ linux-2.6.29-rc3.owrt.om/include/linux/mmc/core.h 2009-05-10 22:28:00.000000000 +0200
89742 @@ -129,6 +129,8 @@
89743 struct mmc_host;
89744 struct mmc_card;
89745
89746 +extern void mmc_flush_scheduled_work(void);
89747 +
89748 extern void mmc_wait_for_req(struct mmc_host *, struct mmc_request *);
89749 extern int mmc_wait_for_cmd(struct mmc_host *, struct mmc_command *, int);
89750 extern int mmc_wait_for_app_cmd(struct mmc_host *, struct mmc_card *,
89751 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mmc/sdio_ids.h linux-2.6.29-rc3.owrt.om/include/linux/mmc/sdio_ids.h
89752 --- linux-2.6.29-rc3.owrt/include/linux/mmc/sdio_ids.h 2009-05-10 22:04:47.000000000 +0200
89753 +++ linux-2.6.29-rc3.owrt.om/include/linux/mmc/sdio_ids.h 2009-05-10 22:28:00.000000000 +0200
89754 @@ -25,5 +25,9 @@
89755
89756 #define SDIO_VENDOR_ID_MARVELL 0x02df
89757 #define SDIO_DEVICE_ID_MARVELL_LIBERTAS 0x9103
89758 +#define SDIO_DEVICE_ID_MARVELL_88W8688 0x9104
89759 +#define SDIO_VENDOR_ID_ATHEROS 0x0271
89760 +#define SDIO_DEVICE_ID_ATHEROS_AR6001 0x0100
89761 +#define SDIO_DEVICE_ID_ATHEROS_AR6002 0x0200
89762
89763 #endif
89764 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/mm.h linux-2.6.29-rc3.owrt.om/include/linux/mm.h
89765 --- linux-2.6.29-rc3.owrt/include/linux/mm.h 2009-05-10 22:09:07.000000000 +0200
89766 +++ linux-2.6.29-rc3.owrt.om/include/linux/mm.h 2009-05-10 22:28:00.000000000 +0200
89767 @@ -725,7 +725,7 @@
89768 }
89769 #endif
89770 struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags);
89771 -
89772 +void shmem_set_file(struct vm_area_struct *, struct file *);
89773 int shmem_zero_setup(struct vm_area_struct *);
89774
89775 #ifndef CONFIG_MMU
89776 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/neo1973_vibrator.h linux-2.6.29-rc3.owrt.om/include/linux/neo1973_vibrator.h
89777 --- linux-2.6.29-rc3.owrt/include/linux/neo1973_vibrator.h 1970-01-01 01:00:00.000000000 +0100
89778 +++ linux-2.6.29-rc3.owrt.om/include/linux/neo1973_vibrator.h 2009-05-10 22:28:00.000000000 +0200
89779 @@ -0,0 +1,5 @@
89780 +struct neo1973_vib_platform_data {
89781 + int (* enable_fiq)(void);
89782 + void (*disable_fiq)(void);
89783 + void (*kick_fiq)(void);
89784 +};
89785 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/pcap7200.h linux-2.6.29-rc3.owrt.om/include/linux/pcap7200.h
89786 --- linux-2.6.29-rc3.owrt/include/linux/pcap7200.h 1970-01-01 01:00:00.000000000 +0100
89787 +++ linux-2.6.29-rc3.owrt.om/include/linux/pcap7200.h 2009-05-10 22:28:00.000000000 +0200
89788 @@ -0,0 +1,25 @@
89789 +#ifndef _LINUX_PCPA7200_H
89790 +#define _LINUX_PCPA7200_H
89791 +
89792 +enum op_mode {
89793 + SLEEP,
89794 + WAKEUP,
89795 + SINGLE_TOUCH,
89796 + MULTI_TOUCH,
89797 +};
89798 +
89799 +enum gesture {
89800 + ZOOM,
89801 + FST_ZOOM,
89802 + SND_ZOOM,
89803 + ROTATE,
89804 + FST_SLIDE,
89805 + SND_SLIDE,
89806 +};
89807 +
89808 +struct pcap7200_platform_data {
89809 + enum op_mode mode;
89810 + void (*reset)(void);
89811 +};
89812 +
89813 +#endif /* _LINUX_PCPA7200_H */
89814 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/pcf50606.h linux-2.6.29-rc3.owrt.om/include/linux/pcf50606.h
89815 --- linux-2.6.29-rc3.owrt/include/linux/pcf50606.h 1970-01-01 01:00:00.000000000 +0100
89816 +++ linux-2.6.29-rc3.owrt.om/include/linux/pcf50606.h 2009-05-10 22:28:00.000000000 +0200
89817 @@ -0,0 +1,91 @@
89818 +#ifndef _LINUX_PCF50606_H
89819 +#define _LINUX_PCF50606_H
89820 +
89821 +#include <linux/pcf506xx.h>
89822 +
89823 +
89824 +/* public in-kernel pcf50606 api */
89825 +enum pcf50606_regulator_id {
89826 + PCF50606_REGULATOR_DCD,
89827 + PCF50606_REGULATOR_DCDE,
89828 + PCF50606_REGULATOR_DCUD,
89829 + PCF50606_REGULATOR_D1REG,
89830 + PCF50606_REGULATOR_D2REG,
89831 + PCF50606_REGULATOR_D3REG,
89832 + PCF50606_REGULATOR_LPREG,
89833 + PCF50606_REGULATOR_IOREG,
89834 + __NUM_PCF50606_REGULATORS
89835 +};
89836 +
89837 +struct pcf50606_data;
89838 +
89839 +/* This is an ugly construct on how to access the (currently single/global)
89840 + * pcf50606 handle from other code in the kernel. I didn't really come up with
89841 + * a more decent method of dynamically resolving this */
89842 +extern struct pcf50606_data *pcf50606_global;
89843 +
89844 +extern void
89845 +pcf50606_go_standby(void);
89846 +
89847 +extern void
89848 +pcf50606_gpo0_set(struct pcf50606_data *pcf, int on);
89849 +
89850 +extern int
89851 +pcf50606_gpo0_get(struct pcf50606_data *pcf);
89852 +
89853 +extern int
89854 +pcf50606_voltage_set(struct pcf50606_data *pcf,
89855 + enum pcf50606_regulator_id reg,
89856 + unsigned int millivolts);
89857 +extern unsigned int
89858 +pcf50606_voltage_get(struct pcf50606_data *pcf,
89859 + enum pcf50606_regulator_id reg);
89860 +extern int
89861 +pcf50606_onoff_get(struct pcf50606_data *pcf,
89862 + enum pcf50606_regulator_id reg);
89863 +
89864 +extern int
89865 +pcf50606_onoff_set(struct pcf50606_data *pcf,
89866 + enum pcf50606_regulator_id reg, int on);
89867 +
89868 +extern void
89869 +pcf50606_charge_fast(struct pcf50606_data *pcf, int on);
89870 +
89871 +
89872 +#define PCF50606_FEAT_EXTON 0x00000001 /* not yet supported */
89873 +#define PCF50606_FEAT_MBC 0x00000002
89874 +#define PCF50606_FEAT_BBC 0x00000004 /* not yet supported */
89875 +#define PCF50606_FEAT_TSC 0x00000008 /* not yet supported */
89876 +#define PCF50606_FEAT_WDT 0x00000010
89877 +#define PCF50606_FEAT_ACD 0x00000020
89878 +#define PCF50606_FEAT_RTC 0x00000040
89879 +#define PCF50606_FEAT_PWM 0x00000080
89880 +#define PCF50606_FEAT_CHGCUR 0x00000100
89881 +#define PCF50606_FEAT_BATVOLT 0x00000200
89882 +#define PCF50606_FEAT_BATTEMP 0x00000400
89883 +#define PCF50606_FEAT_PWM_BL 0x00000800
89884 +
89885 +struct pcf50606_platform_data {
89886 + /* general */
89887 + unsigned int used_features;
89888 + unsigned int onkey_seconds_required;
89889 +
89890 + /* voltage regulator related */
89891 + struct pmu_voltage_rail rails[__NUM_PCF50606_REGULATORS];
89892 + unsigned int used_regulators;
89893 +
89894 + /* charger related */
89895 + unsigned int r_fix_batt;
89896 + unsigned int r_fix_batt_par;
89897 + unsigned int r_sense_milli;
89898 +
89899 + /* backlight related */
89900 + unsigned int init_brightness;
89901 +
89902 + struct {
89903 + u_int8_t mbcc3; /* charger voltage / current */
89904 + } charger;
89905 + pmu_cb cb;
89906 +};
89907 +
89908 +#endif
89909 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/pcf50633.h linux-2.6.29-rc3.owrt.om/include/linux/pcf50633.h
89910 --- linux-2.6.29-rc3.owrt/include/linux/pcf50633.h 1970-01-01 01:00:00.000000000 +0100
89911 +++ linux-2.6.29-rc3.owrt.om/include/linux/pcf50633.h 2009-05-10 22:28:00.000000000 +0200
89912 @@ -0,0 +1,176 @@
89913 +#ifndef _LINUX_PCF50633_H
89914 +#define _LINUX_PCF50633_H
89915 +
89916 +#include <linux/pcf506xx.h>
89917 +#include <linux/regulator/machine.h>
89918 +
89919 +
89920 +/* public in-kernel pcf50633 api */
89921 +enum pcf50633_regulator_id {
89922 + PCF50633_REGULATOR_AUTO,
89923 + PCF50633_REGULATOR_DOWN1,
89924 + PCF50633_REGULATOR_DOWN2,
89925 + PCF50633_REGULATOR_MEMLDO,
89926 + PCF50633_REGULATOR_LDO1,
89927 + PCF50633_REGULATOR_LDO2,
89928 + PCF50633_REGULATOR_LDO3,
89929 + PCF50633_REGULATOR_LDO4,
89930 + PCF50633_REGULATOR_LDO5,
89931 + PCF50633_REGULATOR_LDO6,
89932 + PCF50633_REGULATOR_HCLDO,
89933 + __NUM_PCF50633_REGULATORS
89934 +};
89935 +
89936 +enum pcf50633_reg_int1 {
89937 + PCF50633_INT1_ADPINS = 0x01, /* Adapter inserted */
89938 + PCF50633_INT1_ADPREM = 0x02, /* Adapter removed */
89939 + PCF50633_INT1_USBINS = 0x04, /* USB inserted */
89940 + PCF50633_INT1_USBREM = 0x08, /* USB removed */
89941 + /* reserved */
89942 + PCF50633_INT1_ALARM = 0x40, /* RTC alarm time is reached */
89943 + PCF50633_INT1_SECOND = 0x80, /* RTC periodic second interrupt */
89944 +};
89945 +
89946 +enum pcf50633_reg_int2 {
89947 + PCF50633_INT2_ONKEYR = 0x01, /* ONKEY rising edge */
89948 + PCF50633_INT2_ONKEYF = 0x02, /* ONKEY falling edge */
89949 + PCF50633_INT2_EXTON1R = 0x04, /* EXTON1 rising edge */
89950 + PCF50633_INT2_EXTON1F = 0x08, /* EXTON1 falling edge */
89951 + PCF50633_INT2_EXTON2R = 0x10, /* EXTON2 rising edge */
89952 + PCF50633_INT2_EXTON2F = 0x20, /* EXTON2 falling edge */
89953 + PCF50633_INT2_EXTON3R = 0x40, /* EXTON3 rising edge */
89954 + PCF50633_INT2_EXTON3F = 0x80, /* EXTON3 falling edge */
89955 +};
89956 +
89957 +enum pcf50633_reg_int3 {
89958 + PCF50633_INT3_BATFULL = 0x01, /* Battery full */
89959 + PCF50633_INT3_CHGHALT = 0x02, /* Charger halt */
89960 + PCF50633_INT3_THLIMON = 0x04,
89961 + PCF50633_INT3_THLIMOFF = 0x08,
89962 + PCF50633_INT3_USBLIMON = 0x10,
89963 + PCF50633_INT3_USBLIMOFF = 0x20,
89964 + PCF50633_INT3_ADCRDY = 0x40, /* ADC conversion finished */
89965 + PCF50633_INT3_ONKEY1S = 0x80, /* ONKEY pressed 1 second */
89966 +};
89967 +
89968 +enum pcf50633_reg_int4 {
89969 + PCF50633_INT4_LOWSYS = 0x01,
89970 + PCF50633_INT4_LOWBAT = 0x02,
89971 + PCF50633_INT4_HIGHTMP = 0x04,
89972 + PCF50633_INT4_AUTOPWRFAIL = 0x08,
89973 + PCF50633_INT4_DWN1PWRFAIL = 0x10,
89974 + PCF50633_INT4_DWN2PWRFAIL = 0x20,
89975 + PCF50633_INT4_LEDPWRFAIL = 0x40,
89976 + PCF50633_INT4_LEDOVP = 0x80,
89977 +};
89978 +
89979 +enum pcf50633_reg_int5 {
89980 + PCF50633_INT5_LDO1PWRFAIL = 0x01,
89981 + PCF50633_INT5_LDO2PWRFAIL = 0x02,
89982 + PCF50633_INT5_LDO3PWRFAIL = 0x04,
89983 + PCF50633_INT5_LDO4PWRFAIL = 0x08,
89984 + PCF50633_INT5_LDO5PWRFAIL = 0x10,
89985 + PCF50633_INT5_LDO6PWRFAIL = 0x20,
89986 + PCF50633_INT5_HCLDOPWRFAIL = 0x40,
89987 + PCF50633_INT5_HCLDOOVL = 0x80,
89988 +};
89989 +
89990 +struct pcf50633_data;
89991 +extern struct pcf50633_data *pcf50633_global;
89992 +
89993 +extern void
89994 +pcf50633_go_standby(void);
89995 +
89996 +enum pcf50633_gpio {
89997 + PCF50633_GPIO1 = 1,
89998 + PCF50633_GPIO2 = 2,
89999 + PCF50633_GPIO3 = 3,
90000 + PCF50633_GPO = 4,
90001 +};
90002 +
90003 +extern void
90004 +pcf50633_gpio_set(struct pcf50633_data *pcf, enum pcf50633_gpio gpio, int on);
90005 +
90006 +extern int
90007 +pcf50633_gpio_get(struct pcf50633_data *pcf, enum pcf50633_gpio gpio);
90008 +
90009 +extern int
90010 +pcf50633_voltage_set(struct pcf50633_data *pcf,
90011 + enum pcf50633_regulator_id reg,
90012 + unsigned int millivolts);
90013 +extern unsigned int
90014 +pcf50633_voltage_get(struct pcf50633_data *pcf,
90015 + enum pcf50633_regulator_id reg);
90016 +
90017 +extern int
90018 +pcf50633_onoff_get(struct pcf50633_data *pcf,
90019 + enum pcf50633_regulator_id reg);
90020 +
90021 +extern int
90022 +pcf50633_onoff_set(struct pcf50633_data *pcf,
90023 + enum pcf50633_regulator_id reg, int on);
90024 +
90025 +extern void
90026 +pcf50633_backlight_resume(struct pcf50633_data *pcf);
90027 +
90028 +extern u_int16_t
90029 +pcf50633_battvolt(struct pcf50633_data *pcf);
90030 +
90031 +extern int
90032 +pcf50633_report_resumers(struct pcf50633_data *pcf, char *buf);
90033 +
90034 +extern int
90035 +pcf50633_notify_usb_current_limit_change(struct pcf50633_data *pcf,
90036 + unsigned int ma);
90037 +extern int
90038 +pcf50633_wait_for_ready(struct pcf50633_data *pcf, int timeout_ms,
90039 + char *name);
90040 +
90041 +/* 0 = initialized and resumed and ready to roll, !=0 = either not
90042 + * initialized or not resumed yet
90043 + */
90044 +extern int
90045 +pcf50633_ready(struct pcf50633_data *pcf);
90046 +
90047 +#define PCF50633_FEAT_EXTON 0x00000001 /* not yet supported */
90048 +#define PCF50633_FEAT_MBC 0x00000002
90049 +#define PCF50633_FEAT_BBC 0x00000004 /* not yet supported */
90050 +#define PCF50633_FEAT_RTC 0x00000040
90051 +#define PCF50633_FEAT_CHGCUR 0x00000100
90052 +#define PCF50633_FEAT_BATVOLT 0x00000200
90053 +#define PCF50633_FEAT_BATTEMP 0x00000400
90054 +#define PCF50633_FEAT_PWM_BL 0x00000800
90055 +
90056 +struct pcf50633_platform_data {
90057 + /* general */
90058 + unsigned int used_features;
90059 + unsigned int onkey_seconds_sig_init;
90060 + unsigned int onkey_seconds_shutdown;
90061 +
90062 + /* callback to attach platform children (to enforce suspend / resume
90063 + * ordering */
90064 + void (*attach_child_devices)(struct device *parent_device);
90065 +
90066 + /* voltage regulator related */
90067 + struct pmu_voltage_rail rails[__NUM_PCF50633_REGULATORS];
90068 + unsigned int used_regulators;
90069 +
90070 + /* charger related */
90071 + unsigned int r_fix_batt;
90072 + unsigned int r_fix_batt_par;
90073 + unsigned int r_sense_milli;
90074 + int flag_use_apm_emulation;
90075 +
90076 + unsigned char resumers[5];
90077 +
90078 + struct {
90079 + u_int8_t mbcc3; /* charger voltage / current */
90080 + } charger;
90081 + pmu_cb cb;
90082 +
90083 + /* post-resume backlight bringup */
90084 + int defer_resume_backlight;
90085 + u8 resume_backlight_ramp_speed;
90086 +};
90087 +
90088 +#endif /* _PCF50633_H */
90089 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/pcf506xx.h linux-2.6.29-rc3.owrt.om/include/linux/pcf506xx.h
90090 --- linux-2.6.29-rc3.owrt/include/linux/pcf506xx.h 1970-01-01 01:00:00.000000000 +0100
90091 +++ linux-2.6.29-rc3.owrt.om/include/linux/pcf506xx.h 2009-05-10 22:28:00.000000000 +0200
90092 @@ -0,0 +1,34 @@
90093 +#ifndef _LINUX_PCF506XX_H
90094 +#define _LINUX_PCF506XX_H
90095 +
90096 +
90097 +#define PMU_VRAIL_F_SUSPEND_ON 0x00000001 /* Remains on during suspend */
90098 +#define PMU_VRAIL_F_UNUSED 0x00000002 /* This rail is not used */
90099 +struct pmu_voltage_rail {
90100 + char *name;
90101 + unsigned int flags;
90102 + struct {
90103 + unsigned int init;
90104 + unsigned int max;
90105 + } voltage;
90106 +};
90107 +
90108 +enum pmu_event {
90109 + PMU_EVT_NONE,
90110 + PMU_EVT_INSERT,
90111 + PMU_EVT_REMOVE,
90112 +#ifdef CONFIG_SENSORS_PCF50633
90113 + PMU_EVT_USB_INSERT,
90114 + PMU_EVT_USB_REMOVE,
90115 +#endif
90116 + PMU_EVT_CHARGER_ACTIVE,
90117 + PMU_EVT_CHARGER_IDLE,
90118 + PMU_EVT_CHARGER_CHANGE,
90119 + __NUM_PMU_EVTS
90120 +};
90121 +
90122 +typedef int (*pmu_cb)(struct device *dev, unsigned int feature,
90123 + enum pmu_event event);
90124 +
90125 +
90126 +#endif /* !_LINUX_PCF506XX_H */
90127 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/resume-dependency.h linux-2.6.29-rc3.owrt.om/include/linux/resume-dependency.h
90128 --- linux-2.6.29-rc3.owrt/include/linux/resume-dependency.h 1970-01-01 01:00:00.000000000 +0100
90129 +++ linux-2.6.29-rc3.owrt.om/include/linux/resume-dependency.h 2009-05-10 22:28:00.000000000 +0200
90130 @@ -0,0 +1,114 @@
90131 +#ifndef __RESUME_DEPENDENCY_H__
90132 +#define __RESUME_DEPENDENCY_H__
90133 +
90134 +/* Resume dependency framework
90135 + *
90136 + * (C) 2008 Openmoko, Inc.
90137 + * Author: Andy Green <andy@openmoko.com>
90138 + *
90139 + * This program is free software; you can redistribute it and/or
90140 + * modify it under the terms of the GNU General Public License as
90141 + * published by the Free Software Foundation; version 2.1.
90142 + *
90143 + * This program is distributed in the hope that it will be useful,
90144 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
90145 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90146 + * GNU General Public License for more details.
90147 + *
90148 + * You should have received a copy of the GNU General Public License
90149 + * along with this program; if not, write to the Free Software
90150 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
90151 + * MA 02111-1307 USA
90152 + *
90153 + */
90154 +
90155 +#include <linux/list.h>
90156 +
90157 +struct resume_dependency {
90158 + struct list_head list;
90159 +
90160 + void (*callback)(void *); /* called with context as arg */
90161 + void * context;
90162 + int called_flag; /* set to 1 after called, use for multi dep */
90163 +};
90164 +
90165 +/* if you are a driver accept to have other drivers as dependencies, you need to
90166 + * instantiate a struct resume_dependency above, then initialize it by invoking
90167 + * init_resume_dependency_list() on it
90168 + */
90169 +
90170 +#define init_resume_dependency_list(_head) \
90171 + printk(KERN_INFO "##### init_resume_dependency_list(head=%p)\n", (_head)); \
90172 + INIT_LIST_HEAD(&(_head)->list);
90173 +
90174 +
90175 +/* if your resume function depends on something else being resumed first, you
90176 + * can register the dependency by calling this in your suspend function with
90177 + * head being the list held by the thing you are dependent on, and dep being
90178 + * your struct resume_dependency
90179 + */
90180 +
90181 +#define register_resume_dependency(_head, _dep) { \
90182 + struct list_head *_pos, *_q; \
90183 + struct resume_dependency *_d; \
90184 +\
90185 + printk(KERN_ERR "##### register_resume_dependency(head=%p, dep=%p)\n", (_head), (_dep)); \
90186 + (_dep)->called_flag = 1; \
90187 + list_for_each_safe(_pos, _q, &((_head)->list)) { \
90188 + _d = list_entry(_pos, struct resume_dependency, list); \
90189 + if (_d == (_dep)) { \
90190 + list_del(_pos); \
90191 + printk(KERN_ERR "##### duplicate dependency removed first\n"); \
90192 + } \
90193 + } \
90194 + list_add(&(_dep)->list, &(_head)->list); \
90195 +}
90196 +
90197 +/* In the resume function that things can be dependent on, at the end you
90198 + * invoke this macro. This calls back the dependent resumes now it is safe to
90199 + * use the resumed thing they were dependent on.
90200 + */
90201 +
90202 +#define callback_all_resume_dependencies(_head) { \
90203 + struct list_head *_pos, *_q; \
90204 + struct resume_dependency *_dep; \
90205 +\
90206 + printk(KERN_ERR "##### callback_all_resume_dependencies(head=%p)\n", (_head)); \
90207 + list_for_each_safe(_pos, _q, &((_head)->list)) { \
90208 + _dep = list_entry(_pos, struct resume_dependency, list); \
90209 + printk(KERN_ERR "##### callback list entry (head=%p, dep=%p)\n", (_head), (_dep)); \
90210 + _dep->called_flag = 1; \
90211 + printk(KERN_ERR "##### callback=%p(context=%p))\n", (_dep->callback),(_dep->context)); \
90212 + (_dep->callback)(_dep->context); \
90213 + list_del(_pos); \
90214 + } \
90215 +}
90216 +
90217 +/* When a dependency is added, it is not actually active; the dependent resume
90218 + * handler will function as normal. The dependency is activated by the suspend
90219 + * handler for the driver that will be doing the callbacks. This ensures that
90220 + * if the suspend is aborted for any reason (error, driver busy, etc), that all
90221 + * suspended drivers will resume, even if the driver upon which they are dependent
90222 + * did not suspend, and hence will not resume, and thus would be unable to perform
90223 + * the callbacks.
90224 + */
90225 +
90226 +#define activate_all_resume_dependencies(_head) { \
90227 + struct list_head *_pos, *_q; \
90228 + struct resume_dependency *_dep; \
90229 +\
90230 + printk(KERN_ERR "##### activate_all_resume_dependencies(head=%p)\n", (_head)); \
90231 + list_for_each_safe(_pos, _q, &((_head)->list)) { \
90232 + _dep = list_entry(_pos, struct resume_dependency, list); \
90233 + printk(KERN_ERR "##### activating callback list entry (head=%p, dep=%p)\n", (_head), (_dep)); \
90234 + _dep->called_flag = 0; \
90235 + } \
90236 +}
90237 +
90238 +/* if your resume action is dependent on multiple drivers being resumed already,
90239 + * register the same callback with each driver you are dependent on, and check
90240 + * .called_flag for all of the struct resume_dependency. When they are all 1
90241 + * you know it is the last callback and you can resume, otherwise just return
90242 + */
90243 +
90244 +#endif
90245 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/rtc/pcf50633.h linux-2.6.29-rc3.owrt.om/include/linux/rtc/pcf50633.h
90246 --- linux-2.6.29-rc3.owrt/include/linux/rtc/pcf50633.h 1970-01-01 01:00:00.000000000 +0100
90247 +++ linux-2.6.29-rc3.owrt.om/include/linux/rtc/pcf50633.h 2009-05-10 22:28:00.000000000 +0200
90248 @@ -0,0 +1,9 @@
90249 +enum pcf50633_rtc_event {
90250 + PCF50633_RTC_EVENT_ALARM,
90251 + PCF50633_RTC_EVENT_SECOND,
90252 +};
90253 +
90254 +extern void pcf50633_rtc_handle_event(struct pcf50633_data *pcf,
90255 + enum pcf50633_rtc_event evt);
90256 +
90257 +
90258 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/spi/glamo.h linux-2.6.29-rc3.owrt.om/include/linux/spi/glamo.h
90259 --- linux-2.6.29-rc3.owrt/include/linux/spi/glamo.h 1970-01-01 01:00:00.000000000 +0100
90260 +++ linux-2.6.29-rc3.owrt.om/include/linux/spi/glamo.h 2009-05-10 22:28:00.000000000 +0200
90261 @@ -0,0 +1,27 @@
90262 +#ifndef __GLAMO_SPI_H
90263 +#define __GLAMO_SPI_H
90264 +
90265 +#include <linux/glamo-gpio.h>
90266 +
90267 +struct spi_board_info;
90268 +struct glamofb_handle;
90269 +struct glamo_core;
90270 +
90271 +struct glamo_spi_info {
90272 + unsigned long board_size;
90273 + struct spi_board_info *board_info;
90274 + struct glamofb_handle *glamofb_handle;
90275 +};
90276 +
90277 +struct glamo_spigpio_info {
90278 + unsigned int pin_clk;
90279 + unsigned int pin_mosi;
90280 + unsigned int pin_miso;
90281 + unsigned int pin_cs;
90282 + int bus_num;
90283 +
90284 + struct glamo_core *glamo;
90285 +};
90286 +
90287 +
90288 +#endif
90289 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/spi/spi_bitbang.h linux-2.6.29-rc3.owrt.om/include/linux/spi/spi_bitbang.h
90290 --- linux-2.6.29-rc3.owrt/include/linux/spi/spi_bitbang.h 2009-05-10 22:09:08.000000000 +0200
90291 +++ linux-2.6.29-rc3.owrt.om/include/linux/spi/spi_bitbang.h 2009-05-10 22:28:00.000000000 +0200
90292 @@ -31,6 +31,9 @@
90293 u8 use_dma;
90294 u8 flags; /* extra spi->mode support */
90295
90296 + /* Support for synchronous non blocking transfers */
90297 + int non_blocking_transfer;
90298 +
90299 struct spi_master *master;
90300
90301 /* setup_transfer() changes clock and/or wordsize to match settings
90302 @@ -62,6 +65,8 @@
90303 extern int spi_bitbang_transfer(struct spi_device *spi, struct spi_message *m);
90304 extern int spi_bitbang_setup_transfer(struct spi_device *spi,
90305 struct spi_transfer *t);
90306 +extern int spi_bitbang_transfer_sync(struct spi_device *spi,
90307 + struct spi_message *m);
90308
90309 /* start or stop queue processing */
90310 extern int spi_bitbang_start(struct spi_bitbang *spi);
90311 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/spi/spi.h linux-2.6.29-rc3.owrt.om/include/linux/spi/spi.h
90312 --- linux-2.6.29-rc3.owrt/include/linux/spi/spi.h 2009-05-10 22:04:47.000000000 +0200
90313 +++ linux-2.6.29-rc3.owrt.om/include/linux/spi/spi.h 2009-05-10 22:28:00.000000000 +0200
90314 @@ -264,6 +264,13 @@
90315 int (*transfer)(struct spi_device *spi,
90316 struct spi_message *mesg);
90317
90318 + /*
90319 + * Synchronous non blocking transfer function. Should guarantee
90320 + * data availability when it returns
90321 + */
90322 + int (*transfer_sync)(struct spi_device *spi,
90323 + struct spi_message *mesg);
90324 +
90325 /* called on release() to free memory provided by spi_master */
90326 void (*cleanup)(struct spi_device *spi);
90327 };
90328 @@ -573,6 +580,29 @@
90329 return spi->master->transfer(spi, message);
90330 }
90331
90332 +/**
90333 + * spi_non_blocking_transfer - Synchronous, non blocking transfer
90334 + * @spi: device with which data will be exchanged
90335 + * @message: describes the data transfers with optional completion handlers
90336 + * Context: any (irqs may be blocked, etc)
90337 + *
90338 + * Data is guaranteed to be written or read when this function returns.
90339 + *
90340 + * Note : This may not be supported by all spi masters.
90341 + */
90342 +
90343 +static inline int
90344 +spi_non_blocking_transfer(struct spi_device *spi, struct spi_message *message)
90345 +{
90346 + if (unlikely(!spi->master->transfer_sync)) {
90347 + dev_err(&spi->master->dev,
90348 + "non-blocking transfers not supported\n");
90349 + return -EIO;
90350 + }
90351 +
90352 + return spi->master->transfer_sync(spi, message);
90353 +}
90354 +
90355 /*---------------------------------------------------------------------------*/
90356
90357 /* All these synchronous SPI transfer routines are utilities layered
90358 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/suspend.h linux-2.6.29-rc3.owrt.om/include/linux/suspend.h
90359 --- linux-2.6.29-rc3.owrt/include/linux/suspend.h 2009-05-10 22:04:48.000000000 +0200
90360 +++ linux-2.6.29-rc3.owrt.om/include/linux/suspend.h 2009-05-10 22:28:00.000000000 +0200
90361 @@ -146,6 +146,12 @@
90362 struct pbe *next;
90363 };
90364
90365 +/**
90366 + * global indication we are somewhere between start of suspend and end of
90367 + * resume, nonzero is true
90368 + */
90369 +extern int global_inside_suspend;
90370 +
90371 /* mm/page_alloc.c */
90372 extern void mark_free_pages(struct zone *zone);
90373
90374 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/vt.h linux-2.6.29-rc3.owrt.om/include/linux/vt.h
90375 --- linux-2.6.29-rc3.owrt/include/linux/vt.h 2009-05-10 22:04:47.000000000 +0200
90376 +++ linux-2.6.29-rc3.owrt.om/include/linux/vt.h 2009-05-10 22:28:00.000000000 +0200
90377 @@ -18,8 +18,19 @@
90378 * resizing).
90379 */
90380 #define MIN_NR_CONSOLES 1 /* must be at least 1 */
90381 +#if (CONFIG_NR_TTY_DEVICES < 4)
90382 +/* Lower Limit */
90383 +#define MAX_NR_CONSOLES 4 /* serial lines start at 64 */
90384 +#define MAX_NR_USER_CONSOLES 4 /* must be root to allocate above this */
90385 +#elif (CONFIG_NR_TTY_DEVICES > 63)
90386 +/* Upper Limit */
90387 #define MAX_NR_CONSOLES 63 /* serial lines start at 64 */
90388 #define MAX_NR_USER_CONSOLES 63 /* must be root to allocate above this */
90389 +#else
90390 +/* They chose a sensible number */
90391 +#define MAX_NR_CONSOLES CONFIG_NR_TTY_DEVICES
90392 +#define MAX_NR_USER_CONSOLES CONFIG_NR_TTY_DEVICES
90393 +#endif
90394 /* Note: the ioctl VT_GETSTATE does not work for
90395 consoles 16 and higher (since it returns a short) */
90396
90397 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/linux/wakelock.h linux-2.6.29-rc3.owrt.om/include/linux/wakelock.h
90398 --- linux-2.6.29-rc3.owrt/include/linux/wakelock.h 1970-01-01 01:00:00.000000000 +0100
90399 +++ linux-2.6.29-rc3.owrt.om/include/linux/wakelock.h 2009-05-10 22:28:00.000000000 +0200
90400 @@ -0,0 +1,91 @@
90401 +/* include/linux/wakelock.h
90402 + *
90403 + * Copyright (C) 2007-2008 Google, Inc.
90404 + *
90405 + * This software is licensed under the terms of the GNU General Public
90406 + * License version 2, as published by the Free Software Foundation, and
90407 + * may be copied, distributed, and modified under those terms.
90408 + *
90409 + * This program is distributed in the hope that it will be useful,
90410 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
90411 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
90412 + * GNU General Public License for more details.
90413 + *
90414 + */
90415 +
90416 +#ifndef _LINUX_WAKELOCK_H
90417 +#define _LINUX_WAKELOCK_H
90418 +
90419 +#include <linux/list.h>
90420 +#include <linux/ktime.h>
90421 +
90422 +/* A wake_lock prevents the system from entering suspend or other low power
90423 + * states when active. If the type is set to WAKE_LOCK_SUSPEND, the wake_lock
90424 + * prevents a full system suspend. If the type is WAKE_LOCK_IDLE, low power
90425 + * states that cause large interrupt latencies or that disable a set of
90426 + * interrupts will not entered from idle until the wake_locks are released.
90427 + */
90428 +
90429 +enum {
90430 + WAKE_LOCK_SUSPEND, /* Prevent suspend */
90431 + WAKE_LOCK_IDLE, /* Prevent low power idle */
90432 + WAKE_LOCK_TYPE_COUNT
90433 +};
90434 +
90435 +struct wake_lock {
90436 +#ifdef CONFIG_ANDROID_HAS_WAKELOCK
90437 + struct list_head link;
90438 + int flags;
90439 + const char *name;
90440 + unsigned long expires;
90441 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
90442 + struct {
90443 + int count;
90444 + int expire_count;
90445 + int wakeup_count;
90446 + ktime_t total_time;
90447 + ktime_t prevent_suspend_time;
90448 + ktime_t max_time;
90449 + ktime_t last_time;
90450 + } stat;
90451 +#endif
90452 +#endif
90453 +};
90454 +
90455 +#ifdef CONFIG_ANDROID_HAS_WAKELOCK
90456 +
90457 +void wake_lock_init(struct wake_lock *lock, int type, const char *name);
90458 +void wake_lock_destroy(struct wake_lock *lock);
90459 +void wake_lock(struct wake_lock *lock);
90460 +void wake_lock_timeout(struct wake_lock *lock, long timeout);
90461 +void wake_unlock(struct wake_lock *lock);
90462 +
90463 +/* wake_lock_active returns a non-zero value if the wake_lock is currently
90464 + * locked. If the wake_lock has a timeout, it does not check the timeout
90465 + * but if the timeout had aready been checked it will return 0.
90466 + */
90467 +int wake_lock_active(struct wake_lock *lock);
90468 +
90469 +/* has_wake_lock returns 0 if no wake locks of the specified type are active,
90470 + * and non-zero if one or more wake locks are held. Specifically it returns
90471 + * -1 if one or more wake locks with no timeout are active or the
90472 + * number of jiffies until all active wake locks time out.
90473 + */
90474 +long has_wake_lock(int type);
90475 +
90476 +#else
90477 +
90478 +static inline void wake_lock_init(struct wake_lock *lock, int type,
90479 + const char *name) {}
90480 +static inline void wake_lock_destroy(struct wake_lock *lock) {}
90481 +static inline void wake_lock(struct wake_lock *lock) {}
90482 +static inline void wake_lock_timeout(struct wake_lock *lock, long timeout) {}
90483 +static inline void wake_unlock(struct wake_lock *lock) {}
90484 +
90485 +static inline int wake_lock_active(struct wake_lock *lock) { return 0; }
90486 +static inline long has_wake_lock(int type) { return 0; }
90487 +
90488 +#endif
90489 +
90490 +#endif
90491 +
90492 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/include/sound/soc-dapm.h linux-2.6.29-rc3.owrt.om/include/sound/soc-dapm.h
90493 --- linux-2.6.29-rc3.owrt/include/sound/soc-dapm.h 2009-05-10 22:04:48.000000000 +0200
90494 +++ linux-2.6.29-rc3.owrt.om/include/sound/soc-dapm.h 2009-05-10 22:28:00.000000000 +0200
90495 @@ -182,6 +182,15 @@
90496 .get = snd_soc_dapm_get_value_enum_double, \
90497 .put = snd_soc_dapm_put_value_enum_double, \
90498 .private_value = (unsigned long)&xenum }
90499 +/* NOTE: Openmoko-specific "DAPM " prefix added to controls for
90500 + * backwards compatibility.
90501 + */
90502 +#define SOC_DAPM_PIN_SWITCH(xname) \
90503 +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "DAPM " xname " Switch", \
90504 + .info = snd_soc_dapm_info_pin_switch, \
90505 + .get = snd_soc_dapm_get_pin_switch, \
90506 + .put = snd_soc_dapm_put_pin_switch, \
90507 + .private_value = (unsigned long)xname }
90508
90509 /* dapm stream operations */
90510 #define SND_SOC_DAPM_STREAM_NOP 0x0
90511 @@ -228,6 +237,12 @@
90512 struct snd_ctl_elem_value *ucontrol);
90513 int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
90514 struct snd_ctl_elem_value *ucontrol);
90515 +int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
90516 + struct snd_ctl_elem_info *uinfo);
90517 +int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
90518 + struct snd_ctl_elem_value *uncontrol);
90519 +int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
90520 + struct snd_ctl_elem_value *uncontrol);
90521 int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
90522 const struct snd_soc_dapm_widget *widget);
90523 int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
90524 @@ -250,12 +265,19 @@
90525 int snd_soc_dapm_sys_add(struct device *dev);
90526
90527 /* dapm audio pin control and status */
90528 -int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin);
90529 -int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin);
90530 -int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin);
90531 -int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin);
90532 +int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin);
90533 +int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin);
90534 +int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin);
90535 +int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin);
90536 int snd_soc_dapm_sync(struct snd_soc_codec *codec);
90537
90538 +/* dapm audio endpoint control */
90539 +int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
90540 + char *pin, int status);
90541 +int snd_soc_dapm_get_endpoint(struct snd_soc_codec *codec,
90542 + char *pin);
90543 +int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec);
90544 +
90545 /* dapm widget types */
90546 enum snd_soc_dapm_type {
90547 snd_soc_dapm_input = 0, /* input pin */
90548 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/init/Kconfig linux-2.6.29-rc3.owrt.om/init/Kconfig
90549 --- linux-2.6.29-rc3.owrt/init/Kconfig 2009-05-10 22:09:09.000000000 +0200
90550 +++ linux-2.6.29-rc3.owrt.om/init/Kconfig 2009-05-10 22:28:00.000000000 +0200
90551 @@ -869,6 +869,15 @@
90552 by some high performance threaded applications. Disabling
90553 this option saves about 7k.
90554
90555 +config ASHMEM
90556 + bool "Enable Android's Shared Memory Subsystem"
90557 + default n
90558 + depends on SHMEM || TINY_SHMEM
90559 + help
90560 + The ashmem subsystem is a new shared memory allocator, similar to
90561 + POSIX SHM but with different behavior and sporting a simpler
90562 + file-based API.
90563 +
90564 config VM_EVENT_COUNTERS
90565 default y
90566 bool "Enable VM event counters for /proc/vmstat" if EMBEDDED
90567 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/kernel/irq/chip.c linux-2.6.29-rc3.owrt.om/kernel/irq/chip.c
90568 --- linux-2.6.29-rc3.owrt/kernel/irq/chip.c 2009-05-10 22:09:09.000000000 +0200
90569 +++ linux-2.6.29-rc3.owrt.om/kernel/irq/chip.c 2009-05-10 22:28:00.000000000 +0200
90570 @@ -383,6 +383,7 @@
90571 out_unlock:
90572 spin_unlock(&desc->lock);
90573 }
90574 +EXPORT_SYMBOL(handle_level_irq);
90575
90576 /**
90577 * handle_fasteoi_irq - irq handler for transparent controllers
90578 @@ -593,6 +594,7 @@
90579 }
90580 spin_unlock_irqrestore(&desc->lock, flags);
90581 }
90582 +EXPORT_SYMBOL(__set_irq_handler);
90583
90584 void
90585 set_irq_chip_and_handler(unsigned int irq, struct irq_chip *chip,
90586 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/kernel/power/main.c linux-2.6.29-rc3.owrt.om/kernel/power/main.c
90587 --- linux-2.6.29-rc3.owrt/kernel/power/main.c 2009-05-10 22:09:09.000000000 +0200
90588 +++ linux-2.6.29-rc3.owrt.om/kernel/power/main.c 2009-05-10 22:28:00.000000000 +0200
90589 @@ -131,6 +131,9 @@
90590
90591 #endif /* CONFIG_PM_SLEEP */
90592
90593 +int global_inside_suspend;
90594 +EXPORT_SYMBOL(global_inside_suspend);
90595 +
90596 #ifdef CONFIG_SUSPEND
90597
90598 #ifdef CONFIG_PM_TEST_SUSPEND
90599 @@ -321,6 +324,8 @@
90600 if (!suspend_ops)
90601 return -ENOSYS;
90602
90603 + global_inside_suspend = 1;
90604 +
90605 if (suspend_ops->begin) {
90606 error = suspend_ops->begin(state);
90607 if (error)
90608 @@ -362,6 +367,8 @@
90609 Close:
90610 if (suspend_ops->end)
90611 suspend_ops->end();
90612 + global_inside_suspend = 0;
90613 +
90614 return error;
90615
90616 Recover_platform:
90617 @@ -388,6 +395,9 @@
90618
90619
90620 static const char * const pm_states[PM_SUSPEND_MAX] = {
90621 +#ifdef CONFIG_ANDROID_EARLYSUSPEND
90622 + [PM_SUSPEND_ON] = "on",
90623 +#endif
90624 [PM_SUSPEND_STANDBY] = "standby",
90625 [PM_SUSPEND_MEM] = "mem",
90626 };
90627 @@ -424,6 +434,8 @@
90628 return -EBUSY;
90629
90630 printk(KERN_INFO "PM: Syncing filesystems ... ");
90631 + global_inside_suspend = 1;
90632 +
90633 sys_sync();
90634 printk("done.\n");
90635
90636 @@ -505,7 +517,11 @@
90637 const char *buf, size_t n)
90638 {
90639 #ifdef CONFIG_SUSPEND
90640 +#ifdef CONFIG_ANDROID_EARLYSUSPEND
90641 + suspend_state_t state = PM_SUSPEND_ON;
90642 +#else
90643 suspend_state_t state = PM_SUSPEND_STANDBY;
90644 +#endif
90645 const char * const *s;
90646 #endif
90647 char *p;
90648 @@ -527,8 +543,15 @@
90649 break;
90650 }
90651 if (state < PM_SUSPEND_MAX && *s)
90652 +#ifdef CONFIG_ANDROID_EARLYSUSPEND
90653 + if (state == PM_SUSPEND_ON || valid_state(state)) {
90654 + error = 0;
90655 + request_suspend_state(state);
90656 + }
90657 +#else
90658 error = enter_state(state);
90659 #endif
90660 +#endif
90661
90662 Exit:
90663 return error ? error : n;
90664 @@ -561,6 +584,12 @@
90665 power_attr(pm_trace);
90666 #endif /* CONFIG_PM_TRACE */
90667
90668 +#ifdef CONFIG_ANDROID_USER_WAKELOCK
90669 +power_attr(wake_lock);
90670 +power_attr(wake_full_lock);
90671 +power_attr(wake_unlock);
90672 +#endif
90673 +
90674 static struct attribute * g[] = {
90675 &state_attr.attr,
90676 #ifdef CONFIG_PM_TRACE
90677 @@ -569,6 +598,11 @@
90678 #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PM_DEBUG)
90679 &pm_test_attr.attr,
90680 #endif
90681 +#ifdef CONFIG_ANDROID_USER_WAKELOCK
90682 + &wake_lock_attr.attr,
90683 + &wake_unlock_attr.attr,
90684 + &wake_full_lock_attr.attr,
90685 +#endif
90686 NULL,
90687 };
90688
90689 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/kernel/power/power.h linux-2.6.29-rc3.owrt.om/kernel/power/power.h
90690 --- linux-2.6.29-rc3.owrt/kernel/power/power.h 2009-05-10 22:05:04.000000000 +0200
90691 +++ linux-2.6.29-rc3.owrt.om/kernel/power/power.h 2009-05-10 22:28:00.000000000 +0200
90692 @@ -223,3 +223,32 @@
90693 {
90694 }
90695 #endif
90696 +
90697 +#ifdef CONFIG_ANDROID_WAKELOCK
90698 +/* kernel/power/wakelock.c */
90699 +extern struct workqueue_struct *suspend_work_queue;
90700 +extern struct wake_lock main_wake_lock;
90701 +extern suspend_state_t requested_suspend_state;
90702 +#endif
90703 +
90704 +#ifdef CONFIG_ANDROID_USER_WAKELOCK
90705 +ssize_t wake_lock_show(struct kobject *kobj, struct kobj_attribute *attr,
90706 + char *buf);
90707 +ssize_t wake_lock_store(struct kobject *kobj, struct kobj_attribute *attr,
90708 + const char *buf, size_t n);
90709 +ssize_t wake_full_lock_store(struct kobject *kobj, struct kobj_attribute *attr,
90710 + const char *buf, size_t n);
90711 +
90712 +#define wake_full_lock_show wake_lock_show
90713 +
90714 +ssize_t wake_unlock_show(struct kobject *kobj, struct kobj_attribute *attr,
90715 + char *buf);
90716 +ssize_t wake_unlock_store(struct kobject *kobj, struct kobj_attribute *attr,
90717 + const char *buf, size_t n);
90718 +#endif
90719 +
90720 +#ifdef CONFIG_ANDROID_EARLYSUSPEND
90721 +/* kernel/power/earlysuspend.c */
90722 +void request_suspend_state(suspend_state_t state);
90723 +suspend_state_t get_suspend_state(void);
90724 +#endif
90725 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/kernel/power/process.c linux-2.6.29-rc3.owrt.om/kernel/power/process.c
90726 --- linux-2.6.29-rc3.owrt/kernel/power/process.c 2009-05-10 22:05:04.000000000 +0200
90727 +++ linux-2.6.29-rc3.owrt.om/kernel/power/process.c 2009-05-10 22:28:00.000000000 +0200
90728 @@ -13,6 +13,7 @@
90729 #include <linux/module.h>
90730 #include <linux/syscalls.h>
90731 #include <linux/freezer.h>
90732 +#include <linux/wakelock.h>
90733
90734 /*
90735 * Timeout for stopping processes
90736 @@ -36,6 +37,7 @@
90737 struct timeval start, end;
90738 u64 elapsed_csecs64;
90739 unsigned int elapsed_csecs;
90740 + unsigned int wakeup = 0;
90741
90742 do_gettimeofday(&start);
90743
90744 @@ -62,6 +64,10 @@
90745 } while_each_thread(g, p);
90746 read_unlock(&tasklist_lock);
90747 yield(); /* Yield is okay here */
90748 + if (todo && has_wake_lock(WAKE_LOCK_SUSPEND)) {
90749 + wakeup = 1;
90750 + break;
90751 + }
90752 if (time_after(jiffies, end_time))
90753 break;
90754 } while (todo);
90755 @@ -77,11 +83,17 @@
90756 * and caller must call thaw_processes() if something fails),
90757 * but it cleans up leftover PF_FREEZE requests.
90758 */
90759 - printk("\n");
90760 - printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
90761 + if (wakeup) {
90762 + printk("\n");
90763 + printk(KERN_ERR "Freezing of %s aborted\n",
90764 + sig_only ? "user space " : "tasks ");
90765 + } else {
90766 + printk("\n");
90767 + printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
90768 "(%d tasks refusing to freeze):\n",
90769 elapsed_csecs / 100, elapsed_csecs % 100, todo);
90770 - show_state();
90771 + show_state();
90772 + }
90773 read_lock(&tasklist_lock);
90774 do_each_thread(g, p) {
90775 task_lock(p);
90776 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/kernel/printk.c linux-2.6.29-rc3.owrt.om/kernel/printk.c
90777 --- linux-2.6.29-rc3.owrt/kernel/printk.c 2009-05-10 22:09:09.000000000 +0200
90778 +++ linux-2.6.29-rc3.owrt.om/kernel/printk.c 2009-05-10 22:28:00.000000000 +0200
90779 @@ -32,8 +32,11 @@
90780 #include <linux/security.h>
90781 #include <linux/bootmem.h>
90782 #include <linux/syscalls.h>
90783 +#include <linux/jiffies.h>
90784 +#include <linux/suspend.h>
90785
90786 #include <asm/uaccess.h>
90787 +#include <asm/plat-s3c24xx/neo1973.h>
90788
90789 /*
90790 * Architectures can override it:
90791 @@ -67,13 +70,21 @@
90792 int oops_in_progress;
90793 EXPORT_SYMBOL(oops_in_progress);
90794
90795 +void (*printk_emergency_debug_spew_init)(void) = NULL;
90796 +EXPORT_SYMBOL(printk_emergency_debug_spew_init);
90797 +
90798 +void (*printk_emergency_debug_spew_send_string)(const char *) = NULL;
90799 +EXPORT_SYMBOL(printk_emergency_debug_spew_send_string);
90800 +
90801 /*
90802 * console_sem protects the console_drivers list, and also
90803 * provides serialisation for access to the entire console
90804 * driver system.
90805 */
90806 static DECLARE_MUTEX(console_sem);
90807 +#ifndef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90808 static DECLARE_MUTEX(secondary_console_sem);
90809 +#endif
90810 struct console *console_drivers;
90811 EXPORT_SYMBOL_GPL(console_drivers);
90812
90813 @@ -667,8 +678,39 @@
90814 /* Emit the output into the temporary buffer */
90815 printed_len += vscnprintf(printk_buf + printed_len,
90816 sizeof(printk_buf) - printed_len, fmt, args);
90817 -
90818 -
90819 +#if defined(CONFIG_MACH_NEO1973_GTA02) && defined(CONFIG_PM)
90820 + /* if you're debugging resume, the normal methods can change resume
90821 + * ordering behaviours because their debugging output is synchronous
90822 + * (ie, CONFIG_DEBUG_LL). If your problem is an OOPS, this code
90823 + * will not affect the speed and duration and ordering of resume
90824 + * actions, but will give you a chance to read the full undumped
90825 + * syslog AND the OOPS data when it happens
90826 + *
90827 + * if you support it, your debug device init can override the exported
90828 + * emergency_debug_spew_init and emergency_debug_spew_send_string to
90829 + * usually force polling or bitbanging on your debug console device
90830 + */
90831 + if (oops_in_progress && global_inside_suspend &&
90832 + printk_emergency_debug_spew_init &&
90833 + printk_emergency_debug_spew_send_string) {
90834 + unsigned long cur_index;
90835 + char ch[2];
90836 +
90837 + if (global_inside_suspend == 1) {
90838 + (printk_emergency_debug_spew_init)();
90839 +
90840 + ch[1] = '\0';
90841 + cur_index = con_start;
90842 + while (cur_index != log_end) {
90843 + ch[0] = LOG_BUF(cur_index);
90844 + (printk_emergency_debug_spew_send_string)(ch);
90845 + cur_index++;
90846 + }
90847 + global_inside_suspend++; /* only once */
90848 + }
90849 + (printk_emergency_debug_spew_send_string)(printk_buf);
90850 + }
90851 +#endif
90852 /*
90853 * Copy the output into log_buf. If the caller didn't provide
90854 * appropriate log level tags, we insert them here
90855 @@ -891,12 +933,18 @@
90856 printk("Suspending console(s) (use no_console_suspend to debug)\n");
90857 acquire_console_sem();
90858 console_suspended = 1;
90859 +#ifdef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90860 + up(&console_sem);
90861 +#endif
90862 }
90863
90864 void resume_console(void)
90865 {
90866 if (!console_suspend_enabled)
90867 return;
90868 +#ifdef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90869 + down(&console_sem);
90870 +#endif
90871 console_suspended = 0;
90872 release_console_sem();
90873 }
90874 @@ -912,11 +960,17 @@
90875 void acquire_console_sem(void)
90876 {
90877 BUG_ON(in_interrupt());
90878 +#ifndef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90879 if (console_suspended) {
90880 down(&secondary_console_sem);
90881 return;
90882 }
90883 +#endif
90884 down(&console_sem);
90885 +#ifdef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90886 + if (console_suspended)
90887 + return;
90888 +#endif
90889 console_locked = 1;
90890 console_may_schedule = 1;
90891 }
90892 @@ -926,6 +980,12 @@
90893 {
90894 if (down_trylock(&console_sem))
90895 return -1;
90896 +#ifdef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90897 + if (console_suspended) {
90898 + up(&console_sem);
90899 + return -1;
90900 + }
90901 +#endif
90902 console_locked = 1;
90903 console_may_schedule = 0;
90904 return 0;
90905 @@ -979,7 +1039,11 @@
90906 unsigned wake_klogd = 0;
90907
90908 if (console_suspended) {
90909 +#ifdef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90910 + up(&console_sem);
90911 +#else
90912 up(&secondary_console_sem);
90913 +#endif
90914 return;
90915 }
90916
90917 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/kernel/timer.c linux-2.6.29-rc3.owrt.om/kernel/timer.c
90918 --- linux-2.6.29-rc3.owrt/kernel/timer.c 2009-05-10 22:05:04.000000000 +0200
90919 +++ linux-2.6.29-rc3.owrt.om/kernel/timer.c 2009-05-10 22:28:00.000000000 +0200
90920 @@ -813,7 +813,6 @@
90921 * don't have to detach them individually.
90922 */
90923 list_for_each_entry_safe(timer, tmp, &tv_list, entry) {
90924 - BUG_ON(tbase_get_base(timer->base) != base);
90925 internal_add_timer(base, timer);
90926 }
90927
90928 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/lib/Kconfig.debug linux-2.6.29-rc3.owrt.om/lib/Kconfig.debug
90929 --- linux-2.6.29-rc3.owrt/lib/Kconfig.debug 2009-05-10 22:09:09.000000000 +0200
90930 +++ linux-2.6.29-rc3.owrt.om/lib/Kconfig.debug 2009-05-10 22:28:00.000000000 +0200
90931 @@ -847,6 +847,13 @@
90932
90933 Say N if you are unsure.
90934
90935 +config FIND_IRQ_BLOCKERS
90936 + bool "IRQ Blocker statistics"
90937 + depends on ARM
90938 + ---help---
90939 + Enables tracking of IRQ dead-time because something has
90940 + disabled interrupts
90941 +
90942 config DYNAMIC_PRINTK_DEBUG
90943 bool "Enable dynamic printk() call support"
90944 default n
90945 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/MAINTAINERS linux-2.6.29-rc3.owrt.om/MAINTAINERS
90946 --- linux-2.6.29-rc3.owrt/MAINTAINERS 2009-05-10 22:09:09.000000000 +0200
90947 +++ linux-2.6.29-rc3.owrt.om/MAINTAINERS 2009-05-10 22:28:00.000000000 +0200
90948 @@ -1711,6 +1711,20 @@
90949 P: Matthew Wilcox
90950 M: matthew@wil.cx
90951 L: linux-fsdevel@vger.kernel.org
90952 +
90953 +FIC/OPENMOKO NEO1973 GSM PHONE
90954 +P: Harald Welte
90955 +M: laforge@openmoko.org
90956 +L: openmoko-kernel@lists.openmoko.org
90957 +W: http://wiki.openmoko.org/wiki/Kernel
90958 +W: http://wiki.openmoko.org/wiki/Neo1973
90959 +S: Maintained
90960 +
90961 +FRAMEBUFFER LAYER
90962 +P: Antonino Daplas
90963 +M: adaplas@gmail.com
90964 +L: linux-fbdev-devel@lists.sourceforge.net (moderated for non-subscribers)
90965 +W: http://linux-fbdev.sourceforge.net/
90966 S: Maintained
90967
90968 FILESYSTEMS (VFS and infrastructure)
90969 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/makerecovery linux-2.6.29-rc3.owrt.om/makerecovery
90970 --- linux-2.6.29-rc3.owrt/makerecovery 1970-01-01 01:00:00.000000000 +0100
90971 +++ linux-2.6.29-rc3.owrt.om/makerecovery 2009-05-10 22:28:00.000000000 +0200
90972 @@ -0,0 +1,17 @@
90973 +#!/bin/sh
90974 +#
90975 +# make 6MB recovery image from two moredrivers type kernels
90976 +# placed at start and at +4MBytes
90977 +
90978 +if [ -z "$1" ] ; then
90979 + echo "Usage: $0 uImage-moredrivers-..."
90980 + exit 1
90981 +fi
90982 +cat $1 > recovery-$1
90983 +SIZE=`ls -l $1 | tr -s ' ' ' ' | cut -d' ' -f5`
90984 +SPACE=$(( 4 * 1024 * 1024 - $SIZE ))
90985 +dd if=/dev/zero of=_spacer bs=1 count=$SPACE
90986 +cat _spacer >> recovery-$1
90987 +rm -f _spacer
90988 +cat $1 >> recovery-$1
90989 +
90990 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/mm/ashmem.c linux-2.6.29-rc3.owrt.om/mm/ashmem.c
90991 --- linux-2.6.29-rc3.owrt/mm/ashmem.c 1970-01-01 01:00:00.000000000 +0100
90992 +++ linux-2.6.29-rc3.owrt.om/mm/ashmem.c 2009-05-10 22:28:00.000000000 +0200
90993 @@ -0,0 +1,657 @@
90994 +/* drivers/android/ashmem.c
90995 +**
90996 +** Android / Anonymous Shared Memory Subsystem, ashmem
90997 +**
90998 +** Copyright (C) 2008 Google, Inc.
90999 +**
91000 +** Robert Love <rlove@google.com>
91001 +**
91002 +** This software is licensed under the terms of the GNU General Public
91003 +** License version 2, as published by the Free Software Foundation, and
91004 +** may be copied, distributed, and modified under those terms.
91005 +**
91006 +** This program is distributed in the hope that it will be useful,
91007 +** but WITHOUT ANY WARRANTY; without even the implied warranty of
91008 +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
91009 +** GNU General Public License for more details.
91010 +*/
91011 +
91012 +#include <linux/module.h>
91013 +#include <linux/file.h>
91014 +#include <linux/fs.h>
91015 +#include <linux/miscdevice.h>
91016 +#include <linux/security.h>
91017 +#include <linux/mm.h>
91018 +#include <linux/mman.h>
91019 +#include <linux/uaccess.h>
91020 +#include <linux/personality.h>
91021 +#include <linux/bitops.h>
91022 +#include <linux/mutex.h>
91023 +#include <linux/shmem_fs.h>
91024 +#include <linux/ashmem.h>
91025 +
91026 +/*
91027 + * ashmem_area - android shared memory area
91028 + * Lifecycle: From our parent file's open() until its release()
91029 + * Locking: Protected by `ashmem_mutex'
91030 + * Big Note: Mappings do NOT pin this structure; it dies on close()
91031 + */
91032 +struct ashmem_area {
91033 + char name[ASHMEM_NAME_LEN]; /* optional name for /proc/pid/maps */
91034 + struct list_head unpinned_list; /* list of all ashmem areas */
91035 + struct file *file; /* the shmem-based backing file */
91036 + size_t size; /* size of the mapping, in bytes */
91037 + unsigned long prot_mask; /* allowed prot bits, as vm_flags */
91038 +};
91039 +
91040 +/*
91041 + * ashmem_range - represents an interval of unpinned (evictable) pages
91042 + * Lifecycle: From unpin to pin
91043 + * Locking: Protected by `ashmem_mutex'
91044 + */
91045 +struct ashmem_range {
91046 + struct list_head lru; /* entry in LRU list */
91047 + struct list_head unpinned; /* entry in its area's unpinned list */
91048 + struct ashmem_area *asma; /* associated area */
91049 + size_t pgstart; /* starting page, inclusive */
91050 + size_t pgend; /* ending page, inclusive */
91051 + unsigned int purged; /* ASHMEM_NOT or ASHMEM_WAS_PURGED */
91052 +};
91053 +
91054 +/* LRU list of unpinned pages, protected by ashmem_mutex */
91055 +static LIST_HEAD(ashmem_lru_list);
91056 +
91057 +/* Count of pages on our LRU list, protected by ashmem_mutex */
91058 +static unsigned long lru_count;
91059 +
91060 +/*
91061 + * ashmem_mutex - protects the list of and each individual ashmem_area
91062 + *
91063 + * Lock Ordering: ashmex_mutex -> i_mutex -> i_alloc_sem
91064 + */
91065 +static DEFINE_MUTEX(ashmem_mutex);
91066 +
91067 +static struct kmem_cache *ashmem_area_cachep __read_mostly;
91068 +static struct kmem_cache *ashmem_range_cachep __read_mostly;
91069 +
91070 +#define range_size(range) \
91071 + ((range)->pgend - (range)->pgstart + 1)
91072 +
91073 +#define range_on_lru(range) \
91074 + ((range)->purged == ASHMEM_NOT_PURGED)
91075 +
91076 +#define page_range_subsumes_range(range, start, end) \
91077 + (((range)->pgstart >= (start)) && ((range)->pgend <= (end)))
91078 +
91079 +#define page_range_subsumed_by_range(range, start, end) \
91080 + (((range)->pgstart <= (start)) && ((range)->pgend >= (end)))
91081 +
91082 +#define page_in_range(range, page) \
91083 + (((range)->pgstart <= (page)) && ((range)->pgend >= (page)))
91084 +
91085 +#define page_range_in_range(range, start, end) \
91086 + (page_in_range(range, start) || page_in_range(range, end) || \
91087 + page_range_subsumes_range(range, start, end))
91088 +
91089 +#define range_before_page(range, page) \
91090 + ((range)->pgend < (page))
91091 +
91092 +#define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE)
91093 +
91094 +static inline void lru_add(struct ashmem_range *range)
91095 +{
91096 + list_add_tail(&range->lru, &ashmem_lru_list);
91097 + lru_count += range_size(range);
91098 +}
91099 +
91100 +static inline void lru_del(struct ashmem_range *range)
91101 +{
91102 + list_del(&range->lru);
91103 + lru_count -= range_size(range);
91104 +}
91105 +
91106 +/*
91107 + * range_alloc - allocate and initialize a new ashmem_range structure
91108 + *
91109 + * 'asma' - associated ashmem_area
91110 + * 'prev_range' - the previous ashmem_range in the sorted asma->unpinned list
91111 + * 'purged' - initial purge value (ASMEM_NOT_PURGED or ASHMEM_WAS_PURGED)
91112 + * 'start' - starting page, inclusive
91113 + * 'end' - ending page, inclusive
91114 + *
91115 + * Caller must hold ashmem_mutex.
91116 + */
91117 +static int range_alloc(struct ashmem_area *asma,
91118 + struct ashmem_range *prev_range, unsigned int purged,
91119 + size_t start, size_t end)
91120 +{
91121 + struct ashmem_range *range;
91122 +
91123 + range = kmem_cache_zalloc(ashmem_range_cachep, GFP_KERNEL);
91124 + if (unlikely(!range))
91125 + return -ENOMEM;
91126 +
91127 + range->asma = asma;
91128 + range->pgstart = start;
91129 + range->pgend = end;
91130 + range->purged = purged;
91131 +
91132 + list_add_tail(&range->unpinned, &prev_range->unpinned);
91133 +
91134 + if (range_on_lru(range))
91135 + lru_add(range);
91136 +
91137 + return 0;
91138 +}
91139 +
91140 +static void range_del(struct ashmem_range *range)
91141 +{
91142 + list_del(&range->unpinned);
91143 + if (range_on_lru(range))
91144 + lru_del(range);
91145 + kmem_cache_free(ashmem_range_cachep, range);
91146 +}
91147 +
91148 +/*
91149 + * range_shrink - shrinks a range
91150 + *
91151 + * Caller must hold ashmem_mutex.
91152 + */
91153 +static inline void range_shrink(struct ashmem_range *range,
91154 + size_t start, size_t end)
91155 +{
91156 + size_t pre = range_size(range);
91157 +
91158 + range->pgstart = start;
91159 + range->pgend = end;
91160 +
91161 + if (range_on_lru(range))
91162 + lru_count -= pre - range_size(range);
91163 +}
91164 +
91165 +static int ashmem_open(struct inode *inode, struct file *file)
91166 +{
91167 + struct ashmem_area *asma;
91168 + int ret;
91169 +
91170 + ret = nonseekable_open(inode, file);
91171 + if (unlikely(ret))
91172 + return ret;
91173 +
91174 + asma = kmem_cache_zalloc(ashmem_area_cachep, GFP_KERNEL);
91175 + if (unlikely(!asma))
91176 + return -ENOMEM;
91177 +
91178 + INIT_LIST_HEAD(&asma->unpinned_list);
91179 + asma->prot_mask = PROT_MASK;
91180 + file->private_data = asma;
91181 +
91182 + return 0;
91183 +}
91184 +
91185 +static int ashmem_release(struct inode *ignored, struct file *file)
91186 +{
91187 + struct ashmem_area *asma = file->private_data;
91188 + struct ashmem_range *range, *next;
91189 +
91190 + mutex_lock(&ashmem_mutex);
91191 + list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned)
91192 + range_del(range);
91193 + mutex_unlock(&ashmem_mutex);
91194 +
91195 + if (asma->file)
91196 + fput(asma->file);
91197 + kmem_cache_free(ashmem_area_cachep, asma);
91198 +
91199 + return 0;
91200 +}
91201 +
91202 +static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
91203 +{
91204 + struct ashmem_area *asma = file->private_data;
91205 + int ret = 0;
91206 +
91207 + mutex_lock(&ashmem_mutex);
91208 +
91209 + /* user needs to SET_SIZE before mapping */
91210 + if (unlikely(!asma->size)) {
91211 + ret = -EINVAL;
91212 + goto out;
91213 + }
91214 +
91215 + /* requested protection bits must match our allowed protection mask */
91216 + if (unlikely((vma->vm_flags & ~asma->prot_mask) & PROT_MASK)) {
91217 + ret = -EPERM;
91218 + goto out;
91219 + }
91220 +
91221 + if (!asma->file) {
91222 + char *name = ASHMEM_NAME_DEF;
91223 + struct file *vmfile;
91224 +
91225 + if (asma->name[0] != '\0')
91226 + name = asma->name;
91227 +
91228 + /* ... and allocate the backing shmem file */
91229 + vmfile = shmem_file_setup(name, asma->size, vma->vm_flags);
91230 + if (unlikely(IS_ERR(vmfile))) {
91231 + ret = PTR_ERR(vmfile);
91232 + goto out;
91233 + }
91234 + asma->file = vmfile;
91235 + }
91236 + get_file(asma->file);
91237 +
91238 + shmem_set_file(vma, asma->file);
91239 + vma->vm_flags |= VM_CAN_NONLINEAR;
91240 +
91241 +out:
91242 + mutex_unlock(&ashmem_mutex);
91243 + return ret;
91244 +}
91245 +
91246 +/*
91247 + * ashmem_shrink - our cache shrinker, called from mm/vmscan.c :: shrink_slab
91248 + *
91249 + * 'nr_to_scan' is the number of objects (pages) to prune, or 0 to query how
91250 + * many objects (pages) we have in total.
91251 + *
91252 + * 'gfp_mask' is the mask of the allocation that got us into this mess.
91253 + *
91254 + * Return value is the number of objects (pages) remaining, or -1 if we cannot
91255 + * proceed without risk of deadlock (due to gfp_mask).
91256 + *
91257 + * We approximate LRU via least-recently-unpinned, jettisoning unpinned partial
91258 + * chunks of ashmem regions LRU-wise one-at-a-time until we hit 'nr_to_scan'
91259 + * pages freed.
91260 + */
91261 +static int ashmem_shrink(int nr_to_scan, gfp_t gfp_mask)
91262 +{
91263 + struct ashmem_range *range, *next;
91264 +
91265 + /* We might recurse into filesystem code, so bail out if necessary */
91266 + if (nr_to_scan && !(gfp_mask & __GFP_FS))
91267 + return -1;
91268 + if (!nr_to_scan)
91269 + return lru_count;
91270 +
91271 + mutex_lock(&ashmem_mutex);
91272 + list_for_each_entry_safe(range, next, &ashmem_lru_list, lru) {
91273 + struct inode *inode = range->asma->file->f_dentry->d_inode;
91274 + loff_t start = range->pgstart * PAGE_SIZE;
91275 + loff_t end = (range->pgend + 1) * PAGE_SIZE - 1;
91276 +
91277 + vmtruncate_range(inode, start, end);
91278 + range->purged = ASHMEM_WAS_PURGED;
91279 + lru_del(range);
91280 +
91281 + nr_to_scan -= range_size(range);
91282 + if (nr_to_scan <= 0)
91283 + break;
91284 + }
91285 + mutex_unlock(&ashmem_mutex);
91286 +
91287 + return lru_count;
91288 +}
91289 +
91290 +static struct shrinker ashmem_shrinker = {
91291 + .shrink = ashmem_shrink,
91292 + .seeks = DEFAULT_SEEKS * 4,
91293 +};
91294 +
91295 +static int set_prot_mask(struct ashmem_area *asma, unsigned long prot)
91296 +{
91297 + int ret = 0;
91298 +
91299 + mutex_lock(&ashmem_mutex);
91300 +
91301 + /* the user can only remove, not add, protection bits */
91302 + if (unlikely((asma->prot_mask & prot) != prot)) {
91303 + ret = -EINVAL;
91304 + goto out;
91305 + }
91306 +
91307 + /* does the application expect PROT_READ to imply PROT_EXEC? */
91308 + if ((prot & PROT_READ) && (current->personality & READ_IMPLIES_EXEC))
91309 + prot |= PROT_EXEC;
91310 +
91311 + asma->prot_mask = prot;
91312 +
91313 +out:
91314 + mutex_unlock(&ashmem_mutex);
91315 + return ret;
91316 +}
91317 +
91318 +static int set_name(struct ashmem_area *asma, void __user *name)
91319 +{
91320 + int ret = 0;
91321 +
91322 + mutex_lock(&ashmem_mutex);
91323 +
91324 + /* cannot change an existing mapping's name */
91325 + if (unlikely(asma->file)) {
91326 + ret = -EINVAL;
91327 + goto out;
91328 + }
91329 +
91330 + if (unlikely(copy_from_user(asma->name, name, ASHMEM_NAME_LEN)))
91331 + ret = -EFAULT;
91332 + asma->name[ASHMEM_NAME_LEN-1] = '\0';
91333 +
91334 +out:
91335 + mutex_unlock(&ashmem_mutex);
91336 +
91337 + return ret;
91338 +}
91339 +
91340 +static int get_name(struct ashmem_area *asma, void __user *name)
91341 +{
91342 + int ret = 0;
91343 +
91344 + mutex_lock(&ashmem_mutex);
91345 + if (asma->name[0] != '\0') {
91346 + size_t len;
91347 +
91348 + /*
91349 + * Copying only `len', instead of ASHMEM_NAME_LEN, bytes
91350 + * prevents us from revealing one user's stack to another.
91351 + */
91352 + len = strlen(asma->name) + 1;
91353 + if (unlikely(copy_to_user(name, asma->name, len)))
91354 + ret = -EFAULT;
91355 + } else {
91356 + if (unlikely(copy_to_user(name, ASHMEM_NAME_DEF,
91357 + sizeof(ASHMEM_NAME_DEF))))
91358 + ret = -EFAULT;
91359 + }
91360 + mutex_unlock(&ashmem_mutex);
91361 +
91362 + return ret;
91363 +}
91364 +
91365 +/*
91366 + * ashmem_pin - pin the given ashmem region, returning whether it was
91367 + * previously purged (ASHMEM_WAS_PURGED) or not (ASHMEM_NOT_PURGED).
91368 + *
91369 + * Caller must hold ashmem_mutex.
91370 + */
91371 +static int ashmem_pin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
91372 +{
91373 + struct ashmem_range *range, *next;
91374 + int ret = ASHMEM_NOT_PURGED;
91375 +
91376 + list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) {
91377 + /* moved past last applicable page; we can short circuit */
91378 + if (range_before_page(range, pgstart))
91379 + break;
91380 +
91381 + /*
91382 + * The user can ask us to pin pages that span multiple ranges,
91383 + * or to pin pages that aren't even unpinned, so this is messy.
91384 + *
91385 + * Four cases:
91386 + * 1. The requested range subsumes an existing range, so we
91387 + * just remove the entire matching range.
91388 + * 2. The requested range overlaps the start of an existing
91389 + * range, so we just update that range.
91390 + * 3. The requested range overlaps the end of an existing
91391 + * range, so we just update that range.
91392 + * 4. The requested range punches a hole in an existing range,
91393 + * so we have to update one side of the range and then
91394 + * create a new range for the other side.
91395 + */
91396 + if (page_range_in_range(range, pgstart, pgend)) {
91397 + ret |= range->purged;
91398 +
91399 + /* Case #1: Easy. Just nuke the whole thing. */
91400 + if (page_range_subsumes_range(range, pgstart, pgend)) {
91401 + range_del(range);
91402 + continue;
91403 + }
91404 +
91405 + /* Case #2: We overlap from the start, so adjust it */
91406 + if (range->pgstart >= pgstart) {
91407 + range_shrink(range, pgend + 1, range->pgend);
91408 + continue;
91409 + }
91410 +
91411 + /* Case #3: We overlap from the rear, so adjust it */
91412 + if (range->pgend <= pgend) {
91413 + range_shrink(range, range->pgstart, pgstart-1);
91414 + continue;
91415 + }
91416 +
91417 + /*
91418 + * Case #4: We eat a chunk out of the middle. A bit
91419 + * more complicated, we allocate a new range for the
91420 + * second half and adjust the first chunk's endpoint.
91421 + */
91422 + range_alloc(asma, range, range->purged,
91423 + pgend + 1, range->pgend);
91424 + range_shrink(range, range->pgstart, pgstart - 1);
91425 + break;
91426 + }
91427 + }
91428 +
91429 + return ret;
91430 +}
91431 +
91432 +/*
91433 + * ashmem_unpin - unpin the given range of pages. Returns zero on success.
91434 + *
91435 + * Caller must hold ashmem_mutex.
91436 + */
91437 +static int ashmem_unpin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
91438 +{
91439 + struct ashmem_range *range, *next;
91440 + unsigned int purged = ASHMEM_NOT_PURGED;
91441 +
91442 +restart:
91443 + list_for_each_entry_safe(range, next, &asma->unpinned_list, unpinned) {
91444 + /* short circuit: this is our insertion point */
91445 + if (range_before_page(range, pgstart))
91446 + break;
91447 +
91448 + /*
91449 + * The user can ask us to unpin pages that are already entirely
91450 + * or partially pinned. We handle those two cases here.
91451 + */
91452 + if (page_range_subsumed_by_range(range, pgstart, pgend))
91453 + return 0;
91454 + if (page_range_in_range(range, pgstart, pgend)) {
91455 + pgstart = min_t(size_t, range->pgstart, pgstart),
91456 + pgend = max_t(size_t, range->pgend, pgend);
91457 + purged |= range->purged;
91458 + range_del(range);
91459 + goto restart;
91460 + }
91461 + }
91462 +
91463 + return range_alloc(asma, range, purged, pgstart, pgend);
91464 +}
91465 +
91466 +/*
91467 + * ashmem_get_pin_status - Returns ASHMEM_IS_UNPINNED if _any_ pages in the
91468 + * given interval are unpinned and ASHMEM_IS_PINNED otherwise.
91469 + *
91470 + * Caller must hold ashmem_mutex.
91471 + */
91472 +static int ashmem_get_pin_status(struct ashmem_area *asma, size_t pgstart,
91473 + size_t pgend)
91474 +{
91475 + struct ashmem_range *range;
91476 + int ret = ASHMEM_IS_PINNED;
91477 +
91478 + list_for_each_entry(range, &asma->unpinned_list, unpinned) {
91479 + if (range_before_page(range, pgstart))
91480 + break;
91481 + if (page_range_in_range(range, pgstart, pgend)) {
91482 + ret = ASHMEM_IS_UNPINNED;
91483 + break;
91484 + }
91485 + }
91486 +
91487 + return ret;
91488 +}
91489 +
91490 +static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
91491 + void __user *p)
91492 +{
91493 + struct ashmem_pin pin;
91494 + size_t pgstart, pgend;
91495 + int ret = -EINVAL;
91496 +
91497 + if (unlikely(!asma->file))
91498 + return -EINVAL;
91499 +
91500 + if (unlikely(copy_from_user(&pin, p, sizeof(pin))))
91501 + return -EFAULT;
91502 +
91503 + /* per custom, you can pass zero for len to mean "everything onward" */
91504 + if (!pin.len)
91505 + pin.len = asma->size - pin.offset;
91506 +
91507 + if (unlikely((pin.offset | pin.len) & ~PAGE_MASK))
91508 + return -EINVAL;
91509 +
91510 + if (unlikely(((__u32) -1) - pin.offset < pin.len))
91511 + return -EINVAL;
91512 +
91513 + if (unlikely(asma->size < pin.offset + pin.len))
91514 + return -EINVAL;
91515 +
91516 + pgstart = pin.offset / PAGE_SIZE;
91517 + pgend = pgstart + (pin.len / PAGE_SIZE) - 1;
91518 +
91519 + mutex_lock(&ashmem_mutex);
91520 +
91521 + switch (cmd) {
91522 + case ASHMEM_PIN:
91523 + ret = ashmem_pin(asma, pgstart, pgend);
91524 + break;
91525 + case ASHMEM_UNPIN:
91526 + ret = ashmem_unpin(asma, pgstart, pgend);
91527 + break;
91528 + case ASHMEM_GET_PIN_STATUS:
91529 + ret = ashmem_get_pin_status(asma, pgstart, pgend);
91530 + break;
91531 + }
91532 +
91533 + mutex_unlock(&ashmem_mutex);
91534 +
91535 + return ret;
91536 +}
91537 +
91538 +static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
91539 +{
91540 + struct ashmem_area *asma = file->private_data;
91541 + long ret = -ENOTTY;
91542 +
91543 + switch (cmd) {
91544 + case ASHMEM_SET_NAME:
91545 + ret = set_name(asma, (void __user *) arg);
91546 + break;
91547 + case ASHMEM_GET_NAME:
91548 + ret = get_name(asma, (void __user *) arg);
91549 + break;
91550 + case ASHMEM_SET_SIZE:
91551 + ret = -EINVAL;
91552 + if (!asma->file && !(arg & ~PAGE_MASK)) {
91553 + ret = 0;
91554 + asma->size = (size_t) arg;
91555 + }
91556 + break;
91557 + case ASHMEM_GET_SIZE:
91558 + ret = asma->size;
91559 + break;
91560 + case ASHMEM_SET_PROT_MASK:
91561 + ret = set_prot_mask(asma, arg);
91562 + break;
91563 + case ASHMEM_GET_PROT_MASK:
91564 + ret = asma->prot_mask;
91565 + break;
91566 + case ASHMEM_PIN:
91567 + case ASHMEM_UNPIN:
91568 + case ASHMEM_GET_PIN_STATUS:
91569 + ret = ashmem_pin_unpin(asma, cmd, (void __user *) arg);
91570 + break;
91571 + case ASHMEM_PURGE_ALL_CACHES:
91572 + ret = -EPERM;
91573 + if (capable(CAP_SYS_ADMIN)) {
91574 + ret = ashmem_shrink(0, GFP_KERNEL);
91575 + ashmem_shrink(ret, GFP_KERNEL);
91576 + }
91577 + break;
91578 + }
91579 +
91580 + return ret;
91581 +}
91582 +
91583 +static struct file_operations ashmem_fops = {
91584 + .owner = THIS_MODULE,
91585 + .open = ashmem_open,
91586 + .release = ashmem_release,
91587 + .mmap = ashmem_mmap,
91588 + .unlocked_ioctl = ashmem_ioctl,
91589 + .compat_ioctl = ashmem_ioctl,
91590 +};
91591 +
91592 +static struct miscdevice ashmem_misc = {
91593 + .minor = MISC_DYNAMIC_MINOR,
91594 + .name = "ashmem",
91595 + .fops = &ashmem_fops,
91596 +};
91597 +
91598 +static int __init ashmem_init(void)
91599 +{
91600 + int ret;
91601 +
91602 + ashmem_area_cachep = kmem_cache_create("ashmem_area_cache",
91603 + sizeof(struct ashmem_area),
91604 + 0, 0, NULL);
91605 + if (unlikely(!ashmem_area_cachep)) {
91606 + printk(KERN_ERR "ashmem: failed to create slab cache\n");
91607 + return -ENOMEM;
91608 + }
91609 +
91610 + ashmem_range_cachep = kmem_cache_create("ashmem_range_cache",
91611 + sizeof(struct ashmem_range),
91612 + 0, 0, NULL);
91613 + if (unlikely(!ashmem_range_cachep)) {
91614 + printk(KERN_ERR "ashmem: failed to create slab cache\n");
91615 + return -ENOMEM;
91616 + }
91617 +
91618 + ret = misc_register(&ashmem_misc);
91619 + if (unlikely(ret)) {
91620 + printk(KERN_ERR "ashmem: failed to register misc device!\n");
91621 + return ret;
91622 + }
91623 +
91624 + register_shrinker(&ashmem_shrinker);
91625 +
91626 + printk(KERN_INFO "ashmem: initialized\n");
91627 +
91628 + return 0;
91629 +}
91630 +
91631 +static void __exit ashmem_exit(void)
91632 +{
91633 + int ret;
91634 +
91635 + unregister_shrinker(&ashmem_shrinker);
91636 +
91637 + ret = misc_deregister(&ashmem_misc);
91638 + if (unlikely(ret))
91639 + printk(KERN_ERR "ashmem: failed to unregister misc device!\n");
91640 +
91641 + kmem_cache_destroy(ashmem_range_cachep);
91642 + kmem_cache_destroy(ashmem_area_cachep);
91643 +
91644 + printk(KERN_INFO "ashmem: unloaded\n");
91645 +}
91646 +
91647 +module_init(ashmem_init);
91648 +module_exit(ashmem_exit);
91649 +
91650 +MODULE_LICENSE("GPL");
91651 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/mm/Makefile linux-2.6.29-rc3.owrt.om/mm/Makefile
91652 --- linux-2.6.29-rc3.owrt/mm/Makefile 2009-05-10 22:04:53.000000000 +0200
91653 +++ linux-2.6.29-rc3.owrt.om/mm/Makefile 2009-05-10 22:28:00.000000000 +0200
91654 @@ -21,6 +21,8 @@
91655 obj-$(CONFIG_NUMA) += mempolicy.o
91656 obj-$(CONFIG_SPARSEMEM) += sparse.o
91657 obj-$(CONFIG_SPARSEMEM_VMEMMAP) += sparse-vmemmap.o
91658 +obj-$(CONFIG_SHMEM) += shmem.o
91659 +obj-$(CONFIG_ASHMEM) += ashmem.o
91660 obj-$(CONFIG_TMPFS_POSIX_ACL) += shmem_acl.o
91661 obj-$(CONFIG_SLOB) += slob.o
91662 obj-$(CONFIG_MMU_NOTIFIER) += mmu_notifier.o
91663 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/mm/tiny-shmem.c linux-2.6.29-rc3.owrt.om/mm/tiny-shmem.c
91664 --- linux-2.6.29-rc3.owrt/mm/tiny-shmem.c 1970-01-01 01:00:00.000000000 +0100
91665 +++ linux-2.6.29-rc3.owrt.om/mm/tiny-shmem.c 2009-05-10 22:28:00.000000000 +0200
91666 @@ -0,0 +1,148 @@
91667 +/*
91668 + * tiny-shmem.c: simple shmemfs and tmpfs using ramfs code
91669 + *
91670 + * Matt Mackall <mpm@selenic.com> January, 2004
91671 + * derived from mm/shmem.c and fs/ramfs/inode.c
91672 + *
91673 + * This is intended for small system where the benefits of the full
91674 + * shmem code (swap-backed and resource-limited) are outweighed by
91675 + * their complexity. On systems without swap this code should be
91676 + * effectively equivalent, but much lighter weight.
91677 + */
91678 +
91679 +#include <linux/fs.h>
91680 +#include <linux/init.h>
91681 +#include <linux/vfs.h>
91682 +#include <linux/mount.h>
91683 +#include <linux/file.h>
91684 +#include <linux/mm.h>
91685 +#include <linux/module.h>
91686 +#include <linux/swap.h>
91687 +#include <linux/ramfs.h>
91688 +
91689 +static struct file_system_type tmpfs_fs_type = {
91690 + .name = "tmpfs",
91691 + .get_sb = ramfs_get_sb,
91692 + .kill_sb = kill_litter_super,
91693 +};
91694 +
91695 +static struct vfsmount *shm_mnt;
91696 +
91697 +static int __init init_tmpfs(void)
91698 +{
91699 + BUG_ON(register_filesystem(&tmpfs_fs_type) != 0);
91700 +
91701 + shm_mnt = kern_mount(&tmpfs_fs_type);
91702 + BUG_ON(IS_ERR(shm_mnt));
91703 +
91704 + return 0;
91705 +}
91706 +module_init(init_tmpfs)
91707 +
91708 +/**
91709 + * shmem_file_setup - get an unlinked file living in tmpfs
91710 + * @name: name for dentry (to be seen in /proc/<pid>/maps
91711 + * @size: size to be set for the file
91712 + * @flags: vm_flags
91713 + */
91714 +struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
91715 +{
91716 + int error;
91717 + struct file *file;
91718 + struct inode *inode;
91719 + struct dentry *dentry, *root;
91720 + struct qstr this;
91721 +
91722 + if (IS_ERR(shm_mnt))
91723 + return (void *)shm_mnt;
91724 +
91725 + error = -ENOMEM;
91726 + this.name = name;
91727 + this.len = strlen(name);
91728 + this.hash = 0; /* will go */
91729 + root = shm_mnt->mnt_root;
91730 + dentry = d_alloc(root, &this);
91731 + if (!dentry)
91732 + goto put_memory;
91733 +
91734 + error = -ENFILE;
91735 + file = get_empty_filp();
91736 + if (!file)
91737 + goto put_dentry;
91738 +
91739 + error = -ENOSPC;
91740 + inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
91741 + if (!inode)
91742 + goto close_file;
91743 +
91744 + d_instantiate(dentry, inode);
91745 + inode->i_size = size;
91746 + inode->i_nlink = 0; /* It is unlinked */
91747 + init_file(file, shm_mnt, dentry, FMODE_WRITE | FMODE_READ,
91748 + &ramfs_file_operations);
91749 +
91750 +#ifndef CONFIG_MMU
91751 + error = ramfs_nommu_expand_for_mapping(inode, size);
91752 + if (error)
91753 + goto close_file;
91754 +#endif
91755 + return file;
91756 +
91757 +close_file:
91758 + put_filp(file);
91759 +put_dentry:
91760 + dput(dentry);
91761 +put_memory:
91762 + return ERR_PTR(error);
91763 +}
91764 +EXPORT_SYMBOL_GPL(shmem_file_setup);
91765 +
91766 +void shmem_set_file(struct vm_area_struct *vma, struct file *file)
91767 +{
91768 + if (vma->vm_file)
91769 + fput(vma->vm_file);
91770 + vma->vm_file = file;
91771 + vma->vm_ops = &generic_file_vm_ops;
91772 +}
91773 +
91774 +void shmem_set_file(struct vm_area_struct *vma, struct file *file)
91775 +{
91776 + if (vma->vm_file)
91777 + fput(vma->vm_file);
91778 + vma->vm_file = file;
91779 + vma->vm_ops = &generic_file_vm_ops;
91780 +}
91781 +
91782 +/**
91783 + * shmem_zero_setup - setup a shared anonymous mapping
91784 + * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
91785 + */
91786 +int shmem_zero_setup(struct vm_area_struct *vma)
91787 +{
91788 + struct file *file;
91789 + loff_t size = vma->vm_end - vma->vm_start;
91790 +
91791 + file = shmem_file_setup("dev/zero", size, vma->vm_flags);
91792 + if (IS_ERR(file))
91793 + return PTR_ERR(file);
91794 +
91795 + shmem_set_file(vma, file);
91796 +
91797 + return 0;
91798 +}
91799 +
91800 +int shmem_unuse(swp_entry_t entry, struct page *page)
91801 +{
91802 + return 0;
91803 +}
91804 +
91805 +#ifndef CONFIG_MMU
91806 +unsigned long shmem_get_unmapped_area(struct file *file,
91807 + unsigned long addr,
91808 + unsigned long len,
91809 + unsigned long pgoff,
91810 + unsigned long flags)
91811 +{
91812 + return ramfs_nommu_get_unmapped_area(file, addr, len, pgoff, flags);
91813 +}
91814 +#endif
91815 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/remote_install_sdcard linux-2.6.29-rc3.owrt.om/remote_install_sdcard
91816 --- linux-2.6.29-rc3.owrt/remote_install_sdcard 1970-01-01 01:00:00.000000000 +0100
91817 +++ linux-2.6.29-rc3.owrt.om/remote_install_sdcard 2009-05-10 22:28:00.000000000 +0200
91818 @@ -0,0 +1,18 @@
91819 +#!/bin/sh
91820 +
91821 +# automatic kernel updater and reboot - Andy Green <andy@openmoko.com>
91822 +
91823 +GTA_DEVICE_IP=192.168.0.202
91824 +
91825 +# you should set up key-based auth on dropbear if you want
91826 +# to play this game.
91827 +#
91828 +# 1) mkdir /home/root/.ssh
91829 +# 2) chown root:root / /home /home/root
91830 +# 3) chmod 700 /home/root /home/root/.ssh
91831 +# 4) copy your id_*.pub into /home/root/.ssh/authorized_keys
91832 +# 5) chmod 600 /home/root/.ssh/*
91833 +
91834 +scp uImage.bin root@$GTA_DEVICE_IP:/boot
91835 +ssh root@$GTA_DEVICE_IP "mount /dev/mmcblk0p1 / -oremount,ro ; reboot -if &"
91836 +
91837 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/scripts/mkuboot.sh linux-2.6.29-rc3.owrt.om/scripts/mkuboot.sh
91838 --- linux-2.6.29-rc3.owrt/scripts/mkuboot.sh 2009-05-10 22:04:48.000000000 +0200
91839 +++ linux-2.6.29-rc3.owrt.om/scripts/mkuboot.sh 2009-05-10 22:28:00.000000000 +0200
91840 @@ -11,7 +11,7 @@
91841 if [ -z "${MKIMAGE}" ]; then
91842 # Doesn't exist
91843 echo '"mkimage" command not found - U-Boot images will not be built' >&2
91844 - exit 0;
91845 + exit 1;
91846 fi
91847 fi
91848
91849 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/codecs/wm8731.c linux-2.6.29-rc3.owrt.om/sound/soc/codecs/wm8731.c
91850 --- linux-2.6.29-rc3.owrt/sound/soc/codecs/wm8731.c 2009-05-10 22:05:01.000000000 +0200
91851 +++ linux-2.6.29-rc3.owrt.om/sound/soc/codecs/wm8731.c 2009-05-10 22:28:00.000000000 +0200
91852 @@ -73,6 +73,8 @@
91853 u16 *cache = codec->reg_cache;
91854 if (reg >= WM8731_CACHEREGNUM)
91855 return;
91856 +
91857 + printk(KERN_INFO "%s: reg %d, val %04x\n", __func__, reg, value);
91858 cache[reg] = value;
91859 }
91860
91861 @@ -84,6 +86,8 @@
91862 {
91863 u8 data[2];
91864
91865 + printk(KERN_INFO "%s: reg %d val %04x\n", __func__, reg, value);
91866 +
91867 /* data is
91868 * D15..D9 WM8731 register offset
91869 * D8...D0 register data
91870 @@ -521,7 +525,11 @@
91871 if (codec->reg_cache == NULL)
91872 return -ENOMEM;
91873
91874 - wm8731_reset(codec);
91875 + ret = wm8731_reset(codec);
91876 + if (ret < 0) {
91877 + printk(KERN_ERR "wm8731: failed to send reset\n");
91878 + return -EIO;
91879 + }
91880
91881 /* register pcms */
91882 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
91883 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/codecs/wm8753.c linux-2.6.29-rc3.owrt.om/sound/soc/codecs/wm8753.c
91884 --- linux-2.6.29-rc3.owrt/sound/soc/codecs/wm8753.c 2009-05-10 22:09:10.000000000 +0200
91885 +++ linux-2.6.29-rc3.owrt.om/sound/soc/codecs/wm8753.c 2009-05-10 22:28:00.000000000 +0200
91886 @@ -51,8 +51,6 @@
91887
91888 #include "wm8753.h"
91889
91890 -#define WM8753_VERSION "0.16"
91891 -
91892 static int caps_charge = 2000;
91893 module_param(caps_charge, int, 0);
91894 MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
91895 @@ -60,12 +58,6 @@
91896 static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
91897 unsigned int mode);
91898
91899 -/* codec private data */
91900 -struct wm8753_priv {
91901 - unsigned int sysclk;
91902 - unsigned int pcmclk;
91903 -};
91904 -
91905 /*
91906 * wm8753 register cache
91907 * We can't read the WM8753 register space when we
91908 @@ -90,6 +82,14 @@
91909 0x0000, 0x0000
91910 };
91911
91912 +/* codec private data */
91913 +struct wm8753_priv {
91914 + unsigned int sysclk;
91915 + unsigned int pcmclk;
91916 + struct snd_soc_codec codec;
91917 + u16 reg_cache[ARRAY_SIZE(wm8753_reg)];
91918 +};
91919 +
91920 /*
91921 * read wm8753 register cache
91922 */
91923 @@ -1451,7 +1451,15 @@
91924 },
91925 };
91926
91927 -struct snd_soc_dai wm8753_dai[2];
91928 +struct snd_soc_dai wm8753_dai[2] = {
91929 + {
91930 + .name = "dummy1"
91931 + },
91932 + {
91933 + .name = "dummy2"
91934 + },
91935 +};
91936 +
91937 EXPORT_SYMBOL_GPL(wm8753_dai);
91938
91939 static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode)
91940 @@ -1459,30 +1467,35 @@
91941 if (mode < 4) {
91942 int playback_active, capture_active, codec_active, pop_wait;
91943 void *private_data;
91944 + struct list_head list;
91945
91946 playback_active = wm8753_dai[0].playback.active;
91947 capture_active = wm8753_dai[0].capture.active;
91948 codec_active = wm8753_dai[0].active;
91949 private_data = wm8753_dai[0].private_data;
91950 pop_wait = wm8753_dai[0].pop_wait;
91951 + list = wm8753_dai[0].list;
91952 wm8753_dai[0] = wm8753_all_dai[mode << 1];
91953 wm8753_dai[0].playback.active = playback_active;
91954 wm8753_dai[0].capture.active = capture_active;
91955 wm8753_dai[0].active = codec_active;
91956 wm8753_dai[0].private_data = private_data;
91957 wm8753_dai[0].pop_wait = pop_wait;
91958 + wm8753_dai[0].list = list;
91959
91960 playback_active = wm8753_dai[1].playback.active;
91961 capture_active = wm8753_dai[1].capture.active;
91962 codec_active = wm8753_dai[1].active;
91963 private_data = wm8753_dai[1].private_data;
91964 pop_wait = wm8753_dai[1].pop_wait;
91965 + list = wm8753_dai[1].list;
91966 wm8753_dai[1] = wm8753_all_dai[(mode << 1) + 1];
91967 wm8753_dai[1].playback.active = playback_active;
91968 wm8753_dai[1].capture.active = capture_active;
91969 wm8753_dai[1].active = codec_active;
91970 wm8753_dai[1].private_data = private_data;
91971 wm8753_dai[1].pop_wait = pop_wait;
91972 + wm8753_dai[1].list = list;
91973 }
91974 wm8753_dai[0].codec = codec;
91975 wm8753_dai[1].codec = codec;
91976 @@ -1524,6 +1537,11 @@
91977 for (i = 0; i < ARRAY_SIZE(wm8753_reg); i++) {
91978 if (i + 1 == WM8753_RESET)
91979 continue;
91980 +
91981 + /* No point in writing hardware default values back */
91982 + if (cache[i] == wm8753_reg[i])
91983 + continue;
91984 +
91985 data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
91986 data[1] = cache[i] & 0x00ff;
91987 codec->hw_write(codec->control_data, data, 2);
91988 @@ -1542,44 +1560,133 @@
91989 return 0;
91990 }
91991
91992 +static struct snd_soc_codec *wm8753_codec;
91993 +
91994 +static int wm8753_probe(struct platform_device *pdev)
91995 +{
91996 + struct snd_soc_device *socdev = platform_get_drvdata(pdev);
91997 + struct snd_soc_codec *codec;
91998 + int ret = 0;
91999 +
92000 + if (!wm8753_codec) {
92001 + dev_err(&pdev->dev, "WM8753 codec not yet registered\n");
92002 + return -EINVAL;
92003 + }
92004 +
92005 + socdev->codec = wm8753_codec;
92006 + codec = wm8753_codec;
92007 +
92008 + wm8753_set_dai_mode(codec, 0);
92009 +
92010 + /* register pcms */
92011 + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
92012 + if (ret < 0) {
92013 + printk(KERN_ERR "wm8753: failed to create pcms\n");
92014 + goto pcm_err;
92015 + }
92016 +
92017 + wm8753_add_controls(codec);
92018 + wm8753_add_widgets(codec);
92019 + ret = snd_soc_init_card(socdev);
92020 + if (ret < 0) {
92021 + printk(KERN_ERR "wm8753: failed to register card\n");
92022 + goto card_err;
92023 + }
92024 +
92025 + return 0;
92026 +
92027 +card_err:
92028 + snd_soc_free_pcms(socdev);
92029 + snd_soc_dapm_free(socdev);
92030 +
92031 +pcm_err:
92032 + return ret;
92033 +}
92034 +
92035 /*
92036 - * initialise the WM8753 driver
92037 - * register the mixer and dsp interfaces with the kernel
92038 + * This function forces any delayed work to be queued and run.
92039 */
92040 -static int wm8753_init(struct snd_soc_device *socdev)
92041 +static int run_delayed_work(struct delayed_work *dwork)
92042 {
92043 - struct snd_soc_codec *codec = socdev->codec;
92044 - int reg, ret = 0;
92045 + int ret;
92046 +
92047 + /* cancel any work waiting to be queued. */
92048 + ret = cancel_delayed_work(dwork);
92049 +
92050 + /* if there was any work waiting then we run it now and
92051 + * wait for it's completion */
92052 + if (ret) {
92053 + schedule_delayed_work(dwork, 0);
92054 + flush_scheduled_work();
92055 + }
92056 + return ret;
92057 +}
92058 +
92059 +/* power down chip */
92060 +static int wm8753_remove(struct platform_device *pdev)
92061 +{
92062 + struct snd_soc_device *socdev = platform_get_drvdata(pdev);
92063 +
92064 + snd_soc_free_pcms(socdev);
92065 + snd_soc_dapm_free(socdev);
92066 +
92067 + return 0;
92068 +}
92069 +
92070 +struct snd_soc_codec_device soc_codec_dev_wm8753 = {
92071 + .probe = wm8753_probe,
92072 + .remove = wm8753_remove,
92073 + .suspend = wm8753_suspend,
92074 + .resume = wm8753_resume,
92075 +};
92076 +EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
92077 +
92078 +static int wm8753_register(struct wm8753_priv *wm8753)
92079 +{
92080 + int ret, i;
92081 + struct snd_soc_codec *codec = &wm8753->codec;
92082 + u16 reg;
92083 +
92084 + if (wm8753_codec) {
92085 + dev_err(codec->dev, "Multiple WM8753 devices not supported\n");
92086 + ret = -EINVAL;
92087 + goto err;
92088 + }
92089 +
92090 + mutex_init(&codec->mutex);
92091 + INIT_LIST_HEAD(&codec->dapm_widgets);
92092 + INIT_LIST_HEAD(&codec->dapm_paths);
92093
92094 codec->name = "WM8753";
92095 codec->owner = THIS_MODULE;
92096 codec->read = wm8753_read_reg_cache;
92097 codec->write = wm8753_write;
92098 + codec->bias_level = SND_SOC_BIAS_STANDBY;
92099 codec->set_bias_level = wm8753_set_bias_level;
92100 codec->dai = wm8753_dai;
92101 codec->num_dai = 2;
92102 - codec->reg_cache_size = ARRAY_SIZE(wm8753_reg);
92103 - codec->reg_cache = kmemdup(wm8753_reg, sizeof(wm8753_reg), GFP_KERNEL);
92104 -
92105 - if (codec->reg_cache == NULL)
92106 - return -ENOMEM;
92107 -
92108 - wm8753_set_dai_mode(codec, 0);
92109 + codec->reg_cache_size = ARRAY_SIZE(wm8753->reg_cache);
92110 + codec->reg_cache = &wm8753->reg_cache;
92111 + codec->private_data = wm8753;
92112
92113 - wm8753_reset(codec);
92114 + memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache));
92115 + INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
92116
92117 - /* register pcms */
92118 - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
92119 + ret = wm8753_reset(codec);
92120 if (ret < 0) {
92121 - printk(KERN_ERR "wm8753: failed to create pcms\n");
92122 - goto pcm_err;
92123 + dev_err(codec->dev, "Failed to issue reset\n");
92124 + goto err;
92125 }
92126
92127 /* charge output caps */
92128 wm8753_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
92129 - codec->bias_level = SND_SOC_BIAS_STANDBY;
92130 schedule_delayed_work(&codec->delayed_work,
92131 - msecs_to_jiffies(caps_charge));
92132 + msecs_to_jiffies(caps_charge));
92133 +
92134 + /* OpenMoko specific bodge for
92135 + * http://bugzilla.openmoko.org/cgi-bin/bugzilla/show_bug.cgi?id=1172
92136 + */
92137 + wm8753_write(codec, WM8753_ADCTL2, 0x0000);
92138
92139 /* set the update bits */
92140 reg = wm8753_read_reg_cache(codec, WM8753_LDAC);
92141 @@ -1603,58 +1710,69 @@
92142 reg = wm8753_read_reg_cache(codec, WM8753_RINVOL);
92143 wm8753_write(codec, WM8753_RINVOL, reg | 0x0100);
92144
92145 - wm8753_add_controls(codec);
92146 - wm8753_add_widgets(codec);
92147 - ret = snd_soc_init_card(socdev);
92148 - if (ret < 0) {
92149 - printk(KERN_ERR "wm8753: failed to register card\n");
92150 - goto card_err;
92151 + wm8753_codec = codec;
92152 +
92153 + for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++)
92154 + wm8753_dai[i].dev = codec->dev;
92155 +
92156 + ret = snd_soc_register_codec(codec);
92157 + if (ret != 0) {
92158 + dev_err(codec->dev, "Failed to register codec: %d\n", ret);
92159 + goto err;
92160 }
92161
92162 - return ret;
92163 + ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
92164 + if (ret != 0) {
92165 + dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
92166 + goto err_codec;
92167 + }
92168
92169 -card_err:
92170 - snd_soc_free_pcms(socdev);
92171 - snd_soc_dapm_free(socdev);
92172 -pcm_err:
92173 - kfree(codec->reg_cache);
92174 + return 0;
92175 +
92176 +err_codec:
92177 + run_delayed_work(&codec->delayed_work);
92178 + snd_soc_unregister_codec(codec);
92179 +err:
92180 + kfree(wm8753);
92181 return ret;
92182 }
92183
92184 -/* If the i2c layer weren't so broken, we could pass this kind of data
92185 - around */
92186 -static struct snd_soc_device *wm8753_socdev;
92187 +static void wm8753_unregister(struct wm8753_priv *wm8753)
92188 +{
92189 + wm8753_set_bias_level(&wm8753->codec, SND_SOC_BIAS_OFF);
92190 + run_delayed_work(&wm8753->codec.delayed_work);
92191 + snd_soc_unregister_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
92192 + snd_soc_unregister_codec(&wm8753->codec);
92193 + kfree(wm8753);
92194 + wm8753_codec = NULL;
92195 +}
92196
92197 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
92198
92199 -/*
92200 - * WM8753 2 wire address is determined by GPIO5
92201 - * state during powerup.
92202 - * low = 0x1a
92203 - * high = 0x1b
92204 - */
92205 -
92206 static int wm8753_i2c_probe(struct i2c_client *i2c,
92207 const struct i2c_device_id *id)
92208 {
92209 - struct snd_soc_device *socdev = wm8753_socdev;
92210 - struct snd_soc_codec *codec = socdev->codec;
92211 - int ret;
92212 + struct snd_soc_codec *codec;
92213 + struct wm8753_priv *wm8753;
92214
92215 - i2c_set_clientdata(i2c, codec);
92216 + wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
92217 + if (wm8753 == NULL)
92218 + return -ENOMEM;
92219 +
92220 + codec = &wm8753->codec;
92221 + codec->hw_write = (hw_write_t)i2c_master_send;
92222 codec->control_data = i2c;
92223 + i2c_set_clientdata(i2c, wm8753);
92224
92225 - ret = wm8753_init(socdev);
92226 - if (ret < 0)
92227 - pr_err("failed to initialise WM8753\n");
92228 + codec->dev = &i2c->dev;
92229
92230 - return ret;
92231 + return wm8753_register(wm8753);
92232 }
92233
92234 static int wm8753_i2c_remove(struct i2c_client *client)
92235 {
92236 - struct snd_soc_codec *codec = i2c_get_clientdata(client);
92237 - kfree(codec->reg_cache);
92238 + struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
92239 + wm8753_unregister(wm8753);
92240 return 0;
92241 }
92242
92243 @@ -1666,86 +1784,16 @@
92244
92245 static struct i2c_driver wm8753_i2c_driver = {
92246 .driver = {
92247 - .name = "WM8753 I2C Codec",
92248 + .name = "wm8753",
92249 .owner = THIS_MODULE,
92250 },
92251 .probe = wm8753_i2c_probe,
92252 .remove = wm8753_i2c_remove,
92253 .id_table = wm8753_i2c_id,
92254 };
92255 -
92256 -static int wm8753_add_i2c_device(struct platform_device *pdev,
92257 - const struct wm8753_setup_data *setup)
92258 -{
92259 - struct i2c_board_info info;
92260 - struct i2c_adapter *adapter;
92261 - struct i2c_client *client;
92262 - int ret;
92263 -
92264 - ret = i2c_add_driver(&wm8753_i2c_driver);
92265 - if (ret != 0) {
92266 - dev_err(&pdev->dev, "can't add i2c driver\n");
92267 - return ret;
92268 - }
92269 -
92270 - memset(&info, 0, sizeof(struct i2c_board_info));
92271 - info.addr = setup->i2c_address;
92272 - strlcpy(info.type, "wm8753", I2C_NAME_SIZE);
92273 -
92274 - adapter = i2c_get_adapter(setup->i2c_bus);
92275 - if (!adapter) {
92276 - dev_err(&pdev->dev, "can't get i2c adapter %d\n",
92277 - setup->i2c_bus);
92278 - goto err_driver;
92279 - }
92280 -
92281 - client = i2c_new_device(adapter, &info);
92282 - i2c_put_adapter(adapter);
92283 - if (!client) {
92284 - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
92285 - (unsigned int)info.addr);
92286 - goto err_driver;
92287 - }
92288 -
92289 - return 0;
92290 -
92291 -err_driver:
92292 - i2c_del_driver(&wm8753_i2c_driver);
92293 - return -ENODEV;
92294 -}
92295 #endif
92296
92297 #if defined(CONFIG_SPI_MASTER)
92298 -static int __devinit wm8753_spi_probe(struct spi_device *spi)
92299 -{
92300 - struct snd_soc_device *socdev = wm8753_socdev;
92301 - struct snd_soc_codec *codec = socdev->codec;
92302 - int ret;
92303 -
92304 - codec->control_data = spi;
92305 -
92306 - ret = wm8753_init(socdev);
92307 - if (ret < 0)
92308 - dev_err(&spi->dev, "failed to initialise WM8753\n");
92309 -
92310 - return ret;
92311 -}
92312 -
92313 -static int __devexit wm8753_spi_remove(struct spi_device *spi)
92314 -{
92315 - return 0;
92316 -}
92317 -
92318 -static struct spi_driver wm8753_spi_driver = {
92319 - .driver = {
92320 - .name = "wm8753",
92321 - .bus = &spi_bus_type,
92322 - .owner = THIS_MODULE,
92323 - },
92324 - .probe = wm8753_spi_probe,
92325 - .remove = __devexit_p(wm8753_spi_remove),
92326 -};
92327 -
92328 static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
92329 {
92330 struct spi_transfer t;
92331 @@ -1769,120 +1817,69 @@
92332
92333 return len;
92334 }
92335 -#endif
92336 -
92337
92338 -static int wm8753_probe(struct platform_device *pdev)
92339 +static int __devinit wm8753_spi_probe(struct spi_device *spi)
92340 {
92341 - struct snd_soc_device *socdev = platform_get_drvdata(pdev);
92342 - struct wm8753_setup_data *setup;
92343 struct snd_soc_codec *codec;
92344 struct wm8753_priv *wm8753;
92345 - int ret = 0;
92346 -
92347 - pr_info("WM8753 Audio Codec %s", WM8753_VERSION);
92348 -
92349 - setup = socdev->codec_data;
92350 - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
92351 - if (codec == NULL)
92352 - return -ENOMEM;
92353
92354 wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
92355 - if (wm8753 == NULL) {
92356 - kfree(codec);
92357 + if (wm8753 == NULL)
92358 return -ENOMEM;
92359 - }
92360
92361 - codec->private_data = wm8753;
92362 - socdev->codec = codec;
92363 - mutex_init(&codec->mutex);
92364 - INIT_LIST_HEAD(&codec->dapm_widgets);
92365 - INIT_LIST_HEAD(&codec->dapm_paths);
92366 - wm8753_socdev = socdev;
92367 - INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
92368 + codec = &wm8753->codec;
92369 + codec->control_data = spi;
92370 + codec->hw_write = (hw_write_t)wm8753_spi_write;
92371 + codec->dev = &spi->dev;
92372
92373 -#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
92374 - if (setup->i2c_address) {
92375 - codec->hw_write = (hw_write_t)i2c_master_send;
92376 - ret = wm8753_add_i2c_device(pdev, setup);
92377 - }
92378 -#endif
92379 -#if defined(CONFIG_SPI_MASTER)
92380 - if (setup->spi) {
92381 - codec->hw_write = (hw_write_t)wm8753_spi_write;
92382 - ret = spi_register_driver(&wm8753_spi_driver);
92383 - if (ret != 0)
92384 - printk(KERN_ERR "can't add spi driver");
92385 - }
92386 -#endif
92387 + spi->dev.driver_data = wm8753;
92388
92389 - if (ret != 0) {
92390 - kfree(codec->private_data);
92391 - kfree(codec);
92392 - }
92393 - return ret;
92394 + return wm8753_register(wm8753);
92395 }
92396
92397 -/*
92398 - * This function forces any delayed work to be queued and run.
92399 - */
92400 -static int run_delayed_work(struct delayed_work *dwork)
92401 +static int __devexit wm8753_spi_remove(struct spi_device *spi)
92402 {
92403 - int ret;
92404 -
92405 - /* cancel any work waiting to be queued. */
92406 - ret = cancel_delayed_work(dwork);
92407 -
92408 - /* if there was any work waiting then we run it now and
92409 - * wait for it's completion */
92410 - if (ret) {
92411 - schedule_delayed_work(dwork, 0);
92412 - flush_scheduled_work();
92413 - }
92414 - return ret;
92415 + struct wm8753_priv *wm8753 = spi->dev.driver_data;
92416 + wm8753_unregister(wm8753);
92417 + return 0;
92418 }
92419
92420 -/* power down chip */
92421 -static int wm8753_remove(struct platform_device *pdev)
92422 -{
92423 - struct snd_soc_device *socdev = platform_get_drvdata(pdev);
92424 - struct snd_soc_codec *codec = socdev->codec;
92425 +static struct spi_driver wm8753_spi_driver = {
92426 + .driver = {
92427 + .name = "wm8753",
92428 + .bus = &spi_bus_type,
92429 + .owner = THIS_MODULE,
92430 + },
92431 + .probe = wm8753_spi_probe,
92432 + .remove = __devexit_p(wm8753_spi_remove),
92433 +};
92434 +#endif
92435
92436 - if (codec->control_data)
92437 - wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
92438 - run_delayed_work(&codec->delayed_work);
92439 - snd_soc_free_pcms(socdev);
92440 - snd_soc_dapm_free(socdev);
92441 +static int __init wm8753_modinit(void)
92442 +{
92443 + int ret;
92444 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
92445 - i2c_unregister_device(codec->control_data);
92446 - i2c_del_driver(&wm8753_i2c_driver);
92447 + ret = i2c_add_driver(&wm8753_i2c_driver);
92448 + if (ret != 0)
92449 + pr_err("Failed to register WM8753 I2C driver: %d\n", ret);
92450 #endif
92451 #if defined(CONFIG_SPI_MASTER)
92452 - spi_unregister_driver(&wm8753_spi_driver);
92453 + ret = spi_register_driver(&wm8753_spi_driver);
92454 + if (ret != 0)
92455 + pr_err("Failed to register WM8753 SPI driver: %d\n", ret);
92456 #endif
92457 - kfree(codec->private_data);
92458 - kfree(codec);
92459 -
92460 return 0;
92461 }
92462 -
92463 -struct snd_soc_codec_device soc_codec_dev_wm8753 = {
92464 - .probe = wm8753_probe,
92465 - .remove = wm8753_remove,
92466 - .suspend = wm8753_suspend,
92467 - .resume = wm8753_resume,
92468 -};
92469 -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
92470 -
92471 -static int __init wm8753_modinit(void)
92472 -{
92473 - return snd_soc_register_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
92474 -}
92475 module_init(wm8753_modinit);
92476
92477 static void __exit wm8753_exit(void)
92478 {
92479 - snd_soc_unregister_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
92480 +#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
92481 + i2c_del_driver(&wm8753_i2c_driver);
92482 +#endif
92483 +#if defined(CONFIG_SPI_MASTER)
92484 + spi_unregister_driver(&wm8753_spi_driver);
92485 +#endif
92486 }
92487 module_exit(wm8753_exit);
92488
92489 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/codecs/wm8753.h linux-2.6.29-rc3.owrt.om/sound/soc/codecs/wm8753.h
92490 --- linux-2.6.29-rc3.owrt/sound/soc/codecs/wm8753.h 2009-05-10 22:05:01.000000000 +0200
92491 +++ linux-2.6.29-rc3.owrt.om/sound/soc/codecs/wm8753.h 2009-05-10 22:28:00.000000000 +0200
92492 @@ -77,12 +77,6 @@
92493 #define WM8753_BIASCTL 0x3d
92494 #define WM8753_ADCTL2 0x3f
92495
92496 -struct wm8753_setup_data {
92497 - int spi;
92498 - int i2c_bus;
92499 - unsigned short i2c_address;
92500 -};
92501 -
92502 #define WM8753_PLL1 0
92503 #define WM8753_PLL2 1
92504
92505 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/jive_wm8750.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/jive_wm8750.c
92506 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/jive_wm8750.c 1970-01-01 01:00:00.000000000 +0100
92507 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/jive_wm8750.c 2009-05-10 22:28:00.000000000 +0200
92508 @@ -0,0 +1,216 @@
92509 +/* sound/soc/s3c24xx/jive_wm8750.c
92510 + *
92511 + * Copyright 2007,2008 Simtec Electronics
92512 + *
92513 + * Based on sound/soc/pxa/spitz.c
92514 + * Copyright 2005 Wolfson Microelectronics PLC.
92515 + * Copyright 2005 Openedhand Ltd.
92516 + *
92517 + * This program is free software; you can redistribute it and/or modify
92518 + * it under the terms of the GNU General Public License version 2 as
92519 + * published by the Free Software Foundation.
92520 +*/
92521 +
92522 +#include <linux/module.h>
92523 +#include <linux/moduleparam.h>
92524 +#include <linux/timer.h>
92525 +#include <linux/interrupt.h>
92526 +#include <linux/platform_device.h>
92527 +#include <linux/clk.h>
92528 +
92529 +#include <sound/core.h>
92530 +#include <sound/pcm.h>
92531 +#include <sound/soc.h>
92532 +#include <sound/soc-dapm.h>
92533 +
92534 +#include <asm/mach-types.h>
92535 +
92536 +#include "s3c24xx-pcm.h"
92537 +#include "s3c2412-i2s.h"
92538 +
92539 +#include "../codecs/wm8750.h"
92540 +
92541 +static const struct snd_soc_dapm_route audio_map[] = {
92542 + { "Headphone Jack", NULL, "LOUT1" },
92543 + { "Headphone Jack", NULL, "ROUT1" },
92544 + { "Internal Speaker", NULL, "LOUT2" },
92545 + { "Internal Speaker", NULL, "ROUT2" },
92546 + { "LINPUT1", NULL, "Line Input" },
92547 + { "RINPUT1", NULL, "Line Input" },
92548 +};
92549 +
92550 +static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
92551 + SND_SOC_DAPM_HP("Headphone Jack", NULL),
92552 + SND_SOC_DAPM_SPK("Internal Speaker", NULL),
92553 + SND_SOC_DAPM_LINE("Line In", NULL),
92554 +};
92555 +
92556 +static int jive_startup(struct snd_pcm_substream *substream)
92557 +{
92558 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
92559 + struct snd_soc_codec *codec = rtd->socdev->codec;
92560 +
92561 + snd_soc_dapm_enable_pin(codec, "Headphone Jack");
92562 + snd_soc_dapm_enable_pin(codec, "Internal Speaker");
92563 + snd_soc_dapm_enable_pin(codec, "Line In");
92564 +
92565 + snd_soc_dapm_sync(codec);
92566 +
92567 + return 0;
92568 +}
92569 +
92570 +static int jive_hw_params(struct snd_pcm_substream *substream,
92571 + struct snd_pcm_hw_params *params)
92572 +{
92573 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
92574 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
92575 + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
92576 + struct s3c_i2sv2_rate_calc div;
92577 + unsigned int clk = 0;
92578 + int ret = 0;
92579 +
92580 + switch (params_rate(params)) {
92581 + case 8000:
92582 + case 16000:
92583 + case 48000:
92584 + case 96000:
92585 + clk = 12288000;
92586 + break;
92587 + case 11025:
92588 + case 22050:
92589 + case 44100:
92590 + clk = 11289600;
92591 + break;
92592 + }
92593 +
92594 + s3c_i2sv2_calc_rate(&div, NULL, params_rate(params),
92595 + s3c2412_get_iisclk());
92596 +
92597 + /* set codec DAI configuration */
92598 + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
92599 + SND_SOC_DAIFMT_NB_NF |
92600 + SND_SOC_DAIFMT_CBS_CFS);
92601 + if (ret < 0)
92602 + return ret;
92603 +
92604 + /* set cpu DAI configuration */
92605 + ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
92606 + SND_SOC_DAIFMT_NB_NF |
92607 + SND_SOC_DAIFMT_CBS_CFS);
92608 + if (ret < 0)
92609 + return ret;
92610 +
92611 + /* set the codec system clock for DAC and ADC */
92612 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
92613 + SND_SOC_CLOCK_IN);
92614 + if (ret < 0)
92615 + return ret;
92616 +
92617 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_RCLK, div.fs_div);
92618 + if (ret < 0)
92619 + return ret;
92620 +
92621 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_PRESCALER,
92622 + div.clk_div - 1);
92623 + if (ret < 0)
92624 + return ret;
92625 +
92626 + return 0;
92627 +}
92628 +
92629 +static struct snd_soc_ops jive_ops = {
92630 + .startup = jive_startup,
92631 + .hw_params = jive_hw_params,
92632 +};
92633 +
92634 +static int jive_wm8750_init(struct snd_soc_codec *codec)
92635 +{
92636 + int err;
92637 +
92638 + /* These endpoints are not being used. */
92639 + snd_soc_dapm_disable_pin(codec, "LINPUT2");
92640 + snd_soc_dapm_disable_pin(codec, "RINPUT2");
92641 + snd_soc_dapm_disable_pin(codec, "LINPUT3");
92642 + snd_soc_dapm_disable_pin(codec, "RINPUT3");
92643 + snd_soc_dapm_disable_pin(codec, "OUT3");
92644 + snd_soc_dapm_disable_pin(codec, "MONO");
92645 +
92646 + /* Add jive specific widgets */
92647 + err = snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
92648 + ARRAY_SIZE(wm8750_dapm_widgets));
92649 + if (err) {
92650 + printk(KERN_ERR "%s: failed to add widgets (%d)\n",
92651 + __func__, err);
92652 + return err;
92653 + }
92654 +
92655 + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
92656 + snd_soc_dapm_sync(codec);
92657 +
92658 + return 0;
92659 +}
92660 +
92661 +static struct snd_soc_dai_link jive_dai = {
92662 + .name = "wm8750",
92663 + .stream_name = "WM8750",
92664 + .cpu_dai = &s3c2412_i2s_dai,
92665 + .codec_dai = &wm8750_dai,
92666 + .init = jive_wm8750_init,
92667 + .ops = &jive_ops,
92668 +};
92669 +
92670 +/* jive audio machine driver */
92671 +static struct snd_soc_machine snd_soc_machine_jive = {
92672 + .name = "Jive",
92673 + .dai_link = &jive_dai,
92674 + .num_links = 1,
92675 +};
92676 +
92677 +/* jive audio private data */
92678 +static struct wm8750_setup_data jive_wm8750_setup = {
92679 +};
92680 +
92681 +/* jive audio subsystem */
92682 +static struct snd_soc_device jive_snd_devdata = {
92683 + .machine = &snd_soc_machine_jive,
92684 + .platform = &s3c24xx_soc_platform,
92685 + .codec_dev = &soc_codec_dev_wm8750_spi,
92686 + .codec_data = &jive_wm8750_setup,
92687 +};
92688 +
92689 +static struct platform_device *jive_snd_device;
92690 +
92691 +static int __init jive_init(void)
92692 +{
92693 + int ret;
92694 +
92695 + if (!machine_is_jive())
92696 + return 0;
92697 +
92698 + printk("JIVE WM8750 Audio support\n");
92699 +
92700 + jive_snd_device = platform_device_alloc("soc-audio", -1);
92701 + if (!jive_snd_device)
92702 + return -ENOMEM;
92703 +
92704 + platform_set_drvdata(jive_snd_device, &jive_snd_devdata);
92705 + jive_snd_devdata.dev = &jive_snd_device->dev;
92706 + ret = platform_device_add(jive_snd_device);
92707 +
92708 + if (ret)
92709 + platform_device_put(jive_snd_device);
92710 +
92711 + return ret;
92712 +}
92713 +
92714 +static void __exit jive_exit(void)
92715 +{
92716 + platform_device_unregister(jive_snd_device);
92717 +}
92718 +
92719 +module_init(jive_init);
92720 +module_exit(jive_exit);
92721 +
92722 +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
92723 +MODULE_DESCRIPTION("ALSA SoC Jive Audio support");
92724 +MODULE_LICENSE("GPL");
92725 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/Kconfig linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/Kconfig
92726 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/Kconfig 2009-05-10 22:05:01.000000000 +0200
92727 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/Kconfig 2009-05-10 22:28:00.000000000 +0200
92728 @@ -1,6 +1,6 @@
92729 config SND_S3C24XX_SOC
92730 tristate "SoC Audio for the Samsung S3C24XX chips"
92731 - depends on ARCH_S3C2410
92732 + depends on ARCH_S3C2410 || ARCH_S3C64XX
92733 help
92734 Say Y or M if you want to add support for codecs attached to
92735 the S3C24XX AC97, I2S or SSP interface. You will also need
92736 @@ -9,8 +9,16 @@
92737 config SND_S3C24XX_SOC_I2S
92738 tristate
92739
92740 +config SND_S3C_I2SV2_SOC
92741 + tristate
92742 +
92743 config SND_S3C2412_SOC_I2S
92744 tristate
92745 + select SND_S3C_I2SV2_SOC
92746 +
92747 +config SND_S3C64XX_SOC_I2S
92748 + tristate
92749 + select SND_S3C_I2SV2_SOC
92750
92751 config SND_S3C2443_SOC_AC97
92752 tristate
92753 @@ -26,6 +34,33 @@
92754 Say Y if you want to add support for SoC audio on smdk2440
92755 with the WM8753.
92756
92757 +config SND_S3C24XX_SOC_JIVE_WM8750
92758 + tristate "SoC I2S Audio support for Jive"
92759 + depends on SND_S3C24XX_SOC && MACH_JIVE
92760 + select SND_SOC_WM8750
92761 + select SND_SOC_WM8750_SPI
92762 + select SND_S3C2412_SOC_I2S
92763 + help
92764 + Sat Y if you want to add support for SoC audio on the Jive.
92765 +
92766 +config SND_S3C24XX_SOC_NEO1973_GTA02_WM8753
92767 + tristate "SoC I2S Audio support for NEO1973 GTA02 - WM8753"
92768 + depends on SND_S3C24XX_SOC && MACH_NEO1973_GTA02
92769 + select SND_S3C24XX_SOC_I2S
92770 + select SND_SOC_WM8753
92771 + help
92772 + Say Y if you want to add support for SoC audio on neo1973 gta02
92773 + with the WM8753 codec
92774 +
92775 +config SND_S3C24XX_SOC_OM_3D7K_WM8753
92776 + tristate "SoC I2S Audio support for OM 3D7K - WM8753"
92777 + depends on SND_S3C24XX_SOC && MACH_OM_3D7K
92778 + select SND_S3C64XX_SOC_I2S
92779 + select SND_SOC_WM8753
92780 + help
92781 + Say Y if you want support for SoC audio on Openmoko 3D7K
92782 + with the WM8753 codec.
92783 +
92784 config SND_S3C24XX_SOC_SMDK2443_WM9710
92785 tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
92786 depends on SND_S3C24XX_SOC && MACH_SMDK2443
92787 @@ -49,3 +84,11 @@
92788 depends on SND_S3C24XX_SOC
92789 select SND_S3C24XX_SOC_I2S
92790 select SND_SOC_UDA134X
92791 +
92792 +config SND_S3C64XX_SOC_SMDK6410_WM8731
92793 + tristate "SoC I2S Audio support for WM8731 added to an SMDK6410"
92794 + depends on SND_S3C24XX_SOC
92795 + select SND_S3C64XX_SOC_I2S
92796 + select SND_SOC_WM8731
92797 + help
92798 + Support for an WM8731 add-on board on I2S channel 0 on an SMDK6410
92799 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/Makefile linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/Makefile
92800 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/Makefile 2009-05-10 22:05:01.000000000 +0200
92801 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/Makefile 2009-05-10 22:28:00.000000000 +0200
92802 @@ -2,20 +2,32 @@
92803 snd-soc-s3c24xx-objs := s3c24xx-pcm.o
92804 snd-soc-s3c24xx-i2s-objs := s3c24xx-i2s.o
92805 snd-soc-s3c2412-i2s-objs := s3c2412-i2s.o
92806 +snd-soc-s3c64xx-i2s-objs := s3c64xx-i2s.o
92807 snd-soc-s3c2443-ac97-objs := s3c2443-ac97.o
92808 +snd-soc-s3c-i2s-v2-objs := s3c-i2s-v2.o
92809
92810 obj-$(CONFIG_SND_S3C24XX_SOC) += snd-soc-s3c24xx.o
92811 obj-$(CONFIG_SND_S3C24XX_SOC_I2S) += snd-soc-s3c24xx-i2s.o
92812 obj-$(CONFIG_SND_S3C2443_SOC_AC97) += snd-soc-s3c2443-ac97.o
92813 obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
92814 +obj-$(CONFIG_SND_S3C64XX_SOC_I2S) += snd-soc-s3c64xx-i2s.o
92815 +obj-$(CONFIG_SND_S3C_I2SV2_SOC) += snd-soc-s3c-i2s-v2.o
92816
92817 # S3C24XX Machine Support
92818 +snd-soc-jive-wm8750-objs := jive_wm8750.o
92819 snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
92820 snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
92821 snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
92822 snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
92823 +snd-soc-neo1973-gta02-wm8753-objs := neo1973_gta02_wm8753.o
92824 +snd-soc-om-3d7k-wm8753-objs := om_3d7k_wm8753.o
92825 +snd-soc-smdk6410-wm8731-objs := smdk6410-wm8731.o
92826
92827 +obj-$(CONFIG_SND_S3C24XX_SOC_JIVE_WM8750) += snd-soc-jive-wm8750.o
92828 obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
92829 obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
92830 obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
92831 obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
92832 +obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_GTA02_WM8753) += snd-soc-neo1973-gta02-wm8753.o
92833 +obj-$(CONFIG_SND_S3C24XX_SOC_OM_3D7K_WM8753) += snd-soc-om-3d7k-wm8753.o
92834 +obj-$(CONFIG_SND_S3C64XX_SOC_SMDK6410_WM8731) += snd-soc-smdk6410-wm8731.o
92835 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/neo1973_gta02_wm8753.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/neo1973_gta02_wm8753.c
92836 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/neo1973_gta02_wm8753.c 1970-01-01 01:00:00.000000000 +0100
92837 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/neo1973_gta02_wm8753.c 2009-05-10 22:28:00.000000000 +0200
92838 @@ -0,0 +1,481 @@
92839 +/*
92840 + * neo1973_gta02_wm8753.c -- SoC audio for Neo1973
92841 + *
92842 + * Copyright 2007 Openmoko Inc
92843 + * Author: Graeme Gregory <graeme@openmoko.org>
92844 + * Copyright 2007 Wolfson Microelectronics PLC.
92845 + * Author: Graeme Gregory <linux@wolfsonmicro.com>
92846 + * Copyright 2009 Wolfson Microelectronics
92847 + *
92848 + * This program is free software; you can redistribute it and/or modify it
92849 + * under the terms of the GNU General Public License as published by the
92850 + * Free Software Foundation; either version 2 of the License, or (at your
92851 + * option) any later version.
92852 + */
92853 +
92854 +#include <linux/module.h>
92855 +#include <linux/moduleparam.h>
92856 +#include <linux/timer.h>
92857 +#include <linux/interrupt.h>
92858 +#include <linux/platform_device.h>
92859 +#include <sound/core.h>
92860 +#include <sound/pcm.h>
92861 +#include <sound/soc.h>
92862 +#include <sound/soc-dapm.h>
92863 +
92864 +#include <asm/mach-types.h>
92865 +
92866 +#include <plat/regs-iis.h>
92867 +
92868 +#include <mach/regs-clock.h>
92869 +#include <mach/regs-gpio.h>
92870 +#include <mach/hardware.h>
92871 +#include <asm/io.h>
92872 +#include <mach/regs-gpioj.h>
92873 +#include <mach/gta02.h>
92874 +#include "../codecs/wm8753.h"
92875 +#include "s3c24xx-pcm.h"
92876 +#include "s3c24xx-i2s.h"
92877 +
92878 +static struct snd_soc_card neo1973_gta02;
92879 +
92880 +static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
92881 + struct snd_pcm_hw_params *params)
92882 +{
92883 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
92884 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
92885 + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
92886 + unsigned int pll_out = 0, bclk = 0;
92887 + int ret = 0;
92888 + unsigned long iis_clkrate;
92889 +
92890 + iis_clkrate = s3c24xx_i2s_get_clockrate();
92891 +
92892 + switch (params_rate(params)) {
92893 + case 8000:
92894 + case 16000:
92895 + pll_out = 12288000;
92896 + break;
92897 + case 48000:
92898 + bclk = WM8753_BCLK_DIV_4;
92899 + pll_out = 12288000;
92900 + break;
92901 + case 96000:
92902 + bclk = WM8753_BCLK_DIV_2;
92903 + pll_out = 12288000;
92904 + break;
92905 + case 11025:
92906 + bclk = WM8753_BCLK_DIV_16;
92907 + pll_out = 11289600;
92908 + break;
92909 + case 22050:
92910 + bclk = WM8753_BCLK_DIV_8;
92911 + pll_out = 11289600;
92912 + break;
92913 + case 44100:
92914 + bclk = WM8753_BCLK_DIV_4;
92915 + pll_out = 11289600;
92916 + break;
92917 + case 88200:
92918 + bclk = WM8753_BCLK_DIV_2;
92919 + pll_out = 11289600;
92920 + break;
92921 + }
92922 +
92923 + /* set codec DAI configuration */
92924 + ret = snd_soc_dai_set_fmt(codec_dai,
92925 + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
92926 + SND_SOC_DAIFMT_CBM_CFM);
92927 + if (ret < 0)
92928 + return ret;
92929 +
92930 + /* set cpu DAI configuration */
92931 + ret = snd_soc_dai_set_fmt(cpu_dai,
92932 + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
92933 + SND_SOC_DAIFMT_CBM_CFM);
92934 + if (ret < 0)
92935 + return ret;
92936 +
92937 + /* set the codec system clock for DAC and ADC */
92938 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
92939 + SND_SOC_CLOCK_IN);
92940 + if (ret < 0)
92941 + return ret;
92942 +
92943 + /* set MCLK division for sample rate */
92944 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
92945 + S3C2410_IISMOD_32FS);
92946 + if (ret < 0)
92947 + return ret;
92948 +
92949 + /* set codec BCLK division for sample rate */
92950 + ret = snd_soc_dai_set_clkdiv(codec_dai,
92951 + WM8753_BCLKDIV, bclk);
92952 + if (ret < 0)
92953 + return ret;
92954 +
92955 + /* set prescaler division for sample rate */
92956 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
92957 + S3C24XX_PRESCALE(4, 4));
92958 + if (ret < 0)
92959 + return ret;
92960 +
92961 + /* codec PLL input is PCLK/4 */
92962 + ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
92963 + iis_clkrate / 4, pll_out);
92964 + if (ret < 0)
92965 + return ret;
92966 +
92967 + return 0;
92968 +}
92969 +
92970 +static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
92971 +{
92972 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
92973 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
92974 +
92975 + /* disable the PLL */
92976 + return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
92977 +}
92978 +
92979 +/*
92980 + * Neo1973 WM8753 HiFi DAI opserations.
92981 + */
92982 +static struct snd_soc_ops neo1973_gta02_hifi_ops = {
92983 + .hw_params = neo1973_gta02_hifi_hw_params,
92984 + .hw_free = neo1973_gta02_hifi_hw_free,
92985 +};
92986 +
92987 +static int neo1973_gta02_voice_hw_params(
92988 + struct snd_pcm_substream *substream,
92989 + struct snd_pcm_hw_params *params)
92990 +{
92991 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
92992 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
92993 + unsigned int pcmdiv = 0;
92994 + int ret = 0;
92995 + unsigned long iis_clkrate;
92996 +
92997 + iis_clkrate = s3c24xx_i2s_get_clockrate();
92998 +
92999 + if (params_rate(params) != 8000)
93000 + return -EINVAL;
93001 + if (params_channels(params) != 1)
93002 + return -EINVAL;
93003 +
93004 + pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
93005 +
93006 + /* todo: gg check mode (DSP_B) against CSR datasheet */
93007 + /* set codec DAI configuration */
93008 + ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_B |
93009 + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
93010 + if (ret < 0)
93011 + return ret;
93012 +
93013 + /* set the codec system clock for DAC and ADC */
93014 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK,
93015 + 12288000, SND_SOC_CLOCK_IN);
93016 + if (ret < 0)
93017 + return ret;
93018 +
93019 + /* set codec PCM division for sample rate */
93020 + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV,
93021 + pcmdiv);
93022 + if (ret < 0)
93023 + return ret;
93024 +
93025 + /* configue and enable PLL for 12.288MHz output */
93026 + ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2,
93027 + iis_clkrate / 4, 12288000);
93028 + if (ret < 0)
93029 + return ret;
93030 +
93031 + return 0;
93032 +}
93033 +
93034 +static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
93035 +{
93036 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
93037 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
93038 +
93039 + /* disable the PLL */
93040 + return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
93041 +}
93042 +
93043 +static struct snd_soc_ops neo1973_gta02_voice_ops = {
93044 + .hw_params = neo1973_gta02_voice_hw_params,
93045 + .hw_free = neo1973_gta02_voice_hw_free,
93046 +};
93047 +
93048 +#define LM4853_AMP 1
93049 +#define LM4853_SPK 2
93050 +
93051 +static u8 lm4853_state;
93052 +
93053 +/* This has no effect, it exists only to maintain compatibility with
93054 + * existing ALSA state files.
93055 + */
93056 +static int lm4853_set_state(struct snd_kcontrol *kcontrol,
93057 + struct snd_ctl_elem_value *ucontrol)
93058 +{
93059 + int val = ucontrol->value.integer.value[0];
93060 +
93061 + if (val)
93062 + lm4853_state |= LM4853_AMP;
93063 + else
93064 + lm4853_state &= ~LM4853_AMP;
93065 +
93066 + return 0;
93067 +}
93068 +
93069 +static int lm4853_get_state(struct snd_kcontrol *kcontrol,
93070 + struct snd_ctl_elem_value *ucontrol)
93071 +{
93072 + ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP;
93073 +
93074 + return 0;
93075 +}
93076 +
93077 +static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
93078 + struct snd_ctl_elem_value *ucontrol)
93079 +{
93080 + int val = ucontrol->value.integer.value[0];
93081 +
93082 + if (val) {
93083 + lm4853_state |= LM4853_SPK;
93084 + s3c2410_gpio_setpin(GTA02_GPIO_HP_IN, 0);
93085 + } else {
93086 + lm4853_state &= ~LM4853_SPK;
93087 + s3c2410_gpio_setpin(GTA02_GPIO_HP_IN, 1);
93088 + }
93089 +
93090 + return 0;
93091 +}
93092 +
93093 +static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
93094 + struct snd_ctl_elem_value *ucontrol)
93095 +{
93096 + ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1;
93097 +
93098 + return 0;
93099 +}
93100 +
93101 +static int lm4853_event(struct snd_soc_dapm_widget *w,
93102 + struct snd_kcontrol *k,
93103 + int event)
93104 +{
93105 + if (SND_SOC_DAPM_EVENT_ON(event))
93106 + s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT, 0);
93107 +
93108 + if (SND_SOC_DAPM_EVENT_OFF(event))
93109 + s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT, 1);
93110 +
93111 + return 0;
93112 +}
93113 +
93114 +static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
93115 + SND_SOC_DAPM_SPK("Stereo Out", lm4853_event),
93116 + SND_SOC_DAPM_LINE("GSM Line Out", NULL),
93117 + SND_SOC_DAPM_LINE("GSM Line In", NULL),
93118 + SND_SOC_DAPM_MIC("Headset Mic", NULL),
93119 + SND_SOC_DAPM_MIC("Handset Mic", NULL),
93120 + SND_SOC_DAPM_SPK("Handset Spk", NULL),
93121 +};
93122 +
93123 +
93124 +/* example machine audio_mapnections */
93125 +static const struct snd_soc_dapm_route audio_map[] = {
93126 +
93127 + /* Connections to the lm4853 amp */
93128 + {"Stereo Out", NULL, "LOUT1"},
93129 + {"Stereo Out", NULL, "ROUT1"},
93130 +
93131 + /* Connections to the GSM Module */
93132 + {"GSM Line Out", NULL, "MONO1"},
93133 + {"GSM Line Out", NULL, "MONO2"},
93134 + {"RXP", NULL, "GSM Line In"},
93135 + {"RXN", NULL, "GSM Line In"},
93136 +
93137 + /* Connections to Headset */
93138 + {"MIC1", NULL, "Mic Bias"},
93139 + {"Mic Bias", NULL, "Headset Mic"},
93140 +
93141 + /* Call Mic */
93142 + {"MIC2", NULL, "Mic Bias"},
93143 + {"MIC2N", NULL, "Mic Bias"},
93144 + {"Mic Bias", NULL, "Handset Mic"},
93145 +
93146 + /* Call Speaker */
93147 + {"Handset Spk", NULL, "LOUT2"},
93148 + {"Handset Spk", NULL, "ROUT2"},
93149 +
93150 + /* Connect the ALC pins */
93151 + {"ACIN", NULL, "ACOP"},
93152 +};
93153 +
93154 +static const struct snd_kcontrol_new wm8753_neo1973_gta02_controls[] = {
93155 + SOC_DAPM_PIN_SWITCH("Stereo Out"),
93156 + SOC_DAPM_PIN_SWITCH("GSM Line Out"),
93157 + SOC_DAPM_PIN_SWITCH("GSM Line In"),
93158 + SOC_DAPM_PIN_SWITCH("Headset Mic"),
93159 + SOC_DAPM_PIN_SWITCH("Handset Mic"),
93160 + SOC_DAPM_PIN_SWITCH("Handset Spk"),
93161 +
93162 + /* This has no effect, it exists only to maintain compatibility with
93163 + * existing ALSA state files.
93164 + */
93165 + SOC_SINGLE_EXT("Amp State Switch", 6, 0, 1, 0,
93166 + lm4853_get_state,
93167 + lm4853_set_state),
93168 + SOC_SINGLE_EXT("Amp Spk Switch", 7, 0, 1, 0,
93169 + lm4853_get_spk,
93170 + lm4853_set_spk),
93171 +};
93172 +
93173 +/*
93174 + * This is an example machine initialisation for a wm8753 connected to a
93175 + * neo1973 GTA02.
93176 + */
93177 +static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
93178 +{
93179 + int i, err;
93180 +
93181 + /* set up NC codec pins */
93182 + snd_soc_dapm_nc_pin(codec, "OUT3");
93183 + snd_soc_dapm_nc_pin(codec, "OUT4");
93184 + snd_soc_dapm_nc_pin(codec, "LINE1");
93185 + snd_soc_dapm_nc_pin(codec, "LINE2");
93186 +
93187 + /* Add neo1973 gta02 specific widgets */
93188 + snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
93189 + ARRAY_SIZE(wm8753_dapm_widgets));
93190 +
93191 + /* add neo1973 gta02 specific controls */
93192 + for (i = 0; i < ARRAY_SIZE(wm8753_neo1973_gta02_controls); i++) {
93193 + err = snd_ctl_add(codec->card,
93194 + snd_soc_cnew(&wm8753_neo1973_gta02_controls[i],
93195 + codec, NULL));
93196 + if (err < 0)
93197 + return err;
93198 + }
93199 +
93200 + /* set up neo1973 gta02 specific audio path audio_map */
93201 + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
93202 +
93203 + /* set endpoints to default off mode */
93204 + snd_soc_dapm_disable_pin(codec, "Stereo Out");
93205 + snd_soc_dapm_disable_pin(codec, "GSM Line Out");
93206 + snd_soc_dapm_disable_pin(codec, "GSM Line In");
93207 + snd_soc_dapm_disable_pin(codec, "Headset Mic");
93208 + snd_soc_dapm_disable_pin(codec, "Handset Mic");
93209 + snd_soc_dapm_disable_pin(codec, "Handset Spk");
93210 +
93211 + snd_soc_dapm_sync(codec);
93212 +
93213 + return 0;
93214 +}
93215 +
93216 +/*
93217 + * BT Codec DAI
93218 + */
93219 +static struct snd_soc_dai bt_dai = {
93220 + .name = "Bluetooth",
93221 + .id = 0,
93222 + .playback = {
93223 + .channels_min = 1,
93224 + .channels_max = 1,
93225 + .rates = SNDRV_PCM_RATE_8000,
93226 + .formats = SNDRV_PCM_FMTBIT_S16_LE,},
93227 + .capture = {
93228 + .channels_min = 1,
93229 + .channels_max = 1,
93230 + .rates = SNDRV_PCM_RATE_8000,
93231 + .formats = SNDRV_PCM_FMTBIT_S16_LE,},
93232 +};
93233 +
93234 +static struct snd_soc_dai_link neo1973_gta02_dai[] = {
93235 +{ /* Hifi Playback - for similatious use with voice below */
93236 + .name = "WM8753",
93237 + .stream_name = "WM8753 HiFi",
93238 + .cpu_dai = &s3c24xx_i2s_dai,
93239 + .codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
93240 + .init = neo1973_gta02_wm8753_init,
93241 + .ops = &neo1973_gta02_hifi_ops,
93242 +},
93243 +{ /* Voice via BT */
93244 + .name = "Bluetooth",
93245 + .stream_name = "Voice",
93246 + .cpu_dai = &bt_dai,
93247 + .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
93248 + .ops = &neo1973_gta02_voice_ops,
93249 +},
93250 +};
93251 +
93252 +static struct snd_soc_card neo1973_gta02 = {
93253 + .name = "neo1973-gta02",
93254 + .platform = &s3c24xx_soc_platform,
93255 + .dai_link = neo1973_gta02_dai,
93256 + .num_links = ARRAY_SIZE(neo1973_gta02_dai),
93257 +};
93258 +
93259 +static struct snd_soc_device neo1973_gta02_snd_devdata = {
93260 + .card = &neo1973_gta02,
93261 + .codec_dev = &soc_codec_dev_wm8753,
93262 +};
93263 +
93264 +static struct platform_device *neo1973_gta02_snd_device;
93265 +
93266 +static int __init neo1973_gta02_init(void)
93267 +{
93268 + int ret;
93269 +
93270 + if (!machine_is_neo1973_gta02()) {
93271 + printk(KERN_INFO
93272 + "Only GTA02 is supported by this ASoC driver\n");
93273 + return -ENODEV;
93274 + }
93275 +
93276 + /* register bluetooth DAI here */
93277 + ret = snd_soc_register_dai(&bt_dai);
93278 + if (ret)
93279 + return ret;
93280 +
93281 + neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
93282 + if (!neo1973_gta02_snd_device)
93283 + return -ENOMEM;
93284 +
93285 + platform_set_drvdata(neo1973_gta02_snd_device,
93286 + &neo1973_gta02_snd_devdata);
93287 + neo1973_gta02_snd_devdata.dev = &neo1973_gta02_snd_device->dev;
93288 + ret = platform_device_add(neo1973_gta02_snd_device);
93289 +
93290 + if (ret) {
93291 + platform_device_put(neo1973_gta02_snd_device);
93292 + return ret;
93293 + }
93294 +
93295 + /* Initialise GPIOs used by amp */
93296 + s3c2410_gpio_cfgpin(GTA02_GPIO_HP_IN, S3C2410_GPIO_OUTPUT);
93297 + s3c2410_gpio_cfgpin(GTA02_GPIO_AMP_SHUT, S3C2410_GPIO_OUTPUT);
93298 +
93299 + /* Amp off by default */
93300 + s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT, 1);
93301 +
93302 + /* Speaker off by default */
93303 + s3c2410_gpio_setpin(GTA02_GPIO_HP_IN, 1);
93304 +
93305 + return ret;
93306 +}
93307 +module_init(neo1973_gta02_init);
93308 +
93309 +static void __exit neo1973_gta02_exit(void)
93310 +{
93311 + snd_soc_unregister_dai(&bt_dai);
93312 + platform_device_unregister(neo1973_gta02_snd_device);
93313 +}
93314 +module_exit(neo1973_gta02_exit);
93315 +
93316 +/* Module information */
93317 +MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org");
93318 +MODULE_DESCRIPTION("ALSA SoC WM8753 Neo1973 GTA02");
93319 +MODULE_LICENSE("GPL");
93320 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/neo1973_wm8753.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/neo1973_wm8753.c
93321 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/neo1973_wm8753.c 2009-05-10 22:05:01.000000000 +0200
93322 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/neo1973_wm8753.c 2009-05-10 22:28:00.000000000 +0200
93323 @@ -29,11 +29,11 @@
93324 #include <mach/regs-clock.h>
93325 #include <mach/regs-gpio.h>
93326 #include <mach/hardware.h>
93327 -#include <mach/audio.h>
93328 +#include <plat/audio.h>
93329 #include <linux/io.h>
93330 #include <mach/spi-gpio.h>
93331
93332 -#include <asm/plat-s3c24xx/regs-iis.h>
93333 +#include <plat/regs-iis.h>
93334
93335 #include "../codecs/wm8753.h"
93336 #include "lm4857.h"
93337 @@ -585,15 +585,9 @@
93338 .num_links = ARRAY_SIZE(neo1973_dai),
93339 };
93340
93341 -static struct wm8753_setup_data neo1973_wm8753_setup = {
93342 - .i2c_bus = 0,
93343 - .i2c_address = 0x1a,
93344 -};
93345 -
93346 static struct snd_soc_device neo1973_snd_devdata = {
93347 .card = &neo1973,
93348 .codec_dev = &soc_codec_dev_wm8753,
93349 - .codec_data = &neo1973_wm8753_setup,
93350 };
93351
93352 static int lm4857_i2c_probe(struct i2c_client *client,
93353 @@ -652,13 +646,13 @@
93354 }
93355
93356 static const struct i2c_device_id lm4857_i2c_id[] = {
93357 - { "neo1973_lm4857", 0 },
93358 + { "lm4857", 0 },
93359 { }
93360 };
93361
93362 static struct i2c_driver lm4857_i2c_driver = {
93363 .driver = {
93364 - .name = "LM4857 I2C Amp",
93365 + .name = "lm4857",
93366 .owner = THIS_MODULE,
93367 },
93368 .suspend = lm4857_suspend,
93369 @@ -675,7 +669,7 @@
93370 {
93371 int ret;
93372
93373 - DBG("Entered %s\n", __func__);
93374 + printk(KERN_DEBUG "Entered %s\n", __func__);
93375
93376 if (!machine_is_neo1973_gta01()) {
93377 printk(KERN_INFO
93378 @@ -683,6 +677,11 @@
93379 return -ENODEV;
93380 }
93381
93382 + /* register bluetooth DAI here */
93383 + ret = snd_soc_register_dai(&bt_dai);
93384 + if (ret)
93385 + return ret;
93386 +
93387 neo1973_snd_device = platform_device_alloc("soc-audio", -1);
93388 if (!neo1973_snd_device)
93389 return -ENOMEM;
93390 @@ -708,6 +707,7 @@
93391 {
93392 DBG("Entered %s\n", __func__);
93393
93394 + snd_soc_unregister_dai(&bt_dai);
93395 i2c_del_driver(&lm4857_i2c_driver);
93396 platform_device_unregister(neo1973_snd_device);
93397 }
93398 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/om_3d7k_wm8753.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/om_3d7k_wm8753.c
93399 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/om_3d7k_wm8753.c 1970-01-01 01:00:00.000000000 +0100
93400 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/om_3d7k_wm8753.c 2009-05-10 22:28:00.000000000 +0200
93401 @@ -0,0 +1,600 @@
93402 +/*
93403 + * om_3d7k_wm8753.c -- SoC audio for 3D7K
93404 + *
93405 + * Based on neo1973_gta02_wm8753
93406 + *
93407 + * Copyright 2009 Openmoko Inc
93408 + * Author: Ben Dooks <ben@simtec.co.uk>
93409 + * Copyright 2007 Openmoko Inc
93410 + * Author: Graeme Gregory <graeme@openmoko.org>
93411 + * Copyright 2007 Wolfson Microelectronics PLC.
93412 + * Author: Graeme Gregory <linux@wolfsonmicro.com>
93413 + *
93414 + * This program is free software; you can redistribute it and/or modify it
93415 + * under the terms of the GNU General Public License as published by the
93416 + * Free Software Foundation; either version 2 of the License, or (at your
93417 + * option) any later version.
93418 + */
93419 +
93420 +#include <linux/module.h>
93421 +#include <linux/moduleparam.h>
93422 +#include <linux/timer.h>
93423 +#include <linux/interrupt.h>
93424 +#include <linux/platform_device.h>
93425 +#include <linux/i2c.h>
93426 +#include <sound/core.h>
93427 +#include <sound/pcm.h>
93428 +#include <sound/soc.h>
93429 +#include <sound/soc-dapm.h>
93430 +
93431 +#include <asm/mach-types.h>
93432 +#include <asm/hardware/scoop.h>
93433 +
93434 +#include <plat/regs-s3c2412-iis.h>
93435 +
93436 +#include "../codecs/wm8753.h"
93437 +#include "s3c24xx-pcm.h"
93438 +#include "s3c64xx-i2s.h"
93439 +
93440 +/* define the scenarios */
93441 +#define NEO_AUDIO_OFF 0
93442 +#define NEO_GSM_CALL_AUDIO_HANDSET 1
93443 +#define NEO_GSM_CALL_AUDIO_HEADSET 2
93444 +#define NEO_GSM_CALL_AUDIO_BLUETOOTH 3
93445 +#define NEO_STEREO_TO_SPEAKERS 4
93446 +#define NEO_STEREO_TO_HEADPHONES 5
93447 +#define NEO_CAPTURE_HANDSET 6
93448 +#define NEO_CAPTURE_HEADSET 7
93449 +#define NEO_CAPTURE_BLUETOOTH 8
93450 +#define NEO_STEREO_TO_HANDSET_SPK 9
93451 +
93452 +static struct snd_soc_card om_3d7k;
93453 +
93454 +static int om_3d7k_hifi_hw_params(struct snd_pcm_substream *substream,
93455 + struct snd_pcm_hw_params *params)
93456 +{
93457 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
93458 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
93459 + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
93460 + unsigned int pll_out = 0, bclk = 0;
93461 + int ret = 0;
93462 + unsigned long iis_clkrate;
93463 +
93464 + iis_clkrate = s3c64xx_i2s_get_clockrate(cpu_dai);
93465 +
93466 + switch (params_rate(params)) {
93467 + case 8000:
93468 + case 16000:
93469 + pll_out = 12288000;
93470 + break;
93471 + case 48000:
93472 + bclk = WM8753_BCLK_DIV_4;
93473 + pll_out = 12288000;
93474 + break;
93475 + case 96000:
93476 + bclk = WM8753_BCLK_DIV_2;
93477 + pll_out = 12288000;
93478 + break;
93479 + case 11025:
93480 + bclk = WM8753_BCLK_DIV_16;
93481 + pll_out = 11289600;
93482 + break;
93483 + case 22050:
93484 + bclk = WM8753_BCLK_DIV_8;
93485 + pll_out = 11289600;
93486 + break;
93487 + case 44100:
93488 + bclk = WM8753_BCLK_DIV_4;
93489 + pll_out = 11289600;
93490 + break;
93491 + case 88200:
93492 + bclk = WM8753_BCLK_DIV_2;
93493 + pll_out = 11289600;
93494 + break;
93495 + }
93496 +
93497 + ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_MUX, 0,
93498 + SND_SOC_CLOCK_OUT);
93499 + if (ret < 0)
93500 + goto err;
93501 +
93502 + /* set codec DAI configuration */
93503 + ret = snd_soc_dai_set_fmt(codec_dai,
93504 + SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_NB_NF |
93505 + SND_SOC_DAIFMT_CBM_CFM);
93506 + if (ret < 0)
93507 + goto err;
93508 +
93509 + /* set cpu DAI configuration */
93510 + ret = snd_soc_dai_set_fmt(cpu_dai,
93511 + SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
93512 + SND_SOC_DAIFMT_CBM_CFM);
93513 + if (ret < 0)
93514 + goto err;
93515 +
93516 + /* set the codec system clock for DAC and ADC */
93517 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_MCLK, pll_out,
93518 + SND_SOC_CLOCK_IN);
93519 + if (ret < 0)
93520 + goto err;
93521 +
93522 +#if 0
93523 + /* do not think we need to set this if the cpu is not the bitclk
93524 + * master */
93525 + /* set MCLK division for sample rate */
93526 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
93527 + S3C2410_IISMOD_32FS);
93528 + if (ret < 0)
93529 + return ret;
93530 +#endif
93531 +
93532 + /* set codec BCLK division for sample rate */
93533 + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
93534 + if (ret < 0)
93535 + goto err;
93536 +
93537 + /* set prescaler division for sample rate */
93538 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C64XX_DIV_PRESCALER, 2-1);
93539 + if (ret < 0)
93540 + goto err;
93541 +
93542 + /* codec PLL input is ACLK/2 */
93543 + ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
93544 + iis_clkrate / 2, pll_out);
93545 + if (ret < 0)
93546 + goto err;
93547 +
93548 + return 0;
93549 +
93550 +err:
93551 + printk(KERN_ERR "%s: failed %d\n", __func__, ret);
93552 + return ret;
93553 +}
93554 +
93555 +static int om_3d7k_hifi_hw_free(struct snd_pcm_substream *substream)
93556 +{
93557 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
93558 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
93559 +
93560 + /* disable the PLL */
93561 + return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
93562 +}
93563 +
93564 +/*
93565 + * 3D7K WM8753 HiFi DAI opserations.
93566 + */
93567 +static struct snd_soc_ops om_3d7k_hifi_ops = {
93568 + .hw_params = om_3d7k_hifi_hw_params,
93569 + .hw_free = om_3d7k_hifi_hw_free,
93570 +};
93571 +
93572 +static int om_3d7k_voice_hw_params(struct snd_pcm_substream *substream,
93573 + struct snd_pcm_hw_params *params)
93574 +{
93575 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
93576 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
93577 + unsigned int pcmdiv = 0;
93578 + int ret = 0;
93579 + unsigned long iis_clkrate;
93580 +
93581 + iis_clkrate = s3c64xx_i2s_get_clockrate(rtd->dai->cpu_dai);
93582 +
93583 + if (params_rate(params) != 8000)
93584 + return -EINVAL;
93585 + if (params_channels(params) != 1)
93586 + return -EINVAL;
93587 +
93588 + pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
93589 +
93590 + /* todo: gg check mode (DSP_B) against CSR datasheet */
93591 + /* set codec DAI configuration */
93592 + ret = snd_soc_dai_set_fmt(codec_dai, (SND_SOC_DAIFMT_DSP_B |
93593 + SND_SOC_DAIFMT_NB_NF |
93594 + SND_SOC_DAIFMT_CBS_CFS));
93595 + if (ret < 0)
93596 + return ret;
93597 +
93598 + /* set the codec system clock for DAC and ADC */
93599 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8753_PCMCLK,
93600 + 12288000, SND_SOC_CLOCK_IN);
93601 + if (ret < 0)
93602 + return ret;
93603 +
93604 + /* set codec PCM division for sample rate */
93605 + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
93606 + if (ret < 0)
93607 + return ret;
93608 +
93609 + /* configue and enable PLL for 12.288MHz output */
93610 + ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL2,
93611 + iis_clkrate / 2, 12288000);
93612 + if (ret < 0)
93613 + return ret;
93614 +
93615 + return 0;
93616 +}
93617 +
93618 +static int om_3d7k_voice_hw_free(struct snd_pcm_substream *substream)
93619 +{
93620 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
93621 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
93622 +
93623 + /* disable the PLL */
93624 + return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
93625 +}
93626 +
93627 +static struct snd_soc_ops om_3d7k_voice_ops = {
93628 + .hw_params = om_3d7k_voice_hw_params,
93629 + .hw_free = om_3d7k_voice_hw_free,
93630 +};
93631 +
93632 +static int om_3d7k_set_stereo_out(struct snd_kcontrol *kcontrol,
93633 + struct snd_ctl_elem_value *ucontrol)
93634 +{
93635 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93636 + int val = ucontrol->value.integer.value[0];
93637 +
93638 + snd_soc_dapm_set_endpoint(codec, "Stereo Out", val);
93639 + snd_soc_dapm_sync(codec);
93640 +
93641 + return 0;
93642 +}
93643 +
93644 +static int om_3d7k_get_stereo_out(struct snd_kcontrol *kcontrol,
93645 + struct snd_ctl_elem_value *ucontrol)
93646 +{
93647 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93648 +
93649 + ucontrol->value.integer.value[0] =
93650 + snd_soc_dapm_get_endpoint(codec, "Stereo Out");
93651 +
93652 + return 0;
93653 +}
93654 +
93655 +
93656 +static int om_3d7k_set_gsm_out(struct snd_kcontrol *kcontrol,
93657 + struct snd_ctl_elem_value *ucontrol)
93658 +{
93659 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93660 + int val = ucontrol->value.integer.value[0];
93661 +
93662 + snd_soc_dapm_set_endpoint(codec, "GSM Line Out", val);
93663 + snd_soc_dapm_sync(codec);
93664 +
93665 + return 0;
93666 +}
93667 +
93668 +static int om_3d7k_get_gsm_out(struct snd_kcontrol *kcontrol,
93669 + struct snd_ctl_elem_value *ucontrol)
93670 +{
93671 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93672 +
93673 + ucontrol->value.integer.value[0] =
93674 + snd_soc_dapm_get_endpoint(codec, "GSM Line Out");
93675 +
93676 + return 0;
93677 +}
93678 +
93679 +static int om_3d7k_set_gsm_in(struct snd_kcontrol *kcontrol,
93680 + struct snd_ctl_elem_value *ucontrol)
93681 +{
93682 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93683 + int val = ucontrol->value.integer.value[0];
93684 +
93685 + snd_soc_dapm_set_endpoint(codec, "GSM Line In", val);
93686 + snd_soc_dapm_sync(codec);
93687 +
93688 + return 0;
93689 +}
93690 +
93691 +static int om_3d7k_get_gsm_in(struct snd_kcontrol *kcontrol,
93692 + struct snd_ctl_elem_value *ucontrol)
93693 +{
93694 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93695 +
93696 + ucontrol->value.integer.value[0] =
93697 + snd_soc_dapm_get_endpoint(codec, "GSM Line In");
93698 +
93699 + return 0;
93700 +}
93701 +
93702 +static int om_3d7k_set_headset_mic(struct snd_kcontrol *kcontrol,
93703 + struct snd_ctl_elem_value *ucontrol)
93704 +{
93705 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93706 + int val = ucontrol->value.integer.value[0];
93707 +
93708 + snd_soc_dapm_set_endpoint(codec, "Headset Mic", val);
93709 + snd_soc_dapm_sync(codec);
93710 +
93711 + return 0;
93712 +}
93713 +
93714 +static int om_3d7k_get_headset_mic(struct snd_kcontrol *kcontrol,
93715 + struct snd_ctl_elem_value *ucontrol)
93716 +{
93717 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93718 +
93719 + ucontrol->value.integer.value[0] =
93720 + snd_soc_dapm_get_endpoint(codec, "Headset Mic");
93721 +
93722 + return 0;
93723 +}
93724 +
93725 +static int om_3d7k_set_handset_mic(struct snd_kcontrol *kcontrol,
93726 + struct snd_ctl_elem_value *ucontrol)
93727 +{
93728 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93729 + int val = ucontrol->value.integer.value[0];
93730 +
93731 + snd_soc_dapm_set_endpoint(codec, "Handset Mic", val);
93732 +
93733 + snd_soc_dapm_sync(codec);
93734 +
93735 + return 0;
93736 +}
93737 +
93738 +static int om_3d7k_get_handset_mic(struct snd_kcontrol *kcontrol,
93739 + struct snd_ctl_elem_value *ucontrol)
93740 +{
93741 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93742 +
93743 + ucontrol->value.integer.value[0] =
93744 + snd_soc_dapm_get_endpoint(codec, "Handset Mic");
93745 +
93746 + return 0;
93747 +}
93748 +
93749 +static int om_3d7k_set_handset_spk(struct snd_kcontrol *kcontrol,
93750 + struct snd_ctl_elem_value *ucontrol)
93751 +{
93752 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93753 + int val = ucontrol->value.integer.value[0];
93754 +
93755 + snd_soc_dapm_set_endpoint(codec, "Handset Spk", val);
93756 +
93757 + snd_soc_dapm_sync(codec);
93758 +
93759 + return 0;
93760 +}
93761 +
93762 +static int om_3d7k_get_handset_spk(struct snd_kcontrol *kcontrol,
93763 + struct snd_ctl_elem_value *ucontrol)
93764 +{
93765 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93766 +
93767 + ucontrol->value.integer.value[0] =
93768 + snd_soc_dapm_get_endpoint(codec, "Handset Spk");
93769 +
93770 + return 0;
93771 +}
93772 +
93773 +static int om_3d7k_set_headset_spk(struct snd_kcontrol *kcontrol,
93774 + struct snd_ctl_elem_value *ucontrol)
93775 +{
93776 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93777 + int val = ucontrol->value.integer.value[0];
93778 +
93779 + snd_soc_dapm_set_endpoint(codec, "Headset Spk", val);
93780 +
93781 + snd_soc_dapm_sync(codec);
93782 +
93783 + return 0;
93784 +}
93785 +
93786 +static int om_3d7k_get_headset_spk(struct snd_kcontrol *kcontrol,
93787 + struct snd_ctl_elem_value *ucontrol)
93788 +{
93789 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93790 +
93791 + ucontrol->value.integer.value[0] =
93792 + snd_soc_dapm_get_endpoint(codec, "Headset Spk");
93793 +
93794 + return 0;
93795 +}
93796 +
93797 +static const struct snd_soc_dapm_widget wm8753_dapm_widgets[] = {
93798 + SND_SOC_DAPM_LINE("Stereo Out", NULL),
93799 + SND_SOC_DAPM_LINE("GSM Line Out", NULL),
93800 + SND_SOC_DAPM_LINE("GSM Line In", NULL),
93801 + SND_SOC_DAPM_MIC("Headset Mic", NULL),
93802 + SND_SOC_DAPM_MIC("Handset Mic", NULL),
93803 + SND_SOC_DAPM_SPK("Handset Spk", NULL),
93804 + SND_SOC_DAPM_SPK("Headset Spk", NULL),
93805 +};
93806 +
93807 +
93808 +/* example machine audio_mapnections */
93809 +static const struct snd_soc_dapm_route audio_map[] = {
93810 +
93811 + {"Stereo Out", NULL, "LOUT2"},
93812 + {"Stereo Out", NULL, "ROUT2"},
93813 +
93814 + /* Connections to the GSM Module */
93815 + {"GSM Line Out", NULL, "MONO1"},
93816 + {"GSM Line Out", NULL, "MONO2"},
93817 + {"RXP", NULL, "GSM Line In"},
93818 + {"RXN", NULL, "GSM Line In"},
93819 +
93820 + /* Connections to Headset */
93821 + {"MIC1", NULL, "Mic Bias"},
93822 + {"Mic Bias", NULL, "Headset Mic"},
93823 +
93824 + /* Call Mic */
93825 + {"MIC2", NULL, "Mic Bias"},
93826 + {"MIC2N", NULL, "Mic Bias"},
93827 + {"Mic Bias", NULL, "Handset Mic"},
93828 +
93829 + /* Call Speaker */
93830 + {"Handset Spk", NULL, "OUT3"},
93831 + {"Handset Spk", NULL, "LOUT1"},
93832 +
93833 + {"Headset Spk", NULL, "ROUT1"},
93834 + {"Headset Spk", NULL, "LOUT1"},
93835 +
93836 + /* Connect the ALC pins */
93837 + {"ACIN", NULL, "ACOP"},
93838 +};
93839 +
93840 +static const struct snd_kcontrol_new wm8753_om_3d7k_controls[] = {
93841 + SOC_SINGLE_EXT("DAPM Stereo Out Switch", 0, 0, 1, 0,
93842 + om_3d7k_get_stereo_out,
93843 + om_3d7k_set_stereo_out),
93844 + SOC_SINGLE_EXT("DAPM GSM Line Out Switch", 1, 0, 1, 0,
93845 + om_3d7k_get_gsm_out,
93846 + om_3d7k_set_gsm_out),
93847 + SOC_SINGLE_EXT("DAPM GSM Line In Switch", 2, 0, 1, 0,
93848 + om_3d7k_get_gsm_in,
93849 + om_3d7k_set_gsm_in),
93850 + SOC_SINGLE_EXT("DAPM Headset Mic Switch", 3, 0, 1, 0,
93851 + om_3d7k_get_headset_mic,
93852 + om_3d7k_set_headset_mic),
93853 + SOC_SINGLE_EXT("DAPM Handset Mic Switch", 4, 0, 1, 0,
93854 + om_3d7k_get_handset_mic,
93855 + om_3d7k_set_handset_mic),
93856 + SOC_SINGLE_EXT("DAPM Handset Spk Switch", 5, 0, 1, 0,
93857 + om_3d7k_get_handset_spk,
93858 + om_3d7k_set_handset_spk),
93859 + SOC_SINGLE_EXT("DAPM Headset Spk Switch", 6, 0, 1, 0,
93860 + om_3d7k_get_headset_spk,
93861 + om_3d7k_set_headset_spk),
93862 +};
93863 +
93864 +/*
93865 + * This is an example machine initialisation for a wm8753 connected to a
93866 + * neo1973 GTA02.
93867 + */
93868 +static int om_3d7k_wm8753_init(struct snd_soc_codec *codec)
93869 +{
93870 + int i, err;
93871 +
93872 + /* set up NC codec pins */
93873 + snd_soc_dapm_set_endpoint(codec, "OUT4", 0);
93874 + snd_soc_dapm_set_endpoint(codec, "LINE1", 0);
93875 + snd_soc_dapm_set_endpoint(codec, "LINE2", 0);
93876 +
93877 +
93878 + /* Add neo1973 gta02 specific widgets */
93879 + snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
93880 + ARRAY_SIZE(wm8753_dapm_widgets));
93881 +
93882 + /* add neo1973 gta02 specific controls */
93883 + for (i = 0; i < ARRAY_SIZE(wm8753_om_3d7k_controls); i++) {
93884 + err = snd_ctl_add(codec->card,
93885 + snd_soc_cnew(&wm8753_om_3d7k_controls[i],
93886 + codec, NULL));
93887 + if (err < 0)
93888 + return err;
93889 + }
93890 +
93891 + /* set up neo1973 gta02 specific audio path audio_mapnects */
93892 + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
93893 +
93894 + /* set endpoints to default off mode */
93895 + snd_soc_dapm_set_endpoint(codec, "Stereo Out", 0);
93896 + snd_soc_dapm_set_endpoint(codec, "GSM Line Out",0);
93897 + snd_soc_dapm_set_endpoint(codec, "GSM Line In", 0);
93898 + snd_soc_dapm_set_endpoint(codec, "Headset Mic", 0);
93899 + snd_soc_dapm_set_endpoint(codec, "Handset Mic", 0);
93900 + snd_soc_dapm_set_endpoint(codec, "Handset Spk", 0);
93901 + snd_soc_dapm_set_endpoint(codec, "Headset Spk", 0);
93902 +
93903 + snd_soc_dapm_sync(codec);
93904 +
93905 + return 0;
93906 +}
93907 +
93908 +/*
93909 + * BT Codec DAI
93910 + */
93911 +static struct snd_soc_dai bt_dai =
93912 +{ .name = "Bluetooth",
93913 + .id = 0,
93914 + .playback = {
93915 + .channels_min = 1,
93916 + .channels_max = 1,
93917 + .rates = SNDRV_PCM_RATE_8000,
93918 + .formats = SNDRV_PCM_FMTBIT_S16_LE,
93919 + },
93920 + .capture = {
93921 + .channels_min = 1,
93922 + .channels_max = 1,
93923 + .rates = SNDRV_PCM_RATE_8000,
93924 + .formats = SNDRV_PCM_FMTBIT_S16_LE,
93925 + },
93926 +};
93927 +
93928 +static struct snd_soc_dai_link om_3d7k_dai[] = {
93929 + { /* Hifi Playback - for similatious use with voice below */
93930 + .name = "WM8753",
93931 + .stream_name = "WM8753 HiFi",
93932 + .cpu_dai = &s3c64xx_i2s_dai,
93933 + .codec_dai = &wm8753_dai[WM8753_DAI_HIFI],
93934 + .init = om_3d7k_wm8753_init,
93935 + .ops = &om_3d7k_hifi_ops,
93936 + },
93937 + { /* Voice via BT */
93938 + .name = "Bluetooth",
93939 + .stream_name = "Voice",
93940 + .cpu_dai = &bt_dai,
93941 + .codec_dai = &wm8753_dai[WM8753_DAI_VOICE],
93942 + .ops = &om_3d7k_voice_ops,
93943 + },
93944 +};
93945 +
93946 +static struct snd_soc_card om_3d7k = {
93947 + .name = "om-3d7k",
93948 + .platform = &s3c24xx_soc_platform,
93949 + .dai_link = om_3d7k_dai,
93950 + .num_links = ARRAY_SIZE(om_3d7k_dai),
93951 +};
93952 +
93953 +static struct snd_soc_device om_3d7k_snd_devdata = {
93954 + .card = &om_3d7k,
93955 + .codec_dev = &soc_codec_dev_wm8753,
93956 +};
93957 +
93958 +static struct platform_device *om_3d7k_snd_device;
93959 +
93960 +static int __init om_3d7k_init(void)
93961 +{
93962 + int ret;
93963 +
93964 + if (!machine_is_om_3d7k()) {
93965 + printk(KERN_INFO "Only 3D7K supported by ASoC driver\n");
93966 + return -ENODEV;
93967 + }
93968 +
93969 + /* register bluetooth DAI here */
93970 + ret = snd_soc_register_dai(&bt_dai);
93971 + if (ret)
93972 + return ret;
93973 +
93974 + om_3d7k_snd_device = platform_device_alloc("soc-audio", 1);
93975 + if (!om_3d7k_snd_device)
93976 + return -ENOMEM;
93977 +
93978 + platform_set_drvdata(om_3d7k_snd_device, &om_3d7k_snd_devdata);
93979 + om_3d7k_snd_devdata.dev = &om_3d7k_snd_device->dev;
93980 + ret = platform_device_add(om_3d7k_snd_device);
93981 +
93982 + if (ret) {
93983 + platform_device_put(om_3d7k_snd_device);
93984 + return ret;
93985 + }
93986 +
93987 + return ret;
93988 +}
93989 +
93990 +static void __exit om_3d7k_exit(void)
93991 +{
93992 + platform_device_unregister(om_3d7k_snd_device);
93993 +}
93994 +
93995 +module_init(om_3d7k_init);
93996 +module_exit(om_3d7k_exit);
93997 +
93998 +/* Module information */
93999 +MODULE_AUTHOR("Graeme Gregory, graeme@openmoko.org; Ben Dooks <ben@simtec.co.uk>");
94000 +MODULE_DESCRIPTION("ALSA SoC WM8753 OM 3D7K");
94001 +MODULE_LICENSE("GPL");
94002 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c2412-i2s.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c2412-i2s.c
94003 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c2412-i2s.c 2009-05-10 22:05:01.000000000 +0200
94004 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c2412-i2s.c 2009-05-10 22:28:00.000000000 +0200
94005 @@ -22,6 +22,7 @@
94006 #include <linux/delay.h>
94007 #include <linux/clk.h>
94008 #include <linux/kernel.h>
94009 +#include <linux/io.h>
94010
94011 #include <sound/core.h>
94012 #include <sound/pcm.h>
94013 @@ -30,20 +31,16 @@
94014 #include <sound/soc.h>
94015 #include <mach/hardware.h>
94016
94017 -#include <linux/io.h>
94018 -#include <asm/dma.h>
94019 -
94020 -#include <asm/plat-s3c24xx/regs-s3c2412-iis.h>
94021 +#include <plat/regs-s3c2412-iis.h>
94022
94023 -#include <mach/regs-gpio.h>
94024 -#include <mach/audio.h>
94025 +#include <plat/regs-gpio.h>
94026 +#include <plat/audio.h>
94027 #include <mach/dma.h>
94028
94029 #include "s3c24xx-pcm.h"
94030 #include "s3c2412-i2s.h"
94031
94032 #define S3C2412_I2S_DEBUG 0
94033 -#define S3C2412_I2S_DEBUG_CON 0
94034
94035 #if S3C2412_I2S_DEBUG
94036 #define DBG(x...) printk(KERN_INFO x)
94037 @@ -73,431 +70,7 @@
94038 .dma_size = 4,
94039 };
94040
94041 -struct s3c2412_i2s_info {
94042 - struct device *dev;
94043 - void __iomem *regs;
94044 - struct clk *iis_clk;
94045 - struct clk *iis_pclk;
94046 - struct clk *iis_cclk;
94047 -
94048 - u32 suspend_iismod;
94049 - u32 suspend_iiscon;
94050 - u32 suspend_iispsr;
94051 -};
94052 -
94053 -static struct s3c2412_i2s_info s3c2412_i2s;
94054 -
94055 -#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
94056 -
94057 -#if S3C2412_I2S_DEBUG_CON
94058 -static void dbg_showcon(const char *fn, u32 con)
94059 -{
94060 - printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d, RXFFULL=%d\n", fn,
94061 - bit_set(con, S3C2412_IISCON_LRINDEX),
94062 - bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY),
94063 - bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY),
94064 - bit_set(con, S3C2412_IISCON_TXFIFO_FULL),
94065 - bit_set(con, S3C2412_IISCON_RXFIFO_FULL));
94066 -
94067 - printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n",
94068 - fn,
94069 - bit_set(con, S3C2412_IISCON_TXDMA_PAUSE),
94070 - bit_set(con, S3C2412_IISCON_RXDMA_PAUSE),
94071 - bit_set(con, S3C2412_IISCON_TXCH_PAUSE),
94072 - bit_set(con, S3C2412_IISCON_RXCH_PAUSE));
94073 - printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn,
94074 - bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE),
94075 - bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE),
94076 - bit_set(con, S3C2412_IISCON_IIS_ACTIVE));
94077 -}
94078 -#else
94079 -static inline void dbg_showcon(const char *fn, u32 con)
94080 -{
94081 -}
94082 -#endif
94083 -
94084 -/* Turn on or off the transmission path. */
94085 -static void s3c2412_snd_txctrl(int on)
94086 -{
94087 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
94088 - void __iomem *regs = i2s->regs;
94089 - u32 fic, con, mod;
94090 -
94091 - DBG("%s(%d)\n", __func__, on);
94092 -
94093 - fic = readl(regs + S3C2412_IISFIC);
94094 - con = readl(regs + S3C2412_IISCON);
94095 - mod = readl(regs + S3C2412_IISMOD);
94096 -
94097 - DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
94098 -
94099 - if (on) {
94100 - con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
94101 - con &= ~S3C2412_IISCON_TXDMA_PAUSE;
94102 - con &= ~S3C2412_IISCON_TXCH_PAUSE;
94103 -
94104 - switch (mod & S3C2412_IISMOD_MODE_MASK) {
94105 - case S3C2412_IISMOD_MODE_TXONLY:
94106 - case S3C2412_IISMOD_MODE_TXRX:
94107 - /* do nothing, we are in the right mode */
94108 - break;
94109 -
94110 - case S3C2412_IISMOD_MODE_RXONLY:
94111 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94112 - mod |= S3C2412_IISMOD_MODE_TXRX;
94113 - break;
94114 -
94115 - default:
94116 - dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n");
94117 - }
94118 -
94119 - writel(con, regs + S3C2412_IISCON);
94120 - writel(mod, regs + S3C2412_IISMOD);
94121 - } else {
94122 - /* Note, we do not have any indication that the FIFO problems
94123 - * tha the S3C2410/2440 had apply here, so we should be able
94124 - * to disable the DMA and TX without resetting the FIFOS.
94125 - */
94126 -
94127 - con |= S3C2412_IISCON_TXDMA_PAUSE;
94128 - con |= S3C2412_IISCON_TXCH_PAUSE;
94129 - con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
94130 -
94131 - switch (mod & S3C2412_IISMOD_MODE_MASK) {
94132 - case S3C2412_IISMOD_MODE_TXRX:
94133 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94134 - mod |= S3C2412_IISMOD_MODE_RXONLY;
94135 - break;
94136 -
94137 - case S3C2412_IISMOD_MODE_TXONLY:
94138 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94139 - con &= ~S3C2412_IISCON_IIS_ACTIVE;
94140 - break;
94141 -
94142 - default:
94143 - dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n");
94144 - }
94145 -
94146 - writel(mod, regs + S3C2412_IISMOD);
94147 - writel(con, regs + S3C2412_IISCON);
94148 - }
94149 -
94150 - fic = readl(regs + S3C2412_IISFIC);
94151 - dbg_showcon(__func__, con);
94152 - DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
94153 -}
94154 -
94155 -static void s3c2412_snd_rxctrl(int on)
94156 -{
94157 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
94158 - void __iomem *regs = i2s->regs;
94159 - u32 fic, con, mod;
94160 -
94161 - DBG("%s(%d)\n", __func__, on);
94162 -
94163 - fic = readl(regs + S3C2412_IISFIC);
94164 - con = readl(regs + S3C2412_IISCON);
94165 - mod = readl(regs + S3C2412_IISMOD);
94166 -
94167 - DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
94168 -
94169 - if (on) {
94170 - con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
94171 - con &= ~S3C2412_IISCON_RXDMA_PAUSE;
94172 - con &= ~S3C2412_IISCON_RXCH_PAUSE;
94173 -
94174 - switch (mod & S3C2412_IISMOD_MODE_MASK) {
94175 - case S3C2412_IISMOD_MODE_TXRX:
94176 - case S3C2412_IISMOD_MODE_RXONLY:
94177 - /* do nothing, we are in the right mode */
94178 - break;
94179 -
94180 - case S3C2412_IISMOD_MODE_TXONLY:
94181 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94182 - mod |= S3C2412_IISMOD_MODE_TXRX;
94183 - break;
94184 -
94185 - default:
94186 - dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
94187 - }
94188 -
94189 - writel(mod, regs + S3C2412_IISMOD);
94190 - writel(con, regs + S3C2412_IISCON);
94191 - } else {
94192 - /* See txctrl notes on FIFOs. */
94193 -
94194 - con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
94195 - con |= S3C2412_IISCON_RXDMA_PAUSE;
94196 - con |= S3C2412_IISCON_RXCH_PAUSE;
94197 -
94198 - switch (mod & S3C2412_IISMOD_MODE_MASK) {
94199 - case S3C2412_IISMOD_MODE_RXONLY:
94200 - con &= ~S3C2412_IISCON_IIS_ACTIVE;
94201 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94202 - break;
94203 -
94204 - case S3C2412_IISMOD_MODE_TXRX:
94205 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94206 - mod |= S3C2412_IISMOD_MODE_TXONLY;
94207 - break;
94208 -
94209 - default:
94210 - dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
94211 - }
94212 -
94213 - writel(con, regs + S3C2412_IISCON);
94214 - writel(mod, regs + S3C2412_IISMOD);
94215 - }
94216 -
94217 - fic = readl(regs + S3C2412_IISFIC);
94218 - DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
94219 -}
94220 -
94221 -
94222 -/*
94223 - * Wait for the LR signal to allow synchronisation to the L/R clock
94224 - * from the codec. May only be needed for slave mode.
94225 - */
94226 -static int s3c2412_snd_lrsync(void)
94227 -{
94228 - u32 iiscon;
94229 - unsigned long timeout = jiffies + msecs_to_jiffies(5);
94230 -
94231 - DBG("Entered %s\n", __func__);
94232 -
94233 - while (1) {
94234 - iiscon = readl(s3c2412_i2s.regs + S3C2412_IISCON);
94235 - if (iiscon & S3C2412_IISCON_LRINDEX)
94236 - break;
94237 -
94238 - if (timeout < jiffies) {
94239 - printk(KERN_ERR "%s: timeout\n", __func__);
94240 - return -ETIMEDOUT;
94241 - }
94242 - }
94243 -
94244 - return 0;
94245 -}
94246 -
94247 -/*
94248 - * Check whether CPU is the master or slave
94249 - */
94250 -static inline int s3c2412_snd_is_clkmaster(void)
94251 -{
94252 - u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
94253 -
94254 - DBG("Entered %s\n", __func__);
94255 -
94256 - iismod &= S3C2412_IISMOD_MASTER_MASK;
94257 - return !(iismod == S3C2412_IISMOD_SLAVE);
94258 -}
94259 -
94260 -/*
94261 - * Set S3C2412 I2S DAI format
94262 - */
94263 -static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
94264 - unsigned int fmt)
94265 -{
94266 - u32 iismod;
94267 -
94268 -
94269 - DBG("Entered %s\n", __func__);
94270 -
94271 - iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
94272 - DBG("hw_params r: IISMOD: %x \n", iismod);
94273 -
94274 - switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
94275 - case SND_SOC_DAIFMT_CBM_CFM:
94276 - iismod &= ~S3C2412_IISMOD_MASTER_MASK;
94277 - iismod |= S3C2412_IISMOD_SLAVE;
94278 - break;
94279 - case SND_SOC_DAIFMT_CBS_CFS:
94280 - iismod &= ~S3C2412_IISMOD_MASTER_MASK;
94281 - iismod |= S3C2412_IISMOD_MASTER_INTERNAL;
94282 - break;
94283 - default:
94284 - DBG("unknwon master/slave format\n");
94285 - return -EINVAL;
94286 - }
94287 -
94288 - iismod &= ~S3C2412_IISMOD_SDF_MASK;
94289 -
94290 - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
94291 - case SND_SOC_DAIFMT_RIGHT_J:
94292 - iismod |= S3C2412_IISMOD_SDF_MSB;
94293 - break;
94294 - case SND_SOC_DAIFMT_LEFT_J:
94295 - iismod |= S3C2412_IISMOD_SDF_LSB;
94296 - break;
94297 - case SND_SOC_DAIFMT_I2S:
94298 - iismod |= S3C2412_IISMOD_SDF_IIS;
94299 - break;
94300 - default:
94301 - DBG("Unknown data format\n");
94302 - return -EINVAL;
94303 - }
94304 -
94305 - writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD);
94306 - DBG("hw_params w: IISMOD: %x \n", iismod);
94307 - return 0;
94308 -}
94309 -
94310 -static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
94311 - struct snd_pcm_hw_params *params,
94312 - struct snd_soc_dai *dai)
94313 -{
94314 - struct snd_soc_pcm_runtime *rtd = substream->private_data;
94315 - u32 iismod;
94316 -
94317 - DBG("Entered %s\n", __func__);
94318 -
94319 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
94320 - rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_out;
94321 - else
94322 - rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_in;
94323 -
94324 - /* Working copies of register */
94325 - iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
94326 - DBG("%s: r: IISMOD: %x\n", __func__, iismod);
94327 -
94328 - switch (params_format(params)) {
94329 - case SNDRV_PCM_FORMAT_S8:
94330 - iismod |= S3C2412_IISMOD_8BIT;
94331 - break;
94332 - case SNDRV_PCM_FORMAT_S16_LE:
94333 - iismod &= ~S3C2412_IISMOD_8BIT;
94334 - break;
94335 - }
94336 -
94337 - writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD);
94338 - DBG("%s: w: IISMOD: %x\n", __func__, iismod);
94339 - return 0;
94340 -}
94341 -
94342 -static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
94343 - struct snd_soc_dai *dai)
94344 -{
94345 - int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
94346 - unsigned long irqs;
94347 - int ret = 0;
94348 -
94349 - DBG("Entered %s\n", __func__);
94350 -
94351 - switch (cmd) {
94352 - case SNDRV_PCM_TRIGGER_START:
94353 - /* On start, ensure that the FIFOs are cleared and reset. */
94354 -
94355 - writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH,
94356 - s3c2412_i2s.regs + S3C2412_IISFIC);
94357 -
94358 - /* clear again, just in case */
94359 - writel(0x0, s3c2412_i2s.regs + S3C2412_IISFIC);
94360 -
94361 - case SNDRV_PCM_TRIGGER_RESUME:
94362 - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
94363 - if (!s3c2412_snd_is_clkmaster()) {
94364 - ret = s3c2412_snd_lrsync();
94365 - if (ret)
94366 - goto exit_err;
94367 - }
94368 -
94369 - local_irq_save(irqs);
94370 -
94371 - if (capture)
94372 - s3c2412_snd_rxctrl(1);
94373 - else
94374 - s3c2412_snd_txctrl(1);
94375 -
94376 - local_irq_restore(irqs);
94377 - break;
94378 -
94379 - case SNDRV_PCM_TRIGGER_STOP:
94380 - case SNDRV_PCM_TRIGGER_SUSPEND:
94381 - case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
94382 - local_irq_save(irqs);
94383 -
94384 - if (capture)
94385 - s3c2412_snd_rxctrl(0);
94386 - else
94387 - s3c2412_snd_txctrl(0);
94388 -
94389 - local_irq_restore(irqs);
94390 - break;
94391 - default:
94392 - ret = -EINVAL;
94393 - break;
94394 - }
94395 -
94396 -exit_err:
94397 - return ret;
94398 -}
94399 -
94400 -/* default table of all avaialable root fs divisors */
94401 -static unsigned int s3c2412_iis_fs[] = { 256, 512, 384, 768, 0 };
94402 -
94403 -int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info,
94404 - unsigned int *fstab,
94405 - unsigned int rate, struct clk *clk)
94406 -{
94407 - unsigned long clkrate = clk_get_rate(clk);
94408 - unsigned int div;
94409 - unsigned int fsclk;
94410 - unsigned int actual;
94411 - unsigned int fs;
94412 - unsigned int fsdiv;
94413 - signed int deviation = 0;
94414 - unsigned int best_fs = 0;
94415 - unsigned int best_div = 0;
94416 - unsigned int best_rate = 0;
94417 - unsigned int best_deviation = INT_MAX;
94418 -
94419 -
94420 - if (fstab == NULL)
94421 - fstab = s3c2412_iis_fs;
94422 -
94423 - for (fs = 0;; fs++) {
94424 - fsdiv = s3c2412_iis_fs[fs];
94425 -
94426 - if (fsdiv == 0)
94427 - break;
94428 -
94429 - fsclk = clkrate / fsdiv;
94430 - div = fsclk / rate;
94431 -
94432 - if ((fsclk % rate) > (rate / 2))
94433 - div++;
94434 -
94435 - if (div <= 1)
94436 - continue;
94437 -
94438 - actual = clkrate / (fsdiv * div);
94439 - deviation = actual - rate;
94440 -
94441 - printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n",
94442 - fsdiv, div, actual, deviation);
94443 -
94444 - deviation = abs(deviation);
94445 -
94446 - if (deviation < best_deviation) {
94447 - best_fs = fsdiv;
94448 - best_div = div;
94449 - best_rate = actual;
94450 - best_deviation = deviation;
94451 - }
94452 -
94453 - if (deviation == 0)
94454 - break;
94455 - }
94456 -
94457 - printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n",
94458 - best_fs, best_div, best_rate);
94459 -
94460 - info->fs_div = best_fs;
94461 - info->clk_div = best_div;
94462 -
94463 - return 0;
94464 -}
94465 -EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate);
94466 +static struct s3c_i2sv2_info s3c2412_i2s;
94467
94468 /*
94469 * Set S3C2412 Clock source
94470 @@ -512,10 +85,12 @@
94471
94472 switch (clk_id) {
94473 case S3C2412_CLKSRC_PCLK:
94474 + s3c2412_i2s.master = 1;
94475 iismod &= ~S3C2412_IISMOD_MASTER_MASK;
94476 iismod |= S3C2412_IISMOD_MASTER_INTERNAL;
94477 break;
94478 case S3C2412_CLKSRC_I2SCLK:
94479 + s3c2412_i2s.master = 0;
94480 iismod &= ~S3C2412_IISMOD_MASTER_MASK;
94481 iismod |= S3C2412_IISMOD_MASTER_EXTERNAL;
94482 break;
94483 @@ -527,74 +102,6 @@
94484 return 0;
94485 }
94486
94487 -/*
94488 - * Set S3C2412 Clock dividers
94489 - */
94490 -static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
94491 - int div_id, int div)
94492 -{
94493 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
94494 - u32 reg;
94495 -
94496 - DBG("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div);
94497 -
94498 - switch (div_id) {
94499 - case S3C2412_DIV_BCLK:
94500 - reg = readl(i2s->regs + S3C2412_IISMOD);
94501 - reg &= ~S3C2412_IISMOD_BCLK_MASK;
94502 - writel(reg | div, i2s->regs + S3C2412_IISMOD);
94503 -
94504 - DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
94505 - break;
94506 -
94507 - case S3C2412_DIV_RCLK:
94508 - if (div > 3) {
94509 - /* convert value to bit field */
94510 -
94511 - switch (div) {
94512 - case 256:
94513 - div = S3C2412_IISMOD_RCLK_256FS;
94514 - break;
94515 -
94516 - case 384:
94517 - div = S3C2412_IISMOD_RCLK_384FS;
94518 - break;
94519 -
94520 - case 512:
94521 - div = S3C2412_IISMOD_RCLK_512FS;
94522 - break;
94523 -
94524 - case 768:
94525 - div = S3C2412_IISMOD_RCLK_768FS;
94526 - break;
94527 -
94528 - default:
94529 - return -EINVAL;
94530 - }
94531 - }
94532 -
94533 - reg = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
94534 - reg &= ~S3C2412_IISMOD_RCLK_MASK;
94535 - writel(reg | div, i2s->regs + S3C2412_IISMOD);
94536 - DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
94537 - break;
94538 -
94539 - case S3C2412_DIV_PRESCALER:
94540 - if (div >= 0) {
94541 - writel((div << 8) | S3C2412_IISPSR_PSREN,
94542 - i2s->regs + S3C2412_IISPSR);
94543 - } else {
94544 - writel(0x0, i2s->regs + S3C2412_IISPSR);
94545 - }
94546 - DBG("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR));
94547 - break;
94548 -
94549 - default:
94550 - return -EINVAL;
94551 - }
94552 -
94553 - return 0;
94554 -}
94555
94556 struct clk *s3c2412_get_iisclk(void)
94557 {
94558 @@ -606,20 +113,16 @@
94559 static int s3c2412_i2s_probe(struct platform_device *pdev,
94560 struct snd_soc_dai *dai)
94561 {
94562 + int ret;
94563 +
94564 DBG("Entered %s\n", __func__);
94565
94566 - s3c2412_i2s.dev = &pdev->dev;
94567 + ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS);
94568 + if (ret)
94569 + return ret;
94570
94571 - s3c2412_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
94572 - if (s3c2412_i2s.regs == NULL)
94573 - return -ENXIO;
94574 -
94575 - s3c2412_i2s.iis_pclk = clk_get(&pdev->dev, "iis");
94576 - if (s3c2412_i2s.iis_pclk == NULL) {
94577 - DBG("failed to get iis_clock\n");
94578 - iounmap(s3c2412_i2s.regs);
94579 - return -ENODEV;
94580 - }
94581 + s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in;
94582 + s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
94583
94584 s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk");
94585 if (s3c2412_i2s.iis_cclk == NULL) {
94586 @@ -628,12 +131,12 @@
94587 return -ENODEV;
94588 }
94589
94590 - clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll"));
94591 + /* Set MPLL as the source for IIS CLK */
94592
94593 - clk_enable(s3c2412_i2s.iis_pclk);
94594 + clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll"));
94595 clk_enable(s3c2412_i2s.iis_cclk);
94596
94597 - s3c2412_i2s.iis_clk = s3c2412_i2s.iis_pclk;
94598 + s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk;
94599
94600 /* Configure the I2S pins in correct mode */
94601 s3c2410_gpio_cfgpin(S3C2410_GPE0, S3C2410_GPE0_I2SLRCK);
94602 @@ -642,66 +145,8 @@
94603 s3c2410_gpio_cfgpin(S3C2410_GPE3, S3C2410_GPE3_I2SSDI);
94604 s3c2410_gpio_cfgpin(S3C2410_GPE4, S3C2410_GPE4_I2SSDO);
94605
94606 - s3c2412_snd_txctrl(0);
94607 - s3c2412_snd_rxctrl(0);
94608 -
94609 - return 0;
94610 -}
94611 -
94612 -#ifdef CONFIG_PM
94613 -static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
94614 -{
94615 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
94616 - u32 iismod;
94617 -
94618 - if (dai->active) {
94619 - i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
94620 - i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
94621 - i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
94622 -
94623 - /* some basic suspend checks */
94624 -
94625 - iismod = readl(i2s->regs + S3C2412_IISMOD);
94626 -
94627 - if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
94628 - pr_warning("%s: RXDMA active?\n", __func__);
94629 -
94630 - if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
94631 - pr_warning("%s: TXDMA active?\n", __func__);
94632 -
94633 - if (iismod & S3C2412_IISCON_IIS_ACTIVE)
94634 - pr_warning("%s: IIS active\n", __func__);
94635 - }
94636 -
94637 - return 0;
94638 -}
94639 -
94640 -static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
94641 -{
94642 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
94643 -
94644 - pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
94645 - dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
94646 -
94647 - if (dai->active) {
94648 - writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
94649 - writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
94650 - writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
94651 -
94652 - writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
94653 - i2s->regs + S3C2412_IISFIC);
94654 -
94655 - ndelay(250);
94656 - writel(0x0, i2s->regs + S3C2412_IISFIC);
94657 -
94658 - }
94659 -
94660 return 0;
94661 }
94662 -#else
94663 -#define s3c2412_i2s_suspend NULL
94664 -#define s3c2412_i2s_resume NULL
94665 -#endif /* CONFIG_PM */
94666
94667 #define S3C2412_I2S_RATES \
94668 (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
94669 @@ -709,11 +154,9 @@
94670 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
94671
94672 struct snd_soc_dai s3c2412_i2s_dai = {
94673 - .name = "s3c2412-i2s",
94674 - .id = 0,
94675 - .probe = s3c2412_i2s_probe,
94676 - .suspend = s3c2412_i2s_suspend,
94677 - .resume = s3c2412_i2s_resume,
94678 + .name = "s3c2412-i2s",
94679 + .id = 0,
94680 + .probe = s3c2412_i2s_probe,
94681 .playback = {
94682 .channels_min = 2,
94683 .channels_max = 2,
94684 @@ -727,10 +170,6 @@
94685 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,
94686 },
94687 .ops = {
94688 - .trigger = s3c2412_i2s_trigger,
94689 - .hw_params = s3c2412_i2s_hw_params,
94690 - .set_fmt = s3c2412_i2s_set_fmt,
94691 - .set_clkdiv = s3c2412_i2s_set_clkdiv,
94692 .set_sysclk = s3c2412_i2s_set_sysclk,
94693 },
94694 };
94695 @@ -738,7 +177,7 @@
94696
94697 static int __init s3c2412_i2s_init(void)
94698 {
94699 - return snd_soc_register_dai(&s3c2412_i2s_dai);
94700 + return s3c_i2sv2_register_dai(&s3c2412_i2s_dai);
94701 }
94702 module_init(s3c2412_i2s_init);
94703
94704 @@ -748,7 +187,6 @@
94705 }
94706 module_exit(s3c2412_i2s_exit);
94707
94708 -
94709 /* Module information */
94710 MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
94711 MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");
94712 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c2412-i2s.h linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c2412-i2s.h
94713 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c2412-i2s.h 2009-05-10 22:05:01.000000000 +0200
94714 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c2412-i2s.h 2009-05-10 22:28:00.000000000 +0200
94715 @@ -15,9 +15,11 @@
94716 #ifndef __SND_SOC_S3C24XX_S3C2412_I2S_H
94717 #define __SND_SOC_S3C24XX_S3C2412_I2S_H __FILE__
94718
94719 -#define S3C2412_DIV_BCLK (1)
94720 -#define S3C2412_DIV_RCLK (2)
94721 -#define S3C2412_DIV_PRESCALER (3)
94722 +#include "s3c-i2s-v2.h"
94723 +
94724 +#define S3C2412_DIV_BCLK S3C_I2SV2_DIV_BCLK
94725 +#define S3C2412_DIV_RCLK S3C_I2SV2_DIV_RCLK
94726 +#define S3C2412_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
94727
94728 #define S3C2412_CLKSRC_PCLK (0)
94729 #define S3C2412_CLKSRC_I2SCLK (1)
94730 @@ -26,13 +28,4 @@
94731
94732 extern struct snd_soc_dai s3c2412_i2s_dai;
94733
94734 -struct s3c2412_rate_calc {
94735 - unsigned int clk_div; /* for prescaler */
94736 - unsigned int fs_div; /* for root frame clock */
94737 -};
94738 -
94739 -extern int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info,
94740 - unsigned int *fstab,
94741 - unsigned int rate, struct clk *clk);
94742 -
94743 #endif /* __SND_SOC_S3C24XX_S3C2412_I2S_H */
94744 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c2443-ac97.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c2443-ac97.c
94745 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c2443-ac97.c 2009-05-10 22:05:01.000000000 +0200
94746 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c2443-ac97.c 2009-05-10 22:28:00.000000000 +0200
94747 @@ -31,7 +31,7 @@
94748 #include <plat/regs-ac97.h>
94749 #include <mach/regs-gpio.h>
94750 #include <mach/regs-clock.h>
94751 -#include <mach/audio.h>
94752 +#include <plat/audio.h>
94753 #include <asm/dma.h>
94754 #include <mach/dma.h>
94755
94756 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c24xx-i2s.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c24xx-i2s.c
94757 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c24xx-i2s.c 2009-05-10 22:05:01.000000000 +0200
94758 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c24xx-i2s.c 2009-05-10 22:28:00.000000000 +0200
94759 @@ -4,7 +4,7 @@
94760 * (c) 2006 Wolfson Microelectronics PLC.
94761 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
94762 *
94763 - * (c) 2004-2005 Simtec Electronics
94764 + * Copyright 2004-2005 Simtec Electronics
94765 * http://armlinux.simtec.co.uk/
94766 * Ben Dooks <ben@simtec.co.uk>
94767 *
94768 @@ -30,11 +30,11 @@
94769 #include <mach/hardware.h>
94770 #include <mach/regs-gpio.h>
94771 #include <mach/regs-clock.h>
94772 -#include <mach/audio.h>
94773 +#include <plat/audio.h>
94774 #include <asm/dma.h>
94775 #include <mach/dma.h>
94776
94777 -#include <asm/plat-s3c24xx/regs-iis.h>
94778 +#include <plat/regs-iis.h>
94779
94780 #include "s3c24xx-pcm.h"
94781 #include "s3c24xx-i2s.h"
94782 @@ -175,7 +175,7 @@
94783 static int s3c24xx_snd_lrsync(void)
94784 {
94785 u32 iiscon;
94786 - int timeout = 50; /* 5ms */
94787 + int timeout = 5; /* 500us, 125 should be enough at 8kHz */
94788
94789 DBG("Entered %s\n", __func__);
94790
94791 @@ -291,11 +291,14 @@
94792 case SNDRV_PCM_TRIGGER_START:
94793 case SNDRV_PCM_TRIGGER_RESUME:
94794 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
94795 - if (!s3c24xx_snd_is_clkmaster()) {
94796 - ret = s3c24xx_snd_lrsync();
94797 - if (ret)
94798 - goto exit_err;
94799 - }
94800 + if (!s3c24xx_snd_is_clkmaster())
94801 + /* we ignore the return code, if it sync'd then fine,
94802 + * if it didn't sync, which happens after resume the
94803 + * first time when there was a live stream at suspend,
94804 + * just let it timeout, the stream picks up OK after
94805 + * that and LRCK is evidently working again.
94806 + */
94807 + s3c24xx_snd_lrsync();
94808
94809 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
94810 s3c24xx_snd_rxctrl(1);
94811 @@ -315,7 +318,6 @@
94812 break;
94813 }
94814
94815 -exit_err:
94816 return ret;
94817 }
94818
94819 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c24xx-pcm.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c24xx-pcm.c
94820 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c24xx-pcm.c 2009-05-10 22:05:01.000000000 +0200
94821 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c24xx-pcm.c 2009-05-10 22:28:00.000000000 +0200
94822 @@ -4,7 +4,7 @@
94823 * (c) 2006 Wolfson Microelectronics PLC.
94824 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
94825 *
94826 - * (c) 2004-2005 Simtec Electronics
94827 + * Copyright 2004-2005 Simtec Electronics
94828 * http://armlinux.simtec.co.uk/
94829 * Ben Dooks <ben@simtec.co.uk>
94830 *
94831 @@ -29,7 +29,7 @@
94832 #include <asm/dma.h>
94833 #include <mach/hardware.h>
94834 #include <mach/dma.h>
94835 -#include <mach/audio.h>
94836 +#include <plat/audio.h>
94837
94838 #include "s3c24xx-pcm.h"
94839
94840 @@ -82,11 +82,19 @@
94841 {
94842 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
94843 dma_addr_t pos = prtd->dma_pos;
94844 + unsigned int limit;
94845 int ret;
94846
94847 DBG("Entered %s\n", __func__);
94848
94849 - while (prtd->dma_loaded < prtd->dma_limit) {
94850 + if (s3c_dma_has_circular()) {
94851 + limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
94852 + } else
94853 + limit = prtd->dma_limit;
94854 +
94855 + DBG("%s: loaded %d, limit %d\n", __func__, prtd->dma_loaded, limit);
94856 +
94857 + while (prtd->dma_loaded < limit) {
94858 unsigned long len = prtd->dma_period;
94859
94860 DBG("dma_loaded: %d\n", prtd->dma_loaded);
94861 @@ -130,7 +138,7 @@
94862 snd_pcm_period_elapsed(substream);
94863
94864 spin_lock(&prtd->lock);
94865 - if (prtd->state & ST_RUNNING) {
94866 + if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
94867 prtd->dma_loaded--;
94868 s3c24xx_pcm_enqueue(substream);
94869 }
94870 @@ -168,9 +176,14 @@
94871 prtd->params->client, NULL);
94872
94873 if (ret < 0) {
94874 - DBG(KERN_ERR "failed to get dma channel\n");
94875 + DBG(KERN_ERR "failed to get dma channel: %d\n", ret);
94876 return ret;
94877 }
94878 +
94879 + /* use the circular buffering if we have it available. */
94880 + if (s3c_dma_has_circular())
94881 + s3c2410_dma_setflags(prtd->params->channel,
94882 + S3C2410_DMAF_CIRCULAR);
94883 }
94884
94885 s3c2410_dma_set_buffdone_fn(prtd->params->channel,
94886 @@ -225,23 +238,16 @@
94887 * sync to pclk, half-word transfers to the IIS-FIFO. */
94888 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
94889 s3c2410_dma_devconfig(prtd->params->channel,
94890 - S3C2410_DMASRC_MEM, S3C2410_DISRCC_INC |
94891 - S3C2410_DISRCC_APB, prtd->params->dma_addr);
94892 -
94893 - s3c2410_dma_config(prtd->params->channel,
94894 - prtd->params->dma_size,
94895 - S3C2410_DCON_SYNC_PCLK |
94896 - S3C2410_DCON_HANDSHAKE);
94897 + S3C2410_DMASRC_MEM,
94898 + prtd->params->dma_addr);
94899 } else {
94900 - s3c2410_dma_config(prtd->params->channel,
94901 - prtd->params->dma_size,
94902 - S3C2410_DCON_HANDSHAKE |
94903 - S3C2410_DCON_SYNC_PCLK);
94904 -
94905 s3c2410_dma_devconfig(prtd->params->channel,
94906 - S3C2410_DMASRC_HW, 0x3,
94907 - prtd->params->dma_addr);
94908 + S3C2410_DMASRC_HW,
94909 + prtd->params->dma_addr);
94910 }
94911 +
94912 + s3c2410_dma_config(prtd->params->channel,
94913 + prtd->params->dma_size);
94914
94915 /* flush the DMA channel */
94916 s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
94917 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c24xx_uda134x.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c24xx_uda134x.c
94918 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c24xx_uda134x.c 2009-05-10 22:05:01.000000000 +0200
94919 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c24xx_uda134x.c 2009-05-10 22:28:00.000000000 +0200
94920 @@ -22,7 +22,7 @@
94921 #include <sound/s3c24xx_uda134x.h>
94922 #include <sound/uda134x.h>
94923
94924 -#include <asm/plat-s3c24xx/regs-iis.h>
94925 +#include <plat/regs-iis.h>
94926
94927 #include "s3c24xx-pcm.h"
94928 #include "s3c24xx-i2s.h"
94929 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c64xx-i2s.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c64xx-i2s.c
94930 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c64xx-i2s.c 1970-01-01 01:00:00.000000000 +0100
94931 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c64xx-i2s.c 2009-05-10 22:28:00.000000000 +0200
94932 @@ -0,0 +1,219 @@
94933 +/* sound/soc/s3c24xx/s3c64xx-i2s.c
94934 + *
94935 + * ALSA SoC Audio Layer - S3C64XX I2S driver
94936 + *
94937 + * Copyright 2008 Openmoko, Inc.
94938 + * Copyright 2008 Simtec Electronics
94939 + * Ben Dooks <ben@simtec.co.uk>
94940 + * http://armlinux.simtec.co.uk/
94941 + *
94942 + * This program is free software; you can redistribute it and/or modify
94943 + * it under the terms of the GNU General Public License version 2 as
94944 + * published by the Free Software Foundation.
94945 + */
94946 +
94947 +#include <linux/init.h>
94948 +#include <linux/module.h>
94949 +#include <linux/device.h>
94950 +#include <linux/delay.h>
94951 +#include <linux/clk.h>
94952 +#include <linux/kernel.h>
94953 +#include <linux/gpio.h>
94954 +#include <linux/io.h>
94955 +
94956 +#include <sound/core.h>
94957 +#include <sound/pcm.h>
94958 +#include <sound/pcm_params.h>
94959 +#include <sound/initval.h>
94960 +#include <sound/soc.h>
94961 +
94962 +#include <plat/regs-s3c2412-iis.h>
94963 +#include <plat/gpio-bank-d.h>
94964 +#include <plat/gpio-bank-e.h>
94965 +#include <plat/gpio-cfg.h>
94966 +#include <plat/audio.h>
94967 +
94968 +#include <mach/map.h>
94969 +#include <mach/dma.h>
94970 +
94971 +#include "s3c24xx-pcm.h"
94972 +#include "s3c64xx-i2s.h"
94973 +
94974 +static struct s3c2410_dma_client s3c64xx_dma_client_out = {
94975 + .name = "I2S PCM Stereo out"
94976 +};
94977 +
94978 +static struct s3c2410_dma_client s3c64xx_dma_client_in = {
94979 + .name = "I2S PCM Stereo in"
94980 +};
94981 +
94982 +static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = {
94983 + [0] = {
94984 + .channel = DMACH_I2S0_OUT,
94985 + .client = &s3c64xx_dma_client_out,
94986 + .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD,
94987 + .dma_size = 4,
94988 + },
94989 + [1] = {
94990 + .channel = DMACH_I2S1_OUT,
94991 + .client = &s3c64xx_dma_client_out,
94992 + .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD,
94993 + .dma_size = 4,
94994 + },
94995 +};
94996 +
94997 +static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_in[2] = {
94998 + [0] = {
94999 + .channel = DMACH_I2S0_IN,
95000 + .client = &s3c64xx_dma_client_in,
95001 + .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD,
95002 + .dma_size = 4,
95003 + },
95004 + [1] = {
95005 + .channel = DMACH_I2S1_IN,
95006 + .client = &s3c64xx_dma_client_in,
95007 + .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD,
95008 + .dma_size = 4,
95009 + },
95010 +};
95011 +
95012 +static struct s3c_i2sv2_info s3c64xx_i2s[2];
95013 +
95014 +static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
95015 +{
95016 + return cpu_dai->private_data;
95017 +}
95018 +
95019 +static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
95020 + int clk_id, unsigned int freq, int dir)
95021 +{
95022 + struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
95023 + u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
95024 +
95025 + switch (clk_id) {
95026 + case S3C64XX_CLKSRC_PCLK:
95027 + iismod &= ~S3C64XX_IISMOD_IMS_SYSMUX;
95028 + break;
95029 +
95030 + case S3C64XX_CLKSRC_MUX:
95031 + iismod |= S3C64XX_IISMOD_IMS_SYSMUX;
95032 + break;
95033 +
95034 + default:
95035 + return -EINVAL;
95036 + }
95037 +
95038 + writel(iismod, i2s->regs + S3C2412_IISMOD);
95039 +
95040 + return 0;
95041 +}
95042 +
95043 +unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *dai)
95044 +{
95045 + struct s3c_i2sv2_info *i2s = to_info(dai);
95046 +
95047 + return clk_get_rate(i2s->iis_cclk);
95048 +}
95049 +EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clockrate);
95050 +
95051 +static int s3c64xx_i2s_probe(struct platform_device *pdev,
95052 + struct snd_soc_dai *dai)
95053 +{
95054 + struct device *dev = &pdev->dev;
95055 + struct s3c_i2sv2_info *i2s;
95056 + int ret;
95057 +
95058 + dev_dbg(dev, "%s: probing dai %d\n", __func__, pdev->id);
95059 +
95060 + if (pdev->id < 0 || pdev->id > ARRAY_SIZE(s3c64xx_i2s)) {
95061 + dev_err(dev, "id %d out of range\n", pdev->id);
95062 + return -EINVAL;
95063 + }
95064 +
95065 + i2s = &s3c64xx_i2s[pdev->id];
95066 +
95067 + ret = s3c_i2sv2_probe(pdev, dai, i2s,
95068 + pdev->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0);
95069 + if (ret)
95070 + return ret;
95071 +
95072 + i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
95073 + i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
95074 +
95075 + i2s->iis_cclk = clk_get(dev, "audio-bus");
95076 + if (IS_ERR(i2s->iis_cclk)) {
95077 + dev_err(dev, "failed to get audio-bus");
95078 + iounmap(i2s->regs);
95079 + return -ENODEV;
95080 + }
95081 +
95082 + /* configure GPIO for i2s port */
95083 + switch (pdev->id) {
95084 + case 0:
95085 + s3c_gpio_cfgpin(S3C64XX_GPD(0), S3C64XX_GPD0_I2S0_CLK);
95086 + s3c_gpio_cfgpin(S3C64XX_GPD(1), S3C64XX_GPD1_I2S0_CDCLK);
95087 + s3c_gpio_cfgpin(S3C64XX_GPD(2), S3C64XX_GPD2_I2S0_LRCLK);
95088 + s3c_gpio_cfgpin(S3C64XX_GPD(3), S3C64XX_GPD3_I2S0_DI);
95089 + s3c_gpio_cfgpin(S3C64XX_GPD(4), S3C64XX_GPD4_I2S0_D0);
95090 + break;
95091 + case 1:
95092 + s3c_gpio_cfgpin(S3C64XX_GPE(0), S3C64XX_GPE0_I2S1_CLK);
95093 + s3c_gpio_cfgpin(S3C64XX_GPE(1), S3C64XX_GPE1_I2S1_CDCLK);
95094 + s3c_gpio_cfgpin(S3C64XX_GPE(2), S3C64XX_GPE2_I2S1_LRCLK);
95095 + s3c_gpio_cfgpin(S3C64XX_GPE(3), S3C64XX_GPE3_I2S1_DI);
95096 + s3c_gpio_cfgpin(S3C64XX_GPE(4), S3C64XX_GPE4_I2S1_D0);
95097 + }
95098 +
95099 + return 0;
95100 +}
95101 +
95102 +
95103 +#define S3C64XX_I2S_RATES \
95104 + (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
95105 + SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
95106 + SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
95107 +
95108 +#define S3C64XX_I2S_FMTS \
95109 + (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE)
95110 +
95111 +struct snd_soc_dai s3c64xx_i2s_dai = {
95112 + .name = "s3c64xx-i2s",
95113 + .id = 0,
95114 + .probe = s3c64xx_i2s_probe,
95115 + .playback = {
95116 + .channels_min = 2,
95117 + .channels_max = 2,
95118 + .rates = S3C64XX_I2S_RATES,
95119 + .formats = S3C64XX_I2S_FMTS,
95120 + },
95121 + .capture = {
95122 + .channels_min = 2,
95123 + .channels_max = 2,
95124 + .rates = S3C64XX_I2S_RATES,
95125 + .formats = S3C64XX_I2S_FMTS,
95126 + },
95127 + .ops = {
95128 + .set_sysclk = s3c64xx_i2s_set_sysclk,
95129 + },
95130 +};
95131 +EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
95132 +
95133 +static int __init s3c64xx_i2s_init(void)
95134 +{
95135 + return s3c_i2sv2_register_dai(&s3c64xx_i2s_dai);
95136 +}
95137 +module_init(s3c64xx_i2s_init);
95138 +
95139 +static void __exit s3c64xx_i2s_exit(void)
95140 +{
95141 + snd_soc_unregister_dai(&s3c64xx_i2s_dai);
95142 +}
95143 +module_exit(s3c64xx_i2s_exit);
95144 +
95145 +/* Module information */
95146 +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
95147 +MODULE_DESCRIPTION("S3C64XX I2S SoC Interface");
95148 +MODULE_LICENSE("GPL");
95149 +
95150 +
95151 +
95152 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c64xx-i2s.h linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c64xx-i2s.h
95153 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c64xx-i2s.h 1970-01-01 01:00:00.000000000 +0100
95154 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c64xx-i2s.h 2009-05-10 22:28:00.000000000 +0200
95155 @@ -0,0 +1,31 @@
95156 +/* sound/soc/s3c24xx/s3c64xx-i2s.h
95157 + *
95158 + * ALSA SoC Audio Layer - S3C64XX I2S driver
95159 + *
95160 + * Copyright 2008 Openmoko, Inc.
95161 + * Copyright 2008 Simtec Electronics
95162 + * Ben Dooks <ben@simtec.co.uk>
95163 + * http://armlinux.simtec.co.uk/
95164 + *
95165 + * This program is free software; you can redistribute it and/or modify
95166 + * it under the terms of the GNU General Public License version 2 as
95167 + * published by the Free Software Foundation.
95168 + */
95169 +
95170 +#ifndef __SND_SOC_S3C24XX_S3C64XX_I2S_H
95171 +#define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__
95172 +
95173 +#include "s3c-i2s-v2.h"
95174 +
95175 +#define S3C64XX_DIV_BCLK S3C_I2SV2_DIV_BCLK
95176 +#define S3C64XX_DIV_RCLK S3C_I2SV2_DIV_RCLK
95177 +#define S3C64XX_DIV_PRESCALER S3C_I2SV2_DIV_PRESCALER
95178 +
95179 +#define S3C64XX_CLKSRC_PCLK (0)
95180 +#define S3C64XX_CLKSRC_MUX (1)
95181 +
95182 +extern struct snd_soc_dai s3c64xx_i2s_dai;
95183 +
95184 +extern unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *cpu_dai);
95185 +
95186 +#endif /* __SND_SOC_S3C24XX_S3C64XX_I2S_H */
95187 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c-i2s-v2.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c-i2s-v2.c
95188 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c-i2s-v2.c 1970-01-01 01:00:00.000000000 +0100
95189 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c-i2s-v2.c 2009-05-10 22:28:00.000000000 +0200
95190 @@ -0,0 +1,645 @@
95191 +/* sound/soc/s3c24xx/s3c-i2c-v2.c
95192 + *
95193 + * ALSA Soc Audio Layer - I2S core for newer Samsung SoCs.
95194 + *
95195 + * Copyright (c) 2006 Wolfson Microelectronics PLC.
95196 + * Graeme Gregory graeme.gregory@wolfsonmicro.com
95197 + * linux@wolfsonmicro.com
95198 + *
95199 + * Copyright (c) 2008, 2007, 2004-2005 Simtec Electronics
95200 + * http://armlinux.simtec.co.uk/
95201 + * Ben Dooks <ben@simtec.co.uk>
95202 + *
95203 + * This program is free software; you can redistribute it and/or modify it
95204 + * under the terms of the GNU General Public License as published by the
95205 + * Free Software Foundation; either version 2 of the License, or (at your
95206 + * option) any later version.
95207 + */
95208 +
95209 +#include <linux/init.h>
95210 +#include <linux/module.h>
95211 +#include <linux/device.h>
95212 +#include <linux/delay.h>
95213 +#include <linux/clk.h>
95214 +#include <linux/kernel.h>
95215 +#include <linux/io.h>
95216 +
95217 +#include <sound/core.h>
95218 +#include <sound/pcm.h>
95219 +#include <sound/pcm_params.h>
95220 +#include <sound/initval.h>
95221 +#include <sound/soc.h>
95222 +
95223 +#include <plat/regs-s3c2412-iis.h>
95224 +
95225 +#include <plat/audio.h>
95226 +#include <mach/dma.h>
95227 +
95228 +#include "s3c-i2s-v2.h"
95229 +
95230 +#define S3C2412_I2S_DEBUG_CON 0
95231 +#define S3C2412_I2S_DEBUG 0
95232 +
95233 +#if S3C2412_I2S_DEBUG
95234 +#define DBG(x...) printk(KERN_INFO x)
95235 +#else
95236 +#define DBG(x...) do { } while (0)
95237 +#endif
95238 +
95239 +static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
95240 +{
95241 + return cpu_dai->private_data;
95242 +}
95243 +
95244 +#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
95245 +
95246 +#if S3C2412_I2S_DEBUG_CON
95247 +static void dbg_showcon(const char *fn, u32 con)
95248 +{
95249 + printk(KERN_DEBUG "%s: LRI=%d, TXFEMPT=%d, RXFEMPT=%d, TXFFULL=%d, RXFFULL=%d\n", fn,
95250 + bit_set(con, S3C2412_IISCON_LRINDEX),
95251 + bit_set(con, S3C2412_IISCON_TXFIFO_EMPTY),
95252 + bit_set(con, S3C2412_IISCON_RXFIFO_EMPTY),
95253 + bit_set(con, S3C2412_IISCON_TXFIFO_FULL),
95254 + bit_set(con, S3C2412_IISCON_RXFIFO_FULL));
95255 +
95256 + printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n",
95257 + fn,
95258 + bit_set(con, S3C2412_IISCON_TXDMA_PAUSE),
95259 + bit_set(con, S3C2412_IISCON_RXDMA_PAUSE),
95260 + bit_set(con, S3C2412_IISCON_TXCH_PAUSE),
95261 + bit_set(con, S3C2412_IISCON_RXCH_PAUSE));
95262 + printk(KERN_DEBUG "%s: ACTIVE: TXDMA=%d, RXDMA=%d, IIS=%d\n", fn,
95263 + bit_set(con, S3C2412_IISCON_TXDMA_ACTIVE),
95264 + bit_set(con, S3C2412_IISCON_RXDMA_ACTIVE),
95265 + bit_set(con, S3C2412_IISCON_IIS_ACTIVE));
95266 +}
95267 +#else
95268 +static inline void dbg_showcon(const char *fn, u32 con)
95269 +{
95270 +}
95271 +#endif
95272 +
95273 +
95274 +/* Turn on or off the transmission path. */
95275 +void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
95276 +{
95277 + void __iomem *regs = i2s->regs;
95278 + u32 fic, con, mod;
95279 +
95280 + DBG("%s(%d)\n", __func__, on);
95281 +
95282 + fic = readl(regs + S3C2412_IISFIC);
95283 + con = readl(regs + S3C2412_IISCON);
95284 + mod = readl(regs + S3C2412_IISMOD);
95285 +
95286 + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
95287 +
95288 + if (on) {
95289 + con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
95290 + con &= ~S3C2412_IISCON_TXDMA_PAUSE;
95291 + con &= ~S3C2412_IISCON_TXCH_PAUSE;
95292 +
95293 + switch (mod & S3C2412_IISMOD_MODE_MASK) {
95294 + case S3C2412_IISMOD_MODE_TXONLY:
95295 + case S3C2412_IISMOD_MODE_TXRX:
95296 + /* do nothing, we are in the right mode */
95297 + break;
95298 +
95299 + case S3C2412_IISMOD_MODE_RXONLY:
95300 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95301 + mod |= S3C2412_IISMOD_MODE_TXRX;
95302 + break;
95303 +
95304 + default:
95305 + dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n");
95306 + }
95307 +
95308 + writel(con, regs + S3C2412_IISCON);
95309 + writel(mod, regs + S3C2412_IISMOD);
95310 + } else {
95311 + /* Note, we do not have any indication that the FIFO problems
95312 + * tha the S3C2410/2440 had apply here, so we should be able
95313 + * to disable the DMA and TX without resetting the FIFOS.
95314 + */
95315 +
95316 + con |= S3C2412_IISCON_TXDMA_PAUSE;
95317 + con |= S3C2412_IISCON_TXCH_PAUSE;
95318 + con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
95319 +
95320 + switch (mod & S3C2412_IISMOD_MODE_MASK) {
95321 + case S3C2412_IISMOD_MODE_TXRX:
95322 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95323 + mod |= S3C2412_IISMOD_MODE_RXONLY;
95324 + break;
95325 +
95326 + case S3C2412_IISMOD_MODE_TXONLY:
95327 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95328 + con &= ~S3C2412_IISCON_IIS_ACTIVE;
95329 + break;
95330 +
95331 + default:
95332 + dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n");
95333 + }
95334 +
95335 + writel(mod, regs + S3C2412_IISMOD);
95336 + writel(con, regs + S3C2412_IISCON);
95337 + }
95338 +
95339 + fic = readl(regs + S3C2412_IISFIC);
95340 + dbg_showcon(__func__, con);
95341 + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
95342 +}
95343 +EXPORT_SYMBOL_GPL(s3c2412_snd_txctrl);
95344 +
95345 +void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
95346 +{
95347 + void __iomem *regs = i2s->regs;
95348 + u32 fic, con, mod;
95349 +
95350 + DBG("%s(%d)\n", __func__, on);
95351 +
95352 + fic = readl(regs + S3C2412_IISFIC);
95353 + con = readl(regs + S3C2412_IISCON);
95354 + mod = readl(regs + S3C2412_IISMOD);
95355 +
95356 + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
95357 +
95358 + if (on) {
95359 + con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
95360 + con &= ~S3C2412_IISCON_RXDMA_PAUSE;
95361 + con &= ~S3C2412_IISCON_RXCH_PAUSE;
95362 +
95363 + switch (mod & S3C2412_IISMOD_MODE_MASK) {
95364 + case S3C2412_IISMOD_MODE_TXRX:
95365 + case S3C2412_IISMOD_MODE_RXONLY:
95366 + /* do nothing, we are in the right mode */
95367 + break;
95368 +
95369 + case S3C2412_IISMOD_MODE_TXONLY:
95370 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95371 + mod |= S3C2412_IISMOD_MODE_TXRX;
95372 + break;
95373 +
95374 + default:
95375 + dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
95376 + }
95377 +
95378 + writel(mod, regs + S3C2412_IISMOD);
95379 + writel(con, regs + S3C2412_IISCON);
95380 + } else {
95381 + /* See txctrl notes on FIFOs. */
95382 +
95383 + con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
95384 + con |= S3C2412_IISCON_RXDMA_PAUSE;
95385 + con |= S3C2412_IISCON_RXCH_PAUSE;
95386 +
95387 + switch (mod & S3C2412_IISMOD_MODE_MASK) {
95388 + case S3C2412_IISMOD_MODE_RXONLY:
95389 + con &= ~S3C2412_IISCON_IIS_ACTIVE;
95390 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95391 + break;
95392 +
95393 + case S3C2412_IISMOD_MODE_TXRX:
95394 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95395 + mod |= S3C2412_IISMOD_MODE_TXONLY;
95396 + break;
95397 +
95398 + default:
95399 + dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
95400 + }
95401 +
95402 + writel(con, regs + S3C2412_IISCON);
95403 + writel(mod, regs + S3C2412_IISMOD);
95404 + }
95405 +
95406 + fic = readl(regs + S3C2412_IISFIC);
95407 + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
95408 +}
95409 +EXPORT_SYMBOL_GPL(s3c2412_snd_rxctrl);
95410 +
95411 +/*
95412 + * Wait for the LR signal to allow synchronisation to the L/R clock
95413 + * from the codec. May only be needed for slave mode.
95414 + */
95415 +static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s)
95416 +{
95417 + u32 iiscon;
95418 + unsigned long timeout = jiffies + msecs_to_jiffies(5);
95419 +
95420 + DBG("Entered %s\n", __func__);
95421 +
95422 + while (1) {
95423 + iiscon = readl(i2s->regs + S3C2412_IISCON);
95424 + if (iiscon & S3C2412_IISCON_LRINDEX)
95425 + break;
95426 +
95427 + if (timeout < jiffies) {
95428 + printk(KERN_ERR "%s: timeout\n", __func__);
95429 + return -ETIMEDOUT;
95430 + }
95431 + }
95432 +
95433 + return 0;
95434 +}
95435 +
95436 +/*
95437 + * Set S3C2412 I2S DAI format
95438 + */
95439 +static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
95440 + unsigned int fmt)
95441 +{
95442 + struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
95443 + u32 iismod;
95444 +
95445 + DBG("Entered %s\n", __func__);
95446 +
95447 + iismod = readl(i2s->regs + S3C2412_IISMOD);
95448 + DBG("hw_params r: IISMOD: %x \n", iismod);
95449 +
95450 +#if defined(CONFIG_CPU_S3C2412) || defined(CONFIG_CPU_S3C2413)
95451 +#define IISMOD_MASTER_MASK S3C2412_IISMOD_MASTER_MASK
95452 +#define IISMOD_SLAVE S3C2412_IISMOD_SLAVE
95453 +#define IISMOD_MASTER S3C2412_IISMOD_MASTER_INTERNAL
95454 +#endif
95455 +
95456 +#if defined(CONFIG_PLAT_S3C64XX)
95457 +/* From Rev1.1 datasheet, we have two master and two slave modes:
95458 + * IMS[11:10]:
95459 + * 00 = master mode, fed from PCLK
95460 + * 01 = master mode, fed from CLKAUDIO
95461 + * 10 = slave mode, using PCLK
95462 + * 11 = slave mode, using I2SCLK
95463 + */
95464 +#define IISMOD_MASTER_MASK (1 << 11)
95465 +#define IISMOD_SLAVE (1 << 11)
95466 +#define IISMOD_MASTER (0x0)
95467 +#endif
95468 +
95469 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
95470 + case SND_SOC_DAIFMT_CBM_CFM:
95471 + i2s->master = 0;
95472 + iismod &= ~IISMOD_MASTER_MASK;
95473 + iismod |= IISMOD_SLAVE;
95474 + break;
95475 + case SND_SOC_DAIFMT_CBS_CFS:
95476 + i2s->master = 1;
95477 + iismod &= ~IISMOD_MASTER_MASK;
95478 + iismod |= IISMOD_MASTER;
95479 + break;
95480 + default:
95481 + DBG("unknwon master/slave format\n");
95482 + return -EINVAL;
95483 + }
95484 +
95485 + iismod &= ~S3C2412_IISMOD_SDF_MASK;
95486 +
95487 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
95488 + case SND_SOC_DAIFMT_RIGHT_J:
95489 + iismod |= S3C2412_IISMOD_SDF_MSB;
95490 + break;
95491 + case SND_SOC_DAIFMT_LEFT_J:
95492 + iismod |= S3C2412_IISMOD_SDF_LSB;
95493 + break;
95494 + case SND_SOC_DAIFMT_I2S:
95495 + iismod |= S3C2412_IISMOD_SDF_IIS;
95496 + break;
95497 + default:
95498 + DBG("Unknown data format\n");
95499 + return -EINVAL;
95500 + }
95501 +
95502 + writel(iismod, i2s->regs + S3C2412_IISMOD);
95503 + DBG("hw_params w: IISMOD: %x \n", iismod);
95504 + return 0;
95505 +}
95506 +
95507 +static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
95508 + struct snd_pcm_hw_params *params,
95509 + struct snd_soc_dai *socdai)
95510 +{
95511 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
95512 + struct snd_soc_dai_link *dai = rtd->dai;
95513 + struct s3c_i2sv2_info *i2s = to_info(dai->cpu_dai);
95514 + u32 iismod;
95515 +
95516 + DBG("Entered %s\n", __func__);
95517 +
95518 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
95519 + dai->cpu_dai->dma_data = i2s->dma_playback;
95520 + else
95521 + dai->cpu_dai->dma_data = i2s->dma_capture;
95522 +
95523 + /* Working copies of register */
95524 + iismod = readl(i2s->regs + S3C2412_IISMOD);
95525 + DBG("%s: r: IISMOD: %x\n", __func__, iismod);
95526 +
95527 + switch (params_format(params)) {
95528 + case SNDRV_PCM_FORMAT_S8:
95529 + iismod |= S3C2412_IISMOD_8BIT;
95530 + break;
95531 + case SNDRV_PCM_FORMAT_S16_LE:
95532 + iismod &= ~S3C2412_IISMOD_8BIT;
95533 + break;
95534 + }
95535 +
95536 + writel(iismod, i2s->regs + S3C2412_IISMOD);
95537 + DBG("%s: w: IISMOD: %x\n", __func__, iismod);
95538 + return 0;
95539 +}
95540 +
95541 +static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
95542 + struct snd_soc_dai *dai)
95543 +{
95544 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
95545 + struct s3c_i2sv2_info *i2s = to_info(rtd->dai->cpu_dai);
95546 + int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
95547 + unsigned long irqs;
95548 + int ret = 0;
95549 +
95550 + DBG("Entered %s\n", __func__);
95551 +
95552 + switch (cmd) {
95553 + case SNDRV_PCM_TRIGGER_START:
95554 + /* On start, ensure that the FIFOs are cleared and reset. */
95555 +
95556 + writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH,
95557 + i2s->regs + S3C2412_IISFIC);
95558 +
95559 + /* clear again, just in case */
95560 + writel(0x0, i2s->regs + S3C2412_IISFIC);
95561 +
95562 + case SNDRV_PCM_TRIGGER_RESUME:
95563 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
95564 + if (!i2s->master) {
95565 + ret = s3c2412_snd_lrsync(i2s);
95566 + if (ret)
95567 + goto exit_err;
95568 + }
95569 +
95570 + local_irq_save(irqs);
95571 +
95572 + if (capture)
95573 + s3c2412_snd_rxctrl(i2s, 1);
95574 + else
95575 + s3c2412_snd_txctrl(i2s, 1);
95576 +
95577 + local_irq_restore(irqs);
95578 + break;
95579 +
95580 + case SNDRV_PCM_TRIGGER_STOP:
95581 + case SNDRV_PCM_TRIGGER_SUSPEND:
95582 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
95583 + local_irq_save(irqs);
95584 +
95585 + if (capture)
95586 + s3c2412_snd_rxctrl(i2s, 0);
95587 + else
95588 + s3c2412_snd_txctrl(i2s, 0);
95589 +
95590 + local_irq_restore(irqs);
95591 + break;
95592 + default:
95593 + ret = -EINVAL;
95594 + break;
95595 + }
95596 +
95597 +exit_err:
95598 + return ret;
95599 +}
95600 +
95601 +/*
95602 + * Set S3C2412 Clock dividers
95603 + */
95604 +static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
95605 + int div_id, int div)
95606 +{
95607 + struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
95608 + u32 reg;
95609 +
95610 + DBG("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div);
95611 +
95612 + switch (div_id) {
95613 + case S3C_I2SV2_DIV_BCLK:
95614 + reg = readl(i2s->regs + S3C2412_IISMOD);
95615 + reg &= ~S3C2412_IISMOD_BCLK_MASK;
95616 + writel(reg | div, i2s->regs + S3C2412_IISMOD);
95617 +
95618 + DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
95619 + break;
95620 +
95621 + case S3C_I2SV2_DIV_RCLK:
95622 + if (div > 3) {
95623 + /* convert value to bit field */
95624 +
95625 + switch (div) {
95626 + case 256:
95627 + div = S3C2412_IISMOD_RCLK_256FS;
95628 + break;
95629 +
95630 + case 384:
95631 + div = S3C2412_IISMOD_RCLK_384FS;
95632 + break;
95633 +
95634 + case 512:
95635 + div = S3C2412_IISMOD_RCLK_512FS;
95636 + break;
95637 +
95638 + case 768:
95639 + div = S3C2412_IISMOD_RCLK_768FS;
95640 + break;
95641 +
95642 + default:
95643 + return -EINVAL;
95644 + }
95645 + }
95646 +
95647 + reg = readl(i2s->regs + S3C2412_IISMOD);
95648 + reg &= ~S3C2412_IISMOD_RCLK_MASK;
95649 + writel(reg | div, i2s->regs + S3C2412_IISMOD);
95650 + DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
95651 + break;
95652 +
95653 + case S3C_I2SV2_DIV_PRESCALER:
95654 + if (div >= 0) {
95655 + writel((div << 8) | S3C2412_IISPSR_PSREN,
95656 + i2s->regs + S3C2412_IISPSR);
95657 + } else {
95658 + writel(0x0, i2s->regs + S3C2412_IISPSR);
95659 + }
95660 + DBG("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR));
95661 + break;
95662 +
95663 + default:
95664 + return -EINVAL;
95665 + }
95666 +
95667 + return 0;
95668 +}
95669 +
95670 +/* default table of all avaialable root fs divisors */
95671 +static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 };
95672 +
95673 +int s3c2412_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
95674 + unsigned int *fstab,
95675 + unsigned int rate, struct clk *clk)
95676 +{
95677 + unsigned long clkrate = clk_get_rate(clk);
95678 + unsigned int div;
95679 + unsigned int fsclk;
95680 + unsigned int actual;
95681 + unsigned int fs;
95682 + unsigned int fsdiv;
95683 + signed int deviation = 0;
95684 + unsigned int best_fs = 0;
95685 + unsigned int best_div = 0;
95686 + unsigned int best_rate = 0;
95687 + unsigned int best_deviation = INT_MAX;
95688 +
95689 + if (fstab == NULL)
95690 + fstab = iis_fs_tab;
95691 +
95692 + for (fs = 0; fs < ARRAY_SIZE(iis_fs_tab); fs++) {
95693 + fsdiv = iis_fs_tab[fs];
95694 +
95695 + fsclk = clkrate / fsdiv;
95696 + div = fsclk / rate;
95697 +
95698 + if ((fsclk % rate) > (rate / 2))
95699 + div++;
95700 +
95701 + if (div <= 1)
95702 + continue;
95703 +
95704 + actual = clkrate / (fsdiv * div);
95705 + deviation = actual - rate;
95706 +
95707 + printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n",
95708 + fsdiv, div, actual, deviation);
95709 +
95710 + deviation = abs(deviation);
95711 +
95712 + if (deviation < best_deviation) {
95713 + best_fs = fsdiv;
95714 + best_div = div;
95715 + best_rate = actual;
95716 + best_deviation = deviation;
95717 + }
95718 +
95719 + if (deviation == 0)
95720 + break;
95721 + }
95722 +
95723 + printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n",
95724 + best_fs, best_div, best_rate);
95725 +
95726 + info->fs_div = best_fs;
95727 + info->clk_div = best_div;
95728 +
95729 + return 0;
95730 +}
95731 +EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate);
95732 +
95733 +int s3c_i2sv2_probe(struct platform_device *pdev,
95734 + struct snd_soc_dai *dai,
95735 + struct s3c_i2sv2_info *i2s,
95736 + unsigned long base)
95737 +{
95738 + struct device *dev = &pdev->dev;
95739 +
95740 + i2s->dev = dev;
95741 +
95742 + /* record our i2s structure for later use in the callbacks */
95743 + dai->private_data = i2s;
95744 +
95745 + i2s->regs = ioremap(base, 0x100);
95746 + if (i2s->regs == NULL) {
95747 + dev_err(dev, "cannot ioremap registers\n");
95748 + return -ENXIO;
95749 + }
95750 +
95751 + i2s->iis_pclk = clk_get(dev, "iis");
95752 + if (i2s->iis_pclk == NULL) {
95753 + DBG("failed to get iis_clock\n");
95754 + iounmap(i2s->regs);
95755 + return -ENOENT;
95756 + }
95757 +
95758 + clk_enable(i2s->iis_pclk);
95759 +
95760 + s3c2412_snd_txctrl(i2s, 0);
95761 + s3c2412_snd_rxctrl(i2s, 0);
95762 +
95763 + return 0;
95764 +}
95765 +
95766 +EXPORT_SYMBOL_GPL(s3c_i2sv2_probe);
95767 +
95768 +#ifdef CONFIG_PM
95769 +static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
95770 +{
95771 + struct s3c_i2sv2_info *i2s = to_info(dai);
95772 + u32 iismod;
95773 +
95774 + if (dai->active) {
95775 + i2s->suspend_iismod = readl(i2s->regs + S3C2412_IISMOD);
95776 + i2s->suspend_iiscon = readl(i2s->regs + S3C2412_IISCON);
95777 + i2s->suspend_iispsr = readl(i2s->regs + S3C2412_IISPSR);
95778 +
95779 + /* some basic suspend checks */
95780 +
95781 + iismod = readl(i2s->regs + S3C2412_IISMOD);
95782 +
95783 + if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
95784 + pr_warning("%s: RXDMA active?\n", __func__);
95785 +
95786 + if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
95787 + pr_warning("%s: TXDMA active?\n", __func__);
95788 +
95789 + if (iismod & S3C2412_IISCON_IIS_ACTIVE)
95790 + pr_warning("%s: IIS active\n", __func__);
95791 + }
95792 +
95793 + return 0;
95794 +}
95795 +
95796 +static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
95797 +{
95798 + struct s3c_i2sv2_info *i2s = to_info(dai);
95799 +
95800 + pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
95801 + dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
95802 +
95803 + if (dai->active) {
95804 + writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
95805 + writel(i2s->suspend_iismod, i2s->regs + S3C2412_IISMOD);
95806 + writel(i2s->suspend_iispsr, i2s->regs + S3C2412_IISPSR);
95807 +
95808 + writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
95809 + i2s->regs + S3C2412_IISFIC);
95810 +
95811 + ndelay(250);
95812 + writel(0x0, i2s->regs + S3C2412_IISFIC);
95813 + }
95814 +
95815 + return 0;
95816 +}
95817 +#else
95818 +#define s3c2412_i2s_suspend NULL
95819 +#define s3c2412_i2s_resume NULL
95820 +#endif
95821 +
95822 +int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
95823 +{
95824 + dai->ops.trigger = s3c2412_i2s_trigger;
95825 + dai->ops.hw_params = s3c2412_i2s_hw_params;
95826 + dai->ops.set_fmt = s3c2412_i2s_set_fmt;
95827 + dai->ops.set_clkdiv = s3c2412_i2s_set_clkdiv;
95828 +
95829 + dai->suspend = s3c2412_i2s_suspend;
95830 + dai->resume = s3c2412_i2s_resume;
95831 +
95832 + return snd_soc_register_dai(dai);
95833 +}
95834 +
95835 +EXPORT_SYMBOL_GPL(s3c_i2sv2_register_dai);
95836 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c-i2s-v2.h linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c-i2s-v2.h
95837 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/s3c-i2s-v2.h 1970-01-01 01:00:00.000000000 +0100
95838 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/s3c-i2s-v2.h 2009-05-10 22:28:00.000000000 +0200
95839 @@ -0,0 +1,90 @@
95840 +/* sound/soc/s3c24xx/s3c-i2s-v2.h
95841 + *
95842 + * ALSA Soc Audio Layer - S3C_I2SV2 I2S driver
95843 + *
95844 + * Copyright (c) 2007 Simtec Electronics
95845 + * http://armlinux.simtec.co.uk/
95846 + * Ben Dooks <ben@simtec.co.uk>
95847 + *
95848 + * This program is free software; you can redistribute it and/or modify it
95849 + * under the terms of the GNU General Public License as published by the
95850 + * Free Software Foundation; either version 2 of the License, or (at your
95851 + * option) any later version.
95852 +*/
95853 +
95854 +/* This code is the core support for the I2S block found in a number of
95855 + * Samsung SoC devices which is unofficially named I2S-V2. Currently the
95856 + * S3C2412 and the S3C64XX series use this block to provide 1 or 2 I2S
95857 + * channels via configurable GPIO.
95858 + */
95859 +
95860 +#ifndef __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H
95861 +#define __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H __FILE__
95862 +
95863 +#define S3C_I2SV2_DIV_BCLK (1)
95864 +#define S3C_I2SV2_DIV_RCLK (2)
95865 +#define S3C_I2SV2_DIV_PRESCALER (3)
95866 +
95867 +/**
95868 + * struct s3c_i2sv2_info - S3C I2S-V2 information
95869 + * @dev: The parent device passed to use from the probe.
95870 + * @regs: The pointer to the device registe block.
95871 + * @master: True if the I2S core is the I2S bit clock master.
95872 + * @dma_playback: DMA information for playback channel.
95873 + * @dma_capture: DMA information for capture channel.
95874 + * @suspend_iismod: PM save for the IISMOD register.
95875 + * @suspend_iiscon: PM save for the IISCON register.
95876 + * @suspend_iispsr: PM save for the IISPSR register.
95877 + *
95878 + * This is the private codec state for the hardware associated with an
95879 + * I2S channel such as the register mappings and clock sources.
95880 + */
95881 +struct s3c_i2sv2_info {
95882 + struct device *dev;
95883 + void __iomem *regs;
95884 +
95885 + struct clk *iis_pclk;
95886 + struct clk *iis_cclk;
95887 + struct clk *iis_clk;
95888 +
95889 + unsigned char master;
95890 +
95891 + struct s3c24xx_pcm_dma_params *dma_playback;
95892 + struct s3c24xx_pcm_dma_params *dma_capture;
95893 +
95894 + u32 suspend_iismod;
95895 + u32 suspend_iiscon;
95896 + u32 suspend_iispsr;
95897 +};
95898 +
95899 +struct s3c_i2sv2_rate_calc {
95900 + unsigned int clk_div; /* for prescaler */
95901 + unsigned int fs_div; /* for root frame clock */
95902 +};
95903 +
95904 +extern int s3c_i2sv2_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
95905 + unsigned int *fstab,
95906 + unsigned int rate, struct clk *clk);
95907 +
95908 +/**
95909 + * s3c_i2sv2_probe - probe for i2s device helper
95910 + * @pdev: The platform device supplied to the original probe.
95911 + * @dai: The ASoC DAI structure supplied to the original probe.
95912 + * @i2s: Our local i2s structure to fill in.
95913 + * @base: The base address for the registers.
95914 + */
95915 +extern int s3c_i2sv2_probe(struct platform_device *pdev,
95916 + struct snd_soc_dai *dai,
95917 + struct s3c_i2sv2_info *i2s,
95918 + unsigned long base);
95919 +
95920 +/**
95921 + * s3c_i2sv2_register_dai - register dai with soc core
95922 + * @dai: The snd_soc_dai structure to register
95923 + *
95924 + * Fill in any missing fields and then register the given dai with the
95925 + * soc core.
95926 + */
95927 +extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai);
95928 +
95929 +#endif /* __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H */
95930 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/smdk6410-wm8731.c linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/smdk6410-wm8731.c
95931 --- linux-2.6.29-rc3.owrt/sound/soc/s3c24xx/smdk6410-wm8731.c 1970-01-01 01:00:00.000000000 +0100
95932 +++ linux-2.6.29-rc3.owrt.om/sound/soc/s3c24xx/smdk6410-wm8731.c 2009-05-10 22:28:00.000000000 +0200
95933 @@ -0,0 +1,227 @@
95934 +
95935 +
95936 +#include <linux/module.h>
95937 +#include <linux/moduleparam.h>
95938 +#include <linux/kernel.h>
95939 +#include <linux/clk.h>
95940 +#include <linux/timer.h>
95941 +#include <linux/interrupt.h>
95942 +#include <linux/platform_device.h>
95943 +
95944 +#include <sound/core.h>
95945 +#include <sound/pcm.h>
95946 +#include <sound/pcm_params.h>
95947 +#include <sound/soc.h>
95948 +#include <sound/soc-dapm.h>
95949 +
95950 +#include <asm/mach-types.h>
95951 +
95952 +#include "../codecs/wm8731.h"
95953 +#include "s3c64xx-i2s.h"
95954 +
95955 +static struct platform_device *socdev;
95956 +
95957 +
95958 +
95959 +static void wm_shutdown(struct snd_pcm_substream *substream)
95960 +{
95961 + printk(KERN_INFO "%s: substream %p\n", __func__, substream);
95962 +}
95963 +
95964 +static int wm_hw_params(struct snd_pcm_substream *substream,
95965 + struct snd_pcm_hw_params *params)
95966 +{
95967 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
95968 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
95969 + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
95970 + unsigned int fmt;
95971 + int ret;
95972 +
95973 + printk(KERN_INFO "%s: (%p,%p)\n", __func__, substream, params);
95974 + printk(KERN_INFO "%s: dai: cpu %p, codec %p\n", __func__, cpu_dai, codec_dai);
95975 +
95976 + //fmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS;
95977 + fmt = SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM;
95978 + fmt |= SND_SOC_DAIFMT_I2S;
95979 +
95980 + ret = snd_soc_dai_set_fmt(codec_dai, fmt);
95981 + if (ret < 0)
95982 + return ret;
95983 +
95984 + /* set cpu DAI configuration */
95985 + ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
95986 + if (ret < 0)
95987 + return ret;
95988 +
95989 + if (fmt == (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM)) {
95990 + unsigned long iis_clkrate;
95991 +
95992 + ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_MUX, 0,
95993 + SND_SOC_CLOCK_OUT);
95994 + if (ret < 0) {
95995 + printk(KERN_ERR "%s: cpu set_sysclk err\n", __func__);
95996 + return ret;
95997 + }
95998 +
95999 + /* set prescaler division for sample rate */
96000 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C64XX_DIV_PRESCALER, 1);
96001 + if (ret < 0) {
96002 + printk(KERN_ERR "%s: codec clkdiv err\n", __func__);
96003 + return ret;
96004 + }
96005 +
96006 + iis_clkrate = s3c64xx_i2s_get_clockrate(cpu_dai) / 2;
96007 + printk(KERN_INFO "%s: clockrate %ld\n", __func__, iis_clkrate);
96008 +
96009 + iis_clkrate = 12000000; //tmphack//
96010 +
96011 + /* set the codec system clock for DAC and ADC */
96012 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
96013 + iis_clkrate,
96014 + SND_SOC_CLOCK_IN);
96015 + if (ret < 0) {
96016 + printk(KERN_ERR "%s: codec sysclk err\n", __func__);
96017 + return ret;
96018 + }
96019 +
96020 + } else {
96021 + /* TODO */
96022 + BUG();
96023 + }
96024 +
96025 + return 0;
96026 +}
96027 +
96028 +static int wm_startup(struct snd_pcm_substream *substream)
96029 +{
96030 + struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
96031 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
96032 + struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
96033 + int ret;
96034 +
96035 + ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_MUX, 0,
96036 + SND_SOC_CLOCK_OUT);
96037 + if (ret < 0) {
96038 + printk(KERN_ERR "%s: cpu set_sysclk err\n", __func__);
96039 + return ret;
96040 + }
96041 +
96042 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C64XX_DIV_PRESCALER, 1);
96043 + if (ret < 0) {
96044 + printk(KERN_ERR "%s: cpu set_clkdiv err\n", __func__);
96045 + return ret;
96046 + }
96047 +
96048 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
96049 + 12000000, SND_SOC_CLOCK_IN);
96050 + if (ret < 0) {
96051 + printk(KERN_ERR "%s: codec sysclk err\n", __func__);
96052 + return ret;
96053 + }
96054 +
96055 + return 0;
96056 +}
96057 +
96058 +static struct snd_soc_ops wm_ops = {
96059 + .startup = wm_startup,
96060 + .hw_params = wm_hw_params,
96061 + .shutdown = wm_shutdown,
96062 +};
96063 +
96064 +static const struct snd_soc_dapm_widget widgets[] = {
96065 + SND_SOC_DAPM_LINE("Line Out", NULL),
96066 + SND_SOC_DAPM_HP("Headphone Jack", NULL),
96067 + SND_SOC_DAPM_INPUT("Line In"),
96068 +};
96069 +
96070 +static const struct snd_soc_dapm_route intercon[] = {
96071 + /* headphone connected to LHPOUT1, RHPOUT1 */
96072 + {"Headphone Jack", NULL, "LHPOUT"},
96073 + {"Headphone Jack", NULL, "RHPOUT"},
96074 +
96075 + {"Line Out", NULL, "LOUT" },
96076 + {"Line Out", NULL, "ROUT" },
96077 +
96078 + {"LLINEIN", NULL, "Line In" },
96079 + {"RLINEIN", NULL, "Line In" },
96080 +};
96081 +
96082 +static int wm_init(struct snd_soc_codec *codec)
96083 +{
96084 + printk(KERN_DEBUG "%s: codec %p\n", __func__, codec);
96085 +
96086 + snd_soc_dapm_new_controls(codec, widgets, ARRAY_SIZE(widgets));
96087 + snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
96088 +
96089 + snd_soc_dapm_sync(codec);
96090 +
96091 + return 0;
96092 +}
96093 +
96094 +#include "s3c24xx-pcm.h"
96095 +
96096 +static struct snd_soc_dai_link wm_dai_link = {
96097 + .name = "WM8731",
96098 + .stream_name = "WM8731",
96099 + .cpu_dai = &s3c64xx_i2s_dai,
96100 + .codec_dai = &wm8731_dai,
96101 + .init = wm_init,
96102 + .ops = &wm_ops,
96103 +};
96104 +
96105 +static struct snd_soc_card wm_card = {
96106 + .name = "SMDK6410-WM8731",
96107 + .dai_link = &wm_dai_link,
96108 + .platform = &s3c24xx_soc_platform,
96109 + .num_links = 1,
96110 +};
96111 +
96112 +struct wm8731_setup_data wm_setup = {
96113 + .i2c_bus = 0,
96114 + .i2c_address = 0x1a,
96115 +};
96116 +
96117 +static struct snd_soc_device wm_snd_devdata = {
96118 + .card = &wm_card,
96119 + .codec_dev = &soc_codec_dev_wm8731,
96120 + .codec_data = &wm_setup,
96121 +};
96122 +
96123 +static int __init smdk6410_wm8731_init(void)
96124 +{
96125 + int ret;
96126 +
96127 + printk(KERN_INFO "%s: welcome\n", __func__);
96128 +
96129 + if (!machine_is_smdk6410()) {
96130 + printk(KERN_INFO "%s: for SMDK6410s\n", __func__);
96131 + return -ENOENT;
96132 + }
96133 +
96134 + socdev = platform_device_alloc("soc-audio", 0);
96135 + if (!socdev) {
96136 + printk(KERN_ERR "%s: no device\n", __func__);
96137 + return -ENOMEM;
96138 + }
96139 +
96140 + platform_set_drvdata(socdev, &wm_snd_devdata);
96141 +
96142 + wm_snd_devdata.dev = &socdev->dev;
96143 +
96144 + ret = platform_device_add(socdev);
96145 + if (ret) {
96146 + printk(KERN_ERR "%s: failed to add\n", __func__);
96147 + goto err_dev;
96148 + }
96149 +
96150 + printk(KERN_INFO "%s: succesfull\n", __func__);
96151 + return 0;
96152 +
96153 +err_dev:
96154 + platform_device_put(socdev);
96155 + return ret;
96156 +}
96157 +
96158 +module_init(smdk6410_wm8731_init);
96159 +MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
96160 +MODULE_LICENSE("GPL");
96161 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/soc-core.c linux-2.6.29-rc3.owrt.om/sound/soc/soc-core.c
96162 --- linux-2.6.29-rc3.owrt/sound/soc/soc-core.c 2009-05-10 22:09:10.000000000 +0200
96163 +++ linux-2.6.29-rc3.owrt.om/sound/soc/soc-core.c 2009-05-10 22:28:00.000000000 +0200
96164 @@ -1190,6 +1190,7 @@
96165 }
96166 #endif
96167
96168 +
96169 /**
96170 * snd_soc_new_ac97_codec - initailise AC97 device
96171 * @codec: audio codec
96172 diff -ruN --exclude='*.orig' --exclude='*.rej' linux-2.6.29-rc3.owrt/sound/soc/soc-dapm.c linux-2.6.29-rc3.owrt.om/sound/soc/soc-dapm.c
96173 --- linux-2.6.29-rc3.owrt/sound/soc/soc-dapm.c 2009-05-10 22:05:01.000000000 +0200
96174 +++ linux-2.6.29-rc3.owrt.om/sound/soc/soc-dapm.c 2009-05-10 22:28:00.000000000 +0200
96175 @@ -332,6 +332,24 @@
96176
96177 snprintf(path->long_name, name_len, "%s %s",
96178 w->name, w->kcontrols[i].name);
96179 +
96180 + /*
96181 + * This is an ugly Openmoko revert for name
96182 + * changes in alsa configuration. This is mergeable
96183 + * with the future Linux version.
96184 + * We force the truncation again for now because we
96185 + * can't cope with mass breakage on alsa state files
96186 + * that are spread all over the different distros.
96187 + * FIXME: Remember to revert this change.
96188 + */
96189 +
96190 + if (name_len > 32) {
96191 + printk(KERN_WARNING __FILE__ ":%d mixer name "
96192 + "'%s' truncated to 31 characters.\n",
96193 + __LINE__, path->long_name);
96194 + name_len = 32;
96195 + }
96196 +
96197 path->long_name[name_len - 1] = '\0';
96198
96199 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
96200 @@ -876,7 +894,7 @@
96201 }
96202
96203 static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
96204 - char *pin, int status)
96205 + const char *pin, int status)
96206 {
96207 struct snd_soc_dapm_widget *w;
96208
96209 @@ -1396,6 +1414,76 @@
96210 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
96211
96212 /**
96213 + * snd_soc_dapm_info_pin_switch - Info for a pin switch
96214 + *
96215 + * @kcontrol: mixer control
96216 + * @uinfo: control element information
96217 + *
96218 + * Callback to provide information about a pin switch control.
96219 + */
96220 +int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
96221 + struct snd_ctl_elem_info *uinfo)
96222 +{
96223 + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
96224 + uinfo->count = 1;
96225 + uinfo->value.integer.min = 0;
96226 + uinfo->value.integer.max = 1;
96227 +
96228 + return 0;
96229 +}
96230 +EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
96231 +
96232 +/**
96233 + * snd_soc_dapm_get_pin_switch - Get information for a pin switch
96234 + *
96235 + * @kcontrol: mixer control
96236 + * @ucontrol: Value
96237 + */
96238 +int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
96239 + struct snd_ctl_elem_value *ucontrol)
96240 +{
96241 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
96242 + const char *pin = (const char *)kcontrol->private_value;
96243 +
96244 + mutex_lock(&codec->mutex);
96245 +
96246 + ucontrol->value.integer.value[0] =
96247 + snd_soc_dapm_get_pin_status(codec, pin);
96248 +
96249 + mutex_unlock(&codec->mutex);
96250 +
96251 + return 0;
96252 +}
96253 +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
96254 +
96255 +/**
96256 + * snd_soc_dapm_put_pin_switch - Set information for a pin switch
96257 + *
96258 + * @kcontrol: mixer control
96259 + * @ucontrol: Value
96260 + */
96261 +int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
96262 + struct snd_ctl_elem_value *ucontrol)
96263 +{
96264 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
96265 + const char *pin = (const char *)kcontrol->private_value;
96266 +
96267 + mutex_lock(&codec->mutex);
96268 +
96269 + if (ucontrol->value.integer.value[0])
96270 + snd_soc_dapm_enable_pin(codec, pin);
96271 + else
96272 + snd_soc_dapm_disable_pin(codec, pin);
96273 +
96274 + snd_soc_dapm_sync(codec);
96275 +
96276 + mutex_unlock(&codec->mutex);
96277 +
96278 + return 0;
96279 +}
96280 +EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
96281 +
96282 +/**
96283 * snd_soc_dapm_new_control - create new dapm control
96284 * @codec: audio codec
96285 * @widget: widget template
96286 @@ -1549,7 +1637,7 @@
96287 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
96288 * do any widget power switching.
96289 */
96290 -int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, char *pin)
96291 +int snd_soc_dapm_enable_pin(struct snd_soc_codec *codec, const char *pin)
96292 {
96293 return snd_soc_dapm_set_pin(codec, pin, 1);
96294 }
96295 @@ -1564,7 +1652,7 @@
96296 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
96297 * do any widget power switching.
96298 */
96299 -int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, char *pin)
96300 +int snd_soc_dapm_disable_pin(struct snd_soc_codec *codec, const char *pin)
96301 {
96302 return snd_soc_dapm_set_pin(codec, pin, 0);
96303 }
96304 @@ -1584,7 +1672,7 @@
96305 * NOTE: snd_soc_dapm_sync() needs to be called after this for DAPM to
96306 * do any widget power switching.
96307 */
96308 -int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, char *pin)
96309 +int snd_soc_dapm_nc_pin(struct snd_soc_codec *codec, const char *pin)
96310 {
96311 return snd_soc_dapm_set_pin(codec, pin, 0);
96312 }
96313 @@ -1599,7 +1687,7 @@
96314 *
96315 * Returns 1 for connected otherwise 0.
96316 */
96317 -int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, char *pin)
96318 +int snd_soc_dapm_get_pin_status(struct snd_soc_codec *codec, const char *pin)
96319 {
96320 struct snd_soc_dapm_widget *w;
96321
96322 @@ -1613,6 +1701,56 @@
96323 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
96324
96325 /**
96326 + * snd_soc_dapm_get_endpoint - get audio endpoint status
96327 + * @codec: audio codec
96328 + * @endpoint: audio signal endpoint (or start point)
96329 + *
96330 + * Get audio endpoint status - connected or disconnected.
96331 + *
96332 + * Returns status
96333 + */
96334 +int snd_soc_dapm_get_endpoint(struct snd_soc_codec *codec,
96335 + char *endpoint)
96336 +{
96337 + struct snd_soc_dapm_widget *w;
96338 +
96339 + list_for_each_entry(w, &codec->dapm_widgets, list) {
96340 + if (!strcmp(w->name, endpoint)) {
96341 + return w->connected;
96342 + }
96343 + }
96344 +
96345 + return 0;
96346 +}
96347 +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_endpoint);
96348 +
96349 +/**
96350 + * snd_soc_dapm_set_endpoint - set audio endpoint status
96351 + * @codec: audio codec
96352 + * @endpoint: audio signal endpoint (or start point)
96353 + * @status: point status
96354 + *
96355 + * Set audio endpoint status - connected or disconnected.
96356 + *
96357 + * Returns 0 for success else error.
96358 + */
96359 +int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
96360 + char *endpoint, int status)
96361 +{
96362 + struct snd_soc_dapm_widget *w;
96363 +
96364 + list_for_each_entry(w, &codec->dapm_widgets, list) {
96365 + if (!strcmp(w->name, endpoint)) {
96366 + w->connected = status;
96367 + return 0;
96368 + }
96369 + }
96370 +
96371 + return -ENODEV;
96372 +}
96373 +EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
96374 +
96375 +/**
96376 * snd_soc_dapm_free - free dapm resources
96377 * @socdev: SoC device
96378 *
This page took 4.378054 seconds and 5 git commands to generate.