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
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);
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
20 +#ifndef __SP890_TZIC_H__
21 +#define __SP890_TZIC_H__
23 +#define SP890_TZIC_UNLOCK_MAGIC (0x0ACCE550)
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
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
47 #include <asm/ptrace.h>
49 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
50 +void iblock_start(void);
51 +void iblock_end(void);
52 +void iblock_end_maybe(unsigned long flags);
54 +#define iblock_start()
56 +#define iblock_end_maybe(x)
60 * CPU interrupt mask handling.
63 #define raw_local_irq_save(x) \
67 (void) (&temp == &x); \
68 __asm__ __volatile__( \
69 "mrs %0, cpsr @ local_irq_save\n" \
71 #define raw_local_irq_enable() \
75 __asm__ __volatile__( \
76 "mrs %0, cpsr @ local_irq_enable\n" \
77 " bic %0, %0, #128\n" \
79 #define raw_local_irq_disable() \
83 __asm__ __volatile__( \
84 "mrs %0, cpsr @ local_irq_disable\n" \
85 " orr %0, %0, #128\n" \
87 * restore saved IRQ & FIQ state
89 #define raw_local_irq_restore(x) \
90 + ({ iblock_end_maybe(x); \
91 __asm__ __volatile__( \
92 "msr cpsr_c, %0 @ local_irq_restore\n" \
96 + : "memory", "cc"); })
98 #define raw_irqs_disabled_flags(flags) \
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
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 */
114 #define KEXEC_ARCH KEXEC_ARCH_ARM
116 +#define KEXEC_BOOT_PARAMS_SIZE 1536
120 #define KEXEC_ARM_ATAGS_OFFSET 0x1000
121 #define KEXEC_ARM_ZIMAGE_OFFSET 0x8000
124 #endif /* CONFIG_KEXEC */
126 #endif /* _ARM_KEXEC_H */
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 @@
133 menu "CPU Power Management"
135 -if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX || ARCH_PXA)
136 +if (ARCH_SA1100 || ARCH_INTEGRATOR || ARCH_OMAP || ARCH_IMX || ARCH_PXA || \
139 source "drivers/cpufreq/Kconfig"
141 @@ -1126,6 +1127,10 @@
143 select CPU_FREQ_DEFAULT_GOV_USERSPACE
145 +config CPU_FREQ_S3C64XX
146 + bool "CPUfreq support for S3C64xx CPUs"
147 + depends on CPU_FREQ && CPU_S3C6410
151 source "drivers/cpuidle/Kconfig"
152 @@ -1305,6 +1310,8 @@
154 source "drivers/uwb/Kconfig"
156 +source "drivers/ar6000/Kconfig"
158 source "drivers/mmc/Kconfig"
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
166 * FIQ support re-written by Russell King to be more generic
168 + * FIQ handler in C supoprt written by Andy Green <andy@openmoko.com>
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.
174 : "r" (®s->ARM_r8), "I" (PSR_I_BIT | PSR_F_BIT | FIQ_MODE));
177 +/* -------- FIQ handler in C ---------
179 + * Major Caveats for using this
180 + * ---------------------------
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.
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.
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
210 + * If you follow these rules, it is fantastic, an extremely powerful, solid,
211 + * genuine hard realtime feature.
214 +static void (*current_fiq_c_isr)(void);
215 +#define FIQ_C_ISR_STACK_SIZE 256
217 +static void __attribute__((naked)) __jump_to_isr(void)
219 + asm __volatile__ ("mov pc, r8");
223 +static void __attribute__((naked)) __actual_isr(void)
226 + "stmdb sp!, {r0-r12, lr};"
230 + current_fiq_c_isr();
233 + "ldmia sp!, {r0-r12, lr};"
238 +void set_fiq_c_handler(void (*isr)(void))
240 + struct pt_regs regs;
242 + memset(®s, 0, sizeof(regs));
243 + regs.ARM_r8 = (unsigned long) __actual_isr;
244 + regs.ARM_sp = 0xffff001c + FIQ_C_ISR_STACK_SIZE;
246 + set_fiq_handler(__jump_to_isr, 4);
248 + current_fiq_c_isr = isr;
250 + set_fiq_regs(®s);
252 +/* -------- FIQ handler in C ---------*/
254 int claim_fiq(struct fiq_handler *f)
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
263 + * /sys/kernel/iblock/
264 + * All times are in microseconds (us).
267 + * Interrupt blocking time reporting limit, in microseconds.
268 + * 0 disables reporting. Auto-resets to zero after reporting.
271 + * Maximum blocking time recorded. Reset to zero by writing anything.
274 + * Force a delay with interrupts disabled.
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>
288 +unsigned long s3c2410_gettimeoffset(void);
291 +static unsigned long iblock_t0;
293 +static int iblock_max;
296 +void iblock_start(void)
298 + unsigned long flags;
300 + raw_local_save_flags(flags);
301 + if (raw_irqs_disabled_flags(flags))
303 + iblock_t0 = s3c2410_gettimeoffset();
305 +EXPORT_SYMBOL_GPL(iblock_start);
307 +void iblock_end(void)
309 + unsigned long flags;
310 + unsigned long t, us;
312 + raw_local_save_flags(flags);
313 + if (!raw_irqs_disabled_flags(flags))
317 + t = s3c2410_gettimeoffset();
321 + if (us > iblock_max)
325 + if (us < iblock_limit)
327 +// iblock_limit = 0;
328 + printk(KERN_ERR "interrupts were disabled for %lu us !\n", us);
331 +EXPORT_SYMBOL_GPL(iblock_end);
333 +void iblock_end_maybe(unsigned long flags)
335 + if (raw_irqs_disabled_flags(flags))
339 +EXPORT_SYMBOL_GPL(iblock_end_maybe);
341 +static ssize_t limit_read(struct device *dev, struct device_attribute *attr,
344 + return sprintf(buf, "%u us\n", iblock_limit);
348 +static ssize_t limit_write(struct device *dev, struct device_attribute *attr,
349 + const char *buf, size_t count)
354 + tmp = simple_strtoul(buf, &end, 0);
357 + iblock_limit = tmp;
362 +static ssize_t max_read(struct device *dev, struct device_attribute *attr,
365 + return sprintf(buf, "%u us\n", iblock_max);
369 +static ssize_t max_write(struct device *dev, struct device_attribute *attr,
370 + const char *buf, size_t count)
377 +static ssize_t test_write(struct device *dev,
378 + struct device_attribute *attr, const char *buf, size_t count)
380 + unsigned long tmp, flags;
383 + tmp = simple_strtoul(buf, &end, 0);
386 + local_irq_save(flags);
388 + local_irq_restore(flags);
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);
398 +static struct attribute *sysfs_entries[] = {
399 + &dev_attr_limit.attr,
400 + &dev_attr_max.attr,
401 + &dev_attr_test.attr,
406 +static struct attribute_group attr_group = {
408 + .attrs = sysfs_entries,
412 +static int __devinit iblock_init(void)
414 + return sysfs_create_group(kernel_kobj, &attr_group);
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
423 .lock = SPIN_LOCK_UNLOCKED
426 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
427 +extern int iblock_limit;
428 +unsigned long s3c2410_gettimeoffset(void);
432 * do_IRQ handles all hardware IRQ's. Decoded IRQs should not
433 * come via this function. Instead, they should provide their
435 asmlinkage void __exception asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
437 struct pt_regs *old_regs = set_irq_regs(regs);
439 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
444 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
445 + us = s3c2410_gettimeoffset();
449 * Some hardware gives randomly wrong interrupts. Rather
450 * than crashing, do something sensible.
453 generic_handle_irq(irq);
455 +#ifdef CONFIG_FIND_IRQ_BLOCKERS
456 + us = s3c2410_gettimeoffset() - us;
458 + if (iblock_limit && us > iblock_limit && us < 10000000)
459 + printk(KERN_ERR "asm_do_IRQ(%u): %lu us\n", irq, us);
461 /* AT91 specific workaround */
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
469 head-y := head$(MMUEXT).o
470 obj-$(CONFIG_DEBUG_LL) += debug.o
471 +obj-$(CONFIG_FIND_IRQ_BLOCKERS) += iblock.o
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
478 *(.got) /* Global offset table */
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
490 #include <linux/sysdev.h>
491 #include <linux/serial_core.h>
493 +#include <mach/map.h>
494 #include <mach/dma.h>
496 #include <plat/cpu.h>
497 -#include <plat/dma.h>
498 +#include <plat/dma-plat.h>
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>
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
516 -/* arch/arm/mach-s3c2410/include/mach/audio.h
518 - * Copyright (c) 2004-2005 Simtec Electronics
519 - * http://www.simtec.co.uk/products/SWLINUX/
520 - * Ben Dooks <ben@simtec.co.uk>
522 - * S3C24XX - Audio platfrom_device info
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.
529 -#ifndef __ASM_ARCH_AUDIO_H
530 -#define __ASM_ARCH_AUDIO_H __FILE__
532 -/* struct s3c24xx_iis_ops
534 - * called from the s3c24xx audio core to deal with the architecture
535 - * or the codec's setup and control.
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.
541 -struct s3c24xx_iis_ops {
542 - struct module *owner;
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);
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);
554 -struct s3c24xx_platdata_iis {
555 - const char *codec_clk;
556 - struct s3c24xx_iis_ops *ops;
557 - int (*match_dev)(struct device *dev);
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
565 * Copyright (C) 2003,2004,2006 Simtec Electronics
566 * Ben Dooks <ben@simtec.co.uk>
568 - * Samsung S3C241XX DMA support
569 + * Samsung S3C24XX DMA support
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
574 #ifndef __ASM_ARCH_DMA_H
575 #define __ASM_ARCH_DMA_H __FILE__
577 +#include <plat/dma.h>
578 #include <linux/sysdev.h>
579 -#include <mach/hardware.h>
581 #define MAX_DMA_TRANSFER_SIZE 0x100000 /* Data Unit is half word */
585 /* we have 4 dma channels */
586 #ifndef CONFIG_CPU_S3C2443
587 -#define S3C2410_DMA_CHANNELS (4)
588 +#define S3C_DMA_CHANNELS (4)
590 -#define S3C2410_DMA_CHANNELS (6)
591 +#define S3C_DMA_CHANNELS (6)
600 /* enum s3c2410_dma_loadst
602 * This represents the state of the DMA engine, wrt to the loaded / running
604 S3C2410_DMALOAD_1LOADED_1RUNNING,
607 -enum s3c2410_dma_buffresult {
613 -enum s3c2410_dmasrc {
614 - S3C2410_DMASRC_HW, /* source is memory */
615 - S3C2410_DMASRC_MEM /* source is hardware */
618 -/* enum s3c2410_chan_op
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
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 */
636 @@ -137,19 +110,18 @@
637 * waiting for reloads */
638 #define S3C2410_DMAF_AUTOSTART (1<<1) /* auto-start if buffer queued */
640 +#define S3C2410_DMAF_CIRCULAR (0x00) /* circular enqueue not supp. */
644 -struct s3c2410_dma_client {
647 +struct s3c2410_dma_buf;
649 -/* s3c2410_dma_buf_s
652 * internally used buffer structure to describe a queued or running
656 -struct s3c2410_dma_buf;
657 struct s3c2410_dma_buf {
658 struct s3c2410_dma_buf *next;
659 int magic; /* magic */
662 /* [1] is this updated for both recv/send modes? */
664 -struct s3c2410_dma_chan;
666 -/* s3c2410_dma_cbfn_t
668 - * buffer callback routine type
671 -typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
672 - void *buf, int size,
673 - enum s3c2410_dma_buffresult result);
675 -typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
676 - enum s3c2410_chan_op );
678 struct s3c2410_dma_stats {
680 unsigned long timeout_longest;
681 @@ -206,10 +164,10 @@
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 */
691 struct s3c24xx_dma_map *map; /* channel hw maps */
693 @@ -236,213 +194,12 @@
694 struct sys_device dev;
697 -/* the currently allocated channel information */
698 -extern struct s3c2410_dma_chan s3c2410_chans[];
700 -/* note, we don't really use dma_device_t at the moment */
701 typedef unsigned long dma_device_t;
703 -/* functions --------------------------------------------------------------- */
705 -/* s3c2410_dma_request
707 - * request a dma channel exclusivley
710 -extern int s3c2410_dma_request(unsigned int channel,
711 - struct s3c2410_dma_client *, void *dev);
716 - * change the state of the dma channel
719 -extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
721 -/* s3c2410_dma_setflags
723 - * set the channel's flags to a given state
726 -extern int s3c2410_dma_setflags(unsigned int channel,
727 - unsigned int flags);
731 - * free the dma channel (will also abort any outstanding operations)
734 -extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
736 -/* s3c2410_dma_enqueue
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.
743 -extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
744 - dma_addr_t data, int size);
746 -/* s3c2410_dma_config
748 - * configure the dma channel
751 -extern int s3c2410_dma_config(unsigned int channel, int xferunit, int dcon);
753 -/* s3c2410_dma_devconfig
755 - * configure the device we're talking to
758 -extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
759 - int hwcfg, unsigned long devaddr);
761 -/* s3c2410_dma_getposition
763 - * get the position that the dma transfer is currently at
766 -extern int s3c2410_dma_getposition(unsigned int channel,
767 - dma_addr_t *src, dma_addr_t *dest);
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);
772 -/* DMA Register definitions */
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)
786 -#define S3C2410_DISRCC_INC (1<<0)
787 -#define S3C2410_DISRCC_APB (1<<1)
789 -#define S3C2410_DMASKTRIG_STOP (1<<2)
790 -#define S3C2410_DMASKTRIG_ON (1<<1)
791 -#define S3C2410_DMASKTRIG_SWTRIG (1<<0)
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)
798 -#define S3C2410_DCON_INTREQ (1<<29)
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)
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)
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)
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)
824 -#define S3C2410_DCON_SRCSHIFT (24)
825 -#define S3C2410_DCON_SRCMASK (7<<24)
827 -#define S3C2410_DCON_BYTE (0<<20)
828 -#define S3C2410_DCON_HALFWORD (1<<20)
829 -#define S3C2410_DCON_WORD (2<<20)
831 -#define S3C2410_DCON_AUTORELOAD (0<<22)
832 -#define S3C2410_DCON_NORELOAD (1<<22)
833 -#define S3C2410_DCON_HWTRIG (1<<23)
835 -#ifdef CONFIG_CPU_S3C2440
836 -#define S3C2440_DIDSTC_CHKINT (1<<2)
838 -#define S3C2440_DCON_CH0_I2SSDO (5<<24)
839 -#define S3C2440_DCON_CH0_PCMIN (6<<24)
841 -#define S3C2440_DCON_CH1_PCMOUT (5<<24)
842 -#define S3C2440_DCON_CH1_SDI (6<<24)
844 -#define S3C2440_DCON_CH2_PCMIN (5<<24)
845 -#define S3C2440_DCON_CH2_MICIN (6<<24)
847 -#define S3C2440_DCON_CH3_MICIN (5<<24)
848 -#define S3C2440_DCON_CH3_PCMOUT (6<<24)
851 -#ifdef CONFIG_CPU_S3C2412
853 -#define S3C2412_DMAREQSEL_SRC(x) ((x)<<1)
855 -#define S3C2412_DMAREQSEL_HW (1)
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)
880 -#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1)
882 -#define S3C2443_DMAREQSEL_HW (1)
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)
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
915 #ifndef __ASM_ARCH_GPIO_CORE_H
916 #define __ASM_ARCH_GPIO_CORE_H __FILE__
918 +/* currently we just include the platform support */
919 #include <plat/gpio-core.h>
920 -#include <mach/regs-gpio.h>
922 -extern struct s3c_gpio_chip s3c24xx_gpios[];
924 -static inline struct s3c_gpio_chip *s3c_gpiolib_getchip(unsigned int pin)
926 - struct s3c_gpio_chip *chip;
928 - if (pin > S3C2410_GPG10)
931 - chip = &s3c24xx_gpios[pin/32];
932 - return (S3C2410_GPIO_OFFSET(pin) > chip->chip.ngpio) ? chip : NULL;
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
941 #define ARCH_NR_GPIOS (256 + CONFIG_S3C24XX_GPIO_EXTRA)
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 */
949 #include <asm-generic/gpio.h>
950 +#include <mach/gpio-nrs.h>
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
957 +/* arch/arm/mach-s3c2410/include/mach/gpio-nrs.h
959 + * Copyright (c) 2008 Simtec Electronics
960 + * http://armlinux.simtec.co.uk/
961 + * Ben Dooks <ben@simtec.co.uk>
963 + * S3C2410 - GPIO bank numbering
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.
970 +#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
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
987 +#include <mach/regs-gpio.h>
988 +#include <mach/irqs.h>
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
999 +extern void gta01bl_deferred_resume(void);
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;
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
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
1028 +#define GTA01v3_GPIO_nGSM_EN S3C2410_GPG9
1031 +#define GTA01_GPIO_MODEM_DNLOAD S3C2410_GPG0
1034 +#define GTA01Bv2_GPIO_nGSM_EN S3C2410_GPF2
1035 +#define GTA01Bv2_GPIO_VIBRATOR_ON S3C2410_GPB10
1038 +#define GTA01_GPIO_GPS_EN_3V3 S3C2410_GPG9
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
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
1051 +#define GTA01Bv4_GPIO_nNAND_WP S3C2410_GPA16
1052 +#define GTA01Bv4_GPIO_VIBRATOR_ON S3C2410_GPB3
1053 +#define GTA01Bv4_GPIO_PMU_IRQ S3C2410_GPG1
1055 +#define GTA01Bv4_IRQ_PCF50606 IRQ_EINT9
1057 +extern struct pcf50606 *gta01_pcf;
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
1064 +#ifndef __MACH_GTA02_PM_WLAN_H
1065 +#define __MACH_GTA02_PM_WLAN_H
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);
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
1079 /* machine specific hardware definitions should go after this */
1081 -/* currently here until moved into config (todo) */
1082 -#define CONFIG_NO_MULTIWORD_IO
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
1089 #ifndef __ASM_ARM_ARCH_IO_H
1090 #define __ASM_ARM_ARCH_IO_H
1092 -#include <mach/hardware.h>
1093 +#include <mach/map.h>
1095 #define IO_SPACE_LIMIT 0xffffffff
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
1101 #define IRQ_EINT22 S3C2410_IRQ(50)
1102 #define IRQ_EINT23 S3C2410_IRQ(51)
1105 +#define IRQ_EINT_BIT(x) ((x) - IRQ_EINT4 + 4)
1106 #define IRQ_EINT(x) (((x) >= 4) ? (IRQ_EINT4 + (x) - 4) : (IRQ_EINT0 + (x)))
1108 #define IRQ_LCD_FIFO S3C2410_IRQ(52)
1110 #define IRQ_S3C2443_AC97 S3C2410_IRQSUB(28)
1112 #ifdef CONFIG_CPU_S3C2443
1113 -#define NR_IRQS (IRQ_S3C2443_AC97+1)
1114 +#define _NR_IRQS (IRQ_S3C2443_AC97+1)
1116 -#define NR_IRQS (IRQ_S3C2440_AC97+1)
1117 +#define _NR_IRQS (IRQ_S3C2440_AC97+1)
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
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.
1132 +#define IRQ_BOARD_START _NR_IRQS
1133 +#define IRQ_BOARD_END (_NR_IRQS + 10)
1135 +#if defined(CONFIG_MACH_NEO1973_GTA02)
1136 +#define NR_IRQS (IRQ_BOARD_END)
1138 +#define NR_IRQS (IRQ_BOARD_START)
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)
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
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
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
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
1178 +#ifndef _ARCH_MCI_H
1179 +#define _ARCH_MCI_H
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);
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
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
1200 #ifndef __ASM_ARCH_REGS_GPIO_H
1201 #define __ASM_ARCH_REGS_GPIO_H
1203 -#define S3C2410_GPIONO(bank,offset) ((bank) + (offset))
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>
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
1221 #define S3C2410_SDIFSTA (0x38)
1223 #define S3C2410_SDIDATA (0x3C)
1224 +#define S3C2410_SDIDATA_BYTE (0x3C)
1225 #define S3C2410_SDIIMSK (0x40)
1227 #define S3C2440_SDIDATA (0x40)
1230 #define S3C2440_SDICON_SDRESET (1<<8)
1231 #define S3C2440_SDICON_MMCCLOCK (1<<5)
1232 +#define S3C2440_SDIDATA_BYTE (0x48)
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
1241 +#include <linux/resume-dependency.h>
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
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);
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
1263 +/* arch/arm/mach-s3c2410/include/mach/ts.h
1265 + * Copyright (c) 2005 Arnaud Patard <arnaud.patard@rtp-net.org>
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.
1274 + * 24-Mar-2005 RTP Created file
1275 + * 03-Aug-2005 RTP Renamed to ts.h
1278 +#ifndef __ASM_ARM_TS_H
1279 +#define __ASM_ARM_TS_H
1281 +#include <../drivers/input/touchscreen/ts_filter.h>
1283 +struct s3c2410_ts_mach_info {
1284 + /* Touchscreen delay. */
1286 + /* Prescaler value. */
1289 + * Null-terminated array of pointers to filter APIs and configurations
1290 + * we want to use. In the same order they will be applied.
1292 + const struct ts_filter_chain_configuration *filter_config;
1295 +void set_s3c2410ts_info(const struct s3c2410_ts_mach_info *hard_s3c2410ts_info);
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
1302 -/* arch/arm/mach-s3c2410/include/mach/usb-control.h
1304 - * Copyright (c) 2004 Simtec Electronics
1305 - * Ben Dooks <ben@simtec.co.uk>
1307 - * S3C2410 - usb port information
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.
1314 -#ifndef __ASM_ARCH_USBCONTROL_H
1315 -#define __ASM_ARCH_USBCONTROL_H "arch/arm/mach-s3c2410/include/mach/usb-control.h"
1317 -#define S3C_HCDFLG_USED (1)
1319 -struct s3c2410_hcd_port {
1320 - unsigned char flags;
1321 - unsigned char power;
1322 - unsigned char oc_status;
1323 - unsigned char oc_changed;
1326 -struct s3c2410_hcd_info {
1327 - struct usb_hcd *hcd;
1328 - struct s3c2410_hcd_port port[2];
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);
1335 -static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
1337 - if (info->report_oc != NULL) {
1338 - (info->report_oc)(info, ports);
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
1348 select S3C2410_CLOCK
1351 select CPU_LLSERIAL_S3C2410
1352 select S3C2410_PM if PM
1355 Internal node for machines with an BAST style IDE
1359 menu "S3C2410 Machines"
1361 config ARCH_SMDK2410
1365 select PM_H1940 if PM
1366 + select S3C_DEV_USB_HOST
1368 Say Y here if you are using the HP IPAQ H1940
1372 bool "Acer N30 family"
1374 + select S3C_DEV_USB_HOST
1376 Say Y here if you want suppt for the Acer N30, Acer N35,
1377 Navman PiN570, Yakumo AlphaX or Airis NC05 PDAs.
1379 select MACH_BAST_IDE
1382 + select S3C_DEV_USB_HOST
1384 Say Y here if you are using the Simtec Electronics EB2410ITX
1385 development board (also known as BAST)
1388 bool "NexVision OTOM Board"
1390 + select S3C_DEV_USB_HOST
1392 Say Y here if you are using the Nex Vision OTOM board
1395 bool "AML M5900 Series"
1397 select PM_SIMTEC if PM
1398 + select S3C_DEV_USB_HOST
1400 Say Y here if you are using the American Microsystems M5900 Series
1401 <http://www.amltd.com>
1403 config MACH_TCT_HAMMER
1404 bool "TCT Hammer Board"
1406 + select S3C_DEV_USB_HOST
1408 Say Y here if you are using the TinCanTools Hammer Board
1409 <http://www.tincantools.com>
1410 @@ -128,7 +136,27 @@
1414 + select DISPLAY_JBT6K74
1416 Say Y here if you are using the Armzone QT2410
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
1435 + Say Y here if you are using the FIC Neo1973 GSM Phone
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
1443 + * linux/arch/arm/mach-s3c2410/mach-gta01.c
1445 + * S3C2410 Machine Support for the FIC Neo1973 GTA01
1447 + * Copyright (C) 2006-2007 by Openmoko, Inc.
1448 + * Author: Harald Welte <laforge@openmoko.org>
1449 + * All rights reserved.
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.
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.
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
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>
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>
1489 +#include <linux/mmc/host.h>
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>
1496 +#include <linux/gta01_battery.h>
1498 +#include <linux/regulator/machine.h>
1499 +#include <linux/regulator/consumer.h>
1502 +#include <asm/mach/arch.h>
1503 +#include <asm/mach/map.h>
1504 +#include <asm/mach/irq.h>
1506 +#include <mach/hardware.h>
1507 +#include <mach/io.h>
1508 +#include <asm/irq.h>
1509 +#include <asm/mach-types.h>
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>
1517 +#include <mach/gta01.h>
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>
1531 +#include <linux/jbt6k74.h>
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>
1542 +static struct map_desc gta01_iodesc[] __initdata = {
1544 + .virtual = 0xe0000000,
1545 + .pfn = __phys_to_pfn(S3C2410_CS3+0x01000000),
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
1557 +static struct s3c2410_uartcfg gta01_uartcfgs[] = {
1563 + .ufcon = UFCON_GTA01_PORT0,
1575 +static void gta01_pmu_event_callback(struct pcf50606 *pcf, int irq)
1577 + /*TODO : Handle ACD here */
1580 +/* FIXME : Goes away when ACD is handled above */
1582 +static int pmu_callback(struct device *dev, unsigned int feature,
1583 + enum pmu_event event)
1585 + switch (feature) {
1586 + case PCF50606_FEAT_ACD:
1588 + case PMU_EVT_INSERT:
1589 + pcf50606_charge_fast(pcf50606_global, 1);
1591 + case PMU_EVT_REMOVE:
1592 + pcf50606_charge_fast(pcf50606_global, 0);
1606 +struct pcf50606 *gta01_pcf;
1608 +static struct platform_device gta01_pm_gsm_dev = {
1609 + .name = "neo1973-pm-gsm",
1612 +static struct platform_device gta01_pm_bt_dev = {
1613 + .name = "neo1973-pm-bt",
1615 +static struct platform_device gta01_pm_gps_dev = {
1616 + .name = "neo1973-pm-gps",
1619 +static struct regulator_consumer_supply ioreg_consumers[] = {
1621 + .dev = >a01_pm_gps_dev.dev,
1622 + .supply = "GPS_2V8",
1626 +static struct regulator_consumer_supply d1reg_consumers[] = {
1628 + .dev = >a01_pm_gps_dev.dev,
1629 + .supply = "GPS_3V",
1632 + .dev = >a01_pm_bt_dev.dev,
1633 + .supply = "BT_3V1",
1637 +static struct regulator_consumer_supply dcd_consumers[] = {
1639 + .dev = >a01_pm_gps_dev.dev,
1640 + .supply = "GPS_3V3",
1643 + .dev = >a01_pm_gps_dev.dev,
1644 + .supply = "GPS_1V5",
1648 +static struct regulator_consumer_supply d2reg_consumers[] = {
1650 + .dev = >a01_pm_gps_dev.dev,
1651 + .supply = "GPS_2V5",
1654 + .dev = &s3c_device_sdi.dev,
1655 + .supply = "SD_3V3",
1659 +static int gta01_bat_get_charging_status(void)
1661 + struct pcf50606 *pcf = gta01_pcf;
1664 + mbcc1 = pcf50606_reg_read(pcf, PCF50606_REG_MBCC1);
1665 + chgmod = mbcc1 & PCF50606_MBCC1_CHGMOD_MASK;
1667 + if (chgmod == PCF50606_MBCC1_CHGMOD_IDLE)
1673 +static int gta01_bat_get_voltage(void)
1675 + struct pcf50606 *pcf = gta01_pcf;
1678 + adc = pcf50606_adc_sync_read(pcf, PCF50606_ADCMUX_BATVOLT_RES);
1679 + mv = (adc * 6000) / 1024;
1684 +static int gta01_bat_get_current(void)
1686 + struct pcf50606 *pcf = gta01_pcf;
1687 + u16 adc_battvolt, adc_adcin1;
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;
1694 + /*rsense is 220 milli */
1695 + return (res * 1000) / (220 * 1024);
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,
1704 +struct platform_device gta01_bat = {
1705 + .name = "gta01_battery",
1708 + .platform_data = >a01_bat_pdata,
1712 +static void gta01_pcf_probe_done(struct pcf50606 *pcf)
1715 + gta01_bat.dev.parent = pcf->dev;
1716 + platform_device_register(>a01_bat);
1719 +static int gps_registered_regulators = 0;
1721 +static void gta01_pmu_regulator_registered(struct pcf50606 *pcf, int id)
1724 + case PCF50606_REGULATOR_D1REG:
1725 + platform_device_register(>a01_pm_bt_dev);
1726 + gps_registered_regulators++;
1728 + case PCF50606_REGULATOR_D2REG:
1729 + gps_registered_regulators++;
1731 + case PCF50606_REGULATOR_IOREG:
1732 + case PCF50606_REGULATOR_DCD:
1733 + gps_registered_regulators++;
1737 + /* All GPS related regulators registered ? */
1738 + if (gps_registered_regulators == 4)
1739 + platform_device_register(>a01_pm_gps_dev);
1743 +static struct pcf50606_platform_data gta01_pcf_pdata = {
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,
1755 + .mbc_event_callback = gta01_pmu_event_callback,
1756 + .reg_init_data = {
1757 + [PCF50606_REGULATOR_D1REG] = {
1759 + .min_uV = 3000000,
1760 + .max_uV = 3150000,
1761 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1764 + .num_consumer_supplies = ARRAY_SIZE(d1reg_consumers),
1765 + .consumer_supplies = d1reg_consumers,
1768 + [PCF50606_REGULATOR_D2REG] = {
1770 + .min_uV = 1650000,
1771 + .max_uV = 3300000,
1772 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1773 + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
1776 + .num_consumer_supplies = ARRAY_SIZE(d2reg_consumers),
1777 + .consumer_supplies = d2reg_consumers,
1781 + [PCF50606_REGULATOR_D3REG] = {
1783 + .min_uV = 1800000,
1784 + .max_uV = 2100000,
1785 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1790 + .num_consumer_supplies = 0,
1793 + [PCF50606_REGULATOR_DCD] = {
1795 + .min_uV = 1500000,
1796 + .max_uV = 1500000,
1797 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1800 + .num_consumer_supplies = ARRAY_SIZE(dcd_consumers),
1801 + .consumer_supplies = dcd_consumers,
1804 + [PCF50606_REGULATOR_DCDE] = {
1806 + .min_uV = 3300000,
1807 + .max_uV = 3300000,
1808 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1814 + .num_consumer_supplies = 0,
1817 + [PCF50606_REGULATOR_DCUD] = {
1819 + .min_uV = 2100000,
1820 + .max_uV = 2100000,
1821 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1827 + .num_consumer_supplies = 0,
1830 + [PCF50606_REGULATOR_IOREG] = {
1832 + .min_uV = 3300000,
1833 + .max_uV = 3300000,
1834 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1837 + .num_consumer_supplies = ARRAY_SIZE(ioreg_consumers),
1838 + .consumer_supplies = ioreg_consumers,
1842 + [PCF50606_REGULATOR_LPREG] = {
1844 + .min_uV = 3300000,
1845 + .max_uV = 3300000,
1846 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
1849 + .num_consumer_supplies = 0,
1852 + .probe_done = gta01_pcf_probe_done,
1853 + .regulator_registered = gta01_pmu_regulator_registered,
1856 +static void cfg_pmu_vrail(struct regulator_init_data *vrail,
1857 + unsigned int suspend_on, unsigned int min,
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;
1866 +static void mangle_pmu_pdata_by_system_rev(void)
1868 + struct regulator_init_data *reg_init_data;
1870 + reg_init_data = gta01_pcf_pdata.reg_init_data;
1872 + switch (S3C_SYSTEM_REV_ATAG) {
1873 + case GTA01Bv4_SYSTEM_REV:
1875 + /* FIXME : gta01_pcf_pdata.used_features |= PCF50606_FEAT_ACD; */
1877 + case GTA01Bv3_SYSTEM_REV:
1878 + case GTA01Bv2_SYSTEM_REV:
1879 + reg_init_data[PCF50606_REGULATOR_D3REG].constraints.state_mem.enabled = 1;
1881 + case GTA01v4_SYSTEM_REV:
1882 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_DCUD],
1883 + 1, 18000000, 1800000);
1884 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_D1REG],
1885 + 0, 3000000, 3000000);
1886 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_D3REG],
1887 + 0, 2800000, 2800000);
1888 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_DCD],
1889 + 0, 3500000, 3500000);
1891 + case GTA01v3_SYSTEM_REV:
1892 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_D1REG],
1893 + 0, 3000000, 3000000);
1894 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_D2REG],
1895 + 0, 3300000, 3300000);
1896 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_D3REG],
1897 + 0, 3300000, 3300000);
1898 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_DCD],
1899 + 0, 3300000, 3300000);
1900 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_DCUD],
1901 + 1, 1800000, 1800000);
1902 + cfg_pmu_vrail(®_init_data[PCF50606_REGULATOR_IOREG],
1903 + 0, 2800000, 2800000);
1908 +static void gta01_power_off(void)
1910 + pcf50606_reg_write(gta01_pcf, PCF50606_REG_OOCC1,
1911 + PCF50606_OOCC1_GOSTDBY);
1914 +/* LCD driver info */
1916 +/* Configuration for 480x640 toppoly TD028TTEC1.
1917 + * Do not mark this as __initdata or it will break! */
1918 +static struct s3c2410fb_display gta01_displays[] = {
1920 + .type = S3C2410_LCDCON1_TFT,
1927 + .pixclock = 40000, /* HCLK/4 */
1928 + .left_margin = 104,
1929 + .right_margin = 8,
1931 + .upper_margin = 2,
1932 + .lower_margin = 16,
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,
1942 + .type = S3C2410_LCDCON1_TFT,
1949 + .pixclock = 40000, /* HCLK/4 */
1950 + .left_margin = 104,
1951 + .right_margin = 8,
1953 + .upper_margin = 2,
1954 + .lower_margin = 16,
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,
1964 + .type = S3C2410_LCDCON1_TFT,
1971 + .pixclock = 40000, /* HCLK/4 */
1972 + .left_margin = 104,
1973 + .right_margin = 8,
1975 + .upper_margin = 2,
1976 + .lower_margin = 16,
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,
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,
1992 + .lpcsel = ((0xCE6) & ~7) | 1<<4,
1995 +static struct platform_device *gta01_devices[] __initdata = {
2002 + &s3c_device_usbgadget,
2007 +static struct s3c2410_nand_set gta01_nand_sets[] = {
2009 + .name = "neo1973-nand",
2011 + .flags = S3C2410_NAND_BBT,
2015 +static struct s3c2410_platform_nand gta01_nand_info = {
2019 + .nr_sets = ARRAY_SIZE(gta01_nand_sets),
2020 + .sets = gta01_nand_sets,
2023 +static struct regulator *s3c_sdi_regulator;
2025 +static void gta01_mmc_set_power(unsigned char power_mode, unsigned short vdd)
2028 + int mv = 1700; /* 1.7V for MMC_VDD_165_195 */
2029 + struct regulator *regulator;
2031 + printk(KERN_DEBUG "mmc_set_power(power_mode=%u, vdd=%u)\n",
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");
2043 + regulator = s3c_sdi_regulator;
2046 + switch (S3C_SYSTEM_REV_ATAG) {
2047 + case GTA01v3_SYSTEM_REV:
2048 + switch (power_mode) {
2049 + case MMC_POWER_OFF:
2050 + regulator_disable(regulator);
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);
2059 + case MMC_POWER_UP:
2060 + regulator_enable(regulator);
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);
2072 + case MMC_POWER_ON:
2073 + neo1973_gpb_setpin(GTA01_GPIO_SDMMC_ON, 0);
2080 + regulator_put(regulator);
2083 +static struct s3c24xx_mci_pdata gta01_mmc_cfg = {
2084 + .gpio_detect = GTA01_GPIO_nSD_DETECT,
2085 + .set_power = >a01_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,
2093 +static void gta01_udc_command(enum s3c2410_udc_cmd_e cmd)
2095 + printk(KERN_DEBUG "%s(%d)\n", __func__, cmd);
2098 + case S3C2410_UDC_P_ENABLE:
2099 + neo1973_gpb_setpin(GTA01_GPIO_USB_PULLUP, 1);
2101 + case S3C2410_UDC_P_DISABLE:
2102 + neo1973_gpb_setpin(GTA01_GPIO_USB_PULLUP, 0);
2109 +/* use a work queue, since I2C API inherently schedules
2110 + * and we get called in hardirq context from UDC driver */
2113 + struct work_struct work;
2116 +static struct vbus_draw gta01_udc_vbus_drawer;
2118 +static void __gta01_udc_vbus_draw(struct work_struct *work)
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
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);
2133 + /* disable fast charge */
2134 + printk(KERN_DEBUG "udc: disabling fast charge\n");
2135 + pcf50606_charge_fast(gta01_pcf, 0);
2139 +static void gta01_udc_vbus_draw(unsigned int ma)
2141 + gta01_udc_vbus_drawer.ma = ma;
2142 + schedule_work(>a01_udc_vbus_drawer.work);
2145 +static struct s3c2410_udc_mach_info gta01_udc_cfg = {
2146 + .vbus_draw = gta01_udc_vbus_draw,
2149 +/* Touchscreen configuration. */
2151 +#ifdef CONFIG_TOUCHSCREEN_FILTER
2152 +const static struct ts_filter_group_configuration gta01_ts_group = {
2154 + .close_enough = 10,
2155 + .threshold = 6, /* At least half of the points in a group. */
2159 +const static struct ts_filter_median_configuration gta01_ts_median = {
2161 + .decimation_below = 3,
2162 + .decimation_threshold = 8 * 3,
2163 + .decimation_above = 4,
2166 +const static struct ts_filter_mean_configuration gta01_ts_mean = {
2170 +const static struct ts_filter_linear_configuration gta01_ts_linear = {
2171 + .constants = {1, 0, 0, 0, 1, 0, 1}, /* Don't modify coords. */
2177 +const static struct ts_filter_chain_configuration gta01_filter_configuration[] =
2179 +#ifdef CONFIG_TOUCHSCREEN_FILTER
2180 + {&ts_filter_group_api, >a01_ts_group.config},
2181 + {&ts_filter_median_api, >a01_ts_median.config},
2182 + {&ts_filter_mean_api, >a01_ts_mean.config},
2183 + {&ts_filter_linear_api, >a01_ts_linear.config},
2188 +const static struct s3c2410_ts_mach_info gta01_ts_cfg = {
2190 + .presc = 0xff, /* slow as we can go */
2191 + .filter_config = gta01_filter_configuration,
2196 +static void gta01_jbt6k74_reset(int devidx, int level)
2198 + /* empty place holder; gta01 does not yet use this */
2199 + printk(KERN_DEBUG "gta01_jbt6k74_reset\n");
2202 +static void gta01_jbt6k74_resuming(int devidx)
2204 + gta01bl_deferred_resume();
2207 +const struct jbt6k74_platform_data gta01_jbt6k74_pdata = {
2208 + .reset = gta01_jbt6k74_reset,
2209 + .resuming = gta01_jbt6k74_resuming,
2212 +static struct spi_board_info gta01_spi_board_info[] = {
2214 + .modalias = "jbt6k74",
2215 + .platform_data = >a01_jbt6k74_pdata,
2216 + /* controller_data */
2218 + .max_speed_hz = 10 * 1000 * 1000,
2224 +static void spi_gpio_cs(struct s3c2410_spigpio_info *spi, int csidx, int cs)
2227 + case BITBANG_CS_ACTIVE:
2228 + s3c2410_gpio_setpin(S3C2410_GPG3, 0);
2230 + case BITBANG_CS_INACTIVE:
2231 + s3c2410_gpio_setpin(S3C2410_GPG3, 1);
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? ***/
2244 +static struct resource s3c_spi_lcm_resource[] = {
2246 + .start = S3C2410_GPG3,
2247 + .end = S3C2410_GPG3,
2250 + .start = S3C2410_GPG5,
2251 + .end = S3C2410_GPG5,
2254 + .start = S3C2410_GPG6,
2255 + .end = S3C2410_GPG6,
2258 + .start = S3C2410_GPG7,
2259 + .end = S3C2410_GPG7,
2263 +struct platform_device s3c_device_spi_lcm = {
2264 + .name = "spi_s3c24xx_gpio",
2266 + .num_resources = ARRAY_SIZE(s3c_spi_lcm_resource),
2267 + .resource = s3c_spi_lcm_resource,
2269 + .platform_data = &spi_gpio_cfg,
2273 +static struct gta01bl_machinfo backlight_machinfo = {
2274 + .default_intensity = 1,
2275 + .max_intensity = 1,
2277 + .defer_resume_backlight = 1,
2280 +static struct resource gta01_bl_resources[] = {
2282 + .start = GTA01_GPIO_BACKLIGHT,
2283 + .end = GTA01_GPIO_BACKLIGHT,
2287 +struct platform_device gta01_bl_dev = {
2288 + .name = "gta01-bl",
2289 + .num_resources = ARRAY_SIZE(gta01_bl_resources),
2290 + .resource = gta01_bl_resources,
2292 + .platform_data = &backlight_machinfo,
2296 +static struct resource gta01_led_resources[] = {
2298 + .start = GTA01_GPIO_VIBRATOR_ON,
2299 + .end = GTA01_GPIO_VIBRATOR_ON,
2303 +struct platform_device gta01_led_dev = {
2304 + .name = "neo1973-vibrator",
2305 + .num_resources = ARRAY_SIZE(gta01_led_resources),
2306 + .resource = gta01_led_resources,
2309 +static struct resource gta01_button_resources[] = {
2311 + .start = GTA01_GPIO_AUX_KEY,
2312 + .end = GTA01_GPIO_AUX_KEY,
2315 + .start = GTA01_GPIO_HOLD_KEY,
2316 + .end = GTA01_GPIO_HOLD_KEY,
2319 + .start = GTA01_GPIO_JACK_INSERT,
2320 + .end = GTA01_GPIO_JACK_INSERT,
2324 +struct platform_device gta01_button_dev = {
2325 + .name = "neo1973-button",
2326 + .num_resources = ARRAY_SIZE(gta01_button_resources),
2327 + .resource = gta01_button_resources,
2331 +static struct s3c2410_hcd_info gta01_usb_info = {
2333 + .flags = S3C_HCDFLG_USED,
2340 +static void __init gta01_map_io(void)
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));
2347 +static irqreturn_t gta01_modem_irq(int irq, void *param)
2349 + printk(KERN_DEBUG "GSM wakeup interrupt (IRQ %d)\n", irq);
2350 + gta_gsm_interrupts++;
2351 + return IRQ_HANDLED;
2354 +static struct i2c_board_info gta01_i2c_devs[] __initdata = {
2356 + I2C_BOARD_INFO("pcf50606", 0x08),
2357 + .irq = GTA01_IRQ_PCF50606,
2358 + .platform_data = >a01_pcf_pdata,
2361 + I2C_BOARD_INFO("lm4857", 0x7c),
2364 + I2C_BOARD_INFO("wm8753", 0x1a),
2368 +static void __init gta01_machine_init(void)
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;
2380 + s3c_device_usb.dev.platform_data = >a01_usb_info;
2381 + s3c_device_nand.dev.platform_data = >a01_nand_info;
2382 + s3c_device_sdi.dev.platform_data = >a01_mmc_cfg;
2384 + s3c24xx_fb_set_platdata(>a01_lcd_cfg);
2386 + INIT_WORK(>a01_udc_vbus_drawer.work, __gta01_udc_vbus_draw);
2387 + s3c24xx_udc_set_platdata(>a01_udc_cfg);
2388 + s3c_i2c0_set_platdata(NULL);
2389 + set_s3c2410ts_info(>a01_ts_cfg);
2391 + /* Set LCD_RESET / XRES to high */
2392 + s3c2410_gpio_cfgpin(S3C2410_GPC6, S3C2410_GPIO_OUTPUT);
2393 + s3c2410_gpio_setpin(S3C2410_GPC6, 1);
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);
2400 + platform_device_register(>a01_bl_dev);
2401 + platform_device_register(>a01_button_dev);
2402 + platform_device_register(>a01_pm_gsm_dev);
2404 + switch (S3C_SYSTEM_REV_ATAG) {
2405 + case GTA01v3_SYSTEM_REV:
2406 + case GTA01v4_SYSTEM_REV:
2407 + /* just use the default (GTA01_IRQ_PCF50606) */
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;
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;
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));
2425 + platform_device_register(>a01_led_dev);
2427 + platform_add_devices(gta01_devices, ARRAY_SIZE(gta01_devices));
2431 + set_irq_type(GTA01_IRQ_MODEM, IRQ_TYPE_EDGE_RISING);
2432 + rc = request_irq(GTA01_IRQ_MODEM, gta01_modem_irq, IRQF_DISABLED,
2434 + enable_irq_wake(GTA01_IRQ_MODEM);
2435 + printk(KERN_DEBUG "Enabled GSM wakeup IRQ %d (rc=%d)\n",
2436 + GTA01_IRQ_MODEM, rc);
2438 + pm_power_off = >a01_power_off;
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,
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,
2457 +static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
2460 + .oversampling_shift = 2,
2468 &s3c_device_usbgadget,
2471 &s3c_device_bluetooth,
2474 #ifdef CONFIG_PM_H1940
2475 memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
2477 - s3c2410_pm_init();
2481 static void __init h1940_init_irq(void)
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);
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
2494 /* linux/arch/arm/mach-s3c2410/mach-qt2410.c
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.
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)
2509 case BITBANG_CS_ACTIVE:
2510 @@ -321,6 +321,24 @@
2512 __setup("tft=", qt2410_tft_setup);
2514 +static struct resource qt2410_button_resources[] = {
2516 + .start = S3C2410_GPF0,
2517 + .end = S3C2410_GPF0,
2520 + .start = S3C2410_GPF2,
2521 + .end = S3C2410_GPF2,
2525 +struct platform_device qt2410_button_dev = {
2526 + .name ="qt2410-button",
2527 + .num_resources = ARRAY_SIZE(qt2410_button_resources),
2528 + .resource = qt2410_button_resources,
2532 static void __init qt2410_map_io(void)
2534 s3c24xx_init_io(qt2410_iodesc, ARRAY_SIZE(qt2410_iodesc));
2536 s3c2410_gpio_cfgpin(S3C2410_GPB5, S3C2410_GPIO_OUTPUT);
2538 platform_add_devices(qt2410_devices, ARRAY_SIZE(qt2410_devices));
2539 - s3c2410_pm_init();
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
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
2558 obj-$(CONFIG_MACH_BAST_IDE) += bast-ide.o
2559 +obj-$(CONFIG_MACH_NEO1973_GTA01)+= mach-gta01.o
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
2565 #include <plat/cpu.h>
2566 #include <plat/pm.h>
2568 -#ifdef CONFIG_S3C2410_PM_DEBUG
2569 -extern void pm_dbg(const char *fmt, ...);
2570 -#define DBG(fmt...) pm_dbg(fmt)
2572 -#define DBG(fmt...) printk(KERN_DEBUG fmt)
2575 static void s3c2410_pm_prepare(void)
2577 /* ensure at least GSTATUS3 has the resume address */
2579 - __raw_writel(virt_to_phys(s3c2410_cpu_resume), S3C2410_GSTATUS3);
2580 + __raw_writel(virt_to_phys(s3c_cpu_resume), S3C2410_GSTATUS3);
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));
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
2594 #include <mach/dma.h>
2596 -#include <plat/dma.h>
2597 +#include <plat/dma-plat.h>
2598 #include <plat/cpu.h>
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>
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
2619 bool "Logitech Jive"
2621 + select S3C_DEV_USB_HOST
2623 Say Y here if you are using the Logitech Jive.
2629 + select S3C_DEV_USB_HOST
2631 Say Y here if you are using an SMDK2413
2637 + select S3C_DEV_USB_HOST
2639 Say Y here if you are using an VSTMS board
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
2645 * correct address to resume from. */
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);
2655 /* initialise the power management now we've setup everything. */
2657 - s3c2410_pm_init();
2660 s3c_device_nand.dev.platform_data = &jive_nand_info;
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
2667 static int s3c2412_pm_suspend(struct sys_device *dev, pm_message_t state)
2669 - s3c2410_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
2670 + s3c_pm_do_save(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
2675 tmp |= S3C2412_PWRCFG_STANDBYWFI_IDLE;
2676 __raw_writel(tmp, S3C2412_PWRCFG);
2678 - s3c2410_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
2679 + s3c_pm_do_restore(s3c2412_sleep, ARRAY_SIZE(s3c2412_sleep));
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
2688 printk("S3C2412: Initialising architecture\n");
2690 + /* make sure SD/MMC driver can distinguish 2412 from 2410 */
2691 + s3c_device_sdi.name = "s3c2412-sdi";
2693 return sysdev_register(&s3c2412_sysdev);
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
2699 #include <linux/sysdev.h>
2700 #include <linux/serial_core.h>
2702 +#include <mach/map.h>
2703 #include <mach/dma.h>
2705 -#include <plat/dma.h>
2706 +#include <plat/dma-plat.h>
2707 #include <plat/cpu.h>
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>
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
2726 Support for S3C2440 specific DMA code5A
2729 menu "S3C2440 Machines"
2733 select PM_SIMTEC if PM
2734 select HAVE_PATA_PLATFORM
2735 select S3C24XX_GPIO_EXTRA64
2736 + select S3C_DEV_USB_HOST
2738 Say Y here if you are using the Simtec Electronics ANUBIS
2742 select PM_SIMTEC if PM
2743 select S3C24XX_GPIO_EXTRA128
2744 + select S3C_DEV_USB_HOST
2746 Say Y here if you are using the Simtec IM2440D20 module, also
2747 known as the Osiris.
2752 + select S3C_DEV_USB_HOST
2754 Say Y here if you are using the SMDK2440.
2756 config MACH_NEXCODER_2440
2757 bool "NexVision NEXCODER 2440 Light Board"
2759 + select S3C_DEV_USB_HOST
2761 Say Y here if you are using the Nex Vision NEXCODER 2440 Light Board
2764 config MACH_AT2440EVB
2765 bool "Avantech AT2440EVB development board"
2767 + select S3C_DEV_USB_HOST
2769 Say Y here if you are using the AT2440EVB development board
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
2776 + Say Y here if you are using an early hardware revision
2777 + of the FIC/Openmoko Neo1973 GTA02 GSM Phone.
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
2785 #ifdef CONFIG_PM_H1940
2786 memcpy(phys_to_virt(H1940_SUSPEND_RESUMEAT), h1940_pm_return, 1024);
2788 - s3c2410_pm_init();
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
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
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
2806 s3c_device_wdt.resource[1].start = IRQ_S3C2440_WDT;
2807 s3c_device_wdt.resource[1].end = IRQ_S3C2440_WDT;
2809 + /* make sure SD/MMC driver can distinguish 2440 from 2410 */
2810 + s3c_device_sdi.name = "s3c2440-sdi";
2812 /* register our system device for everything else */
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
2822 +#include <mach/regs-gpio.h>
2823 +#include <mach/irqs.h>
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
2833 +#define GTA02_GPIO_n3DL_GSM S3C2410_GPA13 /* v1 + v2 + v3 only */
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
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 + */
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
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 */
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 */
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 */
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
2899 +int gta02_get_pcb_revision(void);
2901 +extern struct pcf50633 *gta02_pcf;
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
2908 select S3C2410_CLOCK
2910 select S3C2410_PM if PM
2911 + select S3C2440_DMA if S3C2410_DMA
2913 select CPU_LLSERIAL_S3C2440
2916 depends on ARCH_S3C2440
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
2925 + select POWER_SUPPLY
2926 + select MACH_NEO1973
2929 + select S3C_DEV_USB_HOST
2931 + Say Y here if you are using the FIC Neo1973 GSM Phone
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
2941 + * linux/arch/arm/mach-s3c2440/mach-gta02.c
2943 + * S3C2440 Machine Support for the FIC GTA02 (Neo1973)
2945 + * Copyright (C) 2006-2007 by Openmoko, Inc.
2946 + * Author: Harald Welte <laforge@openmoko.org>
2947 + * All rights reserved.
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.
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.
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
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>
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>
2987 +#include <linux/i2c.h>
2988 +#include <linux/backlight.h>
2989 +#include <linux/regulator/machine.h>
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>
2997 +#include <linux/lis302dl.h>
2999 +#include <asm/mach/arch.h>
3000 +#include <asm/mach/map.h>
3001 +#include <asm/mach/irq.h>
3003 +#include <mach/hardware.h>
3004 +#include <mach/io.h>
3005 +#include <asm/irq.h>
3006 +#include <asm/mach-types.h>
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>
3021 +#include <mach/gta02.h>
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>
3036 +#include <linux/jbt6k74.h>
3038 +#include <linux/glamofb.h>
3040 +#include <linux/hdq.h>
3041 +#include <linux/bq27000_battery.h>
3043 +#include "../plat-s3c24xx/neo1973_pm_gps.h"
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>
3053 +#include <asm/fiq.h>
3055 +#include <linux/neo1973_vibrator.h>
3057 +/* arbitrates which sensor IRQ owns the shared SPI bus */
3058 +static spinlock_t motion_irq_lock;
3061 +/* -------------------------------------------------------------------------------
3062 + * GTA02 FIQ related
3064 + * Calls into vibrator and hdq and based on the return values
3065 + * determines if we the FIQ source be kept alive
3068 +#define DIVISOR_FROM_US(x) ((x) << 3)
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);
3075 +#ifdef CONFIG_LEDS_NEO1973_VIBRATOR
3076 +#define FIQ_DIVISOR_VIBRATOR DIVISOR_FROM_US(100)
3077 +extern int neo1973_vibrator_fiq_handler(void);
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;
3086 +static void gta02_fiq_handler(void)
3088 + u16 divisor = 0xffff;
3090 + /* Vibrator servicing */
3092 + /* disable further timer interrupts if nobody has any work
3093 + * or adjust rate according to who still has work
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
3100 +#ifdef CONFIG_LEDS_NEO1973_VIBRATOR
3101 + if (neo1973_vibrator_fiq_handler())
3102 + divisor = FIQ_DIVISOR_VIBRATOR;
3105 +#ifdef CONFIG_HDQ_GPIO_BITBANG
3106 + if (hdq_fiq_handler())
3107 + divisor = FIQ_DIVISOR_HDQ;
3110 + if (divisor == 0xffff) /* mask the fiq irq source */
3111 + __raw_writel(__raw_readl(S3C2410_INTMSK) | gta02_fiq_ack_mask,
3113 + else /* still working, maybe at a different rate */
3114 + __raw_writel(divisor, S3C2410_TCNTB(gta02_fiq_timer_index));
3116 + __raw_writel(gta02_fiq_ack_mask, S3C2410_SRCPND);
3119 +static void gta02_fiq_kick(void)
3121 + unsigned long flags;
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)
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)),
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,
3141 + __raw_writel(tcon | S3C2410_TCON_T3START, S3C2410_TCON);
3142 + local_irq_restore(flags);
3145 +static int gta02_fiq_enable(void)
3147 + int irq_index_fiq = IRQ_TIMER3;
3150 + local_fiq_disable();
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);
3156 + /* set up the timer to operate as a pwm device */
3158 + rc = s3c2410_pwm_init(>a02_fiq_pwm_timer);
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;
3168 + rc = s3c2410_pwm_enable(>a02_fiq_pwm_timer);
3172 + s3c2410_pwm_start(>a02_fiq_pwm_timer);
3174 + /* let our selected interrupt be a magic FIQ interrupt */
3175 + __raw_writel(gta02_fiq_ack_mask, S3C2410_INTMOD);
3177 + /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */
3178 + local_fiq_enable();
3180 + set_fiq_c_handler(gta02_fiq_handler);
3185 + printk(KERN_ERR "Could not initialize FIQ for GTA02: %d\n", rc);
3190 +static void gta02_fiq_disable(void)
3192 + __raw_writel(0, S3C2410_INTMOD);
3193 + local_fiq_disable();
3194 + gta02_fiq_irq = 0; /* no active source interrupt now either */
3197 +/* -------------------- /GTA02 FIQ Handler ------------------------------------- */
3200 + * this gets called every 1ms when we paniced.
3203 +static long gta02_panic_blink(long count)
3206 + static long last_blink;
3209 + if (count - last_blink < 100) /* 200ms period, fast blink */
3213 + s3c2410_gpio_cfgpin(GTA02_GPIO_AUX_LED, S3C2410_GPIO_OUTPUT);
3214 + neo1973_gpb_setpin(GTA02_GPIO_AUX_LED, led);
3216 + last_blink = count;
3222 + * returns PCB revision information in b9,b8 and b2,b1,b0
3223 + * Pre-GTA02 A6 returns 0x000
3224 + * GTA02 A6 returns 0x101
3228 +int gta02_get_pcb_revision(void)
3232 + static unsigned long pinlist[] = {
3239 + static int pin_offset[] = {
3243 + for (n = 0 ; n < ARRAY_SIZE(pinlist); n++) {
3245 + * set the PCB version GPIO to be pulled-down input
3246 + * force low briefly first
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);
3256 + if (s3c2410_gpio_getpin(pinlist[n]))
3257 + u |= 1 << pin_offset[n];
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.
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);
3273 +struct platform_device gta02_version_device = {
3274 + .name = "neo1973-version",
3275 + .num_resources = 0,
3278 +struct platform_device gta02_resume_reason_device = {
3279 + .name = "neo1973-resume",
3280 + .num_resources = 0,
3283 +struct platform_device gta02_memconfig_device = {
3284 + .name = "neo1973-memconfig",
3285 + .num_resources = 0,
3288 +static struct map_desc gta02_iodesc[] __initdata = {
3290 + .virtual = 0xe0000000,
3291 + .pfn = __phys_to_pfn(S3C2410_CS3+0x01000000),
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
3301 +static struct s3c2410_uartcfg gta02_uartcfgs[] = {
3326 +struct pcf50633 *gta02_pcf;
3328 +#ifdef CONFIG_CHARGER_PCF50633
3329 +static int gta02_get_charger_online_status(void)
3331 + struct pcf50633 *pcf = gta02_pcf;
3333 + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ONLINE;
3336 +static int gta02_get_charger_active_status(void)
3338 + struct pcf50633 *pcf = gta02_pcf;
3340 + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ACTIVE;
3343 +#define ADC_NOM_CHG_DETECT_1A 6
3344 +#define ADC_NOM_CHG_DETECT_USB 43
3347 +gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res)
3351 + /* Interpret charger type */
3352 + if (res < ((ADC_NOM_CHG_DETECT_USB + ADC_NOM_CHG_DETECT_1A) / 2)) {
3354 + /* Stop GPO driving out now that we have a IA charger */
3355 + pcf50633_gpio_set(pcf, PCF50633_GPO, 0);
3361 + pcf50633_mbc_usb_curlim_set(pcf, ma);
3364 +static struct delayed_work gta02_charger_work;
3365 +static int gta02_usb_vbus_draw;
3367 +static void gta02_charger_worker(struct work_struct *work)
3369 + struct pcf50633 *pcf = gta02_pcf;
3371 + if (gta02_usb_vbus_draw) {
3372 + pcf50633_mbc_usb_curlim_set(pcf, gta02_usb_vbus_draw);
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);
3381 + /* If the PCF50633 ADC is disabled we fallback to a 100mA limit for safety. */
3382 + pcf50633_mbc_usb_curlim_set(pcf, 100);
3388 +#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000)
3389 +static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq)
3391 + if (irq == PCF50633_IRQ_USBINS) {
3392 + schedule_delayed_work(>a02_charger_work,
3393 + GTA02_CHARGER_CONFIGURE_TIMEOUT);
3395 + } else if (irq == PCF50633_IRQ_USBREM) {
3396 + cancel_delayed_work_sync(>a02_charger_work);
3397 + gta02_usb_vbus_draw = 0;
3401 +static void gta02_pmu_force_shutdown(struct pcf50633 *pcf)
3403 + pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_OOCSHDWN,
3404 + PCF50633_OOCSHDWN_GOSTDBY, PCF50633_OOCSHDWN_GOSTDBY);
3408 +static void gta02_udc_vbus_draw(unsigned int ma)
3413 + gta02_usb_vbus_draw = ma;
3415 + schedule_delayed_work(>a02_charger_work,
3416 + GTA02_CHARGER_CONFIGURE_TIMEOUT);
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
3425 +static struct platform_device gta01_pm_gps_dev = {
3426 + .name = "neo1973-pm-gps",
3429 +static struct platform_device gta01_pm_bt_dev = {
3430 + .name = "neo1973-pm-bt",
3433 +static struct platform_device gta02_pm_gsm_dev = {
3434 + .name = "neo1973-pm-gsm",
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.
3444 +static struct platform_device gta02_glamo_dev;
3445 +static void mangle_glamo_res_by_system_rev(void);
3447 +static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf);
3448 +static void gta02_pmu_regulator_registered(struct pcf50633 *pcf, int id);
3450 +static struct platform_device gta02_pm_wlan_dev = {
3451 + .name = "gta02-pm-wlan",
3454 +static struct regulator_consumer_supply ldo4_consumers[] = {
3456 + .dev = >a01_pm_bt_dev.dev,
3457 + .supply = "BT_3V2",
3461 +static struct regulator_consumer_supply ldo5_consumers[] = {
3463 + .dev = >a01_pm_gps_dev.dev,
3464 + .supply = "RF_3V",
3469 + * We need this dummy thing to fill the regulator consumers
3471 +static struct platform_device gta02_mmc_dev = {
3472 + /* details filled in by glamo core */
3475 +static struct regulator_consumer_supply hcldo_consumers[] = {
3477 + .dev = >a02_mmc_dev.dev,
3478 + .supply = "SD_3V3",
3482 +static char *gta02_batteries[] = {
3486 +struct pcf50633_platform_data gta02_pcf_pdata = {
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,
3498 + .batteries = gta02_batteries,
3499 + .num_batteries = ARRAY_SIZE(gta02_batteries),
3500 + .charging_restart_interval = (900 * HZ),
3501 + .chg_ref_current_ma = 1000,
3503 + .reg_init_data = {
3504 + [PCF50633_REGULATOR_AUTO] = {
3507 + .min_uV = 3300000,
3508 + .max_uV = 3300000,
3509 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3516 + .num_consumer_supplies = 0,
3518 + [PCF50633_REGULATOR_DOWN1] = {
3520 + .name = "CORE_1V3",
3521 + .min_uV = 1300000,
3522 + .max_uV = 1600000,
3523 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3527 + .num_consumer_supplies = 0,
3529 + [PCF50633_REGULATOR_DOWN2] = {
3532 + .min_uV = 1800000,
3533 + .max_uV = 1800000,
3534 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3541 + .num_consumer_supplies = 0,
3543 + [PCF50633_REGULATOR_HCLDO] = {
3546 + .min_uV = 2000000,
3547 + .max_uV = 3300000,
3548 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3549 + .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
3552 + .num_consumer_supplies = 1,
3553 + .consumer_supplies = hcldo_consumers,
3555 + [PCF50633_REGULATOR_LDO1] = {
3557 + .name = "GSENSOR_3V3",
3558 + .min_uV = 1300000,
3559 + .max_uV = 1300000,
3560 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3563 + .num_consumer_supplies = 0,
3565 + [PCF50633_REGULATOR_LDO2] = {
3567 + .name = "CODEC_3V3",
3568 + .min_uV = 3300000,
3569 + .max_uV = 3300000,
3570 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3573 + .num_consumer_supplies = 0,
3575 + [PCF50633_REGULATOR_LDO3] = {
3577 + .min_uV = 3000000,
3578 + .max_uV = 3000000,
3579 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3582 + .num_consumer_supplies = 0,
3584 + [PCF50633_REGULATOR_LDO4] = {
3587 + .min_uV = 3200000,
3588 + .max_uV = 3200000,
3589 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3592 + .num_consumer_supplies = 1,
3593 + .consumer_supplies = ldo4_consumers,
3595 + [PCF50633_REGULATOR_LDO5] = {
3598 + .min_uV = 1500000,
3599 + .max_uV = 1500000,
3600 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3606 + .num_consumer_supplies = 1,
3607 + .consumer_supplies = ldo5_consumers,
3609 + [PCF50633_REGULATOR_LDO6] = {
3613 + .max_uV = 3300000,
3614 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3616 + .num_consumer_supplies = 0,
3618 + [PCF50633_REGULATOR_MEMLDO] = {
3620 + .min_uV = 1800000,
3621 + .max_uV = 1800000,
3622 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
3627 + .num_consumer_supplies = 0,
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,
3637 +static void mangle_pmu_pdata_by_system_rev(void)
3639 + struct regulator_init_data *reg_init_data;
3641 + reg_init_data = gta02_pcf_pdata.reg_init_data;
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;
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;
3661 + reg_init_data[PCF50633_REGULATOR_LDO5]
3662 + .constraints.min_uV = 3000000;
3663 + reg_init_data[PCF50633_REGULATOR_LDO5]
3664 + .constraints.max_uV = 3000000;
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;
3678 +#ifdef CONFIG_HDQ_GPIO_BITBANG
3679 +/* BQ27000 Battery */
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
3691 +struct platform_device bq27000_battery_device = {
3692 + .name = "bq27000-battery",
3694 + .platform_data = &bq27000_pdata,
3700 +static void gta02_hdq_attach_child_devices(struct device *parent_device)
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);
3713 +static void gta02_hdq_gpio_direction_out(void)
3715 + s3c2410_gpio_cfgpin(GTA02v5_GPIO_HDQ, S3C2410_GPIO_OUTPUT);
3718 +static void gta02_hdq_gpio_direction_in(void)
3720 + s3c2410_gpio_cfgpin(GTA02v5_GPIO_HDQ, S3C2410_GPIO_INPUT);
3723 +static void gta02_hdq_gpio_set_value(int val)
3726 + s3c2410_gpio_setpin(GTA02v5_GPIO_HDQ, val);
3729 +static int gta02_hdq_gpio_get_value(void)
3731 + return s3c2410_gpio_getpin(GTA02v5_GPIO_HDQ);
3734 +static struct resource gta02_hdq_resources[] = {
3736 + .start = GTA02v5_GPIO_HDQ,
3737 + .end = GTA02v5_GPIO_HDQ,
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,
3748 + .enable_fiq = gta02_fiq_enable,
3749 + .disable_fiq = gta02_fiq_disable,
3750 + .kick_fiq = gta02_fiq_kick,
3754 +struct platform_device gta02_hdq_device = {
3756 + .num_resources = 1,
3757 + .resource = gta02_hdq_resources,
3759 + .platform_data = >a02_hdq_platform_data,
3765 +#ifdef CONFIG_LEDS_NEO1973_VIBRATOR
3766 +/* vibrator (child of FIQ) */
3768 +static struct resource gta02_vibrator_resources[] = {
3770 + .start = GTA02_GPIO_VIBRATOR_ON,
3771 + .end = GTA02_GPIO_VIBRATOR_ON,
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,
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,
3785 + .platform_data = >a02_vib_pdata,
3792 +#define GTA02_FLASH_BASE 0x18000000 /* GCS3 */
3793 +#define GTA02_FLASH_SIZE 0x200000 /* 2MBytes */
3795 +static struct physmap_flash_data gta02_nor_flash_data = {
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,
3805 +static struct platform_device gta02_nor_flash = {
3806 + .name = "physmap-flash",
3809 + .platform_data = >a02_nor_flash_data,
3811 + .resource = >a02_nor_flash_resource,
3812 + .num_resources = 1,
3816 +struct platform_device s3c24xx_pwm_device = {
3817 + .name = "s3c24xx_pwm",
3818 + .num_resources = 0,
3821 +static struct i2c_board_info gta02_i2c_devs[] __initdata = {
3823 + I2C_BOARD_INFO("pcf50633", 0x73),
3824 + .irq = GTA02_IRQ_PCF50633,
3825 + .platform_data = >a02_pcf_pdata,
3828 + I2C_BOARD_INFO("wm8753", 0x1a),
3832 +static struct s3c2410_nand_set gta02_nand_sets[] = {
3834 + .name = "neo1973-nand",
3836 + .flags = S3C2410_NAND_BBT,
3840 +/* choose a set of timings derived from S3C@2442B MCP54
3841 + * data sheet (K5D2G13ACM-D075 MCP Memory)
3844 +static struct s3c2410_platform_nand gta02_nand_info = {
3848 + .nr_sets = ARRAY_SIZE(gta02_nand_sets),
3849 + .sets = gta02_nand_sets,
3850 + .software_ecc = 1,
3854 +static void gta02_s3c_mmc_set_power(unsigned char power_mode,
3855 + unsigned short vdd)
3857 + static int is_on = -1;
3860 + on = power_mode == MMC_POWER_ON || power_mode == MMC_POWER_UP;
3862 + gta02_wlan_reset(!on);
3867 +static struct s3c24xx_mci_pdata gta02_s3c_mmc_cfg = {
3868 + .set_power = gta02_s3c_mmc_set_power,
3871 +static void gta02_udc_command(enum s3c2410_udc_cmd_e 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);
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);
3882 + case S3C2410_UDC_P_RESET:
3883 + printk(KERN_DEBUG "%s S3C2410_UDC_P_RESET\n", __func__);
3891 +/* get PMU to set USB current limit accordingly */
3893 +static struct s3c2410_udc_mach_info gta02_udc_cfg = {
3894 + .vbus_draw = gta02_udc_vbus_draw,
3895 + .udc_command = gta02_udc_command,
3900 +/* Touchscreen configuration. */
3902 +#ifdef CONFIG_TOUCHSCREEN_FILTER
3903 +const static struct ts_filter_group_configuration gta02_ts_group = {
3905 + .close_enough = 10,
3906 + .threshold = 6, /* At least half of the points in a group. */
3910 +const static struct ts_filter_median_configuration gta02_ts_median = {
3912 + .decimation_below = 3,
3913 + .decimation_threshold = 8 * 3,
3914 + .decimation_above = 4,
3917 +const static struct ts_filter_mean_configuration gta02_ts_mean = {
3921 +const static struct ts_filter_linear_configuration gta02_ts_linear = {
3922 + .constants = {1, 0, 0, 0, 1, 0, 1}, /* Don't modify coords. */
3928 +const static struct ts_filter_chain_configuration gta02_filter_configuration[] =
3930 +#ifdef CONFIG_TOUCHSCREEN_FILTER
3931 + {&ts_filter_group_api, >a02_ts_group.config},
3932 + {&ts_filter_median_api, >a02_ts_median.config},
3933 + {&ts_filter_mean_api, >a02_ts_mean.config},
3934 + {&ts_filter_linear_api, >a02_ts_linear.config},
3939 +const static struct s3c2410_ts_mach_info gta02_ts_cfg = {
3941 + .presc = 0xff, /* slow as we can go */
3942 + .filter_config = gta02_filter_configuration,
3947 +static void gta02_bl_set_intensity(int intensity)
3949 + struct pcf50633 *pcf = gta02_pcf;
3950 + int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
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.
3960 + * In the unlikely event that there's another path leading here while
3961 + * we're atomic, we print at least a warning.
3963 + if (in_atomic()) {
3965 + "gta02_bl_set_intensity called while atomic\n");
3969 + if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3))
3970 + old_intensity = 0;
3972 + old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
3974 + if (intensity == old_intensity)
3977 + /* We can't do this anywhere else */
3978 + pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5);
3981 + * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
3982 + * if seen, you have to re-enable the LED unit
3984 + if (!intensity || !old_intensity)
3985 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0);
3987 + if (!intensity) /* illegal to set LEDOUT to 0 */
3988 + ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
3991 + ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
3995 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2);
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,
4006 +static struct platform_device gta02_bl_dev = {
4007 + .name = "generic-bl",
4010 + .platform_data = >a02_bl_info,
4014 +/* SPI: LCM control interface attached to Glamo3362 */
4016 +static void gta02_jbt6k74_reset(int devidx, int level)
4018 + glamo_lcm_reset(level);
4021 +static void gta02_jbt6k74_probe_completed(struct device *dev)
4023 + struct pcf50633 *pcf = gta02_pcf;
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);
4031 + gta02_bl_dev.dev.parent = dev;
4032 + platform_device_register(>a02_bl_dev);
4035 +const struct jbt6k74_platform_data jbt6k74_pdata = {
4036 + .reset = gta02_jbt6k74_reset,
4037 + .probe_completed = gta02_jbt6k74_probe_completed,
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,
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,
4055 +/*----------- SPI: Accelerometers attached to SPI of s3c244x ----------------- */
4057 +void gta02_lis302dl_suspend_io(struct lis302dl_info *lis, int resume)
4059 + struct lis302dl_platform_data *pdata = lis->pdata;
4063 + * we don't want to power them with a high level
4064 + * because GSENSOR_3V3 is not up during suspend
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);
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);
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);
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,
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,
4109 +static struct spi_board_info gta02_spi_board_info[] = {
4111 + .modalias = "jbt6k74",
4112 + /* platform_data */
4113 + .platform_data = &jbt6k74_pdata,
4114 + /* controller_data */
4116 + .max_speed_hz = 100 * 1000,
4121 + .modalias = "lis302dl",
4122 + /* platform_data */
4123 + .platform_data = &lis302_pdata_top,
4124 + /* controller_data */
4126 + .max_speed_hz = 100 * 1000,
4132 + .modalias = "lis302dl",
4133 + /* platform_data */
4134 + .platform_data = &lis302_pdata_bottom,
4135 + /* controller_data */
4137 + .max_speed_hz = 100 * 1000,
4144 +static void gta02_lis302_chip_select(struct s3c2410_spigpio_info *info, int csid, int cs)
4148 + * Huh... "quirk"... CS on this device is not really "CS" like you can
4151 + * When it is 0 it selects SPI interface mode.
4152 + * When it is 1 it selects I2C interface mode.
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
4158 + * When we talk to the "enabled" device, the "disabled" device sees
4159 + * the clocks as I2C clocks, creating havoc.
4161 + * I2C sees MOSI going LOW while CLK HIGH as a START action, thus we
4162 + * must ensure this is never issued.
4165 + int cs_gpio, other_cs_gpio;
4167 + cs_gpio = csid ? S3C2410_GPD13 : S3C2410_GPD12;
4168 + other_cs_gpio = (1 - csid) ? S3C2410_GPD13 : S3C2410_GPD12;
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);
4177 + s3c2410_gpio_setpin(cs_gpio, 1);
4178 + s3c2410_gpio_setpin(other_cs_gpio, 1);
4182 +static struct s3c2410_spigpio_info gta02_spigpio_cfg = {
4183 + .pin_clk = S3C2410_GPG7,
4184 + .pin_mosi = S3C2410_GPG6,
4185 + .pin_miso = S3C2410_GPG5,
4187 + .num_chipselect = 2,
4188 + .chip_select = gta02_lis302_chip_select,
4189 + .non_blocking_transfer = 1,
4192 +static struct platform_device gta02_spi_gpio_dev = {
4193 + .name = "spi_s3c24xx_gpio",
4195 + .platform_data = >a02_spigpio_cfg,
4199 +/*----------- / SPI: Accelerometers attached to SPI of s3c244x ----------------- */
4201 +static struct resource gta02_led_resources[] = {
4203 + .name = "gta02-power:orange",
4204 + .start = GTA02_GPIO_PWR_LED1,
4205 + .end = GTA02_GPIO_PWR_LED1,
4207 + .name = "gta02-power:blue",
4208 + .start = GTA02_GPIO_PWR_LED2,
4209 + .end = GTA02_GPIO_PWR_LED2,
4211 + .name = "gta02-aux:red",
4212 + .start = GTA02_GPIO_AUX_LED,
4213 + .end = GTA02_GPIO_AUX_LED,
4217 +struct platform_device gta02_led_dev = {
4218 + .name = "gta02-led",
4219 + .num_resources = ARRAY_SIZE(gta02_led_resources),
4220 + .resource = gta02_led_resources,
4223 +static struct resource gta02_button_resources[] = {
4225 + .start = GTA02_GPIO_AUX_KEY,
4226 + .end = GTA02_GPIO_AUX_KEY,
4229 + .start = GTA02_GPIO_HOLD_KEY,
4230 + .end = GTA02_GPIO_HOLD_KEY,
4233 + .start = GTA02_GPIO_JACK_INSERT,
4234 + .end = GTA02_GPIO_JACK_INSERT,
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,
4253 +static struct platform_device gta02_pm_usbhost_dev = {
4254 + .name = "neo1973-pm-host",
4259 +static struct s3c2410_hcd_info gta02_usb_info = {
4261 + .flags = S3C_HCDFLG_USED,
4268 +static int glamo_irq_is_wired(void)
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.
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);
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
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");
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");
4299 +static int gta02_glamo_can_set_mmc_power(void)
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:
4312 +/* Smedia Glamo 3362 */
4315 + * we crank down SD Card clock dynamically when GPS is powered
4318 +static int gta02_glamo_mci_use_slow(void)
4320 + return neo1973_pm_gps_is_on();
4323 +static void gta02_glamo_external_reset(int level)
4325 + s3c2410_gpio_setpin(GTA02_GPIO_3D_RESET, level);
4326 + s3c2410_gpio_cfgpin(GTA02_GPIO_3D_RESET, S3C2410_GPIO_OUTPUT);
4329 +static struct glamofb_platform_data gta02_glamo_pdata = {
4332 + /* 24.5MHz --> 40.816ns */
4333 + .pixclock = 40816,
4335 + .right_margin = 16,
4336 + .upper_margin = 2,
4337 + .lower_margin = 16,
4340 + .fb_mem_size = 0x400000, /* glamo has 8 megs of SRAM. we use 4 */
4356 + //.spi_info = &glamo_spi_cfg,
4357 + .spigpio_info = &glamo_spigpio_cfg,
4359 + /* glamo MMC function platform data */
4360 + .mmc_dev = >a02_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
4367 +static struct resource gta02_glamo_resources[] = {
4369 + .start = S3C2410_CS1,
4370 + .end = S3C2410_CS1 + 0x1000000 - 1,
4371 + .flags = IORESOURCE_MEM,
4374 + .start = GTA02_IRQ_3D,
4375 + .end = GTA02_IRQ_3D,
4376 + .flags = IORESOURCE_IRQ,
4379 + .start = GTA02_GPIO_3D_RESET,
4380 + .end = GTA02_GPIO_3D_RESET,
4384 +static struct platform_device gta02_glamo_dev = {
4385 + .name = "glamo3362",
4386 + .num_resources = ARRAY_SIZE(gta02_glamo_resources),
4387 + .resource = gta02_glamo_resources,
4389 + .platform_data = >a02_glamo_pdata,
4393 +static void mangle_glamo_res_by_system_rev(void)
4395 + switch (S3C_SYSTEM_REV_ATAG) {
4396 + case GTA02v1_SYSTEM_REV:
4399 + gta02_glamo_resources[2].start = GTA02_GPIO_3D_RESET;
4400 + gta02_glamo_resources[2].end = GTA02_GPIO_3D_RESET;
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;
4417 +static void __init gta02_map_io(void)
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));
4424 +static irqreturn_t gta02_modem_irq(int irq, void *param)
4426 + printk(KERN_DEBUG "modem wakeup interrupt\n");
4427 + gta_gsm_interrupts++;
4428 + return IRQ_HANDLED;
4431 +static irqreturn_t ar6000_wow_irq(int irq, void *param)
4433 + printk(KERN_DEBUG "ar6000_wow interrupt\n");
4434 + return IRQ_HANDLED;
4438 + * hardware_ecc=1|0
4440 +static char hardware_ecc_str[4] __initdata = "";
4442 +static int __init hardware_ecc_setup(char *str)
4445 + strlcpy(hardware_ecc_str, str, sizeof(hardware_ecc_str));
4449 +__setup("hardware_ecc=", hardware_ecc_setup);
4451 +/* these are the guys that don't need to be children of PMU */
4453 +static struct platform_device *gta02_devices[] __initdata = {
4454 + >a02_version_device,
4457 + >a02_memconfig_device,
4459 + &s3c_device_usbgadget,
4463 + &s3c24xx_pwm_device,
4465 + >a02_pm_wlan_dev, /* not dependent on PMU */
4471 +/* these guys DO need to be children of PMU */
4473 +static struct platform_device *gta02_devices_pmu_children[] = {
4474 + &s3c_device_ts, /* input 1 */
4475 + >a02_pm_gsm_dev,
4476 + >a02_pm_usbhost_dev,
4477 + >a02_spi_gpio_dev, /* input 2 and 3 */
4478 + >a02_button_dev, /* input 4 */
4479 + >a02_resume_reason_device,
4482 +static void gta02_pmu_regulator_registered(struct pcf50633 *pcf, int id)
4484 + struct platform_device *regulator, *pdev;
4488 + regulator = pcf->regulator_pdev[id];
4491 + case PCF50633_REGULATOR_LDO4:
4492 + pdev = >a01_pm_bt_dev;
4494 + case PCF50633_REGULATOR_LDO5:
4495 + pdev = >a01_pm_gps_dev;
4497 + case PCF50633_REGULATOR_HCLDO:
4498 + pdev = >a02_glamo_dev;
4504 + pdev->dev.parent = ®ulator->dev;
4505 + platform_device_register(pdev);
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.
4515 +static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf)
4519 + for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++)
4520 + gta02_devices_pmu_children[n]->dev.parent = pcf->dev;
4522 + mangle_glamo_res_by_system_rev();
4523 + platform_add_devices(gta02_devices_pmu_children,
4524 + ARRAY_SIZE(gta02_devices_pmu_children));
4527 +static void gta02_poweroff(void)
4529 + pcf50633_reg_set_bit_mask(gta02_pcf, PCF50633_REG_OOCSHDWN,
4530 + PCF50633_OOCSHDWN_GOSTDBY, PCF50633_OOCSHDWN_GOSTDBY);
4533 +static void __init gta02_machine_init(void)
4537 + /* set the panic callback to make AUX blink fast */
4538 + panic_blink = gta02_panic_blink;
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;
4550 + spin_lock_init(&motion_irq_lock);
4552 +#ifdef CONFIG_CHARGER_PCF50633
4553 + INIT_DELAYED_WORK(>a02_charger_work, gta02_charger_worker);
4556 + /* Glamo chip select optimization */
4557 +/* *((u32 *)(S3C2410_MEMREG(((1 + 1) << 2)))) = 0x1280; */
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;
4563 + s3c_device_usb.dev.platform_data = >a02_usb_info;
4564 + s3c_device_nand.dev.platform_data = >a02_nand_info;
4565 + s3c_device_sdi.dev.platform_data = >a02_s3c_mmc_cfg;
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);
4573 + s3c24xx_udc_set_platdata(>a02_udc_cfg);
4574 + s3c_i2c0_set_platdata(NULL);
4575 + set_s3c2410ts_info(>a02_ts_cfg);
4577 + mangle_glamo_res_by_system_rev();
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));
4583 + mangle_pmu_pdata_by_system_rev();
4585 + platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
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,
4594 + printk(KERN_ERR "GTA02: can't request GSM modem wakeup IRQ\n");
4595 + enable_irq_wake(GTA02_IRQ_MODEM);
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,
4603 + printk(KERN_ERR "GTA02: can't request ar6k wakeup IRQ\n");
4604 + enable_irq_wake(GTA02_IRQ_WLAN_GPIO1);
4606 + pm_power_off = gta02_poweroff;
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(>a02_hdq_device);
4613 +#ifdef CONFIG_LEDS_NEO1973_VIBRATOR
4614 + gta02_vibrator_dev.dev.parent = &s3c24xx_pwm_device.dev;
4615 + platform_device_register(>a02_vibrator_dev);
4619 +void DEBUG_LED(int n)
4624 + neo1973_gpb_setpin(GTA02_GPIO_PWR_LED1, 1);
4627 + neo1973_gpb_setpin(GTA02_GPIO_PWR_LED2, 1);
4630 + neo1973_gpb_setpin(GTA02_GPIO_AUX_LED, 1);
4633 +// printk(KERN_ERR"die %d\n", *p);
4635 +EXPORT_SYMBOL_GPL(DEBUG_LED);
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,
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
4653 +obj-$(CONFIG_S3C2440_C_FIQ) += fiq_c_isr.o
4655 obj-$(CONFIG_CPU_S3C2442) += s3c2442.o
4656 obj-$(CONFIG_CPU_S3C2442) += clock.o
4657 +obj-$(CONFIG_MACH_NEO1973_GTA02) += mach-gta02.o
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
4666 #include <plat/s3c2442.h>
4667 #include <plat/cpu.h>
4668 +#include <plat/devs.h>
4670 static struct sys_device s3c2442_sysdev = {
4671 .cls = &s3c2442_sysclass,
4674 printk("S3C2442: Initialising architecture\n");
4676 + /* make sure SD/MMC driver can distinguish 2440 from 2410 */
4677 + s3c_device_sdi.name = "s3c2440-sdi";
4679 return sysdev_register(&s3c2442_sysdev);
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
4686 #include <mach/dma.h>
4688 -#include <plat/dma.h>
4689 +#include <plat/dma-plat.h>
4690 #include <plat/cpu.h>
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>
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
4708 +/* arch/arm/mach-s3c24a0/include/mach/io.h
4710 + * Copyright 2008 Simtec Electronics
4711 + * Ben Dooks <ben-linux@fluff.org>
4713 + * IO access and mapping routines for the S3C24A0
4716 +#ifndef __ASM_ARM_ARCH_IO_H
4717 +#define __ASM_ARM_ARCH_IO_H
4719 +/* No current ISA/PCI bus support. */
4720 +#define __io(a) ((void __iomem *)(a))
4721 +#define __mem_pci(a) (a)
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
4728 #define IRQ_EINT17 S3C2410_IRQ(49)
4729 #define IRQ_EINT18 S3C2410_IRQ(50)
4731 +#define IRQ_EINT_BIT(x) ((x) - IRQ_EINT00)
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
4740 #ifndef __ASM_ARCH_DMA_H
4741 #define __ASM_ARCH_DMA_H __FILE__
4743 -/* currently nothing here, placeholder */
4744 +#define S3C_DMA_CHANNELS (16)
4746 +/* see mach-s3c2410/dma.h for notes on dma channel numbers */
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
4768 + DMACH_HSI_I2SV40_TX,
4769 + DMACH_HSI_I2SV40_RX,
4772 + DMACH_PCM1_TX = 16,
4778 + DMACH_AC97_PCMOUT,
4786 + DMACH_SECURITY_RX, /* SDMA1 only */
4787 + DMACH_SECURITY_TX, /* SDMA1 only */
4788 + DMACH_MAX /* the end */
4791 +static __inline__ int s3c_dma_has_circular(void)
4793 + /* we will be supporting ciruclar buffers as soon as we have DMA
4799 +#define S3C2410_DMAF_CIRCULAR (1 << 0)
4801 +#include <plat/dma.h>
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
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)
4817 #define S3C64XX_SZ_GPIO SZ_4K
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)
4825 +#define S3C64XX_PA_MODEM (0x74108000)
4826 +#define S3C64XX_VA_MODEM S3C_ADDR(0x00600000)
4828 +#define S3C64XX_PA_USBHOST (0x74300000)
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)
4836 /* compatibiltiy defines. */
4837 #define S3C_PA_TIMER S3C64XX_PA_TIMER
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
4844 +#define S3C64XX_VA_OTG S3C_VA_OTG
4845 +#define S3C64XX_PA_OTG (0x7C000000)
4847 +#define S3C64XX_VA_OTGSFR S3C_VA_OTGSFR
4848 +#define S3C64XX_PA_OTGSFR (0x7C100000)
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
4855 +/* linux/arch/arm/mach-s3c6400/include/mach/regs-clock.h
4857 + * Copyright 2008 Openmoko, Inc.
4858 + * Copyright 2008 Simtec Electronics
4859 + * http://armlinux.simtec.co.uk/
4860 + * Ben Dooks <ben@simtec.co.uk>
4862 + * S3C64XX - clock register compatibility with s3c24xx
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.
4869 +#include <plat/regs-clock.h>
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
4875 #ifndef __ASM_ARCH_SYSTEM_H
4876 #define __ASM_ARCH_SYSTEM_H __FILE__
4878 +#include <linux/io.h>
4879 +#include <mach/map.h>
4881 +#include <plat/regs-sys.h>
4882 +#include <plat/regs-syscon-power.h>
4884 static void arch_idle(void)
4886 - /* nothing here yet */
4887 + unsigned long flags;
4890 + /* ensure that if we execute the cpu idle sequence that we
4891 + * go into idle mode instead of powering off. */
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);
4899 + local_irq_restore(flags);
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
4910 + * 3D7K GPIO Mappings
4912 + * (C) 2008 by Openmoko Inc.
4913 + * Author: Andy Green <andy@openmoko.com>
4914 + * All rights reserved.
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
4925 +#include <mach/gpio.h>
4926 +#include <mach/irqs.h>
4927 +#include <linux/mfd/pcf50633/core.h>
4929 +extern struct pcf50633 *om_3d7k_pcf;
4931 +/* ATAG_REVISION from bootloader */
4932 +#define OM_3D7Kv1_SYSTEM_REV 0x00000001
4934 +#define OM_3D7K_GPIO_VIBRATOR_ON S3C64XX_GPF(13)
4935 +#define OM_3D7K_GPIO_CLKOUT S3C64XX_GPF(14)
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)
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)
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)
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)
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)
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)
4966 +#define OM_3D7K_GPIO_LCM_SD S3C64XX_GPL(0)
4968 +#define OM_3D7K_GPIO_TP_RESET S3C64XX_GPM(0)
4969 +#define OM_3D7K_GPIO_GPS_LNA_EN S3C64XX_GPM(2)
4971 +#define OM_3D7K_GPIO_USB_FLT S3C64XX_GPM(4)
4972 +#define OM_3D7K_GPIO_USB_OC S3C64XX_GPM(5)
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)
4988 +#define OM_3D7K_GPIO_N_MODEM_RESET S3C64XX_GPO(1)
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)
5004 +#define OM_3D7K_IRQ_LED IRQ_EINT_GROUP(6, 9)
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
5011 +/* arch/arm/mach-s3c6400/include/mach/spi-gpio.h
5013 + * Copyright (c) 2006 Simtec Electronics
5014 + * Ben Dooks <ben@simtec.co.uk>
5016 + * S3C64XX - SPI Controller platfrom_device info
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.
5023 +#ifndef __ASM_ARCH_SPIGPIO_H
5024 +#define __ASM_ARCH_SPIGPIO_H __FILE__
5026 +struct s3c64xx_spigpio_info {
5027 + unsigned long pin_clk;
5028 + unsigned long pin_mosi;
5029 + unsigned long pin_miso;
5032 + int num_chipselect;
5034 + void (*chip_select)(struct s3c64xx_spigpio_info *spi, int csid, int cs);
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
5043 select S3C_DEV_HSMMC1
5046 + select S3C_DEV_USB_HOST
5047 select S3C6410_SETUP_SDHCI
5048 select S3C64XX_SETUP_I2C1
5049 select S3C64XX_SETUP_FB_24BPP
5051 channels 0 and 1 are the same.
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
5065 + select S3C_DEV_CAMIF
5066 + select S3C64XX_SETUP_FB_24BPP
5067 +# select SENSORS_PCF50633
5068 + select POWER_SUPPLY
5069 + select HDQ_GPIO_BITBANG
5072 + select MACH_NEO1973
5074 + Machine support for the Openmoko 3D7K Phone
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
5080 +/* linux/arch/arm/mach-s3c6410/mach-om-3d7k.c
5082 + * Copyright 2008 Openmoko, Inc.
5083 + * Andy Green <andy@openmoko.org>
5085 + * based on mach_smdk6410.c which is
5087 + * Copyright 2008 Openmoko, Inc.
5088 + * Copyright 2008 Simtec Electronics
5089 + * Ben Dooks <ben@simtec.co.uk>
5090 + * http://armlinux.simtec.co.uk/
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.
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>
5119 +#include <video/platform_lcd.h>
5121 +#include <asm/mach/arch.h>
5122 +#include <asm/mach/map.h>
5123 +#include <asm/mach/irq.h>
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>
5132 +#include <asm/irq.h>
5133 +#include <asm/mach-types.h>
5134 +#include <asm/fiq.h>
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>
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>
5152 +/* #include <plat/udc.h> */
5153 +#include <linux/i2c.h>
5154 +#include <linux/backlight.h>
5155 +#include <linux/regulator/machine.h>
5157 +#include <mach/om-3d7k.h>
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>
5165 +#include <plat/regs-usb-hs-otg.h>
5167 +extern struct platform_device s3c_device_usbgadget;
5168 +extern struct platform_device s3c_device_camif; /* @@@ change plat/devs.h */
5171 +/* -------------------------------------------------------------------------------
5172 + * OM_3D7K FIQ related
5174 + * Calls into vibrator and hdq and based on the return values
5175 + * determines if we the FIQ source be kept alive
5178 +#define DIVISOR_FROM_US(x) ((x) * 23)
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);
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;
5192 +/* Convinience defines */
5193 +#define S3C6410_INTMSK (S3C_VA_VIC0 + VIC_INT_ENABLE)
5194 +#define S3C6410_INTMOD (S3C_VA_VIC0 + VIC_INT_SELECT)
5198 +static void om_3d7k_fiq_handler(void)
5200 + u16 divisor = 0xffff;
5202 + /* Vibrator servicing */
5204 + /* disable further timer interrupts if nobody has any work
5205 + * or adjust rate according to who still has work
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
5212 +#ifdef CONFIG_HDQ_GPIO_BITBANG
5213 + if (hdq_fiq_handler())
5214 + divisor = (u16)FIQ_DIVISOR_HDQ;
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));
5223 + __raw_writel((__raw_readl(S3C64XX_TINT_CSTAT) & 0x1f ) | 1 << 8 , S3C64XX_TINT_CSTAT);
5227 +static void om_3d7k_fiq_kick(void)
5229 + unsigned long flags;
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)
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);
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,
5249 + __raw_writel(tcon | S3C2410_TCON_T3START, S3C2410_TCON);
5250 + local_irq_restore(flags);
5253 +static int om_3d7k_fiq_enable(void)
5255 + int irq_index_fiq = IRQ_TIMER3_VIC;
5258 + local_fiq_disable();
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;
5265 + /* set up the timer to operate as a pwm device */
5267 + rc = s3c2410_pwm_init(&om_3d7k_fiq_pwm_timer);
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;
5277 + rc = s3c2410_pwm_enable(&om_3d7k_fiq_pwm_timer);
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);
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);
5290 + s3c2410_pwm_start(&om_3d7k_fiq_pwm_timer);
5292 + /* it's ready to go as soon as we unmask the source in S3C2410_INTMSK */
5293 + local_fiq_enable();
5295 + set_fiq_c_handler(om_3d7k_fiq_handler);
5302 + printk(KERN_ERR "Count not initialize FIQ for OM_3D7K %d \n", rc);
5306 +static void om_3d7k_fiq_disable(void)
5308 + __raw_writel(0, S3C6410_INTMOD);
5309 + local_fiq_disable();
5310 + om_3d7k_fiq_irq = 0; /* no active source interrupt now either */
5313 +/* -------------------- /OM_3D7K FIQ Handler ------------------------------------- */
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
5319 +static struct s3c2410_uartcfg om_3d7k_uartcfgs[] __initdata = {
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.
5358 + * Foreground / interrupt arbitration is okay because the interrupts are
5359 + * disabled around all the foreground SPI code.
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.
5365 + * Servicing is typ 75 - 100us at 400MHz.
5368 +/* #define DEBUG_SPEW_MS */
5369 +#define MG_PER_SAMPLE 18
5371 +struct lis302dl_platform_data lis302_pdata;
5374 + * generic SPI RX and TX bitbang
5375 + * only call with interrupts off!
5378 +static void __3d7k_lis302dl_bitbang(struct lis302dl_info *lis, u8 *tx,
5379 + int tx_bytes, u8 *rx, int rx_bytes)
5381 + struct lis302dl_platform_data *pdata = lis->pdata;
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);
5389 + /* send the register index, r/w and autoinc bits */
5390 + for (n = 0; n < (tx_bytes << 3); n++) {
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);
5399 + for (n = 0; n < (rx_bytes << 3); n++) { /* 8 bits each */
5400 + gpio_direction_output(pdata->pin_clk, 0);
5402 + if (gpio_direction_input(pdata->pin_miso))
5405 + rx[n >> 3] = shifter;
5406 + gpio_direction_output(pdata->pin_clk, 1);
5408 + gpio_direction_output(pdata->pin_chip_select, 1);
5412 +static int om_3d7k_lis302dl_bitbang_read_reg(struct lis302dl_info *lis, u8 reg)
5414 + u8 data = 0xc0 | reg; /* read, autoincrement */
5415 + unsigned long flags;
5417 + local_irq_save(flags);
5419 + __3d7k_lis302dl_bitbang(lis, &data, 1, &data, 1);
5421 + local_irq_restore(flags);
5426 +static void om_3d7k_lis302dl_bitbang_write_reg(struct lis302dl_info *lis, u8 reg,
5429 + u8 data[2] = { 0x00 | reg, val }; /* write, no autoincrement */
5430 + unsigned long flags;
5432 + local_irq_save(flags);
5434 + __3d7k_lis302dl_bitbang(lis, &data[0], 2, NULL, 0);
5436 + local_irq_restore(flags);
5441 +void om_3d7k_lis302dl_suspend_io(struct lis302dl_info *lis, int resume)
5443 + struct lis302dl_platform_data *pdata = lis->pdata;
5447 + * we don't want to power them with a high level
5448 + * because GSENSOR_3V3 is not up during suspend
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);
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);
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));
5470 +struct lis302dl_platform_data lis302_pdata = {
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,
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,
5484 +static struct platform_device s3c_device_spi_acc1 = {
5485 + .name = "lis302dl",
5488 + .platform_data = &lis302_pdata,
5494 +/* framebuffer and LCD setup. */
5496 +/* GPF15 = LCD backlight control
5497 + * GPF13 => Panel power
5498 + * GPN5 = LCD nRESET signal
5499 + * PWM_TOUT1 => backlight brightness
5502 +static void om_3d7k_lcd_power_set(struct plat_lcd_data *pd,
5503 + unsigned int power)
5508 +static struct plat_lcd_data om_3d7k_lcd_power_data = {
5509 + .set_power = om_3d7k_lcd_power_set,
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,
5518 +static struct s3c_fb_pd_win om_3d7k_fb_win0 = {
5519 + /* this is to ensure we use win0 */
5521 + .pixclock = 40816,
5523 + .right_margin = 16,
5524 + .upper_margin = 2,
5525 + .lower_margin = 16,
5532 + .default_bpp = 16,
5535 +static void om_3d7k_fb_gpio_setup(void)
5537 + unsigned int gpio;
5539 + /* GPI0, GPI1, GPI8 are for hardware version contrl.
5540 + * They should be set as input in order to prevent
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);
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);
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,
5564 +struct map_desc om_3d7k_6410_iodesc[] = {};
5566 +static struct resource om_3d7k_button_resources[] = {
5572 + .start = OM_3D7K_GPIO_HOLD,
5573 + .end = OM_3D7K_GPIO_HOLD,
5576 + .start = OM_3D7K_GPIO_JACK_INSERT,
5577 + .end = OM_3D7K_GPIO_JACK_INSERT,
5580 + .start = OM_3D7K_GPIO_KEY_PLUS,
5581 + .end = OM_3D7K_GPIO_KEY_PLUS,
5584 + .start = OM_3D7K_GPIO_KEY_MINUS,
5585 + .end = OM_3D7K_GPIO_KEY_MINUS,
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,
5596 +/********************** PMU ***************************/
5598 + * OM_3D7K PMU Mapping info
5600 + * name maxcurr default Nom consumers
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
5617 +/* PMU driver info */
5620 +static struct regulator_consumer_supply ldo4_consumers[] = {
5622 + .dev = &s3c_device_hsmmc0.dev,
5623 + .supply = "SD_3V",
5627 +static struct platform_device om_3d7k_features_dev = {
5628 + .name = "om-3d7k",
5631 +static struct regulator_consumer_supply ldo5_consumers[] = {
5633 + .dev = &om_3d7k_features_dev.dev,
5634 + .supply = "RF_3V",
5639 +static void om_3d7k_pmu_event_callback(struct pcf50633 *pcf, int irq)
5642 + if (irq == PCF50633_IRQ_USBINS) {
5643 + schedule_delayed_work(&om_3d7k_charger_work,
5644 + GTA02_CHARGER_CONFIGURE_TIMEOUT);
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;
5652 + bq27000_charging_state_change(&bq27000_battery_device);
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);
5659 +/* Global reference */
5660 +struct pcf50633 *om_3d7k_pcf;
5662 +struct pcf50633_platform_data om_3d7k_pcf_pdata = {
5665 + [0] = PCF50633_INT1_USBINS |
5666 + PCF50633_INT1_USBREM |
5667 + PCF50633_INT1_ALARM,
5668 + [1] = PCF50633_INT2_ONKEYF,
5669 + [2] = PCF50633_INT3_ONKEY1S
5671 + .chg_ref_current_ma = 1000,
5672 + .reg_init_data = {
5673 + /* OM_3D7K: Main 3.3V rail */
5674 + [PCF50633_REGULATOR_AUTO] = {
5676 + .min_uV = 3300000,
5677 + .max_uV = 3300000,
5678 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5684 + .num_consumer_supplies = 0,
5686 + /* OM_3D7K: CPU core power */
5687 + [PCF50633_REGULATOR_DOWN1] = {
5690 + .max_uV = 1200000,
5691 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5694 + .num_consumer_supplies = 0,
5696 + /* OM_3D7K: Memories */
5697 + [PCF50633_REGULATOR_DOWN2] = {
5699 + .min_uV = 1800000,
5700 + .max_uV = 1800000,
5701 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5707 + .num_consumer_supplies = 0,
5709 + /* OM_3D7K: Camera 2V8 */
5710 + [PCF50633_REGULATOR_HCLDO] = {
5712 + .min_uV = 2800000,
5713 + .max_uV = 2800000,
5714 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5716 + .num_consumer_supplies = 0,
5717 +/* .consumer_supplies = hcldo_consumers, */
5720 + /* OM_3D7K: Accel 3V3 */
5721 + [PCF50633_REGULATOR_LDO1] = {
5723 + .min_uV = 3300000,
5724 + .max_uV = 3300000,
5725 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5728 + .num_consumer_supplies = 0,
5730 + /* OM_3D7K: Camera 1V5 */
5731 + [PCF50633_REGULATOR_LDO2] = {
5733 + .min_uV = 1500000,
5734 + .max_uV = 1500000,
5735 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5738 + .num_consumer_supplies = 0,
5740 + /* OM_3D7K: Codec 3.3V */
5741 + [PCF50633_REGULATOR_LDO3] = {
5743 + .min_uV = 3300000,
5744 + .max_uV = 3300000,
5745 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5749 + .num_consumer_supplies = 0,
5751 + /* OM_3D7K: uSD Power */
5752 + [PCF50633_REGULATOR_LDO4] = {
5754 + .min_uV = 3000000,
5755 + .max_uV = 3000000,
5756 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5759 + .num_consumer_supplies = 1,
5760 + .consumer_supplies = ldo4_consumers,
5762 + /* OM_3D7K: GPS 3V */
5763 + [PCF50633_REGULATOR_LDO5] = {
5765 + .min_uV = 3000000,
5766 + .max_uV = 3000000,
5767 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5770 + .num_consumer_supplies = 1,
5771 + .consumer_supplies = ldo5_consumers,
5773 + /* OM_3D7K: LCM 3V */
5774 + [PCF50633_REGULATOR_LDO6] = {
5776 + .min_uV = 3000000,
5777 + .max_uV = 3000000,
5778 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5783 + .num_consumer_supplies = 0,
5785 + /* power for memories in suspend */
5786 + [PCF50633_REGULATOR_MEMLDO] = {
5788 + .min_uV = 1800000,
5789 + .max_uV = 1800000,
5790 + .valid_modes_mask = REGULATOR_MODE_NORMAL,
5795 + .num_consumer_supplies = 0,
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,
5804 +static void om_3d7k_bl_set_intensity(int intensity)
5806 + struct pcf50633 *pcf = om_3d7k_pcf;
5807 + int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
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.
5817 + * In the unlikely event that there's another path leading here while
5818 + * we're atomic, we print at least a warning.
5820 + if (in_atomic()) {
5822 + "3d7k_bl_set_intensity called while atomic\n");
5826 + old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT);
5827 + if (intensity == old_intensity)
5830 + /* We can't do this anywhere else */
5831 + pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 5);
5833 + if (!(pcf50633_reg_read(pcf, PCF50633_REG_LEDENA) & 3))
5834 + old_intensity = 0;
5837 + * The PCF50633 cannot handle LEDOUT = 0 (datasheet p60)
5838 + * if seen, you have to re-enable the LED unit
5840 + if (!intensity || !old_intensity)
5841 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0);
5843 + if (!intensity) /* illegal to set LEDOUT to 0 */
5844 + ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
5847 + ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_LEDOUT, 0x3f,
5851 + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 2);
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,
5862 +static struct platform_device om_3d7k_bl_dev = {
5863 + .name = "generic-bl",
5866 + .platform_data = &om_3d7k_bl_info,
5870 +/* BQ27000 Battery */
5871 +static int om_3d7k_get_charger_online_status(void)
5873 + struct pcf50633 *pcf = om_3d7k_pcf;
5875 + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ONLINE;
5878 +static int om_3d7k_get_charger_active_status(void)
5880 + struct pcf50633 *pcf = om_3d7k_pcf;
5882 + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ACTIVE;
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
5896 +struct platform_device bq27000_battery_device = {
5897 + .name = "bq27000-battery",
5899 + .platform_data = &bq27000_pdata,
5903 +#ifdef CONFIG_HDQ_GPIO_BITBANG
5906 +static void om_3d7k_hdq_attach_child_devices(struct device *parent_device)
5908 + bq27000_battery_device.dev.parent = parent_device;
5909 + platform_device_register(&bq27000_battery_device);
5912 +static void om_3d7k_hdq_gpio_direction_out(void)
5914 + unsigned long con;
5915 + void __iomem *regcon = S3C64XX_GPH_BASE;
5917 + con = __raw_readl(regcon);
5918 + con &= ~(0xf << 28);
5919 + con |= 0x01 << 28;
5920 + __raw_writel(con, regcon);
5922 + /* Set pull-up enabled */
5923 + con = __raw_readl(regcon + 0x0c);
5925 + __raw_writel(con, regcon + 0x0c);
5928 +static void om_3d7k_hdq_gpio_direction_in(void)
5930 + unsigned long con;
5931 + void __iomem *regcon = S3C64XX_GPH_BASE;
5933 + con = __raw_readl(regcon);
5934 + con &= ~(0xf << 28);
5935 + __raw_writel(con, regcon);
5938 +static void om_3d7k_hdq_gpio_set_value(int val)
5941 + void __iomem *base = S3C64XX_GPH_BASE;
5943 + dat = __raw_readl(base + 0x08);
5949 + __raw_writel(dat, base + 0x08);
5952 +static int om_3d7k_hdq_gpio_get_value(void)
5955 + void *base = S3C64XX_GPH_BASE;
5957 + dat = __raw_readl(base + 0x08);
5959 + return dat & (1 << 7);
5962 +static struct resource om_3d7k_hdq_resources[] = {
5964 + .start = S3C64XX_GPH(7),
5965 + .end = S3C64XX_GPH(7),
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,
5976 + .enable_fiq = om_3d7k_fiq_enable,
5977 + .disable_fiq = om_3d7k_fiq_disable,
5978 + .kick_fiq = om_3d7k_fiq_kick,
5982 +struct platform_device om_3d7k_hdq_device = {
5984 + .num_resources = 1,
5985 + .resource = om_3d7k_hdq_resources,
5987 + .platform_data = &om_3d7k_hdq_platform_data,
5992 +static void om_3d7k_lp5521_chip_enable(int level)
5994 + gpio_direction_output(OM_3D7K_GPIO_LED_EN, level);
5998 +static struct lp5521_platform_data om_3d7k_lp5521_pdata = {
6000 + [LP5521_BLUE] = LP5521_CONNECTED,
6001 + [LP5521_GREEN] = LP5521_CONNECTED,
6002 + [LP5521_RED] = LP5521_NC,
6004 + .ext_enable = om_3d7k_lp5521_chip_enable,
6007 +static void om_3d7k_pcap7200_reset(void)
6009 + gpio_direction_output(OM_3D7K_GPIO_TP_RESET, 1);
6011 + gpio_direction_output(OM_3D7K_GPIO_TP_RESET, 0);
6014 +static struct pcap7200_platform_data om_3d7k_pcap7200_pdata = {
6015 + .mode = MULTI_TOUCH,
6016 + .reset = om_3d7k_pcap7200_reset,
6019 +static struct i2c_board_info om_3d7k_i2c_devs[] __initdata = {
6021 + I2C_BOARD_INFO("pcf50633", 0x73),
6022 + .irq = OM_3D7K_IRQ_PMU,
6023 + .platform_data = &om_3d7k_pcf_pdata,
6026 + I2C_BOARD_INFO("pcap7200", 0x0a),
6027 + .irq = OM_3D7K_IRQ_TOUCH,
6028 + .platform_data = &om_3d7k_pcap7200_pdata,
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
6038 + .irq = OM_3D7K_IRQ_LED,
6040 + .platform_data = &om_3d7k_lp5521_pdata,
6043 + I2C_BOARD_INFO("wm8753", 0x1a),
6047 +struct platform_device s3c24xx_pwm_device = {
6048 + .name = "s3c24xx_pwm",
6049 + .num_resources = 0,
6052 +struct platform_device om_3d7k_device_spi_lcm;
6054 +static struct platform_device *om_3d7k_devices[] __initdata = {
6057 + &om_3d7k_device_spi_lcm,
6058 + &s3c_device_usbgadget,
6059 + &s3c24xx_pwm_device,
6060 +#ifdef CONFIG_S3C_DEV_CAMIF
6061 + &s3c_device_camif,
6066 +static void om_3d7k_pmu_regulator_registered(struct pcf50633 *pcf, int id)
6068 + struct platform_device *regulator, *pdev;
6070 + regulator = pcf->regulator_pdev[id];
6073 + case PCF50633_REGULATOR_LDO4:
6074 + pdev = &s3c_device_hsmmc0; /* uSD card */
6076 + case PCF50633_REGULATOR_LDO5: /* GPS regulator */
6077 + pdev = &om_3d7k_features_dev;
6079 + case PCF50633_REGULATOR_LDO6:
6080 + pdev = &om_3d7k_lcd_powerdev;
6086 + pdev->dev.parent = ®ulator->dev;
6087 + platform_device_register(pdev);
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 */
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.
6103 +static void om_3d7k_pcf50633_attach_child_devices(struct pcf50633 *pcf)
6107 + om_3d7k_pcf = pcf;
6109 + for (n = 0; n < ARRAY_SIZE(om_3d7k_devices_pmu_children); n++)
6110 + om_3d7k_devices_pmu_children[n]->dev.parent = pcf->dev;
6112 + platform_add_devices(om_3d7k_devices_pmu_children,
6113 + ARRAY_SIZE(om_3d7k_devices_pmu_children));
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);
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);
6125 +static void om_3d7k_l1k002_pwronoff(int level)
6127 + gpio_direction_output(OM_3D7K_GPIO_LCM_SD, 1);
6130 + gpio_direction_output(OM_3D7K_GPIO_LCM_RESET, !!level);
6134 + gpio_direction_output(OM_3D7K_GPIO_LCM_SD, 0);
6138 +const struct l1k002_platform_data om_3d7k_l1k002_pdata = {
6139 + .pwr_onoff = om_3d7k_l1k002_pwronoff,
6142 +static struct spi_board_info om_3d7k_spi_board_info[] = {
6144 + .modalias = "l1k002",
6145 + .platform_data = &om_3d7k_l1k002_pdata,
6146 + /* controller_data */
6148 + .max_speed_hz = 10 * 1000 * 1000,
6154 +static void om_3d7k_jbt6k74_probe_completed(struct device *dev)
6156 + dev_info(dev, "device attached\n");
6159 +const struct jbt6k74_platform_data jbt6k74_pdata = {
6160 + .probe_completed = om_3d7k_jbt6k74_probe_completed,
6163 +static struct spi_board_info alt_om_3d7k_spi_board_info[] = {
6165 + .modalias = "jbt6k74",
6166 + .platform_data = &jbt6k74_pdata,
6167 + /* controller_data */
6169 + .max_speed_hz = 100 * 1000,
6175 +static void spi_gpio_cs(struct s3c64xx_spigpio_info *spi, int csidx, int cs)
6178 + case BITBANG_CS_ACTIVE:
6179 + gpio_direction_output(OM_3D7K_GPIO_LCM_CS, 0);
6181 + case BITBANG_CS_INACTIVE:
6182 + gpio_direction_output(OM_3D7K_GPIO_LCM_CS, 1);
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,
6196 +struct platform_device om_3d7k_device_spi_lcm = {
6197 + .name = "spi_s3c64xx_gpio",
6200 + .platform_data = &spi_gpio_cfg,
6204 +static int attached_lcm;
6206 +static int __init om3d7k_lcm_probe(char *s)
6208 + if (!strcmp(s, "jbt6k74"))
6213 +__setup("om_3d7k_lcm=", om3d7k_lcm_probe);
6215 +extern void s3c64xx_init_io(struct map_desc *, int);
6217 +struct s3c_plat_otg_data s3c_hs_otg_plat_data = {
6222 +static struct s3c2410_hcd_info om3d7k_usb_info = {
6224 + .flags = S3C_HCDFLG_USED,
6231 +static void __init om_3d7k_map_io(void)
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));
6238 +static void __init om_3d7k_machine_init(void)
6242 + s3c_device_usb.dev.platform_data = &om3d7k_usb_info;
6243 + s3c_device_usbgadget.dev.platform_data = &s3c_hs_otg_plat_data;
6245 + s3c_i2c0_set_platdata(NULL);
6246 + s3c_fb_set_platdata(&om_3d7k_lcd_pdata);
6248 + i2c_register_board_info(0, om_3d7k_i2c_devs,
6249 + ARRAY_SIZE(om_3d7k_i2c_devs));
6251 + spi_register_board_info(alt_om_3d7k_spi_board_info,
6252 + ARRAY_SIZE(alt_om_3d7k_spi_board_info));
6254 + spi_register_board_info(om_3d7k_spi_board_info,
6255 + ARRAY_SIZE(om_3d7k_spi_board_info));
6257 + platform_add_devices(om_3d7k_devices, ARRAY_SIZE(om_3d7k_devices));
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);
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,
6270 + .init_irq = s3c6410_init_irq,
6271 + .map_io = om_3d7k_map_io,
6272 + .init_machine = om_3d7k_machine_init,
6273 + .timer = &s3c24xx_timer,
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
6280 #include <asm/mach-types.h>
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>
6290 #include <plat/s3c6410.h>
6291 #include <plat/clock.h>
6292 #include <plat/devs.h>
6293 #include <plat/cpu.h>
6295 +#include <plat/regs-usb-hs-otg.h>
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 @@
6305 &smdk6410_lcd_powerdev,
6306 + &s3c_device_usbgadget,
6310 static struct i2c_board_info i2c_devs0[] __initdata = {
6311 @@ -155,13 +164,36 @@
6313 static void __init smdk6410_map_io(void)
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));
6321 + /* set the LCD type */
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);
6328 + /* remove the lcd bypass */
6329 + tmp = __raw_readl(S3C64XX_MODEM_MIFPCON);
6330 + tmp &= ~MIFPCON_LCD_BYPASS;
6331 + __raw_writel(tmp, S3C64XX_MODEM_MIFPCON);
6334 +struct s3c_plat_otg_data s3c_hs_otg_plat_data = {
6335 + .phyclk = REF_CLK_OSCC
6339 static void __init smdk6410_machine_init(void)
6343 + s3c_device_usbgadget.dev.platform_data = &s3c_hs_otg_plat_data;
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
6354 obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o
6355 +obj-$(CONFIG_MACH_OM_3D7K) += mach-om-3d7k.o \
6356 + om-3d7k-features.o
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
6363 + * Support for features of Openmoko 3D7K
6365 + * (C) 2008 by Openmoko Inc.
6366 + * Author: Andy Green <andy@openmoko.com>
6367 + * All rights reserved.
6369 + * Somewhat based on the GTA01 / 02 neo1973_pm_ stuff mainly by Harald Welte
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
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>
6383 +#include <mach/hardware.h>
6384 +#include <mach/om-3d7k.h>
6385 +#include <asm/mach-types.h>
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>
6392 +#include <plat/sdhci.h>
6393 +#include <plat/devs.h>
6395 +#include <plat/gpio-cfg.h>
6398 + OM_3D7K_GSM, /* GSM module */
6399 + OM_3D7K_USBHOST, /* USB Host power generation */
6400 + OM_3D7K_VIB, /* Vibrator */
6402 + OM_3D7K_FEATURE_COUNT /* always last */
6406 +struct om_3d7k_feature_info {
6407 + const char * name;
6408 + int depower_on_suspend;
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 },
6418 +static struct regulator *gps_regulator;
6422 +static void om_3d7k_features_pwron_set_on(enum feature feature)
6424 + switch (feature) {
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);
6434 + gpio_direction_output(OM_3D7K_GPIO_MODEM_ON, 0);
6436 + gpio_direction_output(OM_3D7K_GPIO_N_MODEM_RESET, 1);
6438 + gpio_direction_output(OM_3D7K_GPIO_MODEM_ON, 1);
6440 + case OM_3D7K_USBHOST:
6441 + pcf50633_gpio_set(om_3d7k_pcf, PCF50633_GPO, 1);
6444 + gpio_direction_output(OM_3D7K_GPIO_VIBRATOR_ON, 1);
6451 +static void om_3d7k_features_pwron_set_off(enum feature feature)
6453 + switch (feature) {
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);
6459 + gpio_direction_output(OM_3D7K_GPIO_MODEM_ON, 1);
6461 + case OM_3D7K_USBHOST:
6462 + pcf50633_gpio_set(om_3d7k_pcf, PCF50633_GPO, 0);
6465 + gpio_direction_output(OM_3D7K_GPIO_VIBRATOR_ON, 0);
6472 +static void om_3d7k_features_pwron_set(enum feature feature, int on)
6474 + if ((on) && (!feature_info[feature].on))
6475 + om_3d7k_features_pwron_set_on(feature);
6477 + if ((!on) && (feature_info[feature].on))
6478 + om_3d7k_features_pwron_set_off(feature);
6481 +static ssize_t om_3d7k_feature_read(struct device *dev,
6482 + struct device_attribute *attr, char *buf)
6488 + while (!hit && feature < OM_3D7K_FEATURE_COUNT) {
6489 + if (!strcmp(attr->attr.name, feature_info[feature].name))
6498 + switch (feature) {
6499 + case OM_3D7K_USBHOST:
6500 + on = pcf50633_gpio_get(om_3d7k_pcf, PCF50633_GPO);
6503 + on = feature_info[feature].on;
6506 + *buf++ = '0' + on;
6513 +static ssize_t om_3d7k_feature_write(struct device *dev,
6514 + struct device_attribute *attr,
6515 + const char *buf, size_t count)
6517 + int on = !!simple_strtoul(buf, NULL, 10);
6521 + while (!hit && feature < OM_3D7K_FEATURE_COUNT) {
6522 + if (!strcmp(attr->attr.name, feature_info[feature].name))
6531 + om_3d7k_features_pwron_set(feature, on);
6532 + feature_info[feature].on = on;
6538 +static DEVICE_ATTR(gsm_power, 0644, om_3d7k_feature_read,
6539 + om_3d7k_feature_write);
6541 +static DEVICE_ATTR(usbhost_power, 0644, om_3d7k_feature_read,
6542 + om_3d7k_feature_write);
6544 +static DEVICE_ATTR(vibrator_power, 0644, om_3d7k_feature_read,
6545 + om_3d7k_feature_write);
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,
6556 +static struct attribute_group om_3d7k_features_attr_group = {
6558 + .attrs = om_3d7k_features_sysfs_entries,
6561 +static int __init om_3d7k_features_probe(struct platform_device *pdev)
6563 + gps_regulator = regulator_get(&pdev->dev, "RF_3V");
6564 + dev_info(&pdev->dev, "starting\n");
6566 + return sysfs_create_group(&pdev->dev.kobj,
6567 + &om_3d7k_features_attr_group);
6570 +static int om_3d7k_features_remove(struct platform_device *pdev)
6573 + regulator_put(gps_regulator);
6574 + sysfs_remove_group(&pdev->dev.kobj, &om_3d7k_features_attr_group);
6581 +static int om_3d7k_features_suspend(struct platform_device *pdev,
6582 + pm_message_t state)
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);
6593 +static int om_3d7k_features_resume(struct platform_device *pdev)
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);
6605 +#define om_3d7k_features_suspend NULL
6606 +#define om_3d7k_features_resume NULL
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,
6615 + .name = "om-3d7k",
6619 +static int __devinit om_3d7k_features_init(void)
6621 + return platform_driver_register(&om_3d7k_features_driver);
6624 +static void om_3d7k_features_exit(void)
6626 + platform_driver_unregister(&om_3d7k_features_driver);
6629 +module_init(om_3d7k_features_init);
6630 +module_exit(om_3d7k_features_exit);
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
6639 s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
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));
6650 ctrl3 = (S3C_SDHCI_CTRL3_FCSEL1 | S3C_SDHCI_CTRL3_FCSEL0);
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);
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);
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));
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
6674 #define PCIO_BASE 0xe0000000
6675 #define IO_SPACE_LIMIT 0xffffffff
6677 -#define __io(a) ((void __iomem *)(PCIO_BASE + (a)))
6678 +#define __io(a) __typesafe_io(PCIO_BASE + (a))
6679 #define __mem_pci(addr) (addr)
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
6686 arch-$(CONFIG_CPU_32v6K) :=-D__LINUX_ARM_ARCH__=6 $(call cc-option,-march=armv6k,-march=armv5t -Wa$(comma)-march=armv6k)
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
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
6699 +/* linux/arch/arm/plat-s3c/dev-camif.c
6701 + * Copyright 2009 Openmoko, Inc.
6702 + * Werner Almesberger <werner@openmoko.org>
6704 + * based on dev-hsmmc.c which is
6706 + * Copyright (c) 2008 Simtec Electronics
6707 + * Ben Dooks <ben@simtec.co.uk>
6708 + * http://armlinux.simtec.co.uk/
6710 + * S3C series device definition for camera interface devices
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.
6717 +#include <linux/kernel.h>
6718 +#include <linux/platform_device.h>
6719 +#include <linux/mmc/host.h>
6721 +#include <mach/map.h>
6722 +#include <plat/devs.h>
6723 +#include <plat/cpu.h>
6726 +#define S3C6400_PA_CAMIF 0x78000000
6727 +#define S3C24XX_SZ_CAMIF (0x1000)
6730 +static struct resource s3c_camif_resource[] = {
6732 + .start = S3C6400_PA_CAMIF,
6733 + .end = S3C6400_PA_CAMIF + S3C24XX_SZ_CAMIF - 1,
6734 + .flags = IORESOURCE_MEM,
6737 + .start = IRQ_CAMIF_C,
6738 + .end = IRQ_CAMIF_C,
6739 + .flags = IORESOURCE_IRQ,
6742 + .start = IRQ_CAMIF_P,
6743 + .end = IRQ_CAMIF_P,
6744 + .flags = IORESOURCE_IRQ,
6749 +static u64 s3c_device_camif_dmamask = 0xffffffffUL;
6751 +struct platform_device s3c_device_camif = {
6752 + .name = "s3c-camif",
6754 + .num_resources = ARRAY_SIZE(s3c_camif_resource),
6755 + .resource = s3c_camif_resource,
6757 + .dma_mask = &s3c_device_camif_dmamask,
6758 + .coherent_dma_mask = 0xffffffffUL
6762 +EXPORT_SYMBOL(s3c_device_camif);
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
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,
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
6782 +/* linux/arch/arm/plat-s3c/dev-usb.c
6784 + * Copyright 2008 Simtec Electronics
6785 + * Ben Dooks <ben@simtec.co.uk>
6786 + * http://armlinux.simtec.co.uk/
6788 + * S3C series device definition for USB host
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.
6795 +#include <linux/kernel.h>
6796 +#include <linux/string.h>
6797 +#include <linux/platform_device.h>
6799 +#include <mach/irqs.h>
6800 +#include <mach/map.h>
6802 +#include <plat/devs.h>
6805 +static struct resource s3c_usb_resource[] = {
6807 + .start = S3C_PA_USBHOST,
6808 + .end = S3C_PA_USBHOST + 0x100 - 1,
6809 + .flags = IORESOURCE_MEM,
6812 + .start = IRQ_USBH,
6814 + .flags = IORESOURCE_IRQ,
6818 +static u64 s3c_device_usb_dmamask = 0xffffffffUL;
6820 +struct platform_device s3c_device_usb = {
6821 + .name = "s3c-ohci",
6823 + .num_resources = ARRAY_SIZE(s3c_usb_resource),
6824 + .resource = s3c_usb_resource,
6826 + .dma_mask = &s3c_device_usb_dmamask,
6827 + .coherent_dma_mask = 0xffffffffUL
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
6836 +/* linux/arch/arm/plat-s3c/dma.c
6838 + * Copyright (c) 2003-2005,2006,2009 Simtec Electronics
6839 + * Ben Dooks <ben@simtec.co.uk>
6840 + * http://armlinux.simtec.co.uk/
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.
6849 +struct s3c2410_dma_buf;
6851 +#include <linux/kernel.h>
6852 +#include <linux/module.h>
6853 +#include <linux/errno.h>
6855 +#include <mach/dma.h>
6856 +#include <mach/irqs.h>
6858 +#include <plat/dma-plat.h>
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];
6864 +/* s3c_dma_lookup_channel
6866 + * change the dma channel number given into a real dma channel id
6869 +struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel)
6871 + if (channel & DMACH_LOW_LEVEL)
6872 + return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
6874 + return s3c_dma_chan_map[channel];
6877 +/* do we need to protect the settings of the fields from
6881 +int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
6883 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
6888 + pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
6890 + chan->op_fn = rtn;
6894 +EXPORT_SYMBOL(s3c2410_dma_set_opfn);
6896 +int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
6898 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
6903 + pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
6905 + chan->callback_fn = rtn;
6909 +EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
6911 +int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
6913 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
6918 + chan->flags = flags;
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
6926 #include <linux/io.h>
6927 #include <linux/gpio.h>
6929 -#include <plat/gpio-core.h>
6930 +#include <mach/gpio-core.h>
6932 #ifdef CONFIG_S3C_GPIO_TRACK
6933 struct s3c_gpio_chip *s3c_gpios[S3C_GPIO_END];
6934 @@ -140,6 +140,15 @@
6936 gc->get = s3c_gpiolib_get;
6939 + if (chip->pm != NULL) {
6940 + if (!chip->pm->save || !chip->pm->resume)
6941 + printk(KERN_ERR "gpio: %s has missing PM functions\n",
6944 + printk(KERN_ERR "gpio: %s has no PM function\n", gc->label);
6947 /* gpiochip_add() prints own failure message on error. */
6948 ret = gpiochip_add(gc);
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
6956 #include <linux/kernel.h>
6957 +#include <linux/module.h>
6958 #include <linux/gpio.h>
6959 #include <linux/io.h>
6965 +EXPORT_SYMBOL(s3c_gpio_cfgpin);
6967 int s3c_gpio_setpull(unsigned int pin, s3c_gpio_pull_t pull)
6973 +EXPORT_SYMBOL(s3c_gpio_setpull);
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
6982 + * arch/arm/plat-s3c/include/mach/cpu.h
6984 + * S3C cpu type detection
6986 + * Copyright (C) 2008 Samsung Electronics
6987 + * Kyungmin Park <kyungmin.park@samsung.com>
6989 + * Derived from OMAP cpu.h
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.
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.
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
7006 +#ifndef __ASM_ARCH_S3C_CPU_H
7007 +#define __ASM_ARCH_S3C_CPU_H
7009 +extern unsigned int system_rev;
7011 +#define S3C_SYSTEM_REV_ATAG (system_rev & 0xffff)
7012 +#define S3C_SYSTEM_REV_CPU (system_rev & 0xffff0000)
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
7020 +#define GET_S3C_CLASS ((system_rev >> 24) & 0xff)
7022 +#define IS_S3C_CLASS(class, id) \
7023 +static inline int is_s3c ##class (void) \
7025 + return (GET_S3C_CLASS == (id)) ? 1 : 0; \
7028 +#define GET_S3C_SUBCLASS ((system_rev >> 20) & 0xfff)
7030 +#define IS_S3C_SUBCLASS(subclass, id) \
7031 +static inline int is_s3c ##subclass (void) \
7033 + return (GET_S3C_SUBCLASS == (id)) ? 1 : 0; \
7036 +IS_S3C_CLASS(24xx, 0x24)
7037 +IS_S3C_CLASS(64xx, 0x64)
7039 +IS_S3C_SUBCLASS(241x, 0x241)
7040 +IS_S3C_SUBCLASS(244x, 0x244)
7042 +#define cpu_is_s3c24xx() 0
7043 +#define cpu_is_s3c241x() 0
7044 +#define cpu_is_s3c244x() 0
7045 +#define cpu_is_s3c64xx() 0
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()
7056 +#if defined(CONFIG_ARCH_S3C64XX)
7057 +# undef cpu_is_s3c64xx
7058 +# define cpu_is_s3c64xx() is_s3c64xx()
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
7069 + * Store Revision A to 1
7070 + * s3c2410a -> s3c2411
7071 + * s3c2440a -> s3c2441
7074 +#define GET_S3C_TYPE ((system_rev >> 16) & 0xffff)
7076 +#define IS_S3C_TYPE(type, id) \
7077 +static inline int is_s3c ##type (void) \
7079 + return (GET_S3C_TYPE == (id)) ? 1 : 0; \
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)
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
7104 +#if defined(CONFIG_ARCH_S3C2410)
7105 +# undef cpu_is_s3c2400
7106 +# define cpu_is_s3c2400() is_s3c2400()
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()
7116 +#if defined(CONFIG_CPU_S3C2412)
7117 +# undef cpu_is_s3c2412
7118 +# define cpu_is_s3c2412() is_s3c2412()
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()
7128 +#if defined(CONFIG_CPU_S3C2442)
7129 +# undef cpu_is_s3c2442
7130 +# define cpu_is_s3c2442() is_s3c2442()
7133 +#if defined(CONFIG_CPU_S3C2443)
7134 +# undef cpu_is_s3c2443
7135 +# define cpu_is_s3c2443() is_s3c2443()
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()
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
7150 #define __ASM_ARM_ARCH_IO_H
7152 /* No current ISA/PCI bus support. */
7154 #define __io(a) __typesafe_io(a)
7155 #define __mem_pci(a) (a)
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
7161 +/* arch/arm/mach-s3c2410/include/mach/audio.h
7163 + * Copyright (c) 2004-2005 Simtec Electronics
7164 + * http://www.simtec.co.uk/products/SWLINUX/
7165 + * Ben Dooks <ben@simtec.co.uk>
7167 + * S3C24XX - Audio platfrom_device info
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.
7174 +#ifndef __ASM_ARCH_AUDIO_H
7175 +#define __ASM_ARCH_AUDIO_H __FILE__
7177 +/* struct s3c24xx_iis_ops
7179 + * called from the s3c24xx audio core to deal with the architecture
7180 + * or the codec's setup and control.
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.
7186 +struct s3c24xx_iis_ops {
7187 + struct module *owner;
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);
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);
7199 +struct s3c24xx_platdata_iis {
7200 + const char *codec_clk;
7201 + struct s3c24xx_iis_ops *ops;
7202 + int (*match_dev)(struct device *dev);
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
7210 extern struct clk clk_ext;
7212 /* S3C64XX specific clocks */
7213 +extern struct clk clk_h2;
7214 extern struct clk clk_27m;
7215 extern struct clk clk_48m;
7219 /* S3C64XX specific functions and clocks */
7221 +extern int s3c64xx_hclk_ctrl(struct clk *clk, int enable);
7222 extern int s3c64xx_sclk_ctrl(struct clk *clk, int enable);
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
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;
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
7239 unsigned long nr_resources;
7242 +struct s3c_plat_otg_data {
7246 extern struct s3c24xx_uart_resources s3c2410_uart_resources[];
7247 extern struct s3c24xx_uart_resources s3c64xx_uart_resources[];
7251 extern struct platform_device s3c_device_usbgadget;
7253 +extern struct platform_device s3c_device_ts;
7255 /* s3c2440 specific devices */
7257 #ifdef CONFIG_CPU_S3C2440
7259 extern struct platform_device s3c_device_camif;
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
7266 +/* arch/arm/plat-s3c/include/plat/dma.h
7268 + * Copyright 2008 Openmoko, Inc.
7269 + * Copyright 2008 Simtec Electronics
7270 + * Ben Dooks <ben@simtec.co.uk>
7271 + * http://armlinux.simtec.co.uk/
7273 + * Samsung S3C DMA core support
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.
7280 +extern struct s3c2410_dma_chan *s3c_dma_lookup_channel(unsigned int channel);
7282 +extern struct s3c2410_dma_chan *s3c_dma_chan_map[];
7284 +/* the currently allocated channel information */
7285 +extern struct s3c2410_dma_chan s3c2410_chans[];
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
7292 +/* arch/arm/plat-s3c/include/plat/dma.h
7294 + * Copyright (C) 2003,2004,2006 Simtec Electronics
7295 + * Ben Dooks <ben@simtec.co.uk>
7297 + * Samsung S3C DMA support
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.
7304 +enum s3c2410_dma_buffresult {
7310 +enum s3c2410_dmasrc {
7311 + S3C2410_DMASRC_HW, /* source is memory */
7312 + S3C2410_DMASRC_MEM /* source is hardware */
7315 +/* enum s3c2410_chan_op
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
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 */
7331 +struct s3c2410_dma_client {
7335 +struct s3c2410_dma_chan;
7337 +/* s3c2410_dma_cbfn_t
7339 + * buffer callback routine type
7342 +typedef void (*s3c2410_dma_cbfn_t)(struct s3c2410_dma_chan *,
7343 + void *buf, int size,
7344 + enum s3c2410_dma_buffresult result);
7346 +typedef int (*s3c2410_dma_opfn_t)(struct s3c2410_dma_chan *,
7347 + enum s3c2410_chan_op );
7351 +/* s3c2410_dma_request
7353 + * request a dma channel exclusivley
7356 +extern int s3c2410_dma_request(unsigned int channel,
7357 + struct s3c2410_dma_client *, void *dev);
7360 +/* s3c2410_dma_ctrl
7362 + * change the state of the dma channel
7365 +extern int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op);
7367 +/* s3c2410_dma_setflags
7369 + * set the channel's flags to a given state
7372 +extern int s3c2410_dma_setflags(unsigned int channel,
7373 + unsigned int flags);
7375 +/* s3c2410_dma_free
7377 + * free the dma channel (will also abort any outstanding operations)
7380 +extern int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *);
7382 +/* s3c2410_dma_enqueue
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.
7389 +extern int s3c2410_dma_enqueue(unsigned int channel, void *id,
7390 + dma_addr_t data, int size);
7393 +/* s3c2410_dma_config
7395 + * configure the dma channel
7398 +extern int s3c2410_dma_config(unsigned int channel, int xferunit);
7400 +/* s3c2410_dma_devconfig
7402 + * configure the device we're talking to
7405 +extern int s3c2410_dma_devconfig(int channel, enum s3c2410_dmasrc source,
7406 + unsigned long devaddr);
7408 +/* s3c2410_dma_getposition
7410 + * get the position that the dma transfer is currently at
7413 +extern int s3c2410_dma_getposition(unsigned int channel,
7414 + dma_addr_t *src, dma_addr_t *dest);
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);
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
7427 +struct s3c_gpio_chip;
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.
7434 +struct s3c_gpio_pm {
7435 + void (*save)(struct s3c_gpio_chip *chip);
7436 + void (*resume)(struct s3c_gpio_chip *chip);
7440 struct s3c_gpio_cfg;
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.
7449 * This wrapper provides the necessary information for the Samsung
7450 * specific gpios being registered with gpiolib.
7452 struct s3c_gpio_chip {
7453 struct gpio_chip chip;
7454 struct s3c_gpio_cfg *config;
7455 + struct s3c_gpio_pm *pm;
7462 static inline struct s3c_gpio_chip *to_s3c_gpio(struct gpio_chip *gpc)
7465 static inline void s3c_gpiolib_track(struct s3c_gpio_chip *chip) { }
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
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
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
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 */
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
7495 * partitions = mtd partition list
7498 +#define S3C2410_NAND_BBT 0x0001
7500 struct s3c2410_nand_set {
7501 unsigned int disable_ecc : 1;
7505 + unsigned int flags;
7508 struct mtd_partition *partitions;
7511 struct s3c2410_nand_set *sets;
7513 + /* force software_ecc at runtime */
7516 void (*select_chip)(struct s3c2410_nand_set *,
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
7523 +/* linux/include/asm-arm/plat-s3c24xx/pm.h
7525 + * Copyright (c) 2004 Simtec Electronics
7526 + * http://armlinux.simtec.co.uk/
7527 + * Written by Ben Dooks, <ben@simtec.co.uk>
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.
7534 +#include <linux/sysdev.h>
7538 + * called from board at initialisation time to setup the power
7544 +extern __init int s3c_pm_init(void);
7548 +static inline int s3c_pm_init(void)
7554 +/* configuration for the IRQ mask over sleep */
7555 +extern unsigned long s3c_irqwake_intmask;
7556 +extern unsigned long s3c_irqwake_eintmask;
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;
7562 +/* per-cpu sleep functions */
7564 +extern void (*pm_cpu_prep)(void);
7565 +extern void (*pm_cpu_sleep)(void);
7567 +/* Flags for PM Control */
7569 +extern unsigned long s3c_pm_flags;
7571 +extern unsigned char pm_uart_udivslot; /* true to save UART UDIVSLOT */
7575 +extern int s3c_cpu_save(unsigned long *saveblk);
7576 +extern void s3c_cpu_resume(void);
7578 +extern void s3c2410_cpu_suspend(void);
7580 +extern unsigned long s3c_sleep_save_phys;
7582 +/* sleep save info */
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.
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.
7592 +struct sleep_save {
7593 + void __iomem *reg;
7594 + unsigned long val;
7597 +#define SAVE_ITEM(x) \
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
7608 + * Save block for UART registers to be held over sleep and restored if they
7609 + * are needed (say by debug).
7611 +struct pm_uart_save {
7620 +/* helper functions to save/restore lists of registers. */
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);
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);
7631 +#define s3c_irqext_wake NULL
7632 +#define s3c24xx_irq_suspend NULL
7633 +#define s3c24xx_irq_resume NULL
7636 +/* PM debug functions */
7638 +#ifdef CONFIG_S3C2410_PM_DEBUG
7640 + * s3c_pm_dbg() - low level debug function for use in suspend/resume.
7641 + * @msg: The message to print.
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.
7647 +extern void s3c_pm_dbg(const char *msg, ...);
7649 +#define S3C_PMDBG(fmt...) s3c_pm_dbg(fmt)
7651 +#define S3C_PMDBG(fmt...) printk(KERN_DEBUG fmt)
7654 +#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
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.
7660 +extern void s3c_pm_debug_smdkled(u32 set, u32 clear);
7663 +static inline void s3c_pm_debug_smdkled(u32 set, u32 clear) { }
7664 +#endif /* CONFIG_S3C_PM_DEBUG_LED_SMDK */
7666 +/* suspend memory checking */
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);
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)
7681 + * s3c_pm_configure_extint() - ensure pins are correctly set for IRQ
7683 + * Setup all the necessary GPIO pins for waking the system on external
7686 +extern void s3c_pm_configure_extint(void);
7689 + * s3c_pm_restore_gpios() - restore the state of the gpios after sleep.
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.
7695 +extern void s3c_pm_restore_gpios(void);
7698 + * s3c_pm_save_gpios() - save the state of the GPIOs for restoring after sleep.
7700 + * Save the GPIO states for resotration on resume. See s3c_pm_restore_gpios().
7702 +extern void s3c_pm_save_gpios(void);
7704 +extern void s3c_pm_save_core(void);
7705 +extern void s3c_pm_restore_core(void);
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
7711 +#ifndef __S3C2410_PWM_H
7712 +#define __S3C2410_PWM_H
7714 +#include <linux/err.h>
7715 +#include <linux/platform_device.h>
7716 +#include <linux/clk.h>
7718 +#include <mach/io.h>
7719 +#include <mach/hardware.h>
7720 +#include <asm/mach-types.h>
7721 +#include <plat/regs-timer.h>
7731 +struct s3c2410_pwm {
7732 + enum pwm_timer timerid;
7734 + unsigned long pclk_rate;
7735 + unsigned long prescaler;
7736 + unsigned long divider;
7737 + unsigned long counter;
7738 + unsigned long comparer;
7741 +struct s3c24xx_pwm_platform_data{
7742 + /* callback to attach platform children (to enforce suspend / resume
7744 + void (*attach_child_devices)(struct device *parent_device);
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);
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
7760 +/* linux/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h
7762 + * Copyright 2007 Simtec Electronics <linux@simtec.co.uk>
7763 + * http://armlinux.simtec.co.uk/
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.
7769 + * S3C2412 IIS register definition
7772 +#ifndef __ASM_ARCH_REGS_S3C2412_IIS_H
7773 +#define __ASM_ARCH_REGS_S3C2412_IIS_H
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)
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)
7795 +#define S3C64XX_IISMOD_IMS_PCLK (0 << 10)
7796 +#define S3C64XX_IISMOD_IMS_SYSMUX (1 << 10)
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)
7824 +#define S3C2412_IISPSR_PSREN (1 << 15)
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)
7833 +#endif /* __ASM_ARCH_REGS_S3C2412_IIS_H */
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 @@
7840 #define S3C2443_DIVSLOT (0x2C)
7842 +/* S3C64XX interrupt registers. */
7843 +#define S3C64XX_UINTP 0x30
7844 +#define S3C64XX_UINTSP 0x34
7845 +#define S3C64XX_UINTM 0x38
7847 #ifndef __ASSEMBLY__
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
7854 * S3C2410 Timer configuration
7857 +#include <plat/map-base.h>
7859 #ifndef __ASM_ARCH_REGS_TIMER_H
7860 #define __ASM_ARCH_REGS_TIMER_H
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
7866 +/* linux/include/asm-arm/arch-s3c2410/regs-udc.h
7868 + * Copyright (C) 2008 Samsung Electronics
7869 + * Copyright (C) 2004 Herbert Poetzl <herbert@13thfloor.at>
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.
7877 +#ifndef __ASM_ARCH_REGS_USB_HS_OTG_H
7878 +#define __ASM_ARCH_REGS_USB_HS_OTG_H
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)
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)
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)
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)
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)
7962 +/* Host Port Control & Status Registers */
7963 +#define S3C_UDC_OTG_HPRT S3C_USBOTGREG(0x440)
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)
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)
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)
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)
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)
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)
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)
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)
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)
8074 +/* S3C_USBOTG_PHYCLK */
8075 +#define REF_CLK_CRYSTAL (0x0<<5)
8076 +#define REF_CLK_OSCC (0x1<<5)
8078 +/* S3C_USBOTG_RSTCON */
8079 +#define SW_RST_OFF (0x0<<0)
8080 +#define SW_RST_ON (0x1<<0)
8082 +/* S3C_UDC_OTG_GOTGCTL */
8083 +#define B_SESSION_VALID (0x1<<19)
8084 +#define A_SESSION_VALID (0x1<<18)
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)
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)
8119 +/* S3C_UDC_OTG_GRSTCTL */
8120 +#define AHB_MASTER_IDLE (1u<<31)
8121 +#define CORE_SOFT_RESET (0x1<<0)
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)
8139 +#define FULL_SPEED_CONTROL_PKT_SIZE 8
8140 +#define FULL_SPEED_BULK_PKT_SIZE 64
8142 +#define HIGH_SPEED_CONTROL_PKT_SIZE 64
8143 +#define HIGH_SPEED_BULK_PKT_SIZE 512
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)
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)
8160 +#define OUT_PKT_RECEIVED (0x2)
8161 +#define OUT_COMPLELTED (0x3)
8162 +#define SETUP_COMPLETED (0x4)
8163 +#define SETUP_PKT_RECEIVED (0x6)
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)
8173 +/* S3C_UDC_OTG_DCTL device control register */
8174 +#define NORMAL_OPERATION (0x1<<0)
8175 +#define SOFT_DISCONNECT (0x1<<1)
8177 +/* S3C_UDC_OTG_DSTS */
8178 +#define ENUM_SPEED(x) (x & (0x3<<1))
8179 +#define FRAME_CNT(x) (x & (0x3ff<<8))
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)
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)
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)
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)
8216 +/* S3C_UDC_OTG_DIEPINTn/DOEPINTn */
8217 +#define AHB_ERROR (0x1<<2)
8218 +#define EPDISBLD (0x1<<1)
8219 +#define TRANSFER_DONE (0x1<<0)
8221 +/* S3C_UDC_OTG_DIEPTSIZn */
8222 +#define PKT_CNT(x) (x<<19)
8223 +#define XFERSIZE(x) (x<<0)
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
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
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
8238 void __iomem *regbase,
8239 struct mmc_ios *ios,
8240 struct mmc_card *card);
8241 + struct sdhci_host * sdhci_host;
8244 +extern void sdhci_s3c_force_presence_change(struct platform_device *pdev);
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
8253 +/* arch/arm/plat-s3c/include/plat/usb-control.h
8255 + * Copyright (c) 2004 Simtec Electronics
8256 + * Ben Dooks <ben@simtec.co.uk>
8258 + * S3C2410 - usb port information
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.
8265 +#ifndef __ASM_ARCH_USBCONTROL_H
8266 +#define __ASM_ARCH_USBCONTROL_H "arch/arm/plat-s3c/include/plat/usb-control.h"
8268 +#define S3C_HCDFLG_USED (1)
8270 +struct s3c2410_hcd_port {
8271 + unsigned char flags;
8272 + unsigned char power;
8273 + unsigned char oc_status;
8274 + unsigned char oc_changed;
8277 +struct s3c2410_hcd_info {
8278 + struct usb_hcd *hcd;
8279 + struct s3c2410_hcd_port port[2];
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);
8286 +static void inline s3c2410_usb_report_oc(struct s3c2410_hcd_info *info, int ports)
8288 + if (info->report_oc != NULL) {
8289 + (info->report_oc)(info, ports);
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
8299 static struct cpu_table *cpu;
8301 +static void __init set_system_rev(unsigned int idcode)
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)
8309 + * Remaining[15:0] are preserved from the value set by ATAG
8312 + * Store Revision A to 1 such as
8313 + * s3c2410A to s3c2411
8314 + * s3c2440A to s3c2441
8317 + system_rev &= 0xffff;
8318 + system_rev |= (idcode & 0x0ffff000) << 4;
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);
8329 static struct cpu_table * __init s3c_lookup_cpu(unsigned long idcode,
8330 struct cpu_table *tab,
8333 panic("Unknown S3C24XX CPU");
8336 + set_system_rev(idcode);
8338 printk("CPU %s (id 0x%08lx)\n", cpu->name, idcode);
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
8345 Resume code. See <file:Documentation/arm/Samsung-S3C24XX/Suspend.txt>
8346 for more information.
8348 +config S3C_PM_DEBUG_LED_SMDK
8349 + bool "SMDK LED suspend/resume debugging"
8350 + depends on PM && (MACH_SMDK6410)
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.
8355 + Note, this currently only works for S3C64XX based SMDK boards.
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
8369 + Internal configuration for S3C DMA core
8374 + PWM timer code for the S3C2410, and similar processors
8376 # device definitions to compile in
8378 config S3C_DEV_HSMMC
8379 @@ -172,4 +193,14 @@
8381 Compile in platform device definition for framebuffer
8383 +config S3C_DEV_USB_HOST
8386 + Compile in platform device definition for USB host.
8388 +config S3C_DEV_CAMIF
8391 + Compile in platform device definitions for camera interface code
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
8399 obj-y += gpio-config.o
8403 +obj-$(CONFIG_S3C_DMA) += dma.o
8407 +obj-$(CONFIG_PM) += pm.o
8408 +obj-$(CONFIG_PM) += pm-gpio.o
8409 +obj-$(CONFIG_S3C2410_PM_CHECK) += pm-check.o
8413 obj-$(CONFIG_S3C_DEV_HSMMC) += dev-hsmmc.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
8421 +obj-$(CONFIG_S3C_PWM) += pwm.o
8422 +obj-$(CONFIG_S3C_DMA) += dma.o
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
8428 +/* linux/arch/arm/plat-s3c/pm.c
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/
8435 + * S3C common power management (suspend to ram) support.
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.
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>
8449 +#include <asm/cacheflush.h>
8450 +#include <mach/hardware.h>
8451 +#include <mach/map.h>
8453 +#include <plat/regs-serial.h>
8454 +#include <mach/regs-clock.h>
8455 +#include <mach/regs-irq.h>
8456 +#include <asm/irq.h>
8458 +#include <plat/pm.h>
8459 +#include <plat/pm-core.h>
8461 +/* for external use */
8463 +unsigned long s3c_pm_flags;
8467 + * This code supports debug output to the low level UARTs for use on
8468 + * resume before the console layer is available.
8471 +#ifdef CONFIG_S3C2410_PM_DEBUG
8472 +extern void printascii(const char *);
8474 +void s3c_pm_dbg(const char *fmt, ...)
8479 + va_start(va, fmt);
8480 + vsprintf(buff, fmt, va);
8486 +static inline void s3c_pm_debug_init(void)
8488 + /* restart uart clocks so we can use them to output */
8489 + s3c_pm_debug_init_uart();
8493 +#define s3c_pm_debug_init() do { } while(0)
8495 +#endif /* CONFIG_S3C2410_PM_DEBUG */
8497 +/* Save the UART configurations if we are configured for debug. */
8499 +unsigned char pm_uart_udivslot;
8501 +#ifdef CONFIG_S3C2410_PM_DEBUG
8503 +struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
8505 +static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
8507 + void __iomem *regs = S3C_VA_UARTx(uart);
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);
8515 + if (pm_uart_udivslot)
8516 + save->udivslot = __raw_readl(regs + S3C2443_DIVSLOT);
8518 + S3C_PMDBG("UART[%d]: ULCON=%04x, UCON=%04x, UFCON=%04x, UBRDIV=%04x\n",
8519 + uart, save->ulcon, save->ucon, save->ufcon, save->ubrdiv);
8522 +static void s3c_pm_save_uarts(void)
8524 + struct pm_uart_save *save = uart_save;
8525 + unsigned int uart;
8527 + for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
8528 + s3c_pm_save_uart(uart, save);
8531 +static void s3c_pm_restore_uart(unsigned int uart, struct pm_uart_save *save)
8533 + void __iomem *regs = S3C_VA_UARTx(uart);
8535 + s3c_pm_arch_update_uart(regs, save);
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);
8543 + if (pm_uart_udivslot)
8544 + __raw_writel(save->udivslot, regs + S3C2443_DIVSLOT);
8547 +static void s3c_pm_restore_uarts(void)
8549 + struct pm_uart_save *save = uart_save;
8550 + unsigned int uart;
8552 + for (uart = 0; uart < CONFIG_SERIAL_SAMSUNG_UARTS; uart++, save++)
8553 + s3c_pm_restore_uart(uart, save);
8556 +static void s3c_pm_save_uarts(void) { }
8557 +static void s3c_pm_restore_uarts(void) { }
8560 +/* The IRQ ext-int code goes here, it is too small to currently bother
8561 + * with its own file. */
8563 +unsigned long s3c_irqwake_intmask = 0xffffffffL;
8564 +unsigned long s3c_irqwake_eintmask = 0xffffffffL;
8566 +int s3c_irqext_wake(unsigned int irqno, unsigned int state)
8568 + unsigned long bit = 1L << IRQ_EINT_BIT(irqno);
8570 + if (!(s3c_irqwake_eintallow & bit))
8573 + printk(KERN_INFO "wake %s for irq %d\n",
8574 + state ? "enabled" : "disabled", irqno);
8577 + s3c_irqwake_eintmask |= bit;
8579 + s3c_irqwake_eintmask &= ~bit;
8584 +/* helper functions to save and restore register state */
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.
8591 + * Run through the list of registers given, saving their contents in the
8592 + * array for later restoration when we wakeup.
8594 +void s3c_pm_do_save(struct sleep_save *ptr, int count)
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);
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.
8607 + * Restore the register values saved from s3c_pm_do_save().
8609 + * Note, we do not use S3C_PMDBG() in here, as the system may not have
8610 + * restore the UARTs state yet
8613 +void s3c_pm_do_restore(struct sleep_save *ptr, int count)
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));
8619 + __raw_writel(ptr->val, ptr->reg);
8624 + * s3c_pm_do_restore_core() - early restore register values from save list.
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.
8630 + * WARNING: Do not put any debug in here that may effect memory or use
8631 + * peripherals, as things may be changing!
8634 +void s3c_pm_do_restore_core(struct sleep_save *ptr, int count)
8636 + for (; count > 0; count--, ptr++)
8637 + __raw_writel(ptr->val, ptr->reg);
8640 +/* s3c2410_pm_show_resume_irqs
8642 + * print any IRQs asserted at resume time (ie, we woke from)
8644 +static void s3c_pm_show_resume_irqs(int start, unsigned long which,
8645 + unsigned long mask)
8651 + for (i = 0; i <= 31; i++) {
8652 + if (which & (1L<<i)) {
8653 + S3C_PMDBG("IRQ %d asserted at resume\n", start+i);
8659 +void (*pm_cpu_prep)(void);
8660 +void (*pm_cpu_sleep)(void);
8662 +#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
8666 + * central control for sleep/resume process
8669 +static int s3c_pm_enter(suspend_state_t state)
8671 + unsigned long regs_save[16];
8673 + /* ensure the debug is initialised (if enabled) */
8675 + s3c_pm_debug_init();
8677 + S3C_PMDBG("%s(%d)\n", __func__, state);
8679 + if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
8680 + printk(KERN_ERR "%s: error: no cpu sleep function\n", __func__);
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)
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__);
8696 + /* store the physical address of the register recovery block */
8698 + s3c_sleep_save_phys = virt_to_phys(regs_save);
8700 + S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
8702 + /* save all necessary core registers not covered by the drivers */
8704 + s3c_pm_save_gpios();
8705 + s3c_pm_save_uarts();
8706 + s3c_pm_save_core();
8708 + /* set the irq configuration for wake */
8710 + s3c_pm_configure_extint();
8712 + S3C_PMDBG("sleep: irq wakeup masks: %08lx,%08lx\n",
8713 + s3c_irqwake_intmask, s3c_irqwake_eintmask);
8715 + s3c_pm_arch_prepare_irqs();
8717 + /* call cpu specific preparation */
8721 + /* flush cache back to ram */
8723 + flush_cache_all();
8725 + s3c_pm_check_store();
8727 + /* send the cpu to sleep... */
8729 + s3c_pm_arch_stop_clocks();
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 */
8735 + if (s3c_cpu_save(regs_save) == 0) {
8736 + flush_cache_all();
8740 + /* restore the cpu state using the kernel's cpu init code. */
8744 + /* restore the system state */
8746 + s3c_pm_restore_core();
8747 + s3c_pm_restore_uarts();
8748 + s3c_pm_restore_gpios();
8750 + s3c_pm_debug_init();
8752 + /* check what irq (if any) restored the system */
8754 + s3c_pm_arch_show_resume_irqs();
8756 + S3C_PMDBG("%s: post sleep, preparing to return\n", __func__);
8758 + s3c_pm_check_restore();
8760 + /* LEDs should now be 1110 */
8761 + s3c_pm_debug_smdkled(1 << 1, 0);
8763 + /* ok, let's return from sleep */
8765 + S3C_PMDBG("S3C PM Resume (post-restore)\n");
8769 +static int s3c_pm_prepare(void)
8771 + /* prepare check area if configured */
8773 + s3c_pm_check_prepare();
8777 +static void s3c_pm_finish(void)
8779 + s3c_pm_check_cleanup();
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,
8791 + * Attach the power management functions. This should be called
8792 + * from the board specific initialisation if the board supports
8796 +int __init s3c_pm_init(void)
8798 + printk("S3C Power Management, Copyright 2004 Simtec Electronics\n");
8800 + suspend_set_ops(&s3c_pm_ops);
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
8807 +/* linux/arch/arm/plat-s3c/pm-check.c
8808 + * originally in linux/arch/arm/plat-s3c24xx/pm.c
8810 + * Copyright (c) 2004,2006,2008 Simtec Electronics
8811 + * http://armlinux.simtec.co.uk
8812 + * Ben Dooks <ben@simtec.co.uk>
8814 + * S3C Power Mangament - suspend/resume memory corruptiuon check.
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.
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>
8827 +#include <plat/pm.h>
8829 +#if CONFIG_S3C2410_PM_CHECK_CHUNKSIZE < 1
8830 +#error CONFIG_S3C2410_PM_CHECK_CHUNKSIZE must be a positive non-zero value
8833 +/* suspend checking code...
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.
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
8843 +#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
8845 +static u32 crc_size; /* size needed for the crc block */
8846 +static u32 *crcs; /* allocated over suspend/resume */
8848 +typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
8852 + * go through the given resource list, and look for system ram
8855 +static void s3c_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
8857 + while (ptr != NULL) {
8858 + if (ptr->child != NULL)
8859 + s3c_pm_run_res(ptr->child, fn, arg);
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);
8869 + ptr = ptr->sibling;
8873 +static void s3c_pm_run_sysram(run_fn_t fn, u32 *arg)
8875 + s3c_pm_run_res(&iomem_resource, fn, arg);
8878 +static u32 *s3c_pm_countram(struct resource *res, u32 *val)
8880 + u32 size = (u32)(res->end - res->start)+1;
8882 + size += CHECK_CHUNKSIZE-1;
8883 + size /= CHECK_CHUNKSIZE;
8885 + S3C_PMDBG("Area %08lx..%08lx, %d blocks\n",
8886 + (unsigned long)res->start, (unsigned long)res->end, size);
8888 + *val += size * sizeof(u32);
8892 +/* s3c_pm_prepare_check
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
8900 +void s3c_pm_check_prepare(void)
8904 + s3c_pm_run_sysram(s3c_pm_countram, &crc_size);
8906 + S3C_PMDBG("s3c_pm_prepare_check: %u checks needed\n", crc_size);
8908 + crcs = kmalloc(crc_size+4, GFP_KERNEL);
8910 + printk(KERN_ERR "Cannot allocated CRC save area\n");
8913 +static u32 *s3c_pm_makecheck(struct resource *res, u32 *val)
8915 + unsigned long addr, left;
8917 + for (addr = res->start; addr < res->end;
8918 + addr += CHECK_CHUNKSIZE) {
8919 + left = res->end - addr;
8921 + if (left > CHECK_CHUNKSIZE)
8922 + left = CHECK_CHUNKSIZE;
8924 + *val = crc32_le(~0, phys_to_virt(addr), left);
8931 +/* s3c_pm_check_store
8933 + * compute the CRC values for the memory blocks before the final
8937 +void s3c_pm_check_store(void)
8940 + s3c_pm_run_sysram(s3c_pm_makecheck, crcs);
8945 + * return TRUE if the area defined by ptr..ptr+size contains the
8946 + * what..what+whatsz
8949 +static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
8951 + if ((what+whatsz) < ptr)
8954 + if (what > (ptr+size))
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.
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.
8970 +static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
8972 + void *save_at = phys_to_virt(s3c_sleep_save_phys);
8973 + unsigned long addr;
8974 + unsigned long left;
8979 + stkpage = (void *)((u32)&calc & ~PAGE_MASK);
8981 + for (addr = res->start; addr < res->end;
8982 + addr += CHECK_CHUNKSIZE) {
8983 + left = res->end - addr;
8985 + if (left > CHECK_CHUNKSIZE)
8986 + left = CHECK_CHUNKSIZE;
8988 + ptr = phys_to_virt(addr);
8990 + if (in_region(ptr, left, stkpage, 4096)) {
8991 + S3C_PMDBG("skipping %08lx, has stack in\n", addr);
8995 + if (in_region(ptr, left, crcs, crc_size)) {
8996 + S3C_PMDBG("skipping %08lx, has crc block in\n", addr);
9000 + if (in_region(ptr, left, save_at, 32*4 )) {
9001 + S3C_PMDBG("skipping %08lx, has save block in\n", addr);
9005 + /* calculate and check the checksum */
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);
9012 + S3C_PMDBG("Restore CRC error at %08lx (%08x vs %08x)\n",
9013 + addr, calc, *val);
9024 + * s3c_pm_check_restore() - memory check called on resume
9026 + * check the CRCs after the restore event and free the memory used
9029 +void s3c_pm_check_restore(void)
9032 + s3c_pm_run_sysram(s3c_pm_runcheck, crcs);
9036 + * s3c_pm_check_cleanup() - free memory resources
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.
9043 +void s3c_pm_check_cleanup(void)
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
9053 +/* linux/arch/arm/plat-s3c/pm-gpio.c
9055 + * Copyright 2008 Openmoko, Inc.
9056 + * Copyright 2008 Simtec Electronics
9057 + * Ben Dooks <ben@simtec.co.uk>
9058 + * http://armlinux.simtec.co.uk/
9060 + * S3C series GPIO PM code
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.
9067 +#include <linux/kernel.h>
9068 +#include <linux/init.h>
9069 +#include <linux/io.h>
9070 +#include <linux/gpio.h>
9072 +#include <mach/gpio-core.h>
9073 +#include <plat/pm.h>
9075 +/* PM GPIO helpers */
9077 +#define OFFS_CON (0x00)
9078 +#define OFFS_DAT (0X04)
9079 +#define OFFS_UP (0X08)
9081 +static void s3c_gpio_pm_1bit_save(struct s3c_gpio_chip *chip)
9083 + chip->pm_save[0] = __raw_readl(chip->base + OFFS_CON);
9084 + chip->pm_save[1] = __raw_readl(chip->base + OFFS_DAT);
9087 +static void s3c_gpio_pm_1bit_resume(struct s3c_gpio_chip *chip)
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];
9096 + /* GPACON only has one bit per control / data and no PULLUPs.
9097 + * GPACON[x] = 0 => Output, 1 => SFN */
9099 + /* first set all SFN bits to SFN */
9101 + gpcon = old_gpcon | gps_gpcon;
9102 + __raw_writel(gpcon, base + OFFS_CON);
9104 + /* now set all the other bits */
9106 + __raw_writel(gps_gpdat, base + OFFS_DAT);
9107 + __raw_writel(gps_gpcon, base + OFFS_CON);
9109 + S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
9110 + chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
9113 +struct s3c_gpio_pm s3c_gpio_pm_1bit = {
9114 + .save = s3c_gpio_pm_1bit_save,
9115 + .resume = s3c_gpio_pm_1bit_resume,
9118 +static void s3c_gpio_pm_2bit_save(struct s3c_gpio_chip *chip)
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);
9125 +/* Test whether the given masked+shifted bits of an GPIO configuration
9126 + * are one of the SFN (special function) modes. */
9128 +static inline int is_sfn(unsigned long con)
9133 +/* Test if the given masked+shifted GPIO configuration is an input */
9135 +static inline int is_in(unsigned long con)
9140 +/* Test if the given masked+shifted GPIO configuration is an output */
9142 +static inline int is_out(unsigned long con)
9148 + * s3c_gpio_pm_2bit_resume() - restore the given GPIO bank
9149 + * @chip: The chip information to resume.
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.
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
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]
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.
9171 + * [1] this assumes that writing to a pin DAT whilst in SFN will set the
9172 + * state for when it is next output.
9174 +static void s3c_gpio_pm_2bit_resume(struct s3c_gpio_chip *chip)
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;
9185 + /* restore GPIO pull-up settings */
9186 + __raw_writel(chip->pm_save[2], base + OFFS_UP);
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.
9193 + for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
9194 + old = (old_gpcon & mask) >> nr;
9195 + new = (gps_gpcon & mask) >> nr;
9197 + /* If there is no change, then skip */
9202 + /* If both are special function, then skip */
9204 + if (is_sfn(old) && is_sfn(new))
9207 + /* Change is IN => OUT, do not change now */
9209 + if (is_in(old) && is_out(new))
9212 + /* Change is SFN => OUT, do not change now */
9214 + if (is_sfn(old) && is_out(new))
9217 + /* We should now be at the case of IN=>SFN,
9218 + * OUT=>SFN, OUT=>IN, SFN=>IN. */
9220 + change_mask |= mask;
9224 + /* Write the new CON settings */
9226 + gpcon = old_gpcon & ~change_mask;
9227 + gpcon |= gps_gpcon & change_mask;
9229 + __raw_writel(gpcon, base + OFFS_CON);
9231 + /* Now change any items that require DAT,CON */
9233 + __raw_writel(gps_gpdat, base + OFFS_DAT);
9234 + __raw_writel(gps_gpcon, base + OFFS_CON);
9236 + S3C_PMDBG("%s: CON %08x => %08x, DAT %08x => %08x\n",
9237 + chip->chip.label, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
9240 +struct s3c_gpio_pm s3c_gpio_pm_2bit = {
9241 + .save = s3c_gpio_pm_2bit_save,
9242 + .resume = s3c_gpio_pm_2bit_resume,
9245 +#ifdef CONFIG_ARCH_S3C64XX
9246 +static void s3c_gpio_pm_4bit_save(struct s3c_gpio_chip *chip)
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);
9252 + if (chip->chip.ngpio > 8)
9253 + chip->pm_save[0] = __raw_readl(chip->base - 4);
9256 +static u32 s3c_gpio_pm_4bit_mask(u32 old_gpcon, u32 gps_gpcon)
9258 + u32 old, new, mask;
9259 + u32 change_mask = 0x0;
9262 + for (nr = 0, mask = 0x0f; nr < 16; nr += 4, mask <<= 4) {
9263 + old = (old_gpcon & mask) >> nr;
9264 + new = (gps_gpcon & mask) >> nr;
9266 + /* If there is no change, then skip */
9271 + /* If both are special function, then skip */
9273 + if (is_sfn(old) && is_sfn(new))
9276 + /* Change is IN => OUT, do not change now */
9278 + if (is_in(old) && is_out(new))
9281 + /* Change is SFN => OUT, do not change now */
9283 + if (is_sfn(old) && is_out(new))
9286 + /* We should now be at the case of IN=>SFN,
9287 + * OUT=>SFN, OUT=>IN, SFN=>IN. */
9289 + change_mask |= mask;
9292 + return change_mask;
9295 +static void s3c_gpio_pm_4bit_con(struct s3c_gpio_chip *chip, int index)
9297 + void __iomem *con = chip->base + (index * 4);
9298 + u32 old_gpcon = __raw_readl(con);
9299 + u32 gps_gpcon = chip->pm_save[index + 1];
9302 + mask = s3c_gpio_pm_4bit_mask(old_gpcon, gps_gpcon);
9304 + gpcon = old_gpcon & ~mask;
9305 + gpcon |= gps_gpcon & mask;
9307 + __raw_writel(gpcon, con);
9310 +static void s3c_gpio_pm_4bit_resume(struct s3c_gpio_chip *chip)
9312 + void __iomem *base = chip->base;
9314 + u32 old_gpdat = __raw_readl(base + OFFS_DAT);
9315 + u32 gps_gpdat = chip->pm_save[2];
9317 + /* First, modify the CON settings */
9320 + old_gpcon[1] = __raw_readl(base + OFFS_CON);
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);
9328 + /* Now change the configurations that require DAT,CON */
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);
9335 + __raw_writel(chip->pm_save[2], base + OFFS_DAT);
9336 + __raw_writel(chip->pm_save[3], base + OFFS_UP);
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);
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);
9351 +struct s3c_gpio_pm s3c_gpio_pm_4bit = {
9352 + .save = s3c_gpio_pm_4bit_save,
9353 + .resume = s3c_gpio_pm_4bit_resume,
9355 +#endif /* CONFIG_ARCH_S3C64XX */
9358 + * s3c_pm_save_gpio() - save gpio chip data for suspend
9359 + * @ourchip: The chip for suspend.
9361 +static void s3c_pm_save_gpio(struct s3c_gpio_chip *ourchip)
9363 + struct s3c_gpio_pm *pm = ourchip->pm;
9365 + if (pm == NULL || pm->save == NULL)
9366 + S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
9368 + pm->save(ourchip);
9372 + * s3c_pm_save_gpios() - Save the state of the GPIO banks.
9374 + * For all the GPIO banks, save the state of each one ready for going
9375 + * into a suspend mode.
9377 +void s3c_pm_save_gpios(void)
9379 + struct s3c_gpio_chip *ourchip;
9380 + unsigned int gpio_nr;
9382 + for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
9383 + ourchip = s3c_gpiolib_getchip(gpio_nr);
9387 + s3c_pm_save_gpio(ourchip);
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]);
9396 + gpio_nr += ourchip->chip.ngpio;
9397 + gpio_nr += CONFIG_S3C_GPIO_SPACE;
9402 + * s3c_pm_resume_gpio() - restore gpio chip data after suspend
9403 + * @ourchip: The suspended chip.
9405 +static void s3c_pm_resume_gpio(struct s3c_gpio_chip *ourchip)
9407 + struct s3c_gpio_pm *pm = ourchip->pm;
9409 + if (pm == NULL || pm->resume == NULL)
9410 + S3C_PMDBG("%s: no pm for %s\n", __func__, ourchip->chip.label);
9412 + pm->resume(ourchip);
9415 +void s3c_pm_restore_gpios(void)
9417 + struct s3c_gpio_chip *ourchip;
9418 + unsigned int gpio_nr;
9420 + for (gpio_nr = 0; gpio_nr < S3C_GPIO_END; gpio_nr++) {
9421 + ourchip = s3c_gpiolib_getchip(gpio_nr);
9425 + s3c_pm_resume_gpio(ourchip);
9427 + gpio_nr += ourchip->chip.ngpio;
9428 + gpio_nr += CONFIG_S3C_GPIO_SPACE;
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
9436 + * arch/arm/plat-s3c/pwm.c
9438 + * Copyright (c) by Javi Roman <javiroman@kernel-labs.org>
9439 + * for the Openmoko Project.
9441 + * S3C2410A SoC PWM support
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.
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
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>
9464 + static unsigned long standby_reg_tcon;
9465 + static unsigned long standby_reg_tcfg0;
9466 + static unsigned long standby_reg_tcfg1;
9469 +int s3c2410_pwm_disable(struct s3c2410_pwm *pwm)
9471 + unsigned long tcon;
9474 + tcon = __raw_readl(S3C2410_TCON);
9475 + tcon &= 0xffffff00;
9476 + __raw_writel(tcon, S3C2410_TCON);
9478 + clk_disable(pwm->pclk);
9479 + clk_put(pwm->pclk);
9483 +EXPORT_SYMBOL_GPL(s3c2410_pwm_disable);
9485 +int s3c2410_pwm_init(struct s3c2410_pwm *pwm)
9487 + pwm->pclk = clk_get(NULL, "timers");
9488 + if (IS_ERR(pwm->pclk))
9489 + return PTR_ERR(pwm->pclk);
9491 + clk_enable(pwm->pclk);
9492 + pwm->pclk_rate = clk_get_rate(pwm->pclk);
9495 +EXPORT_SYMBOL_GPL(s3c2410_pwm_init);
9497 +int s3c2410_pwm_enable(struct s3c2410_pwm *pwm)
9499 + unsigned long tcfg0, tcfg1, tcnt, tcmp;
9501 + /* control registers bits */
9502 + tcfg1 = __raw_readl(S3C2410_TCFG1);
9503 + tcfg0 = __raw_readl(S3C2410_TCFG0);
9505 + /* divider & scaler slection */
9506 + switch (pwm->timerid) {
9508 + tcfg1 &= ~S3C2410_TCFG1_MUX0_MASK;
9509 + tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
9512 + tcfg1 &= ~S3C2410_TCFG1_MUX1_MASK;
9513 + tcfg0 &= ~S3C2410_TCFG_PRESCALER0_MASK;
9516 + tcfg1 &= ~S3C2410_TCFG1_MUX2_MASK;
9517 + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
9520 + tcfg1 &= ~S3C2410_TCFG1_MUX3_MASK;
9521 + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
9524 + /* timer four is not capable of doing PWM */
9527 + clk_disable(pwm->pclk);
9528 + clk_put(pwm->pclk);
9532 + /* divider & scaler values */
9533 + tcfg1 |= pwm->divider;
9534 + __raw_writel(tcfg1, S3C2410_TCFG1);
9536 + switch (pwm->timerid) {
9539 + tcfg0 |= pwm->prescaler;
9540 + __raw_writel(tcfg0, S3C2410_TCFG0);
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",
9551 + /* timer count and compare buffer initial values */
9552 + tcnt = pwm->counter;
9553 + tcmp = pwm->comparer;
9555 + __raw_writel(tcnt, S3C2410_TCNTB(pwm->timerid));
9556 + __raw_writel(tcmp, S3C2410_TCMPB(pwm->timerid));
9558 + /* ensure timer is stopped */
9559 + s3c2410_pwm_stop(pwm);
9563 +EXPORT_SYMBOL_GPL(s3c2410_pwm_enable);
9565 +int s3c2410_pwm_start(struct s3c2410_pwm *pwm)
9567 + unsigned long tcon;
9569 + tcon = __raw_readl(S3C2410_TCON);
9571 + switch (pwm->timerid) {
9573 + tcon |= S3C2410_TCON_T0START;
9574 + tcon &= ~S3C2410_TCON_T0MANUALUPD;
9577 + tcon |= S3C2410_TCON_T1START;
9578 + tcon &= ~S3C2410_TCON_T1MANUALUPD;
9581 + tcon |= S3C2410_TCON_T2START;
9582 + tcon &= ~S3C2410_TCON_T2MANUALUPD;
9585 + tcon |= S3C2410_TCON_T3START;
9586 + tcon &= ~S3C2410_TCON_T3MANUALUPD;
9589 + /* timer four is not capable of doing PWM */
9594 + __raw_writel(tcon, S3C2410_TCON);
9598 +EXPORT_SYMBOL_GPL(s3c2410_pwm_start);
9600 +int s3c2410_pwm_stop(struct s3c2410_pwm *pwm)
9602 + unsigned long tcon;
9604 + tcon = __raw_readl(S3C2410_TCON);
9606 + switch (pwm->timerid) {
9608 + tcon &= ~0x00000000;
9609 + tcon |= S3C2410_TCON_T0RELOAD;
9610 + tcon |= S3C2410_TCON_T0MANUALUPD;
9613 + tcon &= ~0x00000080;
9614 + tcon |= S3C2410_TCON_T1RELOAD;
9615 + tcon |= S3C2410_TCON_T1MANUALUPD;
9618 + tcon &= ~0x00000800;
9619 + tcon |= S3C2410_TCON_T2RELOAD;
9620 + tcon |= S3C2410_TCON_T2MANUALUPD;
9623 + tcon &= ~0x00008000;
9624 + tcon |= S3C2410_TCON_T3RELOAD;
9625 + tcon |= S3C2410_TCON_T3MANUALUPD;
9628 + /* timer four is not capable of doing PWM */
9633 + __raw_writel(tcon, S3C2410_TCON);
9637 +EXPORT_SYMBOL_GPL(s3c2410_pwm_stop);
9639 +int s3c2410_pwm_duty_cycle(int reg_value, struct s3c2410_pwm *pwm)
9641 + __raw_writel(reg_value, S3C2410_TCMPB(pwm->timerid));
9645 +EXPORT_SYMBOL_GPL(s3c2410_pwm_duty_cycle);
9647 +int s3c2410_pwm_dumpregs(void)
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));
9656 +EXPORT_SYMBOL_GPL(s3c2410_pwm_dumpregs);
9658 +static int __init s3c24xx_pwm_probe(struct platform_device *pdev)
9660 + struct s3c24xx_pwm_platform_data *pdata = pdev->dev.platform_data;
9662 + dev_info(&pdev->dev, "s3c24xx_pwm is registered \n");
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
9669 + if (pdata->attach_child_devices)
9670 + (pdata->attach_child_devices)(&pdev->dev);
9676 +static int s3c24xx_pwm_suspend(struct platform_device *pdev, pm_message_t state)
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);
9686 +static int s3c24xx_pwm_resume(struct platform_device *pdev)
9688 + __raw_writel(standby_reg_tcon, S3C2410_TCON);
9689 + __raw_writel(standby_reg_tcfg0, S3C2410_TCFG0);
9690 + __raw_writel(standby_reg_tcfg1, S3C2410_TCFG1);
9695 +#define s3c24xx_pwm_suspend NULL
9696 +#define s3c24xx_pwm_resume NULL
9699 +static struct platform_driver s3c24xx_pwm_driver = {
9701 + .name = "s3c24xx_pwm",
9702 + .owner = THIS_MODULE,
9704 + .probe = s3c24xx_pwm_probe,
9705 + .suspend = s3c24xx_pwm_suspend,
9706 + .resume = s3c24xx_pwm_resume,
9709 +static int __init s3c24xx_pwm_init(void)
9711 + return platform_driver_register(&s3c24xx_pwm_driver);
9714 +static void __exit s3c24xx_pwm_exit(void)
9718 +MODULE_AUTHOR("Javi Roman <javiroman@kernel-labs.org>");
9719 +MODULE_LICENSE("GPL");
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
9727 * IRQs are disabled before entering here from do_gettimeofday()
9730 -static unsigned long s3c2410_gettimeoffset (void)
9731 +unsigned long s3c2410_gettimeoffset (void)
9733 unsigned long tdone;
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
9740 #include <mach/regs-clock.h>
9741 #include <mach/regs-gpio.h>
9742 +#include <mach/hardware.h>
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
9751 platform_add_devices(smdk_devs, ARRAY_SIZE(smdk_devs));
9753 - s3c2410_pm_init();
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
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
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
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
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>
9794 #include <plat/regs-serial.h>
9795 @@ -136,36 +138,6 @@
9796 struct platform_device *s3c24xx_uart_devs[4] = {
9799 -/* USB Host Controller */
9801 -static struct resource s3c_usb_resource[] = {
9803 - .start = S3C24XX_PA_USBHOST,
9804 - .end = S3C24XX_PA_USBHOST + S3C24XX_SZ_USBHOST - 1,
9805 - .flags = IORESOURCE_MEM,
9808 - .start = IRQ_USBH,
9810 - .flags = IORESOURCE_IRQ,
9814 -static u64 s3c_device_usb_dmamask = 0xffffffffUL;
9816 -struct platform_device s3c_device_usb = {
9817 - .name = "s3c2410-ohci",
9819 - .num_resources = ARRAY_SIZE(s3c_usb_resource),
9820 - .resource = s3c_usb_resource,
9822 - .dma_mask = &s3c_device_usb_dmamask,
9823 - .coherent_dma_mask = 0xffffffffUL
9827 -EXPORT_SYMBOL(s3c_device_usb);
9829 /* LCD Controller */
9831 static struct resource s3c_lcd_resource[] = {
9832 @@ -229,6 +201,24 @@
9834 EXPORT_SYMBOL(s3c_device_nand);
9837 +struct platform_device s3c_device_ts = {
9838 + .name = "s3c2410-ts",
9842 +EXPORT_SYMBOL(s3c_device_ts);
9844 +static struct s3c2410_ts_mach_info s3c2410ts_info;
9846 +void set_s3c2410ts_info(const struct s3c2410_ts_mach_info *hard_s3c2410ts_info)
9848 + memcpy(&s3c2410ts_info, hard_s3c2410ts_info,
9849 + sizeof(struct s3c2410_ts_mach_info));
9850 + s3c_device_ts.dev.platform_data = &s3c2410ts_info;
9852 +EXPORT_SYMBOL(set_s3c2410ts_info);
9854 /* USB Device (Gadget)*/
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
9861 #include <asm/irq.h>
9862 #include <mach/hardware.h>
9863 #include <mach/dma.h>
9865 #include <mach/map.h>
9867 -#include <plat/dma.h>
9868 +#include <plat/dma-core.h>
9869 +#include <plat/regs-dma.h>
9870 +#include <plat/dma-plat.h>
9872 /* io map for dma */
9873 static void __iomem *dma_base;
9876 static struct s3c24xx_dma_selection dma_sel;
9878 -/* dma channel state information */
9879 -struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
9881 /* debugging functions */
9883 @@ -135,21 +134,6 @@
9884 #define dbg_showchan(chan) do { } while(0)
9885 #endif /* CONFIG_S3C2410_DMA_DEBUG */
9887 -static struct s3c2410_dma_chan *dma_chan_map[DMACH_MAX];
9889 -/* lookup_dma_channel
9891 - * change the dma channel number given into a real dma channel id
9894 -static struct s3c2410_dma_chan *lookup_dma_channel(unsigned int channel)
9896 - if (channel & DMACH_LOW_LEVEL)
9897 - return &s3c2410_chans[channel & ~DMACH_LOW_LEVEL];
9899 - return dma_chan_map[channel];
9902 /* s3c2410_dma_stats_timeout
9904 * Update DMA stats from timeout info
9911 /* s3c2410_dma_loadbuffer
9913 * load a buffer, and update the channel state
9915 int s3c2410_dma_enqueue(unsigned int channel, void *id,
9916 dma_addr_t data, int size)
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;
9925 int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
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;
9933 chan->irq_claimed = 0;
9935 if (!(channel & DMACH_LOW_LEVEL))
9936 - dma_chan_map[channel] = NULL;
9937 + s3c_dma_chan_map[channel] = NULL;
9939 local_irq_restore(flags);
9943 s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
9945 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
9946 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
9950 @@ -1038,14 +1020,13 @@
9951 /* s3c2410_dma_config
9953 * xfersize: size of unit in bytes (1,2,4)
9954 - * dcon: base value of the DCONx register
9957 int s3c2410_dma_config(unsigned int channel,
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;
9966 pr_debug("%s: chan=%d, xfer_unit=%d, dcon=%08x\n",
9967 __func__, channel, xferunit, dcon);
9968 @@ -1055,10 +1036,33 @@
9970 pr_debug("%s: Initial dcon is %08x\n", __func__, dcon);
9972 - dcon |= chan->dcon & dma_sel.dcon_mask;
9973 + dcon = chan->dcon & dma_sel.dcon_mask;
9975 pr_debug("%s: New dcon is %08x\n", __func__, dcon);
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:
9984 + dcon |= S3C2410_DCON_HANDSHAKE;
9985 + dcon |= S3C2410_DCON_SYNC_PCLK;
9989 + /* note, ensure if need HANDSHAKE or not */
9990 + dcon |= S3C2410_DCON_SYNC_PCLK;
9995 + dcon |= S3C2410_DCON_HANDSHAKE;
9996 + dcon |= S3C2410_DCON_SYNC_HCLK;
10000 switch (xferunit) {
10002 dcon |= S3C2410_DCON_BYTE;
10003 @@ -1089,10 +1093,10 @@
10006 EXPORT_SYMBOL(s3c2410_dma_config);
10008 +#if 0 /* moved to plat-s3c? */
10009 int s3c2410_dma_setflags(unsigned int channel, unsigned int flags)
10011 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
10012 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
10016 @@ -1105,43 +1109,7 @@
10019 EXPORT_SYMBOL(s3c2410_dma_setflags);
10022 -/* do we need to protect the settings of the fields from
10026 -int s3c2410_dma_set_opfn(unsigned int channel, s3c2410_dma_opfn_t rtn)
10028 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
10030 - if (chan == NULL)
10033 - pr_debug("%s: chan=%p, op rtn=%p\n", __func__, chan, rtn);
10035 - chan->op_fn = rtn;
10040 -EXPORT_SYMBOL(s3c2410_dma_set_opfn);
10042 -int s3c2410_dma_set_buffdone_fn(unsigned int channel, s3c2410_dma_cbfn_t rtn)
10044 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
10046 - if (chan == NULL)
10049 - pr_debug("%s: chan=%p, callback rtn=%p\n", __func__, chan, rtn);
10051 - chan->callback_fn = rtn;
10056 -EXPORT_SYMBOL(s3c2410_dma_set_buffdone_fn);
10059 /* s3c2410_dma_devconfig
10061 @@ -1150,29 +1118,38 @@
10062 * source: S3C2410_DMASRC_HW: source is hardware
10063 * S3C2410_DMASRC_MEM: source is memory
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
10069 * devaddr: physical address of the source
10072 int s3c2410_dma_devconfig(int channel,
10073 enum s3c2410_dmasrc source,
10075 unsigned long devaddr)
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;
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);
10089 chan->source = source;
10090 chan->dev_addr = devaddr;
10091 - chan->hw_cfg = hwcfg;
10093 + switch (chan->req_ch) {
10096 + hwcfg = 0; /* AHB */
10100 + hwcfg = S3C2410_DISRCC_APB;
10103 + /* always assume our peripheral desintation is a fixed
10104 + * address in memory. */
10105 + hwcfg |= S3C2410_DISRCC_INC;
10108 case S3C2410_DMASRC_HW:
10109 @@ -1219,7 +1196,7 @@
10111 int s3c2410_dma_getposition(unsigned int channel, dma_addr_t *src, dma_addr_t *dst)
10113 - struct s3c2410_dma_chan *chan = lookup_dma_channel(channel);
10114 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
10118 @@ -1278,8 +1255,8 @@
10120 printk(KERN_INFO "dma%d: restoring configuration\n", cp->number);
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);
10127 /* re-select the dma source for this channel */
10129 @@ -1476,7 +1453,8 @@
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;
10137 /* select the channel */
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
10143 #include <asm/irq.h>
10145 #include <mach/regs-gpio.h>
10146 +#include <mach/regs-gpioj.h>
10148 void s3c2410_gpio_cfgpin(unsigned int pin, unsigned int function)
10150 @@ -215,3 +216,423 @@
10153 EXPORT_SYMBOL(s3c2410_gpio_irq2pin);
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,
10162 + const char *tag_type = NULL,
10163 + *tag_state = NULL,
10164 + *tag_pulldown = NULL,
10168 + for (n = 0; n < count; n++) {
10169 + switch ((cfg >> (2 * n)) & 3) {
10171 + tag_type = "input ";
10174 + tag_type = "OUTPUT ";
10177 + if (function_names_2) {
10178 + if (function_names_2[n])
10179 + tag_type = function_names_2[n];
10181 + tag_type = "*** ILLEGAL CFG (2) *** ";
10183 + tag_type = "(function) ";
10186 + if (function_names_3) {
10187 + if (function_names_3[n])
10188 + tag_type = function_names_3[n];
10190 + tag_type = "*** ILLEGAL CFG (3) *** ";
10192 + tag_type = "(function) ";
10195 + if ((state >> n) & 1)
10196 + tag_state = level1;
10198 + tag_state = level0;
10200 + if (((pull >> n) & 1))
10201 + tag_pulldown = "";
10203 + tag_pulldown = "(pulldown)";
10205 + printk(KERN_INFO"%s%02d: %s %s %s\n", prefix, n, tag_type,
10206 + tag_state, tag_pulldown);
10208 + printk(KERN_INFO"\n");
10211 +static void pretty_dump_a(u32 cfg, u32 state,
10212 + const char ** function_names,
10213 + const char * prefix,
10217 + const char *tag_type = NULL,
10218 + *tag_state = NULL,
10222 + for (n = 0; n < count; n++) {
10223 + switch ((cfg >> n) & 1) {
10225 + tag_type = "OUTPUT ";
10228 + if (function_names) {
10229 + if (function_names[n])
10230 + tag_type = function_names[n];
10232 + tag_type = "*** ILLEGAL CFG *** ";
10234 + tag_type = "(function) ";
10237 + if ((state >> n) & 1)
10238 + tag_state = level1;
10240 + tag_state = level0;
10242 + printk(KERN_INFO"%s%02d: %s %s\n", prefix, n, tag_type,
10245 + printk(KERN_INFO"\n");
10248 +static const char * funcs_a[] = {
10277 +static const char * funcs_b2[] = {
10290 +static const char * funcs_b3[] = {
10304 +static const char * funcs_c2[] = {
10322 +static const char * funcs_c3[] = {
10341 +static const char * funcs_d2[] = {
10359 +static const char * funcs_d3[] = {
10378 +static const char * funcs_e2[] = {
10396 +static const char * funcs_e3[] = {
10415 +static const char * funcs_f2[] = {
10425 +static const char * funcs_f3[] = {
10437 +static const char * funcs_g2[] = {
10455 +static const char * funcs_g3[] = {
10474 +static const char * funcs_h2[] = {
10487 +static const char * funcs_h3[] = {
10501 +static const char * funcs_j2[] = {
10516 +static const char * funcs_j3[] = {
10532 +/* used to dump GPIO states at suspend */
10533 +void s3c24xx_dump_gpio_states(void)
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);
10572 +EXPORT_SYMBOL(s3c24xx_dump_gpio_states);
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
10578 #include <plat/gpio-core.h>
10579 #include <mach/hardware.h>
10580 #include <asm/irq.h>
10581 +#include <plat/pm.h>
10583 #include <mach/regs-gpio.h>
10586 struct s3c_gpio_chip s3c24xx_gpios[] = {
10588 .base = S3C24XX_GPIO_BASE(S3C2410_GPA0),
10589 + .pm = __gpio_pm(&s3c_gpio_pm_1bit),
10591 .base = S3C2410_GPA0,
10592 .owner = THIS_MODULE,
10596 .base = S3C24XX_GPIO_BASE(S3C2410_GPB0),
10597 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10599 .base = S3C2410_GPB0,
10600 .owner = THIS_MODULE,
10604 .base = S3C24XX_GPIO_BASE(S3C2410_GPC0),
10605 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10607 .base = S3C2410_GPC0,
10608 .owner = THIS_MODULE,
10609 @@ -107,6 +111,7 @@
10612 .base = S3C24XX_GPIO_BASE(S3C2410_GPD0),
10613 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10615 .base = S3C2410_GPD0,
10616 .owner = THIS_MODULE,
10617 @@ -116,6 +121,7 @@
10620 .base = S3C24XX_GPIO_BASE(S3C2410_GPE0),
10621 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10623 .base = S3C2410_GPE0,
10625 @@ -125,6 +131,7 @@
10628 .base = S3C24XX_GPIO_BASE(S3C2410_GPF0),
10629 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10631 .base = S3C2410_GPF0,
10632 .owner = THIS_MODULE,
10633 @@ -135,12 +142,23 @@
10636 .base = S3C24XX_GPIO_BASE(S3C2410_GPG0),
10637 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10639 .base = S3C2410_GPG0,
10640 .owner = THIS_MODULE,
10643 .to_irq = s3c24xx_gpiolib_bankg_toirq,
10648 + .base = S3C24XX_GPIO_BASE(S3C2410_GPH0),
10649 + .pm = __gpio_pm(&s3c_gpio_pm_2bit),
10651 + .base = S3C2410_GPH0,
10652 + .owner = THIS_MODULE,
10653 + .label = "GPIOH",
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
10663 + * GTA02 WLAN power management
10665 + * (C) 2008, 2009 by Openmoko Inc.
10666 + * Author: Andy Green <andy@openmoko.com>
10667 + * All rights reserved.
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
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>
10681 +#include <mach/hardware.h>
10682 +#include <asm/mach-types.h>
10683 +#include <asm/plat-s3c24xx/neo1973.h>
10685 +#include <mach/gta02.h>
10686 +#include <mach/gta02-pm-wlan.h>
10687 +#include <mach/regs-gpio.h>
10688 +#include <mach/regs-gpioj.h>
10690 +#include <linux/delay.h>
10691 +#include <linux/rfkill.h>
10694 +/* ----- Module hardware reset ("power") ----------------------------------- */
10697 +void gta02_wlan_reset(int assert_reset)
10699 + if (assert_reset) {
10700 + s3c2410_gpio_setpin(GTA02_GPIO_nWLAN_RESET, 0);
10701 + msleep(200); /* probably excessive but we don't have specs */
10703 + s3c2410_gpio_setpin(GTA02_GPIO_nWLAN_RESET, 1);
10708 +static int gta02_wlan_suspend(struct platform_device *pdev, pm_message_t state)
10710 + dev_dbg(&pdev->dev, "suspending\n");
10715 +static int gta02_wlan_resume(struct platform_device *pdev)
10717 + dev_dbg(&pdev->dev, "resuming\n");
10722 +#define gta02_wlan_suspend NULL
10723 +#define gta02_wlan_resume NULL
10727 +/* ----- rfkill ------------------------------------------------------------ */
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.
10734 + * This platform driver is as good a place as any other.
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;
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.
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.
10754 +int gta02_wlan_query_rfkill_lock(void)
10756 + mutex_lock(>a02_wlan_rfkill_lock);
10757 + return gta02_wlan_rfkill_on;
10759 +EXPORT_SYMBOL_GPL(gta02_wlan_query_rfkill_lock);
10761 +void gta02_wlan_query_rfkill_unlock(void)
10763 + mutex_unlock(>a02_wlan_rfkill_lock);
10765 +EXPORT_SYMBOL_GPL(gta02_wlan_query_rfkill_unlock);
10768 +void gta02_wlan_set_rfkill_cb(int (*cb)(void *user, int on), void *user)
10770 + BUG_ON(!mutex_is_locked(>a02_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(>a02_wlan_rfkill_lock);
10776 +EXPORT_SYMBOL_GPL(gta02_wlan_set_rfkill_cb);
10778 +void gta02_wlan_clear_rfkill_cb(void)
10780 + mutex_lock(>a02_wlan_rfkill_lock);
10781 + BUG_ON(!gta02_wlan_rfkill_cb);
10782 + gta02_wlan_rfkill_cb = NULL;
10783 + mutex_unlock(>a02_wlan_rfkill_lock);
10785 +EXPORT_SYMBOL_GPL(gta02_wlan_clear_rfkill_cb);
10787 +static int gta02_wlan_toggle_radio(void *data, enum rfkill_state state)
10789 + struct device *dev = data;
10790 + int on = state == RFKILL_STATE_UNBLOCKED;
10793 + dev_dbg(dev, "gta02_wlan_toggle_radio: state %d (%p)\n",
10794 + state, gta02_wlan_rfkill_cb);
10795 + mutex_lock(>a02_wlan_rfkill_lock);
10796 + if (gta02_wlan_rfkill_cb)
10797 + res = gta02_wlan_rfkill_cb(gta02_wlan_rfkill_user, on);
10799 + gta02_wlan_rfkill_on = on;
10800 + mutex_unlock(>a02_wlan_rfkill_lock);
10805 +/* ----- Initialization/removal -------------------------------------------- */
10808 +static int __init gta02_wlan_probe(struct platform_device *pdev)
10810 + /* default-on for now */
10811 + const int default_state = 1;
10812 + struct rfkill *rfkill;
10815 + if (!machine_is_neo1973_gta02())
10818 + dev_info(&pdev->dev, "starting\n");
10820 + s3c2410_gpio_cfgpin(GTA02_GPIO_nWLAN_RESET, S3C2410_GPIO_OUTPUT);
10821 + gta02_wlan_reset(1);
10822 + gta02_wlan_reset(0);
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;
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.
10833 + BUG_ON(gta02_wlan_rfkill_cb);
10834 + gta02_wlan_rfkill_on = default_state;
10835 + rfkill->toggle_radio = gta02_wlan_toggle_radio;
10837 + error = rfkill_register(rfkill);
10839 + rfkill_free(rfkill);
10843 + dev_set_drvdata(&pdev->dev, rfkill);
10848 +static int gta02_wlan_remove(struct platform_device *pdev)
10850 + struct rfkill *rfkill = dev_get_drvdata(&pdev->dev);
10852 + rfkill_unregister(rfkill);
10853 + rfkill_free(rfkill);
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,
10864 + .name = "gta02-pm-wlan",
10868 +static int __devinit gta02_wlan_init(void)
10870 + return platform_driver_register(>a02_wlan_driver);
10873 +static void gta02_wlan_exit(void)
10875 + platform_driver_unregister(>a02_wlan_driver);
10878 +module_init(gta02_wlan_init);
10879 +module_exit(gta02_wlan_exit);
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
10888 -/* linux/include/asm-arm/plat-s3c24xx/dma.h
10890 - * Copyright (C) 2006 Simtec Electronics
10891 - * Ben Dooks <ben@simtec.co.uk>
10893 - * Samsung S3C24XX DMA support
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.
10900 -extern struct sysdev_class dma_sysclass;
10901 -extern struct s3c2410_dma_chan s3c2410_chans[S3C2410_DMA_CHANNELS];
10903 -#define DMA_CH_VALID (1<<31)
10904 -#define DMA_CH_NEVER (1<<30)
10906 -struct s3c24xx_dma_addr {
10907 - unsigned long from;
10908 - unsigned long to;
10911 -/* struct s3c24xx_dma_map
10913 - * this holds the mapping information for the channel selected
10914 - * to be connected to the specified device
10917 -struct s3c24xx_dma_map {
10918 - const char *name;
10919 - struct s3c24xx_dma_addr hw_addr;
10921 - unsigned long channels[S3C2410_DMA_CHANNELS];
10922 - unsigned long channels_rx[S3C2410_DMA_CHANNELS];
10925 -struct s3c24xx_dma_selection {
10926 - struct s3c24xx_dma_map *map;
10927 - unsigned long map_size;
10928 - unsigned long dcon_mask;
10930 - void (*select)(struct s3c2410_dma_chan *chan,
10931 - struct s3c24xx_dma_map *map);
10933 - void (*direction)(struct s3c2410_dma_chan *chan,
10934 - struct s3c24xx_dma_map *map,
10935 - enum s3c2410_dmasrc dir);
10938 -extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
10940 -/* struct s3c24xx_dma_order_ch
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.
10947 -struct s3c24xx_dma_order_ch {
10948 - unsigned int list[S3C2410_DMA_CHANNELS]; /* list of channels */
10949 - unsigned int flags; /* flags */
10952 -/* struct s3c24xx_dma_order
10954 - * information provided by either the core or the board to give the
10955 - * dma system a hint on how to allocate channels
10958 -struct s3c24xx_dma_order {
10959 - struct s3c24xx_dma_order_ch channels[DMACH_MAX];
10962 -extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
10964 -/* DMA init code, called from the cpu support code */
10966 -extern int s3c2410_dma_init(void);
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
10974 +/* linux/arch/arm/plat-s3c24xx/include/plat/dma-plat.h
10976 + * Copyright (C) 2006 Simtec Electronics
10977 + * Ben Dooks <ben@simtec.co.uk>
10979 + * Samsung S3C24XX DMA support
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.
10986 +#include <plat/dma-core.h>
10988 +extern struct sysdev_class dma_sysclass;
10989 +extern struct s3c2410_dma_chan s3c2410_chans[S3C_DMA_CHANNELS];
10991 +#define DMA_CH_VALID (1<<31)
10992 +#define DMA_CH_NEVER (1<<30)
10994 +struct s3c24xx_dma_addr {
10995 + unsigned long from;
10996 + unsigned long to;
10999 +/* struct s3c24xx_dma_map
11001 + * this holds the mapping information for the channel selected
11002 + * to be connected to the specified device
11005 +struct s3c24xx_dma_map {
11006 + const char *name;
11007 + struct s3c24xx_dma_addr hw_addr;
11009 + unsigned long channels[S3C_DMA_CHANNELS];
11010 + unsigned long channels_rx[S3C_DMA_CHANNELS];
11013 +struct s3c24xx_dma_selection {
11014 + struct s3c24xx_dma_map *map;
11015 + unsigned long map_size;
11016 + unsigned long dcon_mask;
11018 + void (*select)(struct s3c2410_dma_chan *chan,
11019 + struct s3c24xx_dma_map *map);
11021 + void (*direction)(struct s3c2410_dma_chan *chan,
11022 + struct s3c24xx_dma_map *map,
11023 + enum s3c2410_dmasrc dir);
11026 +extern int s3c24xx_dma_init_map(struct s3c24xx_dma_selection *sel);
11028 +/* struct s3c24xx_dma_order_ch
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.
11035 +struct s3c24xx_dma_order_ch {
11036 + unsigned int list[S3C_DMA_CHANNELS]; /* list of channels */
11037 + unsigned int flags; /* flags */
11040 +/* struct s3c24xx_dma_order
11042 + * information provided by either the core or the board to give the
11043 + * dma system a hint on how to allocate channels
11046 +struct s3c24xx_dma_order {
11047 + struct s3c24xx_dma_order_ch channels[DMACH_MAX];
11050 +extern int s3c24xx_dma_order_set(struct s3c24xx_dma_order *map);
11052 +/* DMA init code, called from the cpu support code */
11054 +extern int s3c2410_dma_init(void);
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
11062 * published by the Free Software Foundation.
11065 +#include <linux/io.h>
11067 +#include <mach/irqs.h>
11068 +#include <mach/hardware.h>
11069 +#include <mach/regs-irq.h>
11070 +#include <mach/regs-gpio.h>
11072 #define irqdbf(x...)
11073 #define irqdbf2(x...)
11077 unsigned long mask;
11078 unsigned long submask;
11079 +#ifdef CONFIG_S3C2440_C_FIQ
11080 + unsigned long flags;
11083 submask = __raw_readl(S3C2410_INTSUBMSK);
11084 +#ifdef CONFIG_S3C2440_C_FIQ
11085 + local_save_flags(flags);
11086 + local_fiq_disable();
11088 mask = __raw_readl(S3C2410_INTMSK);
11090 submask |= (1UL << (irqno - IRQ_S3CUART_RX0));
11093 /* write back masks */
11094 __raw_writel(submask, S3C2410_INTSUBMSK);
11095 +#ifdef CONFIG_S3C2440_C_FIQ
11096 + local_irq_restore(flags);
11103 unsigned long mask;
11104 unsigned long submask;
11105 +#ifdef CONFIG_S3C2440_C_FIQ
11106 + unsigned long flags;
11109 submask = __raw_readl(S3C2410_INTSUBMSK);
11110 +#ifdef CONFIG_S3C2440_C_FIQ
11111 + local_save_flags(flags);
11112 + local_fiq_disable();
11114 mask = __raw_readl(S3C2410_INTMSK);
11116 submask &= ~(1UL << (irqno - IRQ_S3CUART_RX0));
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);
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
11131 #define S3C24XX_SZ_UART SZ_1M
11132 #define S3C_UART_OFFSET (0x4000)
11134 +#define S3C_VA_UARTx(uart) (S3C_VA_UART + ((uart * S3C_UART_OFFSET)))
11137 #define S3C24XX_VA_TIMER S3C_VA_TIMER
11138 #define S3C2410_PA_TIMER (0x51000000)
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
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
11151 +/* linux/arch/arm/plat-s3c24xx/include/plat/pll.h
11153 + * Copyright 2008 Simtec Electronics
11154 + * Ben Dooks <ben@simtec.co.uk>
11155 + * http://armlinux.simtec.co.uk/
11157 + * S3C24xx - PM core support for arch/arm/plat-s3c/pm.c
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.
11164 +static inline void s3c_pm_debug_init_uart(void)
11166 + unsigned long tmp = __raw_readl(S3C2410_CLKCON);
11168 + /* re-start uart clocks */
11169 + tmp |= S3C2410_CLKCON_UART0;
11170 + tmp |= S3C2410_CLKCON_UART1;
11171 + tmp |= S3C2410_CLKCON_UART2;
11173 + __raw_writel(tmp, S3C2410_CLKCON);
11177 +static inline void s3c_pm_arch_prepare_irqs(void)
11179 + __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
11180 + __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
11182 + /* ack any outstanding external interrupts before we go to sleep */
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);
11190 +static inline void s3c_pm_arch_stop_clocks(void)
11192 + __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
11195 +static void s3c_pm_show_resume_irqs(int start, unsigned long which,
11196 + unsigned long mask);
11198 +static inline void s3c_pm_arch_show_resume_irqs(void)
11200 + S3C_PMDBG("post sleep: IRQs 0x%08x, 0x%08x\n",
11201 + __raw_readl(S3C2410_SRCPND),
11202 + __raw_readl(S3C2410_EINTPEND));
11204 + s3c_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
11205 + s3c_irqwake_intmask);
11207 + s3c_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
11208 + s3c_irqwake_eintmask);
11211 +static inline void s3c_pm_arch_update_uart(void __iomem *regs,
11212 + struct pm_uart_save *save)
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
11219 -/* linux/include/asm-arm/plat-s3c24xx/pm.h
11221 - * Copyright (c) 2004 Simtec Electronics
11222 - * Written by Ben Dooks, <ben@simtec.co.uk>
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.
11229 -/* s3c2410_pm_init
11231 - * called from board at initialisation time to setup the power
11237 -extern __init int s3c2410_pm_init(void);
11241 -static inline int s3c2410_pm_init(void)
11247 -/* configuration for the IRQ mask over sleep */
11248 -extern unsigned long s3c_irqwake_intmask;
11249 -extern unsigned long s3c_irqwake_eintmask;
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;
11255 -/* per-cpu sleep functions */
11257 -extern void (*pm_cpu_prep)(void);
11258 -extern void (*pm_cpu_sleep)(void);
11260 -/* Flags for PM Control */
11262 -extern unsigned long s3c_pm_flags;
11264 -/* from sleep.S */
11266 -extern int s3c2410_cpu_save(unsigned long *saveblk);
11267 -extern void s3c2410_cpu_suspend(void);
11268 -extern void s3c2410_cpu_resume(void);
11270 -extern unsigned long s3c2410_sleep_save_phys;
11272 -/* sleep save info */
11274 -struct sleep_save {
11275 - void __iomem *reg;
11276 - unsigned long val;
11279 -#define SAVE_ITEM(x) \
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);
11286 -extern int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state);
11287 -extern int s3c24xx_irq_resume(struct sys_device *dev);
11289 -#define s3c24xx_irq_suspend NULL
11290 -#define s3c24xx_irq_resume NULL
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
11296 +/* arch/arm/mach-s3c2410/include/mach/dma.h
11298 + * Copyright (C) 2003,2004,2006 Simtec Electronics
11299 + * Ben Dooks <ben@simtec.co.uk>
11301 + * Samsung S3C24XX DMA support
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.
11308 +/* DMA Register definitions */
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)
11322 +#define S3C2410_DISRCC_INC (1<<0)
11323 +#define S3C2410_DISRCC_APB (1<<1)
11325 +#define S3C2410_DMASKTRIG_STOP (1<<2)
11326 +#define S3C2410_DMASKTRIG_ON (1<<1)
11327 +#define S3C2410_DMASKTRIG_SWTRIG (1<<0)
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)
11334 +#define S3C2410_DCON_INTREQ (1<<29)
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)
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)
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)
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)
11360 +#define S3C2410_DCON_SRCSHIFT (24)
11361 +#define S3C2410_DCON_SRCMASK (7<<24)
11363 +#define S3C2410_DCON_BYTE (0<<20)
11364 +#define S3C2410_DCON_HALFWORD (1<<20)
11365 +#define S3C2410_DCON_WORD (2<<20)
11367 +#define S3C2410_DCON_AUTORELOAD (0<<22)
11368 +#define S3C2410_DCON_NORELOAD (1<<22)
11369 +#define S3C2410_DCON_HWTRIG (1<<23)
11371 +#if defined(CONFIG_CPU_S3C2440) || defined(CONFIG_CPU_S3C2442)
11372 +#define S3C2440_DIDSTC_CHKINT (1<<2)
11374 +#define S3C2440_DCON_CH0_I2SSDO (5<<24)
11375 +#define S3C2440_DCON_CH0_PCMIN (6<<24)
11377 +#define S3C2440_DCON_CH1_PCMOUT (5<<24)
11378 +#define S3C2440_DCON_CH1_SDI (6<<24)
11380 +#define S3C2440_DCON_CH2_PCMIN (5<<24)
11381 +#define S3C2440_DCON_CH2_MICIN (6<<24)
11383 +#define S3C2440_DCON_CH3_MICIN (5<<24)
11384 +#define S3C2440_DCON_CH3_PCMOUT (6<<24)
11387 +#ifdef CONFIG_CPU_S3C2412
11389 +#define S3C2412_DMAREQSEL_SRC(x) ((x)<<1)
11391 +#define S3C2412_DMAREQSEL_HW (1)
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)
11416 +#define S3C2443_DMAREQSEL_SRC(x) ((x)<<1)
11418 +#define S3C2443_DMAREQSEL_HW (1)
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
11445 +/* arch/arm/mach-s3c2410/include/mach/regs-iis.h
11447 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
11448 + * http://www.simtec.co.uk/products/SWLINUX/
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.
11454 + * S3C2410 IIS register definition
11457 +#ifndef __ASM_ARCH_REGS_IIS_H
11458 +#define __ASM_ARCH_REGS_IIS_H
11460 +#define S3C2410_IISCON (0x00)
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)
11472 +#define S3C2410_IISMOD (0x04)
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)
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)
11500 +#define S3C2410_IISFCON (0x0c)
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)
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)
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
11526 /* linux/arch/arm/plat-s3c24xx/irq.c
11528 - * Copyright (c) 2003,2004 Simtec Electronics
11529 + * Copyright (c) 2003,2004 Simtec Electronics
11530 * Ben Dooks <ben@simtec.co.uk>
11532 * This program is free software; you can redistribute it and/or modify
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
11540 - * 22-Jul-2004 Ben Dooks <ben@simtec.co.uk>
11541 - * Fixed compile warnings
11543 - * 22-Jul-2004 Roc Wu <cooloney@yahoo.com.cn>
11544 - * Fixed s3c_extirq_type
11546 - * 21-Jul-2004 Arnaud Patard (Rtp) <arnaud.patard@rtp-net.org>
11547 - * Addition of ADC/TC demux
11549 - * 04-Oct-2004 Klaus Fetscher <k.fetscher@fetron.de>
11550 - * Fix for set_irq_type() on low EINT numbers
11552 - * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
11553 - * Tidy up KF's patch and sort out new release
11555 - * 05-Oct-2004 Ben Dooks <ben@simtec.co.uk>
11556 - * Add support for power management controls
11558 - * 04-Nov-2004 Ben Dooks
11559 - * Fix standard IRQ wake for EINT0..4 and RTC
11561 - * 22-Feb-2005 Ben Dooks
11562 - * Fixed edge-triggering on ADC IRQ
11564 - * 28-Jun-2005 Ben Dooks
11565 - * Mark IRQ_LCD valid
11567 - * 25-Jul-2005 Ben Dooks
11568 - * Split the S3C2440 IRQ code to separate file
11571 #include <linux/init.h>
11573 #include <linux/interrupt.h>
11574 #include <linux/ioport.h>
11575 #include <linux/sysdev.h>
11576 -#include <linux/io.h>
11578 -#include <mach/hardware.h>
11579 #include <asm/irq.h>
11581 #include <asm/mach/irq.h>
11583 #include <plat/regs-irqtype.h>
11584 @@ -70,76 +35,24 @@
11585 #include <plat/pm.h>
11586 #include <plat/irq.h>
11588 -/* wakeup irq control */
11592 -/* state for IRQs over sleep */
11594 -/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
11596 - * set bit to 1 in allow bitfield to enable the wakeup settings on it
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;
11605 -s3c_irq_wake(unsigned int irqno, unsigned int state)
11607 - unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
11609 - if (!(s3c_irqwake_intallow & irqbit))
11612 - printk(KERN_INFO "wake %s for irq %d\n",
11613 - state ? "enabled" : "disabled", irqno);
11616 - s3c_irqwake_intmask |= irqbit;
11618 - s3c_irqwake_intmask &= ~irqbit;
11624 -s3c_irqext_wake(unsigned int irqno, unsigned int state)
11626 - unsigned long bit = 1L << (irqno - EXTINT_OFF);
11628 - if (!(s3c_irqwake_eintallow & bit))
11631 - printk(KERN_INFO "wake %s for irq %d\n",
11632 - state ? "enabled" : "disabled", irqno);
11635 - s3c_irqwake_eintmask |= bit;
11637 - s3c_irqwake_eintmask &= ~bit;
11643 -#define s3c_irqext_wake NULL
11644 -#define s3c_irq_wake NULL
11649 s3c_irq_mask(unsigned int irqno)
11651 unsigned long mask;
11653 +#ifdef CONFIG_S3C2440_C_FIQ
11654 + unsigned long flags;
11656 irqno -= IRQ_EINT0;
11658 +#ifdef CONFIG_S3C2440_C_FIQ
11659 + local_save_flags(flags);
11660 + local_fiq_disable();
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);
11671 @@ -156,9 +69,19 @@
11673 unsigned long bitval = 1UL << (irqno - IRQ_EINT0);
11674 unsigned long mask;
11675 +#ifdef CONFIG_S3C2440_C_FIQ
11676 + unsigned long flags;
11679 +#ifdef CONFIG_S3C2440_C_FIQ
11680 + local_save_flags(flags);
11681 + local_fiq_disable();
11683 mask = __raw_readl(S3C2410_INTMSK);
11684 __raw_writel(mask|bitval, S3C2410_INTMSK);
11685 +#ifdef CONFIG_S3C2440_C_FIQ
11686 + local_irq_restore(flags);
11689 __raw_writel(bitval, S3C2410_SRCPND);
11690 __raw_writel(bitval, S3C2410_INTPND);
11691 @@ -169,15 +92,25 @@
11692 s3c_irq_unmask(unsigned int irqno)
11694 unsigned long mask;
11695 +#ifdef CONFIG_S3C2440_C_FIQ
11696 + unsigned long flags;
11699 if (irqno != IRQ_TIMER4 && irqno != IRQ_EINT8t23)
11700 irqdbf2("s3c_irq_unmask %d\n", irqno);
11702 irqno -= IRQ_EINT0;
11704 +#ifdef CONFIG_S3C2440_C_FIQ
11705 + local_save_flags(flags);
11706 + local_fiq_disable();
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);
11716 struct irq_chip s3c_irq_level_chip = {
11717 @@ -590,59 +523,6 @@
11723 -static struct sleep_save irq_save[] = {
11724 - SAVE_ITEM(S3C2410_INTMSK),
11725 - SAVE_ITEM(S3C2410_INTSUBMSK),
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
11733 -static unsigned long save_extint[3];
11734 -static unsigned long save_eintflt[4];
11735 -static unsigned long save_eintmask;
11737 -int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
11741 - for (i = 0; i < ARRAY_SIZE(save_extint); i++)
11742 - save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
11744 - for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
11745 - save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
11747 - s3c2410_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
11748 - save_eintmask = __raw_readl(S3C24XX_EINTMASK);
11753 -int s3c24xx_irq_resume(struct sys_device *dev)
11757 - for (i = 0; i < ARRAY_SIZE(save_extint); i++)
11758 - __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
11760 - for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
11761 - __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
11763 - s3c2410_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
11764 - __raw_writel(save_eintmask, S3C24XX_EINTMASK);
11770 -#define s3c24xx_irq_suspend NULL
11771 -#define s3c24xx_irq_resume NULL
11774 /* s3c24xx_init_irq
11776 * Initialise S3C2410 IRQ system
11777 @@ -673,26 +553,26 @@
11780 for (i = 0; i < 4; i++) {
11781 - pend = __raw_readl(S3C2410_INTPND);
11782 + pend = __raw_readl(S3C2410_SUBSRCPND);
11784 if (pend == 0 || pend == last)
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);
11796 for (i = 0; i < 4; i++) {
11797 - pend = __raw_readl(S3C2410_SUBSRCPND);
11798 + pend = __raw_readl(S3C2410_INTPND);
11800 if (pend == 0 || pend == last)
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);
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
11815 +/* linux/arch/arm/plat-s3c24xx/irq-om.c
11817 + * Copyright (c) 2003,2004 Simtec Electronics
11818 + * Ben Dooks <ben@simtec.co.uk>
11819 + * http://armlinux.simtec.co.uk/
11821 + * S3C24XX - IRQ PM code
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.
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>
11834 +#include <plat/cpu.h>
11835 +#include <plat/pm.h>
11836 +#include <plat/irq.h>
11838 +/* state for IRQs over sleep */
11840 +/* default is to allow for EINT0..EINT15, and IRQ_RTC as wakeup sources
11842 + * set bit to 1 in allow bitfield to enable the wakeup settings on it
11845 +unsigned long s3c_irqwake_intallow = 1L << (IRQ_RTC - IRQ_EINT0) | 0xfL;
11846 +unsigned long s3c_irqwake_eintallow = 0x0000fff0L;
11848 +int s3c_irq_wake(unsigned int irqno, unsigned int state)
11850 + unsigned long irqbit = 1 << (irqno - IRQ_EINT0);
11852 + if (!(s3c_irqwake_intallow & irqbit))
11855 + printk(KERN_INFO "wake %s for irq %d\n",
11856 + state ? "enabled" : "disabled", irqno);
11859 + s3c_irqwake_intmask |= irqbit;
11861 + s3c_irqwake_intmask &= ~irqbit;
11866 +static struct sleep_save irq_save[] = {
11867 + SAVE_ITEM(S3C2410_INTMSK),
11868 + SAVE_ITEM(S3C2410_INTSUBMSK),
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
11876 +static unsigned long save_extint[3];
11877 +static unsigned long save_eintflt[4];
11878 +static unsigned long save_eintmask;
11880 +int s3c24xx_irq_suspend(struct sys_device *dev, pm_message_t state)
11884 + for (i = 0; i < ARRAY_SIZE(save_extint); i++)
11885 + save_extint[i] = __raw_readl(S3C24XX_EXTINT0 + (i*4));
11887 + for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
11888 + save_eintflt[i] = __raw_readl(S3C24XX_EINFLT0 + (i*4));
11890 + s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
11891 + save_eintmask = __raw_readl(S3C24XX_EINTMASK);
11896 +int s3c24xx_irq_resume(struct sys_device *dev)
11898 + unsigned int i, irq;
11899 + unsigned long eintpnd;
11900 + struct irq_desc *desc;
11902 + for (i = 0; i < ARRAY_SIZE(save_extint); i++)
11903 + __raw_writel(save_extint[i], S3C24XX_EXTINT0 + (i*4));
11905 + for (i = 0; i < ARRAY_SIZE(save_eintflt); i++)
11906 + __raw_writel(save_eintflt[i], S3C24XX_EINFLT0 + (i*4));
11908 + s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
11909 + __raw_writel(save_eintmask, S3C24XX_EINTMASK);
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.
11917 + eintpnd = __raw_readl(S3C24XX_EINTPEND);
11919 + eintpnd &= save_eintmask;
11920 + eintpnd &= ~0xff; /* ignore lower irqs */
11922 + while (eintpnd) {
11923 + irq = __ffs(eintpnd);
11924 + eintpnd &= ~(1 << irq);
11926 + irq += (IRQ_EINT4 - 4);
11927 + desc = irq_to_desc(irq);
11928 + desc->chip->ack(irq);
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
11939 select ARCH_REQUIRE_GPIOLIB
11940 + select S3C_GPIO_TRACK
11942 Base platform code for any Samsung S3C24XX device
11948 - depends on ARCH_S3C2410 && (CPU_S3C2440 || CPU_S3C2442)
11949 + default y if CPU_S3C2440 || CPU_S3C2442
11951 Support for S3C2440 and S3C2442 Samsung Mobile CPU based systems.
11955 bool "S3C2410 DMA support"
11956 depends on ARCH_S3C2410
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 @@
11963 Common machine code for SMDK2410 and SMDK2440
11965 +config MACH_NEO1973
11968 + select SERIAL_SAMSUNG
11969 + select SERIAL_SAMSUNG_CONSOLE
11971 + Common machine code for Neo1973 hardware
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
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
11986 # machine common support
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 \
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
12000 + * Bluetooth PM code for the FIC Neo1973 GSM Phone
12002 + * (C) 2007 by Openmoko Inc.
12003 + * Author: Harald Welte <laforge@openmoko.org>
12004 + * All rights reserved.
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
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>
12019 +#include <mach/hardware.h>
12020 +#include <asm/mach-types.h>
12021 +#include <asm/plat-s3c24xx/neo1973.h>
12024 +#include <mach/gta01.h>
12025 +#include <linux/pcf50606.h>
12028 +#include <mach/gta02.h>
12029 +#include <linux/mfd/pcf50633/gpio.h>
12031 +#include <linux/regulator/consumer.h>
12033 +#define DRVMSG "FIC Neo1973 Bluetooth Power Management"
12035 +struct gta01_pm_bt_data {
12036 + struct regulator *regulator;
12037 + struct rfkill *rfkill;
12038 + int pre_resume_state;
12041 +static ssize_t bt_read(struct device *dev, struct device_attribute *attr,
12045 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev);
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))
12054 + } else if (!strcmp(attr->attr.name, "reset")) {
12055 + if (machine_is_neo1973_gta01()) {
12056 + if (s3c2410_gpio_getpin(GTA01_GPIO_BT_EN) == 0)
12058 + } else if (machine_is_neo1973_gta02()) {
12059 + if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN) == 0)
12065 + return strlcpy(buf, "0\n", 3);
12067 + return strlcpy(buf, "1\n", 3);
12071 +static void __gta02_pm_bt_toggle_radio(struct device *dev, unsigned int on)
12073 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev);
12075 + dev_info(dev, "__gta02_pm_bt_toggle_radio %d\n", on);
12077 + if (machine_is_neo1973_gta02()) {
12079 + bt_data = dev_get_drvdata(dev);
12081 + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, !on);
12084 + if (!regulator_is_enabled(bt_data->regulator))
12085 + regulator_enable(bt_data->regulator);
12087 + if (regulator_is_enabled(bt_data->regulator))
12088 + regulator_disable(bt_data->regulator);
12091 + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on);
12096 +static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state)
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);
12102 + if (machine_is_neo1973_gta01()) {
12103 + /* if we are powering up, assert reset, then power,
12104 + * then release reset */
12106 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, 0);
12107 + if (!regulator_is_enabled(bt_data->regulator))
12108 + regulator_enable(bt_data->regulator);
12110 + if (regulator_is_enabled(bt_data->regulator))
12111 + regulator_disable(bt_data->regulator);
12113 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, on);
12114 + } else if (machine_is_neo1973_gta02())
12115 + __gta02_pm_bt_toggle_radio(dev, on);
12120 +static ssize_t bt_write(struct device *dev, struct device_attribute *attr,
12121 + const char *buf, size_t count)
12123 + unsigned long on = simple_strtoul(buf, NULL, 10);
12124 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev);
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;
12131 + if (machine_is_neo1973_gta01()) {
12132 + /* if we are powering up, assert reset, then power,
12133 + * then release reset */
12135 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, 0);
12136 + if (!regulator_is_enabled(bt_data->regulator))
12137 + regulator_enable(bt_data->regulator);
12139 + if (regulator_is_enabled(bt_data->regulator))
12140 + regulator_disable(bt_data->regulator);
12143 + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, on);
12144 + } else if (machine_is_neo1973_gta02())
12145 + __gta02_pm_bt_toggle_radio(dev, on);
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);
12159 +static DEVICE_ATTR(power_on, 0644, bt_read, bt_write);
12160 +static DEVICE_ATTR(reset, 0644, bt_read, bt_write);
12163 +static int gta01_bt_suspend(struct platform_device *pdev, pm_message_t state)
12165 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev);
12167 + dev_dbg(&pdev->dev, DRVMSG ": suspending\n");
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);
12181 +static int gta01_bt_resume(struct platform_device *pdev)
12183 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev);
12184 + dev_dbg(&pdev->dev, DRVMSG ": resuming\n");
12186 + if (machine_is_neo1973_gta02()) {
12187 + __gta02_pm_bt_toggle_radio(&pdev->dev,
12188 + bt_data->pre_resume_state);
12194 +#define gta01_bt_suspend NULL
12195 +#define gta01_bt_resume NULL
12198 +static struct attribute *gta01_bt_sysfs_entries[] = {
12199 + &dev_attr_power_on.attr,
12200 + &dev_attr_reset.attr,
12204 +static struct attribute_group gta01_bt_attr_group = {
12206 + .attrs = gta01_bt_sysfs_entries,
12209 +static int __init gta01_bt_probe(struct platform_device *pdev)
12211 + struct rfkill *rfkill;
12212 + struct regulator *regulator;
12213 + struct gta01_pm_bt_data *bt_data;
12216 + dev_info(&pdev->dev, DRVMSG ": starting\n");
12218 + bt_data = kzalloc(sizeof(*bt_data), GFP_KERNEL);
12219 + dev_set_drvdata(&pdev->dev, bt_data);
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))
12227 + bt_data->regulator = regulator;
12229 + /* this tests the true physical state of the regulator... */
12230 + if (regulator_is_enabled(regulator)) {
12232 + * but these only operate on the logical state of the
12233 + * regulator... so we need to logicaly "adopt" it on
12236 + regulator_enable(regulator);
12237 + regulator_disable(regulator);
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))
12248 + bt_data->regulator = regulator;
12250 + /* this tests the true physical state of the regulator... */
12251 + if (regulator_is_enabled(regulator)) {
12253 + * but these only operate on the logical state of the
12254 + * regulator... so we need to logicaly "adopt" it on
12257 + regulator_enable(regulator);
12258 + regulator_disable(regulator);
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);
12266 + rfkill = rfkill_allocate(&pdev->dev, RFKILL_TYPE_BLUETOOTH);
12268 + rfkill->name = pdev->name;
12269 + rfkill->data = &pdev->dev;
12270 + rfkill->state = RFKILL_STATE_OFF;
12271 + rfkill->toggle_radio = bt_rfkill_toggle_radio;
12273 + ret = rfkill_register(rfkill);
12275 + dev_err(&pdev->dev, "Failed to register rfkill\n");
12279 + bt_data->rfkill = rfkill;
12281 + return sysfs_create_group(&pdev->dev.kobj, >a01_bt_attr_group);
12284 +static int gta01_bt_remove(struct platform_device *pdev)
12286 + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev);
12287 + struct regulator *regulator;
12289 + sysfs_remove_group(&pdev->dev.kobj, >a01_bt_attr_group);
12291 + if (bt_data->rfkill) {
12292 + rfkill_unregister(bt_data->rfkill);
12293 + rfkill_free(bt_data->rfkill);
12296 + if (!bt_data || !bt_data->regulator)
12299 + regulator = bt_data->regulator;
12301 + /* Make sure regulator is disabled before calling regulator_put */
12302 + if (regulator_is_enabled(regulator))
12303 + regulator_disable(regulator);
12305 + regulator_put(regulator);
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,
12318 + .name = "neo1973-pm-bt",
12322 +static int __devinit gta01_bt_init(void)
12324 + return platform_driver_register(>a01_bt_driver);
12327 +static void gta01_bt_exit(void)
12329 + platform_driver_unregister(>a01_bt_driver);
12332 +module_init(gta01_bt_init);
12333 +module_exit(gta01_bt_exit);
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
12343 + * GPS Power Management code for the FIC Neo1973 GSM Phone
12345 + * (C) 2007-2009 by Openmoko Inc.
12346 + * Author: Harald Welte <laforge@openmoko.org>
12347 + * All rights reserved.
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
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>
12361 +#include <mach/hardware.h>
12362 +#include <mach/cpu.h>
12364 +#include <asm/mach-types.h>
12366 +#include <asm/plat-s3c24xx/neo1973.h>
12369 +#include <mach/gta01.h>
12370 +#include <linux/mfd/pcf50606/core.h>
12371 +#include <linux/mfd/pcf50606/gpo.h>
12374 +#include <mach/gta02.h>
12375 +#include <linux/mfd/pcf50633/core.h>
12376 +#include <linux/mfd/pcf50633/pmic.h>
12378 +#include <linux/regulator/consumer.h>
12379 +#include <linux/err.h>
12381 +enum gta01_pm_gps_supplies {
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,
12391 + GTA02_GPS_REG_RF_3V,
12393 + /* Always last */
12394 + GTA01_GPS_NUM_REG
12397 +struct neo1973_pm_gps_data {
12399 + int keep_on_in_suspend;
12401 + int power_was_on; /* For GTA02 only */
12402 + int regulator_state[GTA01_GPS_NUM_REG];
12403 + struct regulator *regulator[GTA01_GPS_NUM_REG];
12406 +static struct neo1973_pm_gps_data neo1973_gps;
12408 +int neo1973_pm_gps_is_on(void)
12410 + return neo1973_gps.power_was_on;
12412 +EXPORT_SYMBOL_GPL(neo1973_pm_gps_is_on);
12414 +#ifdef CONFIG_MACH_NEO1973_GTA01
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)
12420 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V8];
12422 + switch (S3C_SYSTEM_REV_ATAG) {
12423 + case GTA01v3_SYSTEM_REV:
12424 + case GTA01v4_SYSTEM_REV:
12426 + regulator_enable(regulator);
12428 + regulator_disable(regulator);
12429 + neo1973_gps.regulator_state[GTA01_GPS_REG_2V8] = on;
12431 + case GTA01Bv2_SYSTEM_REV:
12432 + s3c2410_gpio_setpin(GTA01_GPIO_GPS_EN_2V8, on);
12434 + case GTA01Bv3_SYSTEM_REV:
12435 + case GTA01Bv4_SYSTEM_REV:
12440 +static int gps_power_2v8_get(void)
12443 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V8];
12445 + switch (S3C_SYSTEM_REV_ATAG) {
12446 + case GTA01v3_SYSTEM_REV:
12447 + case GTA01v4_SYSTEM_REV:
12448 + ret = regulator_is_enabled(regulator);
12450 + case GTA01Bv2_SYSTEM_REV:
12451 + if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_EN_2V8))
12454 + case GTA01Bv3_SYSTEM_REV:
12455 + case GTA01Bv4_SYSTEM_REV:
12462 +/* This is the 3V supply (AVDD) for the external RF frontend (LNA bias) */
12463 +static void gps_power_3v_set(int on)
12465 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V];
12467 + switch (S3C_SYSTEM_REV_ATAG) {
12468 + case GTA01v3_SYSTEM_REV:
12469 + case GTA01v4_SYSTEM_REV:
12471 + regulator_enable(regulator);
12473 + regulator_disable(regulator);
12474 + neo1973_gps.regulator_state[GTA01_GPS_REG_3V] = on;
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);
12484 +static int gps_power_3v_get(void)
12487 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V];
12489 + switch (S3C_SYSTEM_REV_ATAG) {
12490 + case GTA01v3_SYSTEM_REV:
12491 + case GTA01v4_SYSTEM_REV:
12492 + ret = regulator_is_enabled(regulator);
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))
12505 +/* This is the 3.3V supply for VDD_IO and VDD_LPREG input */
12506 +static void gps_power_3v3_set(int on)
12508 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V3];
12510 + switch (S3C_SYSTEM_REV_ATAG) {
12511 + case GTA01v3_SYSTEM_REV:
12512 + case GTA01v4_SYSTEM_REV:
12513 + case GTA01Bv2_SYSTEM_REV:
12515 + regulator_enable(regulator);
12517 + regulator_disable(regulator);
12518 + neo1973_gps.regulator_state[GTA01_GPS_REG_3V3] = on;
12520 + case GTA01Bv3_SYSTEM_REV:
12521 + case GTA01Bv4_SYSTEM_REV:
12522 + s3c2410_gpio_setpin(GTA01_GPIO_GPS_EN_3V3, on);
12527 +static int gps_power_3v3_get(void)
12530 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V3];
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);
12538 + case GTA01Bv3_SYSTEM_REV:
12539 + case GTA01Bv4_SYSTEM_REV:
12540 + if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_EN_3V3))
12548 +/* This is the 2.5V supply for VDD_PLLREG and VDD_COREREG input */
12549 +static void gps_power_2v5_set(int on)
12551 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V5];
12553 + switch (S3C_SYSTEM_REV_ATAG) {
12554 + case GTA01v3_SYSTEM_REV:
12555 + /* This is CORE_1V8 and cannot be disabled */
12557 + case GTA01v4_SYSTEM_REV:
12558 + case GTA01Bv2_SYSTEM_REV:
12559 + case GTA01Bv3_SYSTEM_REV:
12560 + case GTA01Bv4_SYSTEM_REV:
12562 + regulator_enable(regulator);
12564 + regulator_disable(regulator);
12565 + neo1973_gps.regulator_state[GTA01_GPS_REG_2V5] = on;
12570 +static int gps_power_2v5_get(void)
12573 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V5];
12575 + switch (S3C_SYSTEM_REV_ATAG) {
12576 + case GTA01v3_SYSTEM_REV:
12577 + /* This is CORE_1V8 and cannot be disabled */
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);
12591 +/* This is the 1.5V supply for VDD_CORE */
12592 +static void gps_power_1v5_set(int on)
12594 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_1V5];
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 */
12602 + case GTA01Bv3_SYSTEM_REV:
12603 + case GTA01Bv4_SYSTEM_REV:
12605 + regulator_enable(regulator);
12607 + regulator_disable(regulator);
12608 + neo1973_gps.regulator_state[GTA01_GPS_REG_1V5] = on;
12613 +static int gps_power_1v5_get(void)
12616 + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_1V5];
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 */
12625 + case GTA01Bv3_SYSTEM_REV:
12626 + case GTA01Bv4_SYSTEM_REV:
12627 + ret = regulator_is_enabled(regulator);
12635 +/* This is the POWERON pin */
12636 +static void gps_pwron_set(int on)
12639 + if (machine_is_neo1973_gta01())
12640 + neo1973_gpb_setpin(GTA01_GPIO_GPS_PWRON, on);
12642 + if (machine_is_neo1973_gta02()) {
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);
12649 + if (!neo1973_gps.power_was_on)
12650 + regulator_enable(neo1973_gps.regulator[
12651 + GTA02_GPS_REG_RF_3V]);
12656 + * take care not to power unpowered GPS from UART TX
12657 + * return them to GPIO and force low
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]);
12669 +static int gps_pwron_get(void)
12671 + if (machine_is_neo1973_gta01())
12672 + return !!s3c2410_gpio_getpin(GTA01_GPIO_GPS_PWRON);
12674 + if (machine_is_neo1973_gta02())
12675 + return regulator_is_enabled(neo1973_gps.regulator[GTA02_GPS_REG_RF_3V]);
12680 +#ifdef CONFIG_MACH_NEO1973_GTA01
12681 +static void gps_rst_set(int on);
12682 +static int gps_rst_get(void);
12686 +/* This is the flag for keeping gps ON during suspend */
12687 +static void gps_keep_on_in_suspend_set(int on)
12689 + neo1973_gps.keep_on_in_suspend = on;
12692 +static int gps_keep_on_in_suspend_get(void)
12694 + return neo1973_gps.keep_on_in_suspend;
12698 +static ssize_t power_gps_read(struct device *dev,
12699 + struct device_attribute *attr, char *buf)
12703 + if (!strcmp(attr->attr.name, "power_on") ||
12704 + !strcmp(attr->attr.name, "pwron")) {
12705 + ret = gps_pwron_get();
12707 + } else if (!strcmp(attr->attr.name, "keep_on_in_suspend")) {
12708 + ret = gps_keep_on_in_suspend_get();
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();
12727 + return strlcpy(buf, "1\n", 3);
12729 + return strlcpy(buf, "0\n", 3);
12732 +static ssize_t power_gps_write(struct device *dev,
12733 + struct device_attribute *attr, const char *buf,
12736 + unsigned long on = simple_strtoul(buf, NULL, 10);
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;
12743 + } else if (!strcmp(attr->attr.name, "keep_on_in_suspend")) {
12744 + gps_keep_on_in_suspend_set(on);
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")) {
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);
12766 +#ifdef CONFIG_MACH_NEO1973_GTA01
12768 +/* This is the nRESET pin */
12769 +static void gps_rst_set(int on)
12771 + switch (S3C_SYSTEM_REV_ATAG) {
12772 + case GTA01v3_SYSTEM_REV:
12773 + pcf50606_gpo_set_active(gta01_pcf, PCF50606_GPO1, on);
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);
12784 +static int gps_rst_get(void)
12786 + switch (S3C_SYSTEM_REV_ATAG) {
12787 + case GTA01v3_SYSTEM_REV:
12788 + return pcf50606_gpo_get_active(gta01_pcf, PCF50606_GPO1);
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))
12803 +static void gps_power_sequence_up(void)
12805 + /* According to PMB2520 Data Sheet, Rev. 2006-06-05,
12806 + * Chapter 4.2.2 */
12808 + /* nRESET must be asserted low */
12811 + /* POWERON must be de-asserted (low) */
12812 + gps_pwron_set(0);
12814 + /* Apply VDD_IO and VDD_LPREG_IN */
12815 + gps_power_3v3_set(1);
12817 + /* VDD_COREREG_IN, VDD_PLLREG_IN */
12818 + gps_power_1v5_set(1);
12819 + gps_power_2v5_set(1);
12821 + /* and VDD_RF may be applied */
12822 + gps_power_2v8_set(1);
12824 + /* We need to enable AVDD, since in GTA01Bv3 it is
12825 + * shared with RFREG_IN */
12826 + gps_power_3v_set(1);
12828 + msleep(3); /* Is 3ms enough? */
12830 + /* De-asert nRESET */
12833 + /* Switch power on */
12834 + gps_pwron_set(1);
12838 +static void gps_power_sequence_down(void)
12840 + /* According to PMB2520 Data Sheet, Rev. 2006-06-05,
12841 + * Chapter 4.2.3.1 */
12842 + gps_pwron_set(0);
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);
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);
12857 + /* Remove VDD_LPREG_IN and VDD_IO */
12858 + if (neo1973_gps.regulator_state[GTA01_GPS_REG_3V3])
12859 + gps_power_3v3_set(0);
12863 +static ssize_t power_sequence_read(struct device *dev,
12864 + struct device_attribute *attr,
12867 + return strlcpy(buf, "power_up power_down\n", PAGE_SIZE);
12870 +static ssize_t power_sequence_write(struct device *dev,
12871 + struct device_attribute *attr,
12872 + const char *buf, size_t count)
12874 + dev_dbg(dev, "wrote: '%s'\n", buf);
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();
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);
12898 +static int gta01_pm_gps_suspend(struct platform_device *pdev,
12899 + pm_message_t state)
12901 +#ifdef CONFIG_MACH_NEO1973_GTA01
12902 + if (machine_is_neo1973_gta01())
12904 + gps_power_sequence_down();
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);
12911 + dev_warn(&pdev->dev, "GTA02: keeping gps ON "
12912 + "during suspend\n");
12918 +static int gta01_pm_gps_resume(struct platform_device *pdev)
12920 +#ifdef CONFIG_MACH_NEO1973_GTA01
12921 + if (machine_is_neo1973_gta01())
12922 + if (neo1973_gps.power_was_on)
12923 + gps_power_sequence_up();
12925 + if (machine_is_neo1973_gta02())
12926 + if (!neo1973_gps.keep_on_in_suspend && neo1973_gps.power_was_on)
12927 + gps_pwron_set(1);
12932 +static DEVICE_ATTR(keep_on_in_suspend, 0644, power_gps_read, power_gps_write);
12934 +#define gta01_pm_gps_suspend NULL
12935 +#define gta01_pm_gps_resume NULL
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);
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 */
12954 + NULL /* terminating entry */
12957 +static struct attribute_group gta01_gps_attr_group = {
12959 + .attrs = gta01_gps_sysfs_entries,
12962 +static struct attribute *gta02_gps_sysfs_entries[] = {
12963 + &dev_attr_power_on.attr,
12965 + &dev_attr_keep_on_in_suspend.attr,
12970 +static struct attribute_group gta02_gps_attr_group = {
12972 + .attrs = gta02_gps_sysfs_entries,
12975 +static int __init gta01_pm_gps_probe(struct platform_device *pdev)
12978 +#ifdef CONFIG_MACH_NEO1973_GTA01
12979 + int entries = ARRAY_SIZE(gta01_gps_sysfs_entries);
12982 + if (machine_is_neo1973_gta01()) {
12983 + s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_PWRON, S3C2410_GPIO_OUTPUT);
12985 + switch (S3C_SYSTEM_REV_ATAG) {
12986 + case GTA01v3_SYSTEM_REV:
12988 + case GTA01v4_SYSTEM_REV:
12989 + s3c2410_gpio_cfgpin(GTA01_GPIO_GPS_RESET,
12990 + S3C2410_GPIO_OUTPUT);
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);
13006 + dev_warn(&pdev->dev, "Unknown GTA01 Revision 0x%x, "
13007 + "AGPS PM features not available!!!\n",
13013 +#ifdef CONFIG_MACH_NEO1973_GTA01
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");
13026 + gps_power_sequence_down();
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;
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;
13044 + ret = sysfs_create_group(&pdev->dev.kobj,
13045 + >a01_gps_attr_group);
13048 + return bus_create_device_link(&platform_bus_type,
13049 + &pdev->dev.kobj, "gta01-pm-gps.0");
13052 + if (machine_is_neo1973_gta02()) {
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));
13060 + return PTR_ERR(neo1973_gps.regulator);
13063 + dev_info(&pdev->dev, "starting\n");
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.
13076 + * u-boot enables LDO5 (GPS), which doesn't make sense and
13077 + * causes confusion. We therefore disable the regulator here.
13079 + pcf50633_reg_write(gta02_pcf, PCF50633_REG_LDO5ENA, 0);
13082 + * take care not to power unpowered GPS from UART TX
13083 + * return them to GPIO and force low
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);
13090 + return sysfs_create_group(&pdev->dev.kobj,
13091 + >a02_gps_attr_group);
13096 +static int gta01_pm_gps_remove(struct platform_device *pdev)
13098 + if (machine_is_neo1973_gta01()) {
13099 +#ifdef CONFIG_MACH_NEO1973_GTA01
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]);
13108 + bus_remove_device_link(&platform_bus_type, "gta01-pm-gps.0");
13109 + sysfs_remove_group(&pdev->dev.kobj, >a01_gps_attr_group);
13112 + if (machine_is_neo1973_gta02()) {
13113 + regulator_put(neo1973_gps.regulator[GTA02_GPS_REG_RF_3V]);
13114 + sysfs_remove_group(&pdev->dev.kobj, >a02_gps_attr_group);
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,
13125 + .name = "neo1973-pm-gps",
13129 +static int __devinit gta01_pm_gps_init(void)
13131 + return platform_driver_register(>a01_pm_gps_driver);
13134 +static void gta01_pm_gps_exit(void)
13136 + platform_driver_unregister(>a01_pm_gps_driver);
13139 +module_init(gta01_pm_gps_init);
13140 +module_exit(gta01_pm_gps_exit);
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
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
13155 + * GSM Management code for the FIC Neo1973 GSM Phone
13157 + * (C) 2007 by Openmoko Inc.
13158 + * Author: Harald Welte <laforge@openmoko.org>
13159 + * All rights reserved.
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
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>
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>
13182 +#include <mach/hardware.h>
13183 +#include <mach/cpu.h>
13186 +#include <mach/gta02.h>
13187 +#include <linux/mfd/pcf50633/gpio.h>
13188 +#include <mach/regs-gpio.h>
13189 +#include <mach/regs-gpioj.h>
13191 +int gta_gsm_interrupts;
13192 +EXPORT_SYMBOL(gta_gsm_interrupts);
13194 +extern void s3c24xx_serial_console_set_silence(int);
13196 +struct gta01pm_priv {
13197 + int gpio_ngsm_en;
13198 + int gpio_ndl_gsm;
13200 + struct console *con;
13203 +static struct gta01pm_priv gta01_gsm;
13205 +static struct console *find_s3c24xx_console(void)
13207 + struct console *con;
13209 + acquire_console_sem();
13211 + for (con = console_drivers; con; con = con->next) {
13212 + if (!strcmp(con->name, "ttySAC"))
13216 + release_console_sem();
13221 +static ssize_t gsm_read(struct device *dev, struct device_attribute *attr,
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))
13228 + } else if (machine_is_neo1973_gta02())
13229 + if (pcf50633_gpio_get(gta02_pcf, PCF50633_GPIO2))
13231 + } else if (!strcmp(attr->attr.name, "download")) {
13232 + if (machine_is_neo1973_gta01()) {
13233 + if (s3c2410_gpio_getpin(GTA01_GPIO_MODEM_DNLOAD))
13235 + } else if (machine_is_neo1973_gta02()) {
13236 + if (!s3c2410_gpio_getpin(GTA02_GPIO_nDL_GSM))
13239 + } else if (!strcmp(attr->attr.name, "flowcontrolled")) {
13240 + if (s3c2410_gpio_getcfg(S3C2410_GPH1) == S3C2410_GPIO_OUTPUT)
13244 + return strlcpy(buf, "0\n", 3);
13246 + return strlcpy(buf, "1\n", 3);
13249 +static void gsm_on_off(struct device *dev, int on)
13252 + if (machine_is_neo1973_gta02()) {
13254 + * Do not drive into powered-down GSM side
13255 + * GTA02 only, because on GTA01 maybe serial
13256 + * is used otherwise.
13258 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPIO_INPUT);
13259 + s3c2410_gpio_cfgpin(S3C2410_GPH2, S3C2410_GPIO_INPUT);
13261 + pcf50633_gpio_set(gta02_pcf, PCF50633_GPIO2, 0);
13264 + if (gta01_gsm.gpio_ngsm_en)
13265 + s3c2410_gpio_setpin(gta01_gsm.gpio_ngsm_en, 1);
13267 + if (gta01_gsm.con) {
13268 + s3c24xx_serial_console_set_silence(0);
13269 + console_start(gta01_gsm.con);
13271 + dev_dbg(dev, "powered down GTA01 GSM, enabling "
13272 + "serial console\n");
13278 + if (gta01_gsm.con) {
13279 + dev_dbg(dev, "powering up GSM, thus "
13280 + "disconnecting serial console\n");
13282 + console_stop(gta01_gsm.con);
13283 + s3c24xx_serial_console_set_silence(1);
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);
13290 + if (gta01_gsm.gpio_ngsm_en)
13291 + s3c2410_gpio_setpin(gta01_gsm.gpio_ngsm_en, 0);
13293 + if (machine_is_neo1973_gta02())
13294 + pcf50633_gpio_set(gta02_pcf, PCF50633_GPIO2, 7);
13298 + neo1973_gpb_setpin(GTA01_GPIO_MODEM_ON, 1);
13300 + neo1973_gpb_setpin(GTA01_GPIO_MODEM_ON, 0);
13303 + * workaround for calypso firmware moko10 and earlier,
13304 + * without this it will leave IRQ line high after
13307 + s3c2410_gpio_setpin(S3C2410_GPH1, 1);
13308 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_OUTP);
13310 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_nRTS0);
13314 +static ssize_t gsm_write(struct device *dev, struct device_attribute *attr,
13315 + const char *buf, size_t count)
13317 + unsigned long on = simple_strtoul(buf, NULL, 10);
13319 + if (!strcmp(attr->attr.name, "power_on")) {
13320 + gsm_on_off(dev, on);
13325 + if (!strcmp(attr->attr.name, "download")) {
13326 + if (machine_is_neo1973_gta01())
13327 + s3c2410_gpio_setpin(GTA01_GPIO_MODEM_DNLOAD, on);
13329 + if (machine_is_neo1973_gta02()) {
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
13340 + if (gta01_gsm.gpio_ndl_gsm)
13341 + disable_irq(gpio_to_irq(
13342 + GTA02_GPIO_JACK_INSERT));
13344 + if (!gta01_gsm.gpio_ndl_gsm)
13345 + enable_irq(gpio_to_irq(
13346 + GTA02_GPIO_JACK_INSERT));
13349 + gta01_gsm.gpio_ndl_gsm = !on;
13350 + s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, !on);
13356 + if (!strcmp(attr->attr.name, "flowcontrolled")) {
13358 + gta_gsm_interrupts = 0;
13359 + s3c2410_gpio_setpin(S3C2410_GPH1, 1);
13360 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_OUTP);
13362 + s3c2410_gpio_cfgpin(S3C2410_GPH1, S3C2410_GPH1_nRTS0);
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);
13375 +static int gta01_gsm_resume(struct platform_device *pdev);
13376 +static int gta01_gsm_suspend(struct platform_device *pdev, pm_message_t state)
13378 + /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we
13379 + * don't need to do much here. */
13381 + /* If flowcontrol asserted, abort if GSM already interrupted */
13382 + if (s3c2410_gpio_getcfg(S3C2410_GPH1) == S3C2410_GPIO_OUTPUT) {
13383 + if (gta_gsm_interrupts)
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);
13397 +gta01_gsm_suspend_late(struct platform_device *pdev, pm_message_t state)
13399 + /* Last chance: abort if GSM already interrupted */
13400 + if (s3c2410_gpio_getcfg(S3C2410_GPH1) == S3C2410_GPIO_OUTPUT) {
13401 + if (gta_gsm_interrupts)
13407 +static int gta01_gsm_resume(struct platform_device *pdev)
13409 + /* GPIO state is saved/restored by S3C2410 core GPIO driver, so we
13410 + * don't need to do much here. */
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);
13417 + if (machine_is_neo1973_gta02())
13418 + s3c2410_gpio_setpin(GTA02_GPIO_nDL_GSM, gta01_gsm.gpio_ndl_gsm);
13423 +#define gta01_gsm_suspend NULL
13424 +#define gta01_gsm_suspend_late NULL
13425 +#define gta01_gsm_resume NULL
13426 +#endif /* CONFIG_PM */
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,
13436 +static struct attribute_group gta01_gsm_attr_group = {
13438 + .attrs = gta01_gsm_sysfs_entries,
13441 +static int __init gta01_gsm_probe(struct platform_device *pdev)
13443 + switch (S3C_SYSTEM_REV_ATAG) {
13444 + case GTA01v3_SYSTEM_REV:
13445 + gta01_gsm.gpio_ngsm_en = GTA01v3_GPIO_nGSM_EN;
13447 + case GTA01v4_SYSTEM_REV:
13448 + gta01_gsm.gpio_ngsm_en = 0;
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);
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;
13465 + dev_warn(&pdev->dev, "Unknown Neo1973 Revision 0x%x, "
13466 + "some PM features not available!!!\n",
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;
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");
13487 + gta01_gsm.con = NULL;
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);
13494 + /* GSM is to be initially off (at boot, or if this module inserted) */
13495 + gsm_on_off(&pdev->dev, 0);
13497 + return sysfs_create_group(&pdev->dev.kobj, >a01_gsm_attr_group);
13500 +static int gta01_gsm_remove(struct platform_device *pdev)
13502 + sysfs_remove_group(&pdev->dev.kobj, >a01_gsm_attr_group);
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,
13514 + .name = "neo1973-pm-gsm",
13518 +static int __devinit gta01_gsm_init(void)
13520 + return platform_driver_register(>a01_gsm_driver);
13523 +static void gta01_gsm_exit(void)
13525 + platform_driver_unregister(>a01_gsm_driver);
13528 +module_init(gta01_gsm_init);
13529 +module_exit(gta01_gsm_exit);
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
13539 + * include/asm-arm/plat-s3c24xx/neo1973.h
13541 + * Common utility code for GTA01 and GTA02
13543 + * Copyright (C) 2008 by Openmoko, Inc.
13544 + * Author: Holger Hans Peter Freyther <freyther@openmoko.org>
13545 + * All rights reserved.
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.
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.
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
13564 +#include <linux/module.h>
13565 +#include <linux/io.h>
13566 +#include <linux/irq.h>
13568 +#include <asm/gpio.h>
13569 +#include <mach/regs-gpio.h>
13570 +#include <asm/plat-s3c24xx/neo1973.h>
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
13576 +static unsigned long gpb_mask;
13577 +static unsigned long gpb_state;
13579 +void neo1973_gpb_add_shadow_gpio(unsigned int gpio)
13581 + unsigned long offset = S3C2410_GPIO_OFFSET(gpio);
13582 + unsigned long flags;
13584 + local_irq_save(flags);
13585 + gpb_mask |= 1L << offset;
13586 + local_irq_restore(flags);
13588 +EXPORT_SYMBOL(neo1973_gpb_add_shadow_gpio);
13590 +static void set_shadow_gpio(unsigned long offset, unsigned int value)
13592 + unsigned long state = value != 0;
13594 + gpb_state &= ~(1L << offset);
13595 + gpb_state |= state << offset;
13598 +void neo1973_gpb_setpin(unsigned int pin, unsigned to)
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;
13605 + BUG_ON(base != S3C24XX_GPIO_BASE(pin));
13607 + local_irq_save(flags);
13608 + dat = __raw_readl(base + 0x04);
13610 + /* Add the shadow values */
13611 + dat &= ~gpb_mask;
13612 + dat |= gpb_state;
13614 + /* Do the operation like s3c2410_gpio_setpin */
13615 + dat &= ~(1L << offset);
13616 + dat |= to << offset;
13618 + /* Update the shadow state */
13619 + if ((1L << offset) & gpb_mask)
13620 + set_shadow_gpio(offset, to);
13622 + __raw_writel(dat, base + 0x04);
13623 + local_irq_restore(flags);
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>
13638 -#include <asm/cacheflush.h>
13639 -#include <mach/hardware.h>
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>
13648 #include <asm/mach/time.h>
13650 #include <plat/pm.h>
13652 -/* for external use */
13654 -unsigned long s3c_pm_flags;
13656 #define PFX "s3c24xx-pm: "
13658 static struct sleep_save core_save[] = {
13659 @@ -84,364 +76,17 @@
13660 SAVE_ITEM(S3C2410_CLKSLOW),
13663 -static struct gpio_sleep {
13664 - void __iomem *base;
13665 - unsigned int gpcon;
13666 - unsigned int gpdat;
13667 - unsigned int gpup;
13670 - .base = S3C2410_GPACON,
13673 - .base = S3C2410_GPBCON,
13676 - .base = S3C2410_GPCCON,
13679 - .base = S3C2410_GPDCON,
13682 - .base = S3C2410_GPECON,
13685 - .base = S3C2410_GPFCON,
13688 - .base = S3C2410_GPGCON,
13691 - .base = S3C2410_GPHCON,
13695 static struct sleep_save misc_save[] = {
13696 SAVE_ITEM(S3C2410_DCLKCON),
13699 -#ifdef CONFIG_S3C2410_PM_DEBUG
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)
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),
13718 - * we send the debug to printascii() to allow it to be seen if the
13719 - * system never wakes up from the sleep
13722 -extern void printascii(const char *);
13724 -void pm_dbg(const char *fmt, ...)
13729 - va_start(va, fmt);
13730 - vsprintf(buff, fmt, va);
13733 - printascii(buff);
13736 -static void s3c2410_pm_debug_init(void)
13738 - unsigned long tmp = __raw_readl(S3C2410_CLKCON);
13740 - /* re-start uart clocks */
13741 - tmp |= S3C2410_CLKCON_UART0;
13742 - tmp |= S3C2410_CLKCON_UART1;
13743 - tmp |= S3C2410_CLKCON_UART2;
13745 - __raw_writel(tmp, S3C2410_CLKCON);
13749 -#define DBG(fmt...) pm_dbg(fmt)
13751 -#define DBG(fmt...) printk(KERN_DEBUG fmt)
13753 -#define s3c2410_pm_debug_init() do { } while(0)
13755 -static struct sleep_save uart_save[] = {};
13758 -#if defined(CONFIG_S3C2410_PM_CHECK) && CONFIG_S3C2410_PM_CHECK_CHUNKSIZE != 0
13760 -/* suspend checking code...
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.
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
13770 -#define CHECK_CHUNKSIZE (CONFIG_S3C2410_PM_CHECK_CHUNKSIZE * 1024)
13772 -static u32 crc_size; /* size needed for the crc block */
13773 -static u32 *crcs; /* allocated over suspend/resume */
13775 -typedef u32 *(run_fn_t)(struct resource *ptr, u32 *arg);
13777 -/* s3c2410_pm_run_res
13779 - * go thorugh the given resource list, and look for system ram
13782 -static void s3c2410_pm_run_res(struct resource *ptr, run_fn_t fn, u32 *arg)
13784 - while (ptr != NULL) {
13785 - if (ptr->child != NULL)
13786 - s3c2410_pm_run_res(ptr->child, fn, arg);
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);
13795 - ptr = ptr->sibling;
13799 -static void s3c2410_pm_run_sysram(run_fn_t fn, u32 *arg)
13801 - s3c2410_pm_run_res(&iomem_resource, fn, arg);
13804 -static u32 *s3c2410_pm_countram(struct resource *res, u32 *val)
13806 - u32 size = (u32)(res->end - res->start)+1;
13808 - size += CHECK_CHUNKSIZE-1;
13809 - size /= CHECK_CHUNKSIZE;
13811 - DBG("Area %08lx..%08lx, %d blocks\n", res->start, res->end, size);
13813 - *val += size * sizeof(u32);
13817 -/* s3c2410_pm_prepare_check
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
13825 -static void s3c2410_pm_check_prepare(void)
13829 - s3c2410_pm_run_sysram(s3c2410_pm_countram, &crc_size);
13831 - DBG("s3c2410_pm_prepare_check: %u checks needed\n", crc_size);
13833 - crcs = kmalloc(crc_size+4, GFP_KERNEL);
13834 - if (crcs == NULL)
13835 - printk(KERN_ERR "Cannot allocated CRC save area\n");
13838 -static u32 *s3c2410_pm_makecheck(struct resource *res, u32 *val)
13840 - unsigned long addr, left;
13842 - for (addr = res->start; addr < res->end;
13843 - addr += CHECK_CHUNKSIZE) {
13844 - left = res->end - addr;
13846 - if (left > CHECK_CHUNKSIZE)
13847 - left = CHECK_CHUNKSIZE;
13849 - *val = crc32_le(~0, phys_to_virt(addr), left);
13856 -/* s3c2410_pm_check_store
13858 - * compute the CRC values for the memory blocks before the final
13862 -static void s3c2410_pm_check_store(void)
13864 - if (crcs != NULL)
13865 - s3c2410_pm_run_sysram(s3c2410_pm_makecheck, crcs);
13870 - * return TRUE if the area defined by ptr..ptr+size contatins the
13871 - * what..what+whatsz
13874 -static inline int in_region(void *ptr, int size, void *what, size_t whatsz)
13876 - if ((what+whatsz) < ptr)
13879 - if (what > (ptr+size))
13885 -static u32 *s3c2410_pm_runcheck(struct resource *res, u32 *val)
13887 - void *save_at = phys_to_virt(s3c2410_sleep_save_phys);
13888 - unsigned long addr;
13889 - unsigned long left;
13893 - for (addr = res->start; addr < res->end;
13894 - addr += CHECK_CHUNKSIZE) {
13895 - left = res->end - addr;
13897 - if (left > CHECK_CHUNKSIZE)
13898 - left = CHECK_CHUNKSIZE;
13900 - ptr = phys_to_virt(addr);
13902 - if (in_region(ptr, left, crcs, crc_size)) {
13903 - DBG("skipping %08lx, has crc block in\n", addr);
13907 - if (in_region(ptr, left, save_at, 32*4 )) {
13908 - DBG("skipping %08lx, has save block in\n", addr);
13912 - /* calculate and check the checksum */
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);
13919 - DBG("Restore CRC error at %08lx (%08x vs %08x)\n",
13920 - addr, calc, *val);
13930 -/* s3c2410_pm_check_restore
13932 - * check the CRCs after the restore event and free the memory used
13936 -static void s3c2410_pm_check_restore(void)
13938 - if (crcs != NULL) {
13939 - s3c2410_pm_run_sysram(s3c2410_pm_runcheck, crcs);
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)
13952 -/* helper functions to save and restore register state */
13954 -void s3c2410_pm_do_save(struct sleep_save *ptr, int count)
13956 - for (; count > 0; count--, ptr++) {
13957 - ptr->val = __raw_readl(ptr->reg);
13958 - DBG("saved %p value %08lx\n", ptr->reg, ptr->val);
13962 -/* s3c2410_pm_do_restore
13964 - * restore the system from the given list of saved registers
13966 - * Note, we do not use DBG() in here, as the system may not have
13967 - * restore the UARTs state yet
13970 -void s3c2410_pm_do_restore(struct sleep_save *ptr, int count)
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));
13976 - __raw_writel(ptr->val, ptr->reg);
13980 -/* s3c2410_pm_do_restore_core
13982 - * similar to s3c2410_pm_do_restore_core
13984 - * WARNING: Do not put any debug in here that may effect memory or use
13985 - * peripherals, as things may be changing!
13988 -static void s3c2410_pm_do_restore_core(struct sleep_save *ptr, int count)
13990 - for (; count > 0; count--, ptr++) {
13991 - __raw_writel(ptr->val, ptr->reg);
13995 -/* s3c2410_pm_show_resume_irqs
13997 - * print any IRQs asserted at resume time (ie, we woke from)
14000 -static void s3c2410_pm_show_resume_irqs(int start, unsigned long which,
14001 - unsigned long mask)
14007 - for (i = 0; i <= 31; i++) {
14008 - if ((which) & (1L<<i)) {
14009 - DBG("IRQ %d asserted at resume\n", start+i);
14014 -/* s3c2410_pm_check_resume_pin
14015 +/* s3c_pm_check_resume_pin
14017 * check to see if the pin is configured correctly for sleep mode, and
14018 * make any necessary adjustments if it is not
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)
14024 unsigned long irqstate;
14025 unsigned long pinstate;
14026 @@ -456,21 +101,21 @@
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);
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);
14041 -/* s3c2410_pm_configure_extint
14042 +/* s3c_pm_configure_extint
14044 * configure all external interrupt pins
14047 -static void s3c2410_pm_configure_extint(void)
14048 +void s3c_pm_configure_extint(void)
14052 @@ -480,336 +125,24 @@
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);
14060 for (pin = S3C2410_GPG0; pin <= S3C2410_GPG7; pin++) {
14061 - s3c2410_pm_check_resume_pin(pin, (pin - S3C2410_GPG0)+8);
14065 -/* offsets for CON/DAT/UP registers */
14067 -#define OFFS_CON (S3C2410_GPACON - S3C2410_GPACON)
14068 -#define OFFS_DAT (S3C2410_GPADAT - S3C2410_GPACON)
14069 -#define OFFS_UP (S3C2410_GPBUP - S3C2410_GPBCON)
14071 -/* s3c2410_pm_save_gpios()
14073 - * Save the state of the GPIOs
14076 -static void s3c2410_pm_save_gpios(void)
14078 - struct gpio_sleep *gps = gpio_save;
14079 - unsigned int gpio;
14081 - for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
14082 - void __iomem *base = gps->base;
14084 - gps->gpcon = __raw_readl(base + OFFS_CON);
14085 - gps->gpdat = __raw_readl(base + OFFS_DAT);
14088 - gps->gpup = __raw_readl(base + OFFS_UP);
14093 -/* Test whether the given masked+shifted bits of an GPIO configuration
14094 - * are one of the SFN (special function) modes. */
14096 -static inline int is_sfn(unsigned long con)
14098 - return (con == 2 || con == 3);
14101 -/* Test if the given masked+shifted GPIO configuration is an input */
14103 -static inline int is_in(unsigned long con)
14108 -/* Test if the given masked+shifted GPIO configuration is an output */
14110 -static inline int is_out(unsigned long con)
14115 -/* s3c2410_pm_restore_gpio()
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.
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
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]
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.
14137 - * [1] this assumes that writing to a pin DAT whilst in SFN will set the
14138 - * state for when it is next output.
14141 -static void s3c2410_pm_restore_gpio(int index, struct gpio_sleep *gps)
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;
14152 - old_gpcon = __raw_readl(base + OFFS_CON);
14153 - old_gpdat = __raw_readl(base + OFFS_DAT);
14155 - if (base == S3C2410_GPACON) {
14156 - /* GPACON only has one bit per control / data and no PULLUPs.
14157 - * GPACON[x] = 0 => Output, 1 => SFN */
14159 - /* first set all SFN bits to SFN */
14161 - gpcon = old_gpcon | gps->gpcon;
14162 - __raw_writel(gpcon, base + OFFS_CON);
14164 - /* now set all the other bits */
14166 - __raw_writel(gps_gpdat, base + OFFS_DAT);
14167 - __raw_writel(gps_gpcon, base + OFFS_CON);
14169 - unsigned long old, new, mask;
14170 - unsigned long change_mask = 0x0;
14172 - old_gpup = __raw_readl(base + OFFS_UP);
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.
14179 - for (nr = 0, mask = 0x03; nr < 32; nr += 2, mask <<= 2) {
14180 - old = (old_gpcon & mask) >> nr;
14181 - new = (gps_gpcon & mask) >> nr;
14183 - /* If there is no change, then skip */
14188 - /* If both are special function, then skip */
14190 - if (is_sfn(old) && is_sfn(new))
14193 - /* Change is IN => OUT, do not change now */
14195 - if (is_in(old) && is_out(new))
14198 - /* Change is SFN => OUT, do not change now */
14200 - if (is_sfn(old) && is_out(new))
14203 - /* We should now be at the case of IN=>SFN,
14204 - * OUT=>SFN, OUT=>IN, SFN=>IN. */
14206 - change_mask |= mask;
14209 - /* Write the new CON settings */
14211 - gpcon = old_gpcon & ~change_mask;
14212 - gpcon |= gps_gpcon & change_mask;
14214 - __raw_writel(gpcon, base + OFFS_CON);
14216 - /* Now change any items that require DAT,CON */
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);
14224 - DBG("GPIO[%d] CON %08lx => %08lx, DAT %08lx => %08lx\n",
14225 - index, old_gpcon, gps_gpcon, old_gpdat, gps_gpdat);
14229 -/** s3c2410_pm_restore_gpios()
14231 - * Restore the state of the GPIOs
14234 -static void s3c2410_pm_restore_gpios(void)
14235 +void s3c_pm_restore_core(void)
14237 - struct gpio_sleep *gps = gpio_save;
14240 - for (gpio = 0; gpio < ARRAY_SIZE(gpio_save); gpio++, gps++) {
14241 - s3c2410_pm_restore_gpio(gpio, gps);
14243 + s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
14244 + s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
14247 -void (*pm_cpu_prep)(void);
14248 -void (*pm_cpu_sleep)(void);
14250 -#define any_allowed(mask, allow) (((mask) & (allow)) != (allow))
14252 -/* s3c2410_pm_enter
14254 - * central control for sleep/resume process
14257 -static int s3c2410_pm_enter(suspend_state_t state)
14258 +void s3c_pm_save_core(void)
14260 - unsigned long regs_save[16];
14262 - /* ensure the debug is initialised (if enabled) */
14264 - s3c2410_pm_debug_init();
14266 - DBG("s3c2410_pm_enter(%d)\n", state);
14268 - if (pm_cpu_prep == NULL || pm_cpu_sleep == NULL) {
14269 - printk(KERN_ERR PFX "error: no cpu sleep functions set\n");
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)
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");
14285 - /* prepare check area if configured */
14287 - s3c2410_pm_check_prepare();
14289 - /* store the physical address of the register recovery block */
14291 - s3c2410_sleep_save_phys = virt_to_phys(regs_save);
14293 - DBG("s3c2410_sleep_save_phys=0x%08lx\n", s3c2410_sleep_save_phys);
14295 - /* save all necessary core registers not covered by the drivers */
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));
14302 - /* set the irq configuration for wake */
14304 - s3c2410_pm_configure_extint();
14306 - DBG("sleep: irq wakeup masks: %08lx,%08lx\n",
14307 - s3c_irqwake_intmask, s3c_irqwake_eintmask);
14309 - __raw_writel(s3c_irqwake_intmask, S3C2410_INTMSK);
14310 - __raw_writel(s3c_irqwake_eintmask, S3C2410_EINTMASK);
14312 - /* ack any outstanding external interrupts before we go to sleep */
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);
14318 - /* call cpu specific preparation */
14322 - /* flush cache back to ram */
14324 - flush_cache_all();
14326 - s3c2410_pm_check_store();
14328 - /* send the cpu to sleep... */
14330 - __raw_writel(0x00, S3C2410_CLKCON); /* turn off clocks over sleep */
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 */
14336 - if (s3c2410_cpu_save(regs_save) == 0) {
14337 - flush_cache_all();
14341 - /* restore the cpu state */
14345 - /* restore the system state */
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();
14352 - s3c2410_pm_debug_init();
14354 - /* check what irq (if any) restored the system */
14356 - DBG("post sleep: IRQs 0x%08x, 0x%08x\n",
14357 - __raw_readl(S3C2410_SRCPND),
14358 - __raw_readl(S3C2410_EINTPEND));
14360 - s3c2410_pm_show_resume_irqs(IRQ_EINT0, __raw_readl(S3C2410_SRCPND),
14361 - s3c_irqwake_intmask);
14363 - s3c2410_pm_show_resume_irqs(IRQ_EINT4-4, __raw_readl(S3C2410_EINTPEND),
14364 - s3c_irqwake_eintmask);
14366 - DBG("post sleep, preparing to return\n");
14368 - s3c2410_pm_check_restore();
14370 - /* ok, let's return from sleep */
14372 - DBG("S3C2410 PM Resume (post-restore)\n");
14374 + s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
14375 + s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
14378 -static struct platform_suspend_ops s3c2410_pm_ops = {
14379 - .enter = s3c2410_pm_enter,
14380 - .valid = suspend_valid_only_mem,
14383 -/* s3c2410_pm_init
14385 - * Attach the power management functions. This should be called
14386 - * from the board specific initialisation if the board supports
14390 -int __init s3c2410_pm_init(void)
14392 - printk("S3C2410 Power Management, (c) 2004 Simtec Electronics\n");
14394 - suspend_set_ops(&s3c2410_pm_ops);
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
14402 __raw_writel(gstatus4, S3C2410_GSTATUS4);
14404 - return s3c2410_pm_init();
14405 + return s3c_pm_init();
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
14413 +/* linux/arch/arm/plat-s3c24xx/pwm-clock.c
14415 + * Copyright (c) 2007 Simtec Electronics
14416 + * Copyright (c) 2007, 2008 Ben Dooks
14417 + * Ben Dooks <ben-linux@fluff.org>
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.
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>
14433 +#include <mach/hardware.h>
14434 +#include <asm/irq.h>
14436 +#include <mach/regs-clock.h>
14437 +#include <mach/regs-gpio.h>
14439 +#include <asm/plat-s3c24xx/clock.h>
14440 +#include <asm/plat-s3c24xx/cpu.h>
14442 +#include <asm/plat-s3c/regs-timer.h>
14444 +/* Each of the timers 0 through 5 go through the following
14445 + * clock tree, with the inputs depending on the timers.
14447 + * pclk ---- [ prescaler 0 ] -+---> timer 0
14450 + * pclk ---- [ prescaler 1 ] -+---> timer 2
14454 + * Which are fed into the timers as so:
14456 + * prescaled 0 ---- [ div 2,4,8,16 ] ---\
14457 + * [mux] -> timer 0
14458 + * tclk 0 ------------------------------/
14460 + * prescaled 0 ---- [ div 2,4,8,16 ] ---\
14461 + * [mux] -> timer 1
14462 + * tclk 0 ------------------------------/
14465 + * prescaled 1 ---- [ div 2,4,8,16 ] ---\
14466 + * [mux] -> timer 2
14467 + * tclk 1 ------------------------------/
14469 + * prescaled 1 ---- [ div 2,4,8,16 ] ---\
14470 + * [mux] -> timer 3
14471 + * tclk 1 ------------------------------/
14473 + * prescaled 1 ---- [ div 2,4,8, 16 ] --\
14474 + * [mux] -> timer 4
14475 + * tclk 1 ------------------------------/
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.
14483 + * prescaled clk --> pwm-tdiv ---\
14484 + * [ mux ] --> timer X
14485 + * tclk -------------------------/
14488 +static unsigned long clk_pwm_scaler_getrate(struct clk *clk)
14490 + unsigned long tcfg0 = __raw_readl(S3C2410_TCFG0);
14492 + if (clk->id == 1) {
14493 + tcfg0 &= S3C2410_TCFG_PRESCALER1_MASK;
14494 + tcfg0 >>= S3C2410_TCFG_PRESCALER1_SHIFT;
14496 + tcfg0 &= S3C2410_TCFG_PRESCALER0_MASK;
14499 + return clk_get_rate(clk->parent) / (tcfg0 + 1);
14502 +/* TODO - add set rate calls. */
14504 +static struct clk clk_timer_scaler[] = {
14506 + .name = "pwm-scaler0",
14508 + .get_rate = clk_pwm_scaler_getrate,
14511 + .name = "pwm-scaler1",
14513 + .get_rate = clk_pwm_scaler_getrate,
14517 +static struct clk clk_timer_tclk[] = {
14519 + .name = "pwm-tclk0",
14523 + .name = "pwm-tclk1",
14528 +struct pwm_tdiv_clk {
14530 + unsigned int divisor;
14533 +static inline struct pwm_tdiv_clk *to_tdiv(struct clk *clk)
14535 + return container_of(clk, struct pwm_tdiv_clk, clk);
14538 +static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
14540 + return 1 << (1 + tcfg1);
14543 +static unsigned long clk_pwm_tdiv_get_rate(struct clk *clk)
14545 + unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
14546 + unsigned int divisor;
14548 + tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
14549 + tcfg1 &= S3C2410_TCFG1_MUX_MASK;
14551 + if (tcfg1 == S3C2410_TCFG1_MUX_TCLK)
14552 + divisor = to_tdiv(clk)->divisor;
14554 + divisor = tcfg_to_divisor(tcfg1);
14556 + return clk_get_rate(clk->parent) / divisor;
14559 +static unsigned long clk_pwm_tdiv_round_rate(struct clk *clk,
14560 + unsigned long rate)
14562 + unsigned long parent_rate;
14563 + unsigned long divisor;
14565 + parent_rate = clk_get_rate(clk->parent);
14566 + divisor = parent_rate / rate;
14568 + if (divisor <= 2)
14570 + else if (divisor <= 4)
14572 + else if (divisor <= 8)
14577 + return parent_rate / divisor;
14580 +static unsigned long clk_pwm_tdiv_bits(struct pwm_tdiv_clk *divclk)
14582 + unsigned long bits;
14584 + switch (divclk->divisor) {
14586 + bits = S3C2410_TCFG1_MUX_DIV2;
14589 + bits = S3C2410_TCFG1_MUX_DIV4;
14592 + bits = S3C2410_TCFG1_MUX_DIV8;
14596 + bits = S3C2410_TCFG1_MUX_DIV16;
14603 +static void clk_pwm_tdiv_update(struct pwm_tdiv_clk *divclk)
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);
14610 + local_irq_save(flags);
14612 + tcfg1 = __raw_readl(S3C2410_TCFG1);
14613 + tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
14614 + tcfg1 |= bits << shift;
14615 + __raw_writel(tcfg1, S3C2410_TCFG1);
14617 + local_irq_restore(flags);
14620 +static int clk_pwm_tdiv_set_rate(struct clk *clk, unsigned long rate)
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;
14627 + tcfg1 >>= S3C2410_TCFG1_SHIFT(clk->id);
14628 + tcfg1 &= S3C2410_TCFG1_MUX_MASK;
14630 + rate = clk_round_rate(clk, rate);
14631 + divisor = parent_rate / rate;
14633 + if (divisor > 16)
14636 + divclk->divisor = divisor;
14638 + /* Update the current MUX settings if we are currently
14639 + * selected as the clock source for this clock. */
14641 + if (tcfg1 != S3C2410_TCFG1_MUX_TCLK)
14642 + clk_pwm_tdiv_update(divclk);
14647 +static struct pwm_tdiv_clk clk_timer_tdiv[] = {
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,
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,
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,
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,
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,
14695 +static int __init clk_pwm_tdiv_register(unsigned int id)
14697 + struct pwm_tdiv_clk *divclk = &clk_timer_tdiv[id];
14698 + unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
14700 + tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
14701 + tcfg1 &= S3C2410_TCFG1_MUX_MASK;
14703 + divclk->clk.id = id;
14704 + divclk->divisor = tcfg_to_divisor(tcfg1);
14706 + return s3c24xx_register_clock(&divclk->clk);
14709 +static inline struct clk *s3c24xx_pwmclk_tclk(unsigned int id)
14711 + return (id >= 2) ? &clk_timer_tclk[1] : &clk_timer_tclk[0];
14714 +static inline struct clk *s3c24xx_pwmclk_tdiv(unsigned int id)
14716 + return &clk_timer_tdiv[id].clk;
14719 +static int clk_pwm_tin_set_parent(struct clk *clk, struct clk *parent)
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);
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;
14734 + clk->parent = parent;
14736 + local_irq_save(flags);
14738 + tcfg1 = __raw_readl(S3C2410_TCFG1);
14739 + tcfg1 &= ~(S3C2410_TCFG1_MUX_MASK << shift);
14740 + __raw_writel(tcfg1 | bits, S3C2410_TCFG1);
14742 + local_irq_restore(flags);
14747 +static struct clk clk_tin[] = {
14749 + .name = "pwm-tin",
14751 + .set_parent = clk_pwm_tin_set_parent,
14754 + .name = "pwm-tin",
14756 + .set_parent = clk_pwm_tin_set_parent,
14759 + .name = "pwm-tin",
14761 + .set_parent = clk_pwm_tin_set_parent,
14764 + .name = "pwm-tin",
14766 + .set_parent = clk_pwm_tin_set_parent,
14769 + .name = "pwm-tin",
14771 + .set_parent = clk_pwm_tin_set_parent,
14775 +static __init int clk_pwm_tin_register(struct clk *pwm)
14777 + unsigned long tcfg1 = __raw_readl(S3C2410_TCFG1);
14778 + unsigned int id = pwm->id;
14780 + struct clk *parent;
14783 + ret = s3c24xx_register_clock(pwm);
14787 + tcfg1 >>= S3C2410_TCFG1_SHIFT(id);
14788 + tcfg1 &= S3C2410_TCFG1_MUX_MASK;
14790 + if (tcfg1 == S3C2410_TCFG1_MUX_TCLK)
14791 + parent = s3c24xx_pwmclk_tclk(id);
14793 + parent = s3c24xx_pwmclk_tdiv(id);
14795 + return clk_set_parent(pwm, parent);
14798 +static __init int s3c24xx_pwmclk_init(void)
14800 + struct clk *clk_timers;
14801 + unsigned int clk;
14804 + clk_timers = clk_get(NULL, "timers");
14805 + if (IS_ERR(clk_timers)) {
14806 + printk(KERN_ERR "%s: no parent clock\n", __func__);
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]);
14814 + printk(KERN_ERR "error adding pwm scaler%d clock\n", clk);
14819 + for (clk = 0; clk < ARRAY_SIZE(clk_timer_tclk); clk++) {
14820 + ret = s3c24xx_register_clock(&clk_timer_tclk[clk]);
14822 + printk(KERN_ERR "error adding pww tclk%d\n", clk);
14827 + for (clk = 0; clk < ARRAY_SIZE(clk_timer_tdiv); clk++) {
14828 + ret = clk_pwm_tdiv_register(clk);
14830 + printk(KERN_ERR "error adding pwm%d tdiv clock\n", clk);
14835 + for (clk = 0; clk < ARRAY_SIZE(clk_tin); clk++) {
14836 + ret = clk_pwm_tin_register(&clk_tin[clk]);
14838 + printk(KERN_ERR "error adding pwm%d tin clock\n", clk);
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
14854 s3c24xx_init_uartdevs("s3c2440-uart", s3c2410_uart_resources, cfg, no);
14857 +extern struct platform_device s3c_device_ts;
14859 void __init s3c244x_map_io(void)
14861 /* register our io-tables */
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";
14870 @@ -145,13 +148,13 @@
14872 static int s3c244x_suspend(struct sys_device *dev, pm_message_t state)
14874 - s3c2410_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
14875 + s3c_pm_do_save(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
14879 static int s3c244x_resume(struct sys_device *dev)
14881 - s3c2410_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
14882 + s3c_pm_do_restore(s3c244x_sleep, ARRAY_SIZE(s3c244x_sleep));
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
14893 - /* s3c2410_cpu_save
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
14899 * 1 => resumed from sleep
14902 -ENTRY(s3c2410_cpu_save)
14903 +ENTRY(s3c_cpu_save)
14904 stmfd sp!, { r4 - r12, lr }
14906 @@ store co-processor registers
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 @@
14920 - .global s3c2410_sleep_save_phys
14921 -s3c2410_sleep_save_phys:
14922 + .global s3c_sleep_save_phys
14923 +s3c_sleep_save_phys:
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.
14935 - /* s3c2410_cpu_resume
14936 + /* s3c_cpu_resume
14938 * resume code entry for bootloader to call
14940 @@ -113,7 +113,7 @@
14941 * must not write to the code segment (code is read-only)
14944 -ENTRY(s3c2410_cpu_resume)
14945 +ENTRY(s3c_cpu_resume)
14946 mov r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
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
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 }
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
14962 +/* linux/arch/arm/plat-s3c24xx/time.c
14964 + * Copyright (C) 2003-2005 Simtec Electronics
14965 + * Ben Dooks, <ben@simtec.co.uk>
14967 + * dyn_tick support by Andrzej Zaborowski based on omap_dyn_tick_timer.
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.
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.
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
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>
14992 +#include <asm/system.h>
14993 +#include <asm/leds.h>
14994 +#include <asm/mach-types.h>
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>
15003 +#include <asm/plat-s3c24xx/clock.h>
15004 +#include <asm/plat-s3c24xx/cpu.h>
15006 +static unsigned long timer_startval;
15007 +static unsigned long timer_usec_ticks;
15008 +static struct work_struct resume_work;
15010 +unsigned long pclk;
15013 +#define TIMER_USEC_SHIFT 16
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
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.
15022 + * Original patch by Dimitry Andric, updated by Ben Dooks
15026 +/* timer_mask_usec_ticks
15028 + * given a clock and divisor, make the value to pass into timer_ticks_to_usec
15029 + * to scale the ticks into usecs
15032 +static inline unsigned long
15033 +timer_mask_usec_ticks(unsigned long scaler, unsigned long pclk)
15035 + unsigned long den = pclk / 1000;
15037 + return ((1000 << TIMER_USEC_SHIFT) * scaler + (den >> 1)) / den;
15040 +/* timer_ticks_to_usec
15042 + * convert timer ticks to usec.
15045 +static inline unsigned long timer_ticks_to_usec(unsigned long ticks)
15047 + unsigned long res;
15049 + res = ticks * timer_usec_ticks;
15050 + res += 1 << (TIMER_USEC_SHIFT - 4); /* round up slightly */
15052 + return res >> TIMER_USEC_SHIFT;
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()
15061 +#define SRCPND_TIMER4 (1<<(IRQ_TIMER4 - IRQ_EINT0))
15063 +unsigned long s3c2410_gettimeoffset (void)
15065 + unsigned long tdone;
15066 + unsigned long irqpend;
15067 + unsigned long tval;
15069 + /* work out how many ticks have gone since last timer interrupt */
15071 + tval = __raw_readl(S3C2410_TCNTO(4));
15072 + tdone = timer_startval - tval;
15074 + /* check to see if there is an interrupt pending */
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.
15083 + tval = __raw_readl(S3C2410_TCNTO(4));
15084 + tdone = timer_startval - tval;
15087 + tdone += timer_startval;
15090 + return timer_ticks_to_usec(tdone);
15095 + * IRQ handler for the timer
15097 +static irqreturn_t
15098 +s3c2410_timer_interrupt(int irq, void *dev_id)
15101 + return IRQ_HANDLED;
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,
15110 +#define use_tclk1_12() ( \
15111 + machine_is_bast() || \
15112 + machine_is_vr1000() || \
15113 + machine_is_anubis() || \
15114 + machine_is_osiris() )
15117 + * Set up timer interrupt, and return the current time in seconds.
15119 + * Currently we only use timer4, as it is the only timer which has no
15120 + * other function that can be exploited externally
15122 +static void s3c2410_timer_setup (void)
15124 + unsigned long tcon;
15125 + unsigned long tcnt;
15126 + unsigned long tcfg1;
15127 + unsigned long tcfg0;
15129 + tcnt = 0xffff; /* default value for tcnt */
15131 + /* read the current timer configuration bits */
15133 + tcon = __raw_readl(S3C2410_TCON);
15134 + tcfg1 = __raw_readl(S3C2410_TCFG1);
15135 + tcfg0 = __raw_readl(S3C2410_TCFG0);
15137 + /* configure the system for whichever machine is in use */
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;
15144 + tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
15145 + tcfg1 |= S3C2410_TCFG1_MUX4_TCLK1;
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.
15151 + * for instance, using 50.7MHz and dividing by 6 gives 8.45MHz
15152 + * (8.45 ticks per usec)
15155 + /* configure clock tick */
15156 + timer_usec_ticks = timer_mask_usec_ticks(6, pclk);
15157 + printk("timer_usec_ticks = %lu\n", timer_usec_ticks);
15159 + tcfg1 &= ~S3C2410_TCFG1_MUX4_MASK;
15160 + tcfg1 |= S3C2410_TCFG1_MUX4_DIV2;
15162 + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
15163 + tcfg0 |= ((6 - 1) / 2) << S3C2410_TCFG_PRESCALER1_SHIFT;
15165 + tcnt = (pclk / 6) / HZ;
15168 + /* timers reload after counting zero, so reduce the count by 1 */
15172 + printk("timer tcon=%08lx, tcnt %04lx, tcfg %08lx,%08lx, usec %08lx\n",
15173 + tcon, tcnt, tcfg0, tcfg1, timer_usec_ticks);
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!");
15181 + __raw_writel(tcfg1, S3C2410_TCFG1);
15182 + __raw_writel(tcfg0, S3C2410_TCFG0);
15184 + timer_startval = tcnt;
15185 + __raw_writel(tcnt, S3C2410_TCNTB(4));
15187 + /* ensure timer is stopped... */
15189 + tcon &= ~(7<<20);
15190 + tcon |= S3C2410_TCON_T4RELOAD;
15191 + tcon |= S3C2410_TCON_T4MANUALUPD;
15193 + __raw_writel(tcon, S3C2410_TCON);
15194 + __raw_writel(tcnt, S3C2410_TCNTB(4));
15195 + __raw_writel(tcnt, S3C2410_TCMPB(4));
15197 + /* start the timer running */
15198 + tcon |= S3C2410_TCON_T4START;
15199 + tcon &= ~S3C2410_TCON_T4MANUALUPD;
15200 + __raw_writel(tcon, S3C2410_TCON);
15202 + __raw_writel(__raw_readl(S3C2410_INTMSK) & (~(1UL << 14)),
15207 +struct sys_timer s3c24xx_timer;
15208 +static void timer_resume_work(struct work_struct *work)
15212 +#ifdef CONFIG_NO_IDLE_HZ
15213 + if (s3c24xx_timer.dyn_tick->state & DYN_TICK_ENABLED)
15214 + s3c24xx_timer.dyn_tick->enable();
15217 + s3c2410_timer_setup();
15220 +static void __init s3c2410_timer_init (void)
15222 + if (!use_tclk1_12()) {
15223 + /* for the h1940 (and others), we use the pclk from the core
15224 + * to generate the timer values.
15227 + /* this is used as default if no other timer can be found */
15228 + clk = clk_get(NULL, "timers");
15230 + panic("failed to get clock for system timer");
15234 + pclk = clk_get_rate(clk);
15235 + printk("pclk = %lu\n", pclk);
15238 + INIT_WORK(&resume_work, timer_resume_work);
15239 + s3c2410_timer_setup();
15240 + setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
15243 +static void s3c2410_timer_resume_work(struct work_struct *work)
15245 + s3c2410_timer_setup();
15248 +static void s3c2410_timer_resume(void)
15250 + static DECLARE_WORK(work, s3c2410_timer_resume_work);
15253 + res = schedule_work(&work);
15256 + "s3c2410_timer_resume_work already queued ???\n");
15259 +#ifdef CONFIG_NO_IDLE_HZ
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.
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.
15267 +#define INPUT_FREQ_SHIFT 9
15269 +static int ticks_last;
15270 +static int ticks_left;
15271 +static uint32_t tcnto_last;
15273 +static inline int s3c24xx_timer_read(void)
15275 + uint32_t tcnto = __raw_readl(S3C2410_TCNTO(4));
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
15283 + if (unlikely(tcnto == tcnto_last))
15284 + return ticks_last;
15288 + ((__raw_readl(S3C2410_TCFG1) >> S3C2410_TCFG1_MUX4_SHIFT) & 3);
15291 +static inline void s3c24xx_timer_program(int ticks)
15293 + uint32_t tcon = __raw_readl(S3C2410_TCON) & ~(7 << 20);
15294 + uint32_t tcfg1 = __raw_readl(S3C2410_TCFG1) & ~S3C2410_TCFG1_MUX4_MASK;
15296 + /* Just make sure the timer is stopped. */
15297 + __raw_writel(tcon, S3C2410_TCON);
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;
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;
15313 + __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV4, S3C2410_TCFG1);
15314 + __raw_writel(ticks_last >> 1, S3C2410_TCNTB(4));
15316 + ticks_last = ticks;
15318 + __raw_writel(tcfg1 | S3C2410_TCFG1_MUX4_DIV2, S3C2410_TCFG1);
15319 + __raw_writel(ticks_last >> 0, S3C2410_TCNTB(4));
15322 + tcnto_last = __raw_readl(S3C2410_TCNTO(4));
15323 + __raw_writel(tcon | S3C2410_TCON_T4MANUALUPD,
15325 + __raw_writel(tcon | S3C2410_TCON_T4START,
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.
15334 +static inline void s3c24xx_timer_program_idle(void)
15336 + s3c24xx_timer_program(0xffff << 3);
15339 +static inline void s3c24xx_timer_update(int restart)
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);
15346 + if (ticks_left >= (1 << INPUT_FREQ_SHIFT))
15347 + s3c24xx_timer_program(ticks_left);
15349 + s3c24xx_timer_program_idle();
15350 + ticks_last += subjiffy;
15352 + ticks_last = subjiffy;
15354 + while (jiffies_elapsed --)
15358 +/* Called when the timer expires. */
15359 +static irqreturn_t s3c24xx_timer_handler(int irq, void *dev_id)
15362 + s3c24xx_timer_update(1);
15364 + return IRQ_HANDLED;
15367 +/* Called to update jiffies with time elapsed. */
15368 +static irqreturn_t s3c24xx_timer_handler_dyn_tick(int irq, void *dev_id)
15370 + s3c24xx_timer_update(0);
15372 + return IRQ_HANDLED;
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.
15380 +static void s3c24xx_timer_reprogram_dyn_tick(unsigned long next_jiffies)
15382 + int subjiffy_left = ticks_last - s3c24xx_timer_read();
15384 + s3c24xx_timer_program(max((int) next_jiffies, 1) << INPUT_FREQ_SHIFT);
15385 + ticks_last += subjiffy_left;
15388 +static unsigned long s3c24xx_timer_offset_dyn_tick(void)
15394 +static int s3c24xx_timer_enable_dyn_tick(void)
15396 + /* Set our constant prescaler. */
15397 + uint32_t tcfg0 = __raw_readl(S3C2410_TCFG0);
15399 + max(min(256, (int) pclk / (HZ << (INPUT_FREQ_SHIFT + 1))), 1);
15401 + tcfg0 &= ~S3C2410_TCFG_PRESCALER1_MASK;
15402 + tcfg0 |= (prescaler - 1) << S3C2410_TCFG_PRESCALER1_SHIFT;
15403 + __raw_writel(tcfg0, S3C2410_TCFG0);
15405 + /* Override handlers. */
15406 + s3c2410_timer_irq.handler = s3c24xx_timer_handler;
15407 + s3c24xx_timer.offset = s3c24xx_timer_offset_dyn_tick;
15409 + printk(KERN_INFO "dyn_tick enabled on s3c24xx timer 4, "
15410 + "%li Hz pclk with prescaler %i\n", pclk, prescaler);
15412 + s3c24xx_timer_program_idle();
15417 +static int s3c24xx_timer_disable_dyn_tick(void)
15419 + s3c2410_timer_irq.handler = s3c2410_timer_interrupt;
15420 + s3c24xx_timer.offset = s3c2410_gettimeoffset;
15421 + s3c2410_timer_setup();
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,
15432 +#endif /* CONFIG_NO_IDLE_HZ */
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,
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
15446 #include <plat/devs.h>
15447 #include <plat/clock.h>
15449 +struct clk clk_h2 = {
15455 struct clk clk_27m = {
15459 return s3c64xx_gate(S3C_PCLK_GATE, clk, enable);
15462 -static int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
15463 +int s3c64xx_hclk_ctrl(struct clk *clk, int enable)
15465 return s3c64xx_gate(S3C_HCLK_GATE, clk, enable);
15467 @@ -152,6 +158,30 @@
15468 .parent = &clk_48m,
15469 .enable = s3c64xx_sclk_ctrl,
15470 .ctrlbit = S3C_CLKCON_SCLK_MMC2_48,
15474 + .parent = &clk_h,
15475 + .enable = s3c64xx_hclk_ctrl,
15476 + .ctrlbit = S3C_CLKCON_HCLK_DMA0,
15480 + .parent = &clk_h,
15481 + .enable = s3c64xx_hclk_ctrl,
15482 + .ctrlbit = S3C_CLKCON_HCLK_DMA1,
15486 + .parent = &clk_h,
15487 + .enable = s3c64xx_hclk_ctrl,
15488 + .ctrlbit = S3C_CLKCON_HCLK_SDMA0,
15492 + .parent = &clk_h,
15493 + .enable = s3c64xx_hclk_ctrl,
15494 + .ctrlbit = S3C_CLKCON_HCLK_SDMA1,
15498 @@ -246,6 +276,7 @@
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
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>
15518 .pfn = __phys_to_pfn(S3C64XX_PA_GPIO),
15523 + .virtual = (unsigned long)S3C64XX_VA_MODEM,
15524 + .pfn = __phys_to_pfn(S3C64XX_PA_MODEM),
15526 + .type = MT_DEVICE,
15528 + .virtual = (unsigned long)S3C_VA_TZIC0,
15529 + .pfn = __phys_to_pfn(S3C64XX_PA_TZIC0),
15531 + .type = MT_DEVICE,
15533 + .virtual = (unsigned long)S3C_VA_TZIC1,
15534 + .pfn = __phys_to_pfn(S3C64XX_PA_TZIC1),
15536 + .type = MT_DEVICE,
15541 +struct sysdev_class s3c64xx_sysclass = {
15542 + .name = "s3c64xx-core",
15545 +static struct sys_device s3c64xx_sysdev = {
15546 + .cls = &s3c64xx_sysclass,
15550 /* read cpu identification code */
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));
15558 +static __init int s3c64xx_sysdev_init(void)
15560 + sysdev_class_register(&s3c64xx_sysclass);
15561 + return sysdev_register(&s3c64xx_sysdev);
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
15569 +/* linux/arch/arm/plat-s3c64xx/cpufreq.c
15571 + * Copyright 2009 Wolfson Microelectronics plc
15573 + * S3C64XX CPUfreq Support
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.
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>
15588 +#include <mach/cpu.h>
15590 +static struct clk *armclk;
15591 +static struct regulator *vddarm;
15593 +struct s3c64xx_dvfs {
15594 + unsigned int vddarm_min;
15595 + unsigned int vddarm_max;
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 },
15606 +static struct cpufreq_frequency_table s3c6410_freq_table[] = {
15616 + { 0, CPUFREQ_TABLE_END },
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;
15623 +static int s3c64xx_cpufreq_verify_speed(struct cpufreq_policy *policy)
15625 + if (policy->cpu != 0)
15628 + return cpufreq_frequency_table_verify(policy, s3c64xx_freq_table);
15631 +static unsigned int s3c64xx_cpufreq_get_speed(unsigned int cpu)
15636 + return clk_get_rate(armclk) / 1000;
15639 +static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
15640 + unsigned int target_freq,
15641 + unsigned int relation)
15645 + struct cpufreq_freqs freqs;
15646 + struct s3c64xx_dvfs *dvfs;
15648 + ret = cpufreq_frequency_table_target(policy, s3c64xx_freq_table,
15649 + target_freq, relation, &i);
15654 + freqs.old = clk_get_rate(armclk) / 1000;
15655 + freqs.new = s3c64xx_freq_table[i].frequency;
15657 + dvfs = &s3c64xx_dvfs_table[s3c64xx_freq_table[i].index];
15659 + if (freqs.old == freqs.new)
15662 + pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
15664 + cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
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);
15672 + pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
15679 + ret = clk_set_rate(armclk, freqs.new * 1000);
15681 + pr_err("cpufreq: Failed to set rate %dkHz: %d\n",
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);
15692 + pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
15699 + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
15701 + pr_debug("cpufreq: Set actual frequency %lukHz\n",
15702 + clk_get_rate(armclk) / 1000);
15707 + if (clk_set_rate(armclk, freqs.old * 1000) < 0)
15708 + pr_err("Failed to restore original clock rate\n");
15710 + cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
15716 +static int __init s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
15719 + struct cpufreq_frequency_table *freq;;
15721 + if (policy->cpu != 0)
15724 + if (cpu_is_s3c6410()) {
15725 + s3c64xx_freq_table = s3c6410_freq_table;
15726 + s3c64xx_dvfs_table = s3c6410_dvfs_table;
15729 + if (s3c64xx_freq_table == NULL) {
15730 + pr_err("cpufreq: No frequency information for this CPU\n");
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);
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");
15751 + /* Check for frequencies we can generate */
15752 + freq = s3c64xx_freq_table;
15753 + while (freq->frequency != CPUFREQ_TABLE_END) {
15756 + r = clk_round_rate(armclk, freq->frequency * 1000);
15759 + if (r != freq->frequency)
15760 + freq->frequency = CPUFREQ_ENTRY_INVALID;
15765 + policy->cur = clk_get_rate(armclk) / 1000;
15766 + policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
15768 + ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
15772 + pr_err("cpufreq: Failed to configure frequency table: %d\n", ret);
15774 + regulator_put(vddarm);
15779 +static struct cpufreq_driver s3c64xx_cpufreq_driver = {
15780 + .owner = THIS_MODULE,
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",
15789 +static int __init s3c64xx_cpufreq_init(void)
15791 + return cpufreq_register_driver(&s3c64xx_cpufreq_driver);
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
15798 +/* Base S3C64XX usbgadget resource and device definitions */
15800 +#include <linux/kernel.h>
15801 +#include <linux/interrupt.h>
15802 +#include <linux/platform_device.h>
15803 +#include <linux/ioport.h>
15805 +#include <mach/map.h>
15806 +#include <plat/map-base.h>
15807 +#include <plat/devs.h>
15808 +#include <plat/irqs.h>
15810 +static struct resource s3c_usbgadget_resource[] = {
15812 + .start = S3C64XX_PA_OTG,
15813 + .end = S3C64XX_PA_OTG + 0x200000 - 1,
15814 + .flags = IORESOURCE_MEM,
15817 + .start = IRQ_OTG,
15819 + .flags = IORESOURCE_IRQ,
15823 +struct platform_device s3c_device_usbgadget = {
15824 + .name = "s3c-otg-usbgadget",
15826 + .num_resources = ARRAY_SIZE(s3c_usbgadget_resource),
15827 + .resource = s3c_usbgadget_resource,
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
15834 +/* linux/arch/arm/plat-s3c64xx/dma.c
15836 + * Copyright 2009 Openmoko, Inc.
15837 + * Copyright 2009 Simtec Electronics
15838 + * Ben Dooks <ben@simtec.co.uk>
15839 + * http://armlinux.simtec.co.uk/
15841 + * S3C64XX DMA core
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.
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>
15859 +#include <mach/dma.h>
15860 +#include <mach/irqs.h>
15862 +#include <plat/dma-plat.h>
15864 +#include <plat/pl080.h>
15865 +#include <mach/map.h>
15866 +#include <plat/regs-sys.h>
15871 +#define pr_debug(x...) printk(x)
15873 +/* dma channel state information */
15876 +struct s3c64xx_dmac {
15877 + struct sys_device sysdev;
15879 + void __iomem *regs;
15880 + struct s3c2410_dma_chan *channels;
15881 + enum dma_ch chanbase;
15884 +/* pool to provide LLI buffers */
15885 +static struct dma_pool *dma_pool;
15887 +/* Debug configuration and code */
15889 +static unsigned char debug_show_buffs = 0;
15891 +static void dbg_showchan(struct s3c2410_dma_chan *chan)
15893 + pr_debug("DMA%d: %08x->%08x L %08x C %08x,%08x S %08x\n",
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));
15903 +static void show_lli(struct pl080_lli *lli)
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);
15910 +static void dbg_showbuffs(struct s3c2410_dma_chan *chan)
15912 + struct s3c64xx_dma_buff *ptr;
15913 + struct s3c64xx_dma_buff *end;
15915 + pr_debug("DMA%d: buffs next %p, curr %p, end %p\n",
15916 + chan->number, chan->next, chan->curr, chan->end);
15918 + ptr = chan->next;
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);
15930 +/* End of Debug */
15932 +static struct s3c2410_dma_chan *s3c64xx_dma_map_channel(unsigned int channel)
15934 + struct s3c2410_dma_chan *chan;
15935 + unsigned int start, offs;
15939 + if (channel >= DMACH_PCM1_TX)
15942 + for (offs = 0; offs < 8; offs++) {
15943 + chan = &s3c2410_chans[start + offs];
15944 + if (!chan->in_use)
15951 + s3c_dma_chan_map[channel] = chan;
15955 +int s3c2410_dma_config(unsigned int channel, int xferunit)
15957 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
15959 + if (chan == NULL)
15962 + switch (xferunit) {
15964 + chan->hw_width = 0;
15967 + chan->hw_width = 1;
15970 + chan->hw_width = 2;
15973 + printk(KERN_ERR "%s: illegal width %d\n", __func__, xferunit);
15979 +EXPORT_SYMBOL(s3c2410_dma_config);
15981 +static void s3c64xx_dma_fill_lli(struct s3c2410_dma_chan *chan,
15982 + struct pl080_lli *lli,
15983 + dma_addr_t data, int size)
15985 + dma_addr_t src, dst;
15986 + u32 control0, control1;
15988 + switch (chan->source) {
15989 + case S3C2410_DMASRC_HW:
15990 + src = chan->dev_addr;
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;
15998 + case S3C2410_DMASRC_MEM:
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;
16010 + /* todo - burst control */
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 */
16016 + lli->src_addr = src;
16017 + lli->dst_addr = dst;
16018 + lli->next_lli = 0;
16019 + lli->control0 = control0;
16020 + lli->control1 = control1;
16023 +static void s3c64xx_lli_to_regs(struct s3c2410_dma_chan *chan,
16024 + struct pl080_lli *lli)
16026 + void __iomem *regs = chan->regs;
16028 + pr_debug("%s: LLI %p => regs\n", __func__, lli);
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);
16038 +static int s3c64xx_dma_start(struct s3c2410_dma_chan *chan)
16040 + struct s3c64xx_dmac *dmac = chan->dmac;
16042 + u32 bit = chan->bit;
16044 + dbg_showchan(chan);
16046 + pr_debug("%s: clearing interrupts\n", __func__);
16048 + /* clear interrupts */
16049 + writel(bit, dmac->regs + PL080_TC_CLEAR);
16050 + writel(bit, dmac->regs + PL080_ERR_CLEAR);
16052 + pr_debug("%s: starting channel\n", __func__);
16054 + config = readl(chan->regs + PL080S_CH_CONFIG);
16055 + config |= PL080_CONFIG_ENABLE;
16057 + pr_debug("%s: writing config %08x\n", __func__, config);
16058 + writel(config, chan->regs + PL080S_CH_CONFIG);
16063 +static int s3c64xx_dma_stop(struct s3c2410_dma_chan *chan)
16068 + pr_debug("%s: stopping channel\n", __func__);
16070 + dbg_showchan(chan);
16072 + config = readl(chan->regs + PL080S_CH_CONFIG);
16073 + config |= PL080_CONFIG_HALT;
16074 + writel(config, chan->regs + PL080S_CH_CONFIG);
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)
16084 + } while (--timeout > 0);
16086 + if (config & PL080_CONFIG_ACTIVE) {
16087 + printk(KERN_ERR "%s: channel still active\n", __func__);
16091 + config = readl(chan->regs + PL080S_CH_CONFIG);
16092 + config &= ~PL080_CONFIG_ENABLE;
16093 + writel(config, chan->regs + PL080S_CH_CONFIG);
16098 +static inline void s3c64xx_dma_bufffdone(struct s3c2410_dma_chan *chan,
16099 + struct s3c64xx_dma_buff *buf,
16100 + enum s3c2410_dma_buffresult result)
16102 + if (chan->callback_fn != NULL)
16103 + (chan->callback_fn)(chan, buf->pw, 0, result);
16106 +static void s3c64xx_dma_freebuff(struct s3c64xx_dma_buff *buff)
16108 + dma_pool_free(dma_pool, buff->lli, buff->lli_dma);
16112 +static int s3c64xx_dma_flush(struct s3c2410_dma_chan *chan)
16114 + struct s3c64xx_dma_buff *buff, *next;
16117 + dbg_showchan(chan);
16119 + pr_debug("%s: flushing channel\n", __func__);
16121 + config = readl(chan->regs + PL080S_CH_CONFIG);
16122 + config &= ~PL080_CONFIG_ENABLE;
16123 + writel(config, chan->regs + PL080S_CH_CONFIG);
16125 + /* dump all the buffers associated with this channel */
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);
16131 + s3c64xx_dma_bufffdone(chan, buff, S3C2410_RES_ABORT);
16132 + s3c64xx_dma_freebuff(buff);
16135 + chan->curr = chan->next = chan->end = NULL;
16140 +int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
16142 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
16149 + case S3C2410_DMAOP_START:
16150 + return s3c64xx_dma_start(chan);
16152 + case S3C2410_DMAOP_STOP:
16153 + return s3c64xx_dma_stop(chan);
16155 + case S3C2410_DMAOP_FLUSH:
16156 + return s3c64xx_dma_flush(chan);
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:
16168 +EXPORT_SYMBOL(s3c2410_dma_ctrl);
16170 +/* s3c2410_dma_enque
16174 +int s3c2410_dma_enqueue(unsigned int channel, void *id,
16175 + dma_addr_t data, int size)
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;
16187 + buff = kzalloc(sizeof(struct s3c64xx_dma_buff), GFP_KERNEL);
16189 + printk(KERN_ERR "%s: no memory for buffer\n", __func__);
16193 + lli = dma_pool_alloc(dma_pool, GFP_KERNEL, &buff->lli_dma);
16195 + printk(KERN_ERR "%s: no memory for lli\n", __func__);
16200 + pr_debug("%s: buff %p, dp %08x lli (%p, %08x) %d\n",
16201 + __func__, buff, data, lli, (u32)buff->lli_dma, size);
16206 + s3c64xx_dma_fill_lli(chan, lli, data, size);
16208 + if ((next = chan->next) != NULL) {
16209 + struct s3c64xx_dma_buff *end = chan->end;
16210 + struct pl080_lli *endlli = end->lli;
16212 + pr_debug("enquing onto channel\n");
16214 + end->next = buff;
16215 + endlli->next_lli = buff->lli_dma;
16217 + if (chan->flags & S3C2410_DMAF_CIRCULAR) {
16218 + struct s3c64xx_dma_buff *curr = chan->curr;
16219 + lli->next_lli = curr->lli_dma;
16222 + if (next == chan->curr) {
16223 + writel(buff->lli_dma, chan->regs + PL080_CH_LLI);
16224 + chan->next = buff;
16227 + show_lli(endlli);
16228 + chan->end = buff;
16230 + pr_debug("enquing onto empty channel\n");
16232 + chan->curr = buff;
16233 + chan->next = buff;
16234 + chan->end = buff;
16236 + s3c64xx_lli_to_regs(chan, lli);
16241 + dbg_showchan(chan);
16242 + dbg_showbuffs(chan);
16250 +EXPORT_SYMBOL(s3c2410_dma_enqueue);
16253 +int s3c2410_dma_devconfig(int channel,
16254 + enum s3c2410_dmasrc source,
16255 + unsigned long devaddr)
16257 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
16261 + printk("%s: channel %d, source %d, dev %08lx, chan %p\n",
16262 + __func__, channel, source, devaddr, chan);
16268 + peripheral = (chan->peripheral & 0xf);
16269 + chan->source = source;
16270 + chan->dev_addr = devaddr;
16272 + pr_debug("%s: peripheral %d\n", __func__, peripheral);
16274 + switch (source) {
16275 + case S3C2410_DMASRC_HW:
16276 + config = 2 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
16277 + config |= peripheral << PL080_CONFIG_SRC_SEL_SHIFT;
16279 + case S3C2410_DMASRC_MEM:
16280 + config = 1 << PL080_CONFIG_FLOW_CONTROL_SHIFT;
16281 + config |= peripheral << PL080_CONFIG_DST_SEL_SHIFT;
16284 + printk(KERN_ERR "%s: bad source\n", __func__);
16288 + /* allow TC and ERR interrupts */
16289 + config |= PL080_CONFIG_TC_IRQ_MASK;
16290 + config |= PL080_CONFIG_ERR_IRQ_MASK;
16292 + pr_debug("%s: config %08x\n", __func__, config);
16294 + writel(config, chan->regs + PL080S_CH_CONFIG);
16298 +EXPORT_SYMBOL(s3c2410_dma_devconfig);
16301 +int s3c2410_dma_getposition(unsigned int channel,
16302 + dma_addr_t *src, dma_addr_t *dst)
16304 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
16311 + *src = readl(chan->regs + PL080_CH_SRC_ADDR);
16314 + *dst = readl(chan->regs + PL080_CH_DST_ADDR);
16318 +EXPORT_SYMBOL(s3c2410_dma_getposition);
16320 +/* s3c2410_request_dma
16322 + * get control of an dma channel
16325 +int s3c2410_dma_request(unsigned int channel,
16326 + struct s3c2410_dma_client *client,
16329 + struct s3c2410_dma_chan *chan;
16330 + unsigned long flags;
16332 + pr_debug("dma%d: s3c2410_request_dma: client=%s, dev=%p\n",
16333 + channel, client->name, dev);
16335 + local_irq_save(flags);
16337 + chan = s3c64xx_dma_map_channel(channel);
16338 + if (chan == NULL) {
16339 + local_irq_restore(flags);
16343 + dbg_showchan(chan);
16345 + chan->client = client;
16346 + chan->in_use = 1;
16347 + chan->peripheral = channel;
16349 + local_irq_restore(flags);
16351 + /* need to setup */
16353 + pr_debug("%s: channel initialised, %p\n", __func__, chan);
16355 + return chan->number | DMACH_LOW_LEVEL;
16358 +EXPORT_SYMBOL(s3c2410_dma_request);
16360 +/* s3c2410_dma_free
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
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.
16371 +int s3c2410_dma_free(unsigned int channel, struct s3c2410_dma_client *client)
16373 + struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
16374 + unsigned long flags;
16376 + if (chan == NULL)
16379 + local_irq_save(flags);
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);
16386 + /* sort out stopping and freeing the channel */
16389 + chan->client = NULL;
16390 + chan->in_use = 0;
16392 + if (!(channel & DMACH_LOW_LEVEL))
16393 + s3c_dma_chan_map[channel] = NULL;
16395 + local_irq_restore(flags);
16400 +EXPORT_SYMBOL(s3c2410_dma_free);
16403 +static void s3c64xx_dma_tcirq(struct s3c64xx_dmac *dmac, int offs)
16405 + struct s3c2410_dma_chan *chan = dmac->channels + offs;
16407 + /* note, we currently do not bother to work out which buffer
16408 + * or buffers have been completed since the last tc-irq. */
16410 + if (chan->callback_fn)
16411 + (chan->callback_fn)(chan, chan->curr->pw, 0, S3C2410_RES_OK);
16414 +static void s3c64xx_dma_errirq(struct s3c64xx_dmac *dmac, int offs)
16416 + printk(KERN_DEBUG "%s: offs %d\n", __func__, offs);
16419 +static irqreturn_t s3c64xx_dma_irq(int irq, void *pw)
16421 + struct s3c64xx_dmac *dmac = pw;
16422 + u32 tcstat, errstat;
16426 + tcstat = readl(dmac->regs + PL080_TC_STATUS);
16427 + errstat = readl(dmac->regs + PL080_ERR_STATUS);
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);
16435 + if (errstat & bit) {
16436 + s3c64xx_dma_errirq(dmac, offs);
16437 + writel(bit, dmac->regs + PL080_ERR_CLEAR);
16441 + return IRQ_HANDLED;
16444 +static struct sysdev_class dma_sysclass = {
16445 + .name = "s3c64xx-dma",
16448 +static int s3c64xx_dma_init1(int chno, enum dma_ch chbase,
16449 + int irq, unsigned int base)
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;
16458 + dmac = kzalloc(sizeof(struct s3c64xx_dmac), GFP_KERNEL);
16460 + printk(KERN_ERR "%s: failed to alloc mem\n", __func__);
16464 + dmac->sysdev.id = chno / 8;
16465 + dmac->sysdev.cls = &dma_sysclass;
16467 + err = sysdev_register(&dmac->sysdev);
16469 + printk(KERN_ERR "%s: failed to register sysdevice\n", __func__);
16473 + regs = ioremap(base, 0x200);
16475 + printk(KERN_ERR "%s: failed to ioremap()\n", __func__);
16480 + snprintf(clkname, sizeof(clkname), "dma%d", dmac->sysdev.id);
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);
16489 + clk_enable(dmac->clk);
16491 + dmac->regs = regs;
16492 + dmac->chanbase = chbase;
16493 + dmac->channels = chptr;
16495 + err = request_irq(irq, s3c64xx_dma_irq, 0, "DMA", dmac);
16497 + printk(KERN_ERR "%s: failed to get irq\n", __func__);
16501 + regptr = regs + PL080_Cx_BASE(0);
16503 + for (ch = 0; ch < 8; ch++, chno++, chptr++) {
16504 + printk(KERN_INFO "%s: registering DMA %d (%p)\n",
16505 + __func__, chno, regptr);
16507 + chptr->bit = 1 << ch;
16508 + chptr->number = chno;
16509 + chptr->dmac = dmac;
16510 + chptr->regs = regptr;
16511 + regptr += PL008_Cx_STRIDE;
16514 + /* for the moment, permanently enable the controller */
16515 + writel(PL080_CONFIG_ENABLE, regs + PL080_CONFIG);
16517 + printk(KERN_INFO "PL080: IRQ %d, at %p\n", irq, regs);
16522 + clk_disable(dmac->clk);
16523 + clk_put(dmac->clk);
16527 + sysdev_unregister(&dmac->sysdev);
16533 +static int __init s3c64xx_dma_init(void)
16537 + printk(KERN_INFO "%s: Registering DMA channels\n", __func__);
16539 + dma_pool = dma_pool_create("DMA-LLI", NULL, 32, 16, 0);
16541 + printk(KERN_ERR "%s: failed to create pool\n", __func__);
16545 + ret = sysdev_class_register(&dma_sysclass);
16547 + printk(KERN_ERR "%s: failed to create sysclass\n", __func__);
16551 + /* Set all DMA configuration to be DMA, not SDMA */
16552 + writel(0xffffff, S3C_SYSREG(0x110));
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);
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
16566 +/* linux/arch/arm/plat-s3c64xx/dma.c
16568 + * Copyright 2009 Simtec Electronics
16569 + * Ben Dooks <ben@simtec.co.uk>
16571 + * S3C64XX DMA core - fake
16573 + * http://armlinux.simtec.co.uk/
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.
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>
16590 +#include <asm/system.h>
16591 +#include <asm/irq.h>
16592 +#include <mach/hardware.h>
16593 +#include <mach/dma.h>
16596 +int s3c2410_dma_ctrl(unsigned int channel, enum s3c2410_chan_op op)
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
16607 #include <mach/map.h>
16608 #include <mach/gpio.h>
16609 +#include <mach/irqs.h>
16610 #include <mach/gpio-core.h>
16612 #include <plat/gpio-cfg.h>
16613 @@ -321,6 +322,11 @@
16614 .get_pull = s3c_gpio_getpull_updown,
16617 +static int s3c_gpiolib_bankn_toirq(struct gpio_chip *chip, unsigned offset)
16619 + return S3C_EINT(0) + offset;
16622 static struct s3c_gpio_chip gpio_2bit[] = {
16624 .base = S3C64XX_GPF_BASE,
16625 @@ -353,6 +359,7 @@
16626 .base = S3C64XX_GPN(0),
16627 .ngpio = S3C64XX_GPIO_N_NR,
16629 + .to_irq = s3c_gpiolib_bankn_toirq,
16632 .base = S3C64XX_GPO_BASE,
16633 @@ -385,12 +392,19 @@
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);
16640 static __init void s3c64xx_gpiolib_add_4bit2(struct s3c_gpio_chip *chip)
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);
16647 +static __init void s3c64xx_gpiolib_add_2bit(struct s3c_gpio_chip *chip)
16649 + chip->pm = __gpio_pm(&s3c_gpio_pm_2bit);
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);
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);
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
16667 +/* linux/arch/arm/plat-s3c64xx/include/plat/dma-plat.h
16669 + * Copyright 2009 Openmoko, Inc.
16670 + * Copyright 2009 Simtec Electronics
16671 + * Ben Dooks <ben@simtec.co.uk>
16672 + * http://armlinux.simtec.co.uk/
16674 + * S3C64XX DMA core
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.
16681 +#define DMACH_LOW_LEVEL (1<<28) /* use this to specifiy hardware ch no */
16683 +struct s3c64xx_dma_buff;
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.
16691 +struct s3c64xx_dma_buff {
16692 + struct s3c64xx_dma_buff *next;
16695 + struct pl080_lli *lli;
16696 + dma_addr_t lli_dma;
16699 +struct s3c64xx_dmac;
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;
16708 + unsigned int flags;
16709 + enum s3c2410_dmasrc source;
16712 + dma_addr_t dev_addr;
16714 + struct s3c2410_dma_client *client;
16715 + struct s3c64xx_dmac *dmac; /* pointer to controller */
16717 + void __iomem *regs;
16719 + /* cdriver callbacks */
16720 + s3c2410_dma_cbfn_t callback_fn; /* buffer done callback */
16721 + s3c2410_dma_opfn_t op_fn; /* channel op callback */
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 */
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
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 */
16743 #define IRQ_IIC1 IRQ_S3C6410_IIC1
16744 +#define IRQ_USBH IRQ_UHOST
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 @@
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))
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 @@
16758 #define NR_IRQS (IRQ_EINT_GROUP9_BASE + IRQ_EINT_GROUP9_NR + 1)
16760 +#define FIQ_START S3C_IRQ(0)
16761 #endif /* __ASM_PLAT_S3C64XX_IRQS_H */
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
16767 +/* arch/arm/include/asm/hardware/pl080.h
16769 + * Copyright 2008 Openmoko, Inc.
16770 + * Copyright 2008 Simtec Electronics
16771 + * http://armlinux.simtec.co.uk/
16772 + * Ben Dooks <ben@simtec.co.uk>
16774 + * ARM PrimeCell PL080 DMA controller
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.
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.
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.
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)
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)
16808 +#define PL080_SYNC (0x34)
16810 +/* Per channel configuration registers */
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)))
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)
16830 +#define PL080_LLI_ADDR_MASK (0x3fffffff << 2)
16831 +#define PL080_LLI_ADDR_SHIFT (2)
16832 +#define PL080_LLI_LM_AHB2 (1 << 0)
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)
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)
16867 +/* DMA linked list chain structure */
16869 +struct pl080_lli {
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
16881 +/* linux/arch/arm/plat-s3c64xx/include/plat/pm-core.h
16883 + * Copyright 2008 Openmoko, Inc.
16884 + * Copyright 2008 Simtec Electronics
16885 + * Ben Dooks <ben@simtec.co.uk>
16886 + * http://armlinux.simtec.co.uk/
16888 + * S3C64XX - PM core support for arch/arm/plat-s3c/pm.c
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.
16895 +#include <plat/regs-gpio.h>
16897 +static inline void s3c_pm_debug_init_uart(void)
16899 + u32 tmp = __raw_readl(S3C_PCLK_GATE);
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
16907 + tmp |= S3C_CLKCON_PCLK_UART0;
16908 + tmp |= S3C_CLKCON_PCLK_UART1;
16909 + tmp |= S3C_CLKCON_PCLK_UART2;
16910 + tmp |= S3C_CLKCON_PCLK_UART3;
16912 + __raw_writel(tmp, S3C_PCLK_GATE);
16916 +static inline void s3c_pm_arch_clear_vic(void __iomem *base)
16918 + __raw_writel(~0, base + VIC_INT_ENABLE_CLEAR);
16919 + __raw_writel(~0, base + VIC_INT_SOFT_CLEAR);
16922 +static inline void s3c_pm_arch_prepare_irqs(void)
16924 + /* shutdown the VICs */
16925 + s3c_pm_arch_clear_vic(S3C_VA_VIC0);
16926 + s3c_pm_arch_clear_vic(S3C_VA_VIC1);
16928 + /* clear any pending EINT0 interrupts */
16929 + __raw_writel(__raw_readl(S3C64XX_EINT0PEND), S3C64XX_EINT0PEND);
16932 +static inline void s3c_pm_arch_stop_clocks(void)
16936 +static inline void s3c_pm_arch_show_resume_irqs(void)
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 */
16943 +#define s3c_irqwake_eintallow ((1 << 28) - 1)
16944 +#define s3c_irqwake_intallow (0)
16946 +static inline void s3c_pm_arch_update_uart(void __iomem *regs,
16947 + struct pm_uart_save *save)
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;
16955 + /* S3C64XX UART blocks only support level interrupts, so ensure that
16956 + * when we restore unused UART blocks we force the level interrupt
16958 + save->ucon |= S3C2410_UCON_TXILEVEL | S3C2410_UCON_RXILEVEL;
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.
16965 + if (ucon_clk != save_clk) {
16966 + new_ucon = save->ucon;
16967 + delta = ucon_clk ^ save_clk;
16969 + /* change from UCLKx => wrong PCLK,
16970 + * either UCLK can be tested for by a bit-test
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;
16982 + S3C_PMDBG("ucon change %04x => %04x (save=%04x)\n",
16983 + ucon, new_ucon, save->ucon);
16984 + save->ucon = new_ucon;
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
16991 +/* arch/arm/plat-s3c64xx/include/plat/regs-camif.h
16993 + * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
16994 + * http://www.simtec.co.uk/products/SWLINUX/
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.
17002 +#ifndef ___ASM_ARCH_REGS_CAMIF_H
17003 +#define ___ASM_ARCH_REGS_CAMIF_H
17005 +#define S3C_CAMIFREG(x) (x)
17007 +/*************************************************************************
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)
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)
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)
17025 +#define S3C_CICOTRGFMT_TARGETHSIZE_CO(x) ((x) << 16)
17026 +#define S3C_CICOTRGFMT_GET_TARGETHSIZE_CO(x) (((x) >> 16) & 0x1FFF)
17028 +#define S3C_CICOTRGFMT_TARGETVSIZE_CO(x) ((x) << 0)
17029 +#define S3C_CICOTRGFMT_GET_TARGETVSIZE_CO(x) (((x) >> 0) & 0x1FFF)
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)
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)
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)
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)
17052 +#define S3C_CICOSTATUS_FRAMECNT_CO(x) ((x) << 26)
17053 +#define S3C_CICOSTATUS_GET_FRAMECNT_CO(x) (((x) >> 26) & 0x3)
17055 +#define S3C_CIPRTRGFMT_TARGETHSIZE_PR(x) ((x) << 16)
17056 +#define S3C_CIPRTRGFMT_GET_TARGETHSIZE_PR(x) (((x) >> 16) & 0x1FFF)
17058 +#define S3C_CIPRTRGFMT_GET_ROT90_PR(x) (((x) >> 13) & 0x1)
17060 +#define S3C_CIPRTRGFMT_TARGETVSIZE_PR(x) ((x) << 0)
17061 +#define S3C_CIPRTRGFMT_GET_TARGETVSIZE_PR(x) (((x) >> 0) & 0x1FFF)
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)
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)
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)
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)
17094 +/* Global Control Register */
17095 +#define S3C_CIGCTRL_SWRST (1 << 31)
17096 +#define S3C_CIGCTRL_CAMRST (1 << 30)
17098 +#if defined (CONFIG_CPU_S3C6400) || defined (CONFIG_CPU_S3C6410)
17099 +#define S3C_CIGCTRL_IRQ_LEVEL (1 << 20)
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)
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)
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)
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)
17130 +#define S3C_CICOTRGFMT_INTERLEAVE_ON (1 << 29)
17131 +#define S3C_CICOTRGFMT_INTERLEAVE_OFF (0 << 29)
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)
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)
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)
17150 +#define S3C_CICOSCCTRL_CSCR2Y_WIDE (1 << 28)
17151 +#define S3C_CICOSCCTRL_CSCR2Y_NARROW (0 << 28)
17153 +#define S3C_CICOSCCTRL_CSCY2R_WIDE (1 << 27)
17154 +#define S3C_CICOSCCTRL_CSCY2R_NARROW (0 << 27)
17156 +#define S3C_CICOSCCTRL_LCDPATHEN_FIFO (1 << 26)
17157 +#define S3C_CICOSCCTRL_LCDPATHEN_DMA (0 << 26)
17159 +#define S3C_CICOSCCTRL_INTERLACE_INTERLACE (1 << 25)
17160 +#define S3C_CICOSCCTRL_INTERLACE_PROGRESSIVE (0 << 25)
17162 +#define S3C_CICOSCCTRL_COSCALERSTART (1 << 15)
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)
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)
17172 +#define S3C_CICOSCCTRL_EXTRGB_EXTENSION (1 << 10)
17173 +#define S3C_CICOSCCTRL_EXTRGB_NORMAL (0 << 10)
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)
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)
17194 +#define S3C_CIPRTRGFMT_ROT90_ROTATE (1 << 13)
17195 +#define S3C_CIPRTRGFMT_ROT90_BYPASS (0 << 13)
17197 +/* Preview DMA Control Register */
17198 +#define S3C_CIPRCTRL_LASTIRQEN_ENABLE (1 << 2)
17199 +#define S3C_CIPRCTRL_LASTIRQEN_NORMAL (0 << 2)
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)
17206 +/* Preview Main-Scaler Control Register */
17207 +#define S3C_CIPRSCCTRL_SAMPLE_PR (1 << 31)
17209 +#define S3C_CIPRSCCTRL_RGBFORMAT_24 (1 << 30)
17210 +#define S3C_CIPRSCCTRL_RGBFORMAT_16 (0 << 30)
17212 +#define S3C_CIPRSCCTRL_START (1 << 15)
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)
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)
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)
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)
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)
17238 +#define S3C_CIIMGCPT_CPT_CODMA_SEL_RGB (1 << 26)
17239 +#define S3C_CIIMGCPT_CPT_CODMA_SEL_YUV (0 << 26)
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)
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)
17258 +/* Image Effects Register */
17259 +#define S3C_CIIMGEFF_IE_ON_PR_ENABLE (1 << 31)
17260 +#define S3C_CIIMGEFF_IE_ON_PR_DISABLE (0 << 31)
17262 +#define S3C_CIIMGEFF_IE_ON_CO_ENABLE (1 << 30)
17263 +#define S3C_CIIMGEFF_IE_ON_CO_DISABLE (0 << 30)
17265 +#define S3C_CIIMGEFF_IE_AFTER_SC_BEFORE (0 << 29)
17266 +#define S3C_CIIMGEFF_IE_AFTER_SC_AFTER (1 << 29)
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)
17275 +/* MSDMA for Codec Source Image Width Register */
17276 +#define S3C_MSCOWIDTH_AUTOLOAD_ENABLE (1 << 31)
17277 +#define S3C_MSCOWIDTH_AUTOLOAD_DISABLE (0 << 31)
17279 +#define S3C_MSCOWIDTH_ADDR_CH_ENABLE (1 << 30)
17280 +#define S3C_MSCOWIDTH_ADDR_CH_DISABLE (0 << 30)
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)
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)
17333 +/*************************************************************************
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)
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 */
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 */
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 */
17449 +#endif /* ___ASM_ARCH_REGS_CAMIF_H */
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
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)
17461 #define S3C6400_CLKDIV0_MFC_MASK (0xf << 28)
17462 @@ -88,10 +89,10 @@
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 @@
17482 /* Base addresses for each of the banks */
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))
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)
17523 +#define S3C64XX_SPCON S3C64XX_GPIOREG(0x1A0)
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)
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)
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)
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)
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)
17560 +#define S3C64XX_SPCON_nRSTOUT_OEN (1 << 21)
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)
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)
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)
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)
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)
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)
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)
17606 +/* External interrupt registers */
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)
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)
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)
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)
17632 +#define S3C64XX_PRIORITY S3C64XX_GPIOREG(0x280)
17633 +#define S3C64XX_PRIORITY_ARB(x) (1 << (x))
17635 +#define S3C64XX_SERVICE S3C64XX_GPIOREG(0x284)
17636 +#define S3C64XX_SERVICEPEND S3C64XX_GPIOREG(0x288)
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)
17645 +#define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920)
17646 +#define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924)
17648 +/* GPIO sleep configuration */
17650 +#define S3C64XX_SPCONSLP S3C64XX_GPIOREG(0x880)
17652 +#define S3C64XX_SPCONSLP_TDO_PULLDOWN (1 << 14)
17653 +#define S3C64XX_SPCONSLP_CKE1INIT (1 << 5)
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)
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)
17666 +#define S3C64XX_SLPEN S3C64XX_GPIOREG(0x930)
17668 +#define S3C64XX_SLPEN_USE_xSLP (1 << 0)
17669 +#define S3C64XX_SLPEN_CFG_BYSLPEN (1 << 1)
17671 #endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_H */
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
17677 +/* linux/arch/arm/plat-s3c64xx/include/mach/regs-gpio-memport.h
17679 + * Copyright 2008 Openmoko, Inc.
17680 + * Copyright 2008 Simtec Electronics
17681 + * Ben Dooks <ben@simtec.co.uk>
17682 + * http://armlinux.simtec.co.uk/
17684 + * S3C64XX - GPIO memory port register definitions
17687 +#ifndef __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H
17688 +#define __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H __FILE__
17690 +#define S3C64XX_MEM0CONSTOP S3C64XX_GPIOREG(0x1B0)
17691 +#define S3C64XX_MEM1CONSTOP S3C64XX_GPIOREG(0x1B4)
17693 +#define S3C64XX_MEM0CONSLP0 S3C64XX_GPIOREG(0x1C0)
17694 +#define S3C64XX_MEM0CONSLP1 S3C64XX_GPIOREG(0x1C4)
17695 +#define S3C64XX_MEM1CONSLP S3C64XX_GPIOREG(0x1C8)
17697 +#define S3C64XX_MEM0DRVCON S3C64XX_GPIOREG(0x1D0)
17698 +#define S3C64XX_MEM1DRVCON S3C64XX_GPIOREG(0x1D4)
17700 +#endif /* __ASM_PLAT_S3C64XX_REGS_GPIO_MEMPORT_H */
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
17706 +/* arch/arm/plat-s3c64xx/include/plat/regs-modem.h
17708 + * Copyright 2008 Openmoko, Inc.
17709 + * Copyright 2008 Simtec Electronics
17710 + * http://armlinux.simtec.co.uk/
17711 + * Ben Dooks <ben@simtec.co.uk>
17713 + * S3C64XX - modem block registers
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.
17720 +#ifndef __PLAT_S3C64XX_REGS_MODEM_H
17721 +#define __PLAT_S3C64XX_REGS_MODEM_H __FILE__
17723 +#define S3C64XX_MODEMREG(x) (S3C64XX_VA_MODEM + (x))
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)
17733 +#define MIFPCON_INT2M_LEVEL (1 << 4)
17734 +#define MIFPCON_LCD_BYPASS (1 << 3)
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
17741 +/* arch/arm/plat-s3c64xx/include/plat/regs-syscon-power.h
17743 + * Copyright 2008 Openmoko, Inc.
17744 + * Copyright 2008 Simtec Electronics
17745 + * http://armlinux.simtec.co.uk/
17746 + * Ben Dooks <ben@simtec.co.uk>
17748 + * S3C64XX - syscon power and sleep control registers
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.
17755 +#ifndef __PLAT_S3C64XX_REGS_SYSCON_POWER_H
17756 +#define __PLAT_S3C64XX_REGS_SYSCON_POWER_H __FILE__
17758 +#define S3C64XX_PWR_CFG S3C_SYSREG(0x804)
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)
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)
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)
17785 +#define S3C64XX_PWRCFG_CFG_BAT_WAKE (1 << 2)
17786 +#define S3C64XX_PWRCFG_OSC27_EN (1 << 0)
17788 +#define S3C64XX_EINT_MASK S3C_SYSREG(0x808)
17790 +#define S3C64XX_NORMAL_CFG S3C_SYSREG(0x810)
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)
17801 +#define S3C64XX_STOP_CFG S3C_SYSREG(0x814)
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)
17809 +#define S3C64XX_SLEEP_CFG S3C_SYSREG(0x818)
17811 +#define S3C64XX_SLEEPCFG_OSC_EN (1 << 0)
17813 +#define S3C64XX_STOP_MEM_CFG S3C_SYSREG(0x81c)
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)
17823 +#define S3C64XX_OSC_STABLE S3C_SYSREG(0x824)
17824 +#define S3C64XX_PWR_STABLE S3C_SYSREG(0x828)
17826 +#define S3C64XX_WAKEUP_STAT S3C_SYSREG(0x908)
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)
17840 +#define S3C64XX_BLK_PWR_STAT S3C_SYSREG(0x90c)
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)
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)
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
17862 #define S3C_SYSREG(x) (S3C_VA_SYS + (x))
17864 +#define S3C64XX_AHB_CON0 S3C_SYSREG(0x100)
17865 +#define S3C64XX_AHB_CON1 S3C_SYSREG(0x104)
17866 +#define S3C64XX_AHB_CON2 S3C_SYSREG(0x108)
17868 #define S3C64XX_OTHERS S3C_SYSREG(0x900)
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
17875 +#ifndef __S3C64XX_TZIC_SP890_H__
17876 +#define __S3C64XX_TZIC_SP890_H__
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)
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 @@
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>
17907 #include <asm/hardware/vic.h>
17909 #include <mach/map.h>
17910 +#include <plat/regs-serial.h>
17911 #include <plat/regs-timer.h>
17912 #include <plat/cpu.h>
17914 @@ -135,9 +137,6 @@
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
17922 static void s3c_irq_uart_mask(unsigned int irq)
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 @@
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>
17936 #include <asm/hardware/vic.h>
17938 #include <plat/regs-irqtype.h>
17939 +#include <plat/regs-gpio.h>
17940 +#include <plat/gpio-cfg.h>
17942 #include <mach/map.h>
17943 #include <plat/cpu.h>
17945 -/* GPIO is 0x7F008xxx, */
17946 -#define S3C64XX_GPIOREG(x) (S3C64XX_VA_GPIO + (x))
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)
17955 -#define S3C64XX_EINT0MASK S3C64XX_GPIOREG(0x920)
17956 -#define S3C64XX_EINT0PEND S3C64XX_GPIOREG(0x924)
17958 +#include <plat/pm.h>
17960 #define eint_offset(irq) ((irq) - IRQ_EINT(0))
17961 #define eint_irq_to_bit(irq) (1 << eint_offset(irq))
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);
17972 static int s3c_irq_eint_set_type(unsigned int irq, unsigned int type)
17974 int offs = eint_offset(irq);
17979 @@ -125,6 +117,14 @@
17980 ctrl |= newvalue << shift;
17981 __raw_writel(ctrl, reg);
17983 + /* set the GPIO pin appropriately */
17986 + pin = S3C64XX_GPN(offs);
17988 + pin = S3C64XX_GPM(offs - 23);
17990 + s3c_gpio_cfgpin(pin, S3C_GPIO_SFN(2));
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,
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
18006 +/* arch/arm/plat-s3c64xx/irq-pm.c
18008 + * Copyright 2008 Openmoko, Inc.
18009 + * Copyright 2008 Simtec Electronics
18010 + * Ben Dooks <ben@simtec.co.uk>
18011 + * http://armlinux.simtec.co.uk/
18013 + * S3C64XX - Interrupt handling Power Management
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.
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>
18027 +#include <asm/hardware/vic.h>
18029 +#include <mach/map.h>
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>
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.
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),
18056 +static struct irq_grp_save {
18060 +} eint_grp_save[5];
18062 +struct irq_vic_save {
18067 + u32 vect_addr[32];
18068 + u32 vect_cntl[32];
18071 +static struct irq_vic_save irq_pm_vic0_save;
18072 +static struct irq_vic_save irq_pm_vic1_save;
18074 +static u32 irq_uart_mask[CONFIG_SERIAL_SAMSUNG_UARTS];
18076 +static void s3c64xx_vic_save(void __iomem *base, struct irq_vic_save *save)
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);
18085 + S3C_PMDBG("%s: select=%08x, enable=%08x, protect=%08x\n", __func__,
18086 + save->int_select, save->int_enable, save->protect);
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));
18094 +static void s3c64xx_vic_restore(void __iomem *base, struct irq_vic_save *save)
18098 + writel(save->int_select, base + VIC_INT_SELECT);
18099 + writel(save->protect, base + VIC_PROTECT);
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);
18105 + /* and the same for the soft-int register */
18107 + writel(save->soft_int, base + VIC_INT_SOFT);
18108 + writel(~save->soft_int, base + VIC_INT_SOFT_CLEAR);
18110 + S3C_PMDBG("%s: vic int_enable=%08x\n", __func__, readl(base + VIC_INT_ENABLE));
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));
18118 +static int s3c64xx_irq_pm_suspend(struct sys_device *dev, pm_message_t state)
18120 + struct irq_grp_save *grp = eint_grp_save;
18123 + S3C_PMDBG("%s: suspending IRQs\n", __func__);
18125 + s3c64xx_vic_save(S3C_VA_VIC0, &irq_pm_vic0_save);
18126 + s3c64xx_vic_save(S3C_VA_VIC1, &irq_pm_vic1_save);
18128 + s3c_pm_do_save(irq_save, ARRAY_SIZE(irq_save));
18130 + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
18131 + irq_uart_mask[i] = __raw_readl(S3C_VA_UARTx(i) + S3C64XX_UINTM);
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));
18142 +static int s3c64xx_irq_pm_resume(struct sys_device *dev)
18144 + struct irq_grp_save *grp = eint_grp_save;
18147 + S3C_PMDBG("%s: resuming IRQs\n", __func__);
18149 + s3c_pm_do_restore(irq_save, ARRAY_SIZE(irq_save));
18151 + s3c64xx_vic_restore(S3C_VA_VIC0, &irq_pm_vic0_save);
18152 + s3c64xx_vic_restore(S3C_VA_VIC1, &irq_pm_vic1_save);
18154 + for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++)
18155 + __raw_writel(irq_uart_mask[i], S3C_VA_UARTx(i) + S3C64XX_UINTM);
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));
18163 + S3C_PMDBG("%s: IRQ configuration restored\n", __func__);
18167 +static struct sysdev_driver s3c64xx_irq_driver = {
18168 + .suspend = s3c64xx_irq_pm_suspend,
18169 + .resume = s3c64xx_irq_pm_resume,
18172 +static int __init s3c64xx_irq_pm_init(void)
18174 + return sysdev_driver_register(&s3c64xx_sysclass, &s3c64xx_irq_driver);
18177 +arch_initcall(s3c64xx_irq_pm_init);
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
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
18189 Base platform code for any Samsung S3C64XX device
18192 Common clock support code for the S3C6400 that is shared
18193 by other CPUs in the series, such as the S3C6410.
18195 +config S3C64XX_DMA
18196 + bool "S3C64XX DMA"
18199 # platform specific device setup
18201 config S3C64XX_SETUP_I2C0
18204 Common setup code for S3C64XX with an 24bpp RGB display helper.
18206 +config S3C64XX_SETUP_USBOTG
18209 + Common setup code for S3C64XX with USB OTG
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
18217 obj-$(CONFIG_CPU_S3C6400_INIT) += s3c6400-init.o
18218 obj-$(CONFIG_CPU_S3C6400_CLOCK) += s3c6400-clock.o
18222 +obj-$(CONFIG_S3C64XX_DMA) += dma.o
18226 +obj-$(CONFIG_PM) += pm.o
18227 +obj-$(CONFIG_PM) += sleep.o
18228 +obj-$(CONFIG_PM) += irq-pm.o
18230 +obj-$(CONFIG_CPU_FREQ_S3C64XX) += cpufreq.o
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
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
18243 +/* linux/arch/arm/plat-s3c64xx/pm.c
18245 + * Copyright 2008 Openmoko, Inc.
18246 + * Copyright 2008 Simtec Electronics
18247 + * Ben Dooks <ben@simtec.co.uk>
18248 + * http://armlinux.simtec.co.uk/
18250 + * S3C64XX CPU PM support.
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.
18257 +#include <linux/init.h>
18258 +#include <linux/suspend.h>
18259 +#include <linux/serial_core.h>
18260 +#include <linux/io.h>
18262 +#include <mach/map.h>
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>
18272 +#ifdef CONFIG_S3C_PM_DEBUG_LED_SMDK
18273 +#include <plat/gpio-bank-n.h>
18275 +void s3c_pm_debug_smdkled(u32 set, u32 clear)
18277 + unsigned long flags;
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);
18288 + reg = __raw_readl(S3C64XX_GPNDAT);
18289 + reg &= ~(clear << 12);
18290 + reg |= set << 12;
18291 + __raw_writel(reg, S3C64XX_GPNDAT);
18293 + local_irq_restore(flags);
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),
18311 + SAVE_ITEM(S3C_EPLL_CON1),
18312 + SAVE_ITEM(S3C_EPLL_CON0),
18314 + SAVE_ITEM(S3C64XX_MEM0DRVCON),
18315 + SAVE_ITEM(S3C64XX_MEM1DRVCON),
18317 +#ifndef CONFIG_CPU_FREQ
18318 + SAVE_ITEM(S3C_APLL_CON),
18319 + SAVE_ITEM(S3C_MPLL_CON),
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),
18328 + SAVE_ITEM(S3C64XX_MODEM_MIFPCON),
18329 + SAVE_ITEM(S3C64XX_SPCON),
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),
18338 +void s3c_pm_configure_extint(void)
18340 + __raw_writel(s3c_irqwake_eintmask, S3C64XX_EINT_MASK);
18343 +void s3c_pm_restore_core(void)
18345 + __raw_writel(0, S3C64XX_EINT_MASK);
18347 + s3c_pm_debug_smdkled(1 << 2, 0);
18349 + s3c_pm_do_restore_core(core_save, ARRAY_SIZE(core_save));
18350 + s3c_pm_do_restore(misc_save, ARRAY_SIZE(misc_save));
18353 +void s3c_pm_save_core(void)
18355 + s3c_pm_do_save(misc_save, ARRAY_SIZE(misc_save));
18356 + s3c_pm_do_save(core_save, ARRAY_SIZE(core_save));
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
18364 +#include <plat/regs-gpio.h>
18366 +static void s3c64xx_cpu_suspend(void)
18368 + unsigned long tmp;
18370 + /* set our standby method to sleep */
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);
18377 + /* clear any old wakeup */
18379 + __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT),
18380 + S3C64XX_WAKEUP_STAT);
18382 + /* set the LED state to 0110 over sleep */
18383 + s3c_pm_debug_smdkled(3 << 1, 0xf);
18385 + /* issue the standby signal into the pm unit. Note, we
18386 + * issue a write-buffer drain just in case */
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));
18397 + /* we should never get past here */
18399 + panic("sleep resumed to originator?");
18402 +static void s3c64xx_pm_prepare(void)
18404 + /* store address of resume. */
18405 + __raw_writel(virt_to_phys(s3c_cpu_resume), S3C64XX_INFORM0);
18407 + /* ensure previous wakeup state is cleared before sleeping */
18408 + __raw_writel(__raw_readl(S3C64XX_WAKEUP_STAT), S3C64XX_WAKEUP_STAT);
18411 +static int s3c64xx_pm_init(void)
18413 + pm_cpu_prep = s3c64xx_pm_prepare;
18414 + pm_cpu_sleep = s3c64xx_cpu_suspend;
18415 + pm_uart_udivslot = 1;
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
18425 #include <mach/hardware.h>
18426 #include <mach/map.h>
18427 +#include <mach/cpu.h>
18429 #include <plat/cpu-freq.h>
18432 .sources = &clk_src_apll,
18435 +static u32 clk_arm_div_mask(void)
18437 + if (cpu_is_s3c6400())
18438 + return S3C6400_CLKDIV0_ARM_MASK;
18440 + if (cpu_is_s3c6410())
18441 + return S3C6410_CLKDIV0_ARM_MASK;
18446 +static unsigned long s3c64xx_clk_arm_get_rate(struct clk *clk)
18448 + unsigned long rate = clk_get_rate(clk->parent);
18451 + val = __raw_readl(S3C_CLK_DIV0);
18452 + val &= clk_arm_div_mask();
18454 + return rate / (val + 1);
18457 +static unsigned long s3c64xx_clk_arm_round_rate(struct clk *clk,
18458 + unsigned long rate)
18460 + unsigned long parent = clk_get_rate(clk->parent);
18462 + int max = clk_arm_div_mask() + 1;
18464 + if (parent < rate)
18467 + div = parent / rate;
18474 + return parent / div;
18477 +static int s3c64xx_clk_arm_set_rate(struct clk *clk, unsigned long rate)
18479 + unsigned int div;
18481 + unsigned long flags;
18483 + div = (clk_get_rate(clk->parent) / rate) - 1;
18485 + if (div > clk_arm_div_mask())
18488 + local_irq_save(flags);
18490 + val = __raw_readl(S3C_CLK_DIV0);
18491 + val &= ~clk_arm_div_mask();
18494 + __raw_writel(val, S3C_CLK_DIV0);
18495 + local_irq_restore(flags);
18500 +static struct clk clk_arm = {
18501 + .name = "armclk",
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,
18509 struct clk clk_fout_epll = {
18510 .name = "fout_epll",
18512 @@ -239,10 +314,12 @@
18514 rate = clk_round_rate(clk, rate);
18515 div = clk_get_rate(clk->parent) / rate;
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);
18527 @@ -282,7 +359,7 @@
18528 if (rate > parent_rate)
18529 rate = parent_rate;
18531 - div = rate / parent_rate;
18532 + div = parent_rate / rate;
18536 @@ -351,7 +428,7 @@
18538 static struct clksrc_clk clk_usbhost = {
18540 - .name = "usb-host-bus",
18541 + .name = "usb-bus-host",
18543 .ctrlbit = S3C_CLKCON_SCLK_UHOST,
18544 .enable = s3c64xx_sclk_ctrl,
18545 @@ -518,6 +595,55 @@
18546 .reg_divider = S3C_CLK_DIV2,
18549 +static struct clk *clkset_camera_list[] = {
18553 +static struct clk_sources clkset_camera = {
18554 + .sources = clkset_camera_list,
18555 + .nr_sources = ARRAY_SIZE(clkset_camera_list),
18558 +static struct clksrc_clk clk_camera = {
18560 + .name = "camera",
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,
18571 + .sources = &clkset_camera,
18572 + .divider_shift = S3C6400_CLKDIV0_CAM_SHIFT,
18573 + .reg_divider = S3C_CLK_DIV0,
18576 +static struct clk *clkset_camif_list[] = {
18580 +static struct clk_sources clkset_camif = {
18581 + .sources = clkset_camif_list,
18582 + .nr_sources = ARRAY_SIZE(clkset_camif_list),
18585 +static struct clksrc_clk clk_camif = {
18589 + .ctrlbit = S3C_CLKCON_HCLK_CAMIF,
18590 + .enable = s3c64xx_hclk_ctrl,
18591 + .set_parent = s3c64xx_setparent_clksrc,
18595 + .sources = &clkset_camif,
18598 /* Clock initialisation code */
18600 static struct clksrc_clk *init_parents[] = {
18601 @@ -534,6 +660,8 @@
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;
18614 + clk_h2.rate = hclk2;
18618 @@ -633,6 +762,9 @@
18627 void __init s3c6400_register_clocks(void)
18628 @@ -650,6 +782,5 @@
18632 - clk_mpll.parent = &clk_mout_mpll.clk;
18633 clk_epll.parent = &clk_mout_epll.clk;
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
18639 +/* linux/0arch/arm/plat-s3c64xx/sleep.S
18641 + * Copyright 2008 Openmoko, Inc.
18642 + * Copyright 2008 Simtec Electronics
18643 + * Ben Dooks <ben@simtec.co.uk>
18644 + * http://armlinux.simtec.co.uk/
18646 + * S3C64XX CPU sleep code
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.
18653 +#include <linux/linkage.h>
18654 +#include <asm/assembler.h>
18655 +#include <mach/map.h>
18657 +#undef S3C64XX_VA_GPIO
18658 +#define S3C64XX_VA_GPIO (0x0)
18660 +#include <plat/regs-gpio.h>
18661 +#include <plat/gpio-bank-n.h>
18663 +#define LL_UART (S3C_PA_UART + (0x400 * CONFIG_S3C_LOWLEVEL_UART_PORT))
18669 + * Save enough processor state to allow the restart of the pm.c
18670 + * code after resume.
18673 + * r0 = pointer to the save block
18675 + * r0 = exit code: 1 => stored data
18676 + * 0 => resumed from sleep
18679 +ENTRY(s3c_cpu_save)
18680 + stmfd sp!, { r4 - r12, lr }
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
18691 + stmia r0, { r4 - r13 } @ Save CP registers and SP
18693 + ldmfd sp, { r4 - r12, pc } @ return, not disturbing SP
18695 + @@ return to the caller, after the MMU is turned on.
18696 + @@ restore the last bits of the stack and return.
18699 + ldmfd sp!, { r4 - r12, pc } @ return, from sp from s3c_cpu_save
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).
18709 + .global s3c_sleep_save_phys
18710 +s3c_sleep_save_phys:
18713 + /* Sleep magic, the word before the resume entry point so that the
18714 + * bootloader can check for a resumeable image. */
18718 + /* s3c_cpu_reusme
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.
18727 +ENTRY(s3c_cpu_resume)
18728 + msr cpsr_c, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
18729 + ldr r2, =LL_UART /* for debug */
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
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 ]
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 ]
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
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
18762 + ldr r0, s3c_sleep_save_phys
18763 + ldmia r0, { r4 - r13 }
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
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
18776 + ldr r2, =resume_with_mmu
18777 + mcr p15, 0, r9, c1, c0, 0 /* turn mmu back on */
18779 + mov pc, r2 /* jump back */
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
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
18797 +# Kernel building helper script (C)2008 Openmoko, Inc
18798 +# Andy Green <andy@openmoko.org>
18800 +# Licensed under GPLv3 or later
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
18808 +# this radically speeds up swapping between build contexts. Note the config
18809 +# for each build lives in the subdir.
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"
18821 +if [ -z "$CROSS_COMPILE" ]; then
18822 + export CROSS_COMPILE=/usr/local/openmoko/arm/bin/arm-angstrom-linux-gnueabi-
18824 +make O=$1 ARCH=arm silentoldconfig
18827 +# figure out what we are building
18832 +if [ ! -z "`grep CONFIG_MACH_NEO1973_GTA01=y $1/.config`" ] ; then
18837 +if [ ! -z "`grep CONFIG_MACH_NEO1973_GTA02=y $1/.config`" ] ; then
18842 +if [ ! -z "`grep CONFIG_MACH_OM_3D7K=y $1/.config`" ] ; then
18847 +if [ ! -z "`grep CONFIG_MACH_SMDK6410=y $1/.config`" ] ; then
18852 +if [ ! -z "`grep CONFIG_MACH_M800=y $1/.config`" ] ; then
18857 +if [ -z "$PRODUCT" ] ; then
18858 + echo "Unable to figure out what we are building from the config"
18863 +# check that we are in a valid branch
18866 +if git branch | head -n1 | grep -q "* (no branch)"; then
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
18875 +# get the branch and head hash for the version we are building to
18876 +# allow source tracability
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
18890 +# actually make it
18893 +if make -j$PARALLEL O=$1 ARCH=arm CONFIG_DEBUG_SECTION_MISMATCH=y EXTRAVERSION=$VERSION; then
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
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
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
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
18914 + tar czf ../modules$VERSION-$HEAD.tar.gz .
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
18929 +if [ -z "$1" ] ; then
18930 + echo "Usage: $0 <DEVICE> eg, $0 GTA02"
18934 +NAME=`echo $1 | cut -d'-' -f1`
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
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 @@
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:
18955 - INITMACHINE(s3c2410_pm_init)
18956 + INITMACHINE(s3c_pm_init)
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.
18962 There is currently no support for over-riding the default method of
18965 enable_irq_wake(IRQ_EINT0);
18967 - s3c2410_pm_init();
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
18978 + * Copyright (c) 2004-2007 Atheros Communications Inc.
18979 + * All rights reserved.
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;
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.
18996 + * This driver is a pseudo ethernet driver to access the Atheros AR6000
18999 +static const char athId[] __attribute__ ((unused)) = "$Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/ar6000_drv.c#2 $";
19001 +#include "ar6000_drv.h"
19004 +MODULE_LICENSE("GPL and additional rights");
19006 +#ifndef REORG_APTC_HEURISTICS
19007 +#undef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19008 +#endif /* REORG_APTC_HEURISTICS */
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 */
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;
19022 +A_TIMER aptcTimer;
19023 +APTC_TRAFFIC_RECORD aptcTR;
19024 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
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;
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);
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");
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
19092 +unsigned int mboxnum = HTC_MAILBOX_NUM_MAX;
19095 +#ifdef CONFIG_AR6000_WLAN_RESET
19096 +unsigned int resetok = 1;
19098 +unsigned int resetok = 0;
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};
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);
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");
19138 +#endif /* DEBUG */
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 */
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 */
19168 +#ifdef BLOCK_TX_PATH_FLAG
19170 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
19171 +module_param(blocktx, int, 0644);
19173 +MODULE_PARM(blocktx, "i");
19175 +#endif /* BLOCK_TX_PATH_FLAG */
19177 +// TODO move to arsoft_c
19178 +USER_RSSI_THOLD rssi_map[12];
19180 +int reconnect_flag = 0;
19182 +DECLARE_WAIT_QUEUE_HEAD(ar6000_scan_queue);
19184 +/* Function declarations */
19185 +static int ar6000_init_module(void);
19186 +static void ar6000_cleanup_module(void);
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);
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);
19200 + * HTC service connection handlers
19202 +static void ar6000_avail_ev(HTC_HANDLE HTCHandle);
19204 +static void ar6000_unavail_ev(void *Instance);
19206 +static void ar6000_target_failure(void *Instance, A_STATUS Status);
19208 +static void ar6000_rx(void *Context, HTC_PACKET *pPacket);
19210 +static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint);
19212 +static void ar6000_tx_complete(void *Context, HTC_PACKET *pPacket);
19214 +static void ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint);
19216 +static void ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint);
19219 + * Static variables
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);
19232 +static A_STATUS ar6000_reinstall_keys(AR_SOFTC_T *ar,A_UINT8 key_op_ctrl);
19236 +static struct ar_cookie s_ar_cookie_mem[MAX_COOKIE_NUM];
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))
19244 +/* Debug log support */
19247 + * Flag to govern whether the debug logs should be parsed in the kernel
19248 + * or reported to the application.
19251 +#define REPORT_DEBUG_LOGS_TO_APP
19255 +ar6000_set_host_app_area(AR_SOFTC_T *ar)
19257 + A_UINT32 address, data;
19258 + struct host_app_area_s host_app_area;
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) {
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)
19278 +dbglog_get_debug_hdr_ptr(AR_SOFTC_T *ar)
19281 + A_UINT32 address;
19284 + address = HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr);
19285 + if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address,
19286 + (A_UCHAR *)¶m, 4)) != A_OK)
19295 + * The dbglog module has been initialized. Its ok to access the relevant
19296 + * data stuctures over the diagnostic window.
19299 +ar6000_dbglog_init_done(AR_SOFTC_T *ar)
19301 + ar->dbglog_init_done = TRUE;
19305 +dbglog_get_debug_fragment(A_INT8 *datap, A_UINT32 len, A_UINT32 limit)
19309 + A_UINT32 numargs;
19311 + A_UINT32 fraglen;
19313 + count = fraglen = 0;
19314 + buffer = (A_INT32 *)datap;
19315 + length = (limit >> 2);
19317 + if (len <= limit) {
19320 + while (count < length) {
19321 + numargs = DBGLOG_GET_NUMARGS(buffer[count]);
19322 + fraglen = (count << 2);
19323 + count += numargs + 1;
19331 +dbglog_parse_debug_logs(A_INT8 *datap, A_UINT32 len)
19335 + A_UINT32 timestamp;
19336 + A_UINT32 debugid;
19337 + A_UINT32 moduleid;
19338 + A_UINT32 numargs;
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) {
19351 + AR_DEBUG_PRINTF("%d %d (%d)\n", moduleid, debugid, timestamp);
19355 + AR_DEBUG_PRINTF("%d %d (%d): 0x%x\n", moduleid, debugid,
19356 + timestamp, buffer[count+1]);
19360 + AR_DEBUG_PRINTF("%d %d (%d): 0x%x, 0x%x\n", moduleid, debugid,
19361 + timestamp, buffer[count+1], buffer[count+2]);
19365 + AR_DEBUG_PRINTF("Invalid args: %d\n", numargs);
19367 + count += numargs + 1;
19372 +ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
19374 + struct dbglog_hdr_s debug_hdr;
19375 + struct dbglog_buf_s debug_buf;
19376 + A_UINT32 address;
19378 + A_UINT32 dropped;
19379 + A_UINT32 firstbuf;
19380 + A_UINT32 debug_hdr_ptr;
19382 + if (!ar->dbglog_init_done) return A_ERROR;
19384 +#ifndef CONFIG_AR6000_WLAN_DEBUG
19388 + AR6000_SPIN_LOCK(&ar->arLock, 0);
19390 + if (ar->dbgLogFetchInProgress) {
19391 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
19395 + /* block out others */
19396 + ar->dbgLogFetchInProgress = TRUE;
19398 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
19400 + debug_hdr_ptr = dbglog_get_debug_hdr_ptr(ar);
19401 + printk("debug_hdr_ptr: 0x%x\n", debug_hdr_ptr);
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);
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)) {
19424 + if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
19425 + (A_UCHAR *)&ar->log_buffer[ar->log_cnt], length))
19429 + ar6000_dbglog_event(ar, dropped, &ar->log_buffer[ar->log_cnt], length);
19430 + ar->log_cnt += length;
19432 + AR_DEBUG_PRINTF("Length: %d (Total size: %d)\n",
19433 + debug_buf.length, debug_buf.bufsize);
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))
19444 + } while (address != firstbuf);
19447 + ar->dbgLogFetchInProgress = FALSE;
19453 +ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped,
19454 + A_INT8 *buffer, A_UINT32 length)
19456 +#ifdef REPORT_DEBUG_LOGS_TO_APP
19457 + #define MAX_WIRELESS_EVENT_SIZE 252
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.
19463 + A_UINT32 send, sent;
19466 + send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
19467 + MAX_WIRELESS_EVENT_SIZE);
19469 + ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, &buffer[sent], send);
19471 + send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
19472 + MAX_WIRELESS_EVENT_SIZE);
19475 + AR_DEBUG_PRINTF("Dropped logs: 0x%x\nDebug info length: %d\n",
19476 + dropped, length);
19478 + /* Interpret the debug logs */
19479 + dbglog_parse_debug_logs(buffer, length);
19480 +#endif /* REPORT_DEBUG_LOGS_TO_APP */
19486 +ar6000_init_module(void)
19488 + static int probed = 0;
19490 + HTC_INIT_INFO initInfo;
19492 + A_MEMZERO(&initInfo,sizeof(initInfo));
19493 + initInfo.AddInstance = ar6000_avail_ev;
19494 + initInfo.DeleteInstance = ar6000_unavail_ev;
19495 + initInfo.TargetFailure = ar6000_target_failure;
19499 + /* Set the debug flags if specified at load time */
19500 + if(debugflags != 0)
19502 + g_dbg_flags = debugflags;
19511 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19512 + memset(&aptcTR, 0, sizeof(APTC_TRAFFIC_RECORD));
19513 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19515 +#ifdef CONFIG_HOST_GPIO_SUPPORT
19516 + ar6000_gpio_init();
19517 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
19519 + status = HTCInit(&initInfo);
19520 + if(status != A_OK)
19526 +static void __exit
19527 +ar6000_cleanup_module(void)
19530 + struct net_device *ar6000_netdev;
19532 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19533 + /* Delete the Adaptive Power Control timer */
19534 + if (timer_pending(&aptcTimer)) {
19535 + del_timer_sync(&aptcTimer);
19537 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
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);
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 */
19552 + AR_DEBUG_PRINTF("ar6000_cleanup: success\n");
19555 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19557 +aptcTimerHandler(unsigned long arg)
19559 + A_UINT32 numbytes;
19560 + A_UINT32 throughput;
19564 + ar = (AR_SOFTC_T *)arg;
19565 + A_ASSERT(ar != NULL);
19566 + A_ASSERT(!timer_pending(&aptcTimer));
19568 + AR6000_SPIN_LOCK(&ar->arLock, 0);
19570 + /* Get the number of bytes transferred */
19571 + numbytes = aptcTR.bytesTransmitted + aptcTR.bytesReceived;
19572 + aptcTR.bytesTransmitted = aptcTR.bytesReceived = 0;
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;
19585 + A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
19588 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
19590 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
19594 +/* set HTC block size, assume BMI is already initialized */
19595 +A_STATUS ar6000_SetHTCBlockSize(AR_SOFTC_T *ar)
19598 + A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX];
19601 + /* get the block sizes */
19602 + status = HIFConfigureDevice(ar->arHifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
19603 + blocksizes, sizeof(blocksizes));
19605 + if (A_FAILED(status)) {
19606 + AR_DEBUG_PRINTF("Failed to get block size info from HIF layer...\n");
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);
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],
19620 + if (A_FAILED(status)) {
19621 + AR_DEBUG_PRINTF("BMIWriteMemory for IO block size failed \n");
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));
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,
19634 + if (A_FAILED(status)) {
19635 + AR_DEBUG_PRINTF("BMIWriteMemory for yield limit failed \n");
19644 +static void free_raw_buffers(AR_SOFTC_T *ar)
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]);
19656 +static int alloc_raw_buffers(AR_SOFTC_T *ar)
19659 + raw_htc_buffer *b;
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);
19666 + ar->raw_htc_read_buffer[i][j] = b;
19668 + for (j = 0; j != RAW_HTC_WRITE_BUFFERS_NUM; j++) {
19669 + b = kzalloc(sizeof(*b), GFP_KERNEL);
19672 + ar->raw_htc_write_buffer[i][j] = b;
19679 + * HTC Event handlers
19682 +ar6000_avail_ev(HTC_HANDLE HTCHandle)
19685 + struct net_device *dev;
19687 + int device_index = 0;
19689 + AR_DEBUG_PRINTF("ar6000_available\n");
19691 + for (i=0; i < MAX_AR6000; i++) {
19692 + if (ar6000_devices[i] == NULL) {
19697 + if (i == MAX_AR6000) {
19698 + AR_DEBUG_PRINTF("ar6000_available: max devices reached\n");
19702 + /* Save this. It gives a bit better readability especially since */
19703 + /* we use another local "i" variable below. */
19704 + device_index = i;
19706 + A_ASSERT(HTCHandle != NULL);
19708 + dev = alloc_etherdev(sizeof(AR_SOFTC_T));
19709 + if (dev == NULL) {
19710 + AR_DEBUG_PRINTF("ar6000_available: can't alloc etherdev\n");
19714 + ether_setup(dev);
19716 + if (netdev_priv(dev) == NULL) {
19717 + printk(KERN_CRIT "ar6000_available: Could not allocate memory\n");
19721 + A_MEMZERO(netdev_priv(dev), sizeof(AR_SOFTC_T));
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;
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;
19738 + ar6000_init_control_info(ar);
19739 + init_waitqueue_head(&arEvent);
19740 + sema_init(&ar->arSem, 1);
19742 + if (alloc_raw_buffers(ar)) {
19743 + free_raw_buffers(ar);
19745 + * @@@ Clean up our own mess, but for anything else, cheerfully mimick
19746 + * the beautiful error non-handling of the rest of this function.
19751 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
19752 + A_INIT_TIMER(&aptcTimer, aptcTimerHandler, ar);
19753 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
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
19760 + * This is intended to support recovery from a corrupted flash on Targets
19761 + * that support flash.
19765 + ar6000_reset_device_skipflash(ar->arHifDevice);
19770 + struct bmi_target_info targ_info;
19772 + if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != A_OK) {
19776 + ar->arVersion.target_ver = targ_info.target_ver;
19777 + ar->arTargetType = targ_info.target_type;
19780 + if (enableuartprint) {
19783 + if (BMIWriteMemory(ar->arHifDevice,
19784 + HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable),
19785 + (A_UCHAR *)¶m,
19788 + AR_DEBUG_PRINTF("BMIWriteMemory for enableuartprint failed \n");
19791 + AR_DEBUG_PRINTF("Serial console prints enabled\n");
19793 +#ifdef CONFIG_HOST_TCMD_SUPPORT
19795 + ar->arTargetMode = AR6000_TCMD_MODE;
19797 + ar->arTargetMode = AR6000_WLAN_MODE;
19800 + if (enabletimerwar) {
19803 + if (BMIReadMemory(ar->arHifDevice,
19804 + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
19805 + (A_UCHAR *)¶m,
19808 + AR_DEBUG_PRINTF("BMIReadMemory for enabletimerwar failed \n");
19812 + param |= HI_OPTION_TIMER_WAR;
19814 + if (BMIWriteMemory(ar->arHifDevice,
19815 + HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
19816 + (A_UCHAR *)¶m,
19819 + AR_DEBUG_PRINTF("BMIWriteMemory for enabletimerwar failed \n");
19822 + AR_DEBUG_PRINTF("Timer WAR enabled\n");
19826 + /* since BMIInit is called in the driver layer, we have to set the block
19827 + * size here for the target */
19829 + if (A_FAILED(ar6000_SetHTCBlockSize(ar))) {
19833 + spin_lock_init(&ar->arLock);
19835 + /* Don't install the init function if BMI is requested */
19838 + dev->init = ar6000_init;
19840 + AR_DEBUG_PRINTF(" BMI enabled \n");
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;
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 */
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
19859 + dev->hard_header_len = ETH_HLEN + sizeof(ATH_LLC_SNAP_HDR) +
19860 + sizeof(WMI_DATA_HDR) + HTC_HEADER_LEN;
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);
19870 + HTCSetInstance(ar->arHtcTarget, ar);
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;
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,
19882 +static void ar6000_target_failure(void *Instance, A_STATUS Status)
19884 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
19885 + WMI_TARGET_ERROR_REPORT_EVENT errEvent;
19886 + static A_BOOL sip = FALSE;
19888 + if (Status != A_OK) {
19889 + if (timer_pending(&ar->arHBChallengeResp.timer)) {
19890 + A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
19893 + /* try dumping target assertion information (if any) */
19894 + ar6000_dump_target_assert_info(ar->arHifDevice,ar->arTargetType);
19897 + * Fetch the logs from the target via the diagnostic
19900 + ar6000_dbglog_get_debug_logs(ar);
19902 + /* Report the error only once */
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));
19917 +ar6000_unavail_ev(void *Instance)
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);
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.
19940 +ar6000_destroy(struct net_device *dev, unsigned int unregister)
19944 + AR_DEBUG_PRINTF("+ar6000_destroy \n");
19946 + if((dev == NULL) || ((ar = netdev_priv(dev)) == NULL))
19948 + AR_DEBUG_PRINTF("%s(): Failed to get device structure.\n", __func__);
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));
19957 + /* Free up the device data structure */
19958 + if (unregister) {
19959 + unregister_netdev(dev);
19961 + ar6000_close(dev);
19964 + free_raw_buffers(ar);
19966 +#ifndef free_netdev
19969 + free_netdev(dev);
19972 + AR_DEBUG_PRINTF("-ar6000_destroy \n");
19975 +static void ar6000_detect_error(unsigned long ptr)
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;
19981 + AR6000_SPIN_LOCK(&ar->arLock, 0);
19983 + if (ar->arHBChallengeResp.outstanding) {
19984 + ar->arHBChallengeResp.missCnt++;
19986 + ar->arHBChallengeResp.missCnt = 0;
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));
20003 + /* Generate the sequence number for the next challenge */
20004 + ar->arHBChallengeResp.seqNum++;
20005 + ar->arHBChallengeResp.outstanding = TRUE;
20007 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
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");
20015 + /* Reschedule the timer for the next challenge */
20016 + A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
20019 +void ar6000_init_profile_info(AR_SOFTC_T *ar)
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;
20037 +ar6000_init_control_info(AR_SOFTC_T *ar)
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;
20048 + ar->arTxPwrSet = FALSE;
20049 + ar->arSkipScan = 0;
20050 + ar->arBeaconInterval = 0;
20051 + ar->arBitRate = 0;
20052 + ar->arMaxRetries = 0;
20053 + ar->arWmmEnabled = TRUE;
20057 +ar6000_open(struct net_device *dev)
20059 + /* Wake up the queues */
20060 + netif_start_queue(dev);
20066 +ar6000_close(struct net_device *dev)
20068 + AR_SOFTC_T *ar = netdev_priv(dev);
20070 + /* Stop the transmit queues */
20071 + netif_stop_queue(dev);
20073 + /* Disable the target and the interrupts associated with it */
20074 + if (ar->arWmiReady == TRUE)
20078 + if (ar->arConnected == TRUE || ar->arConnectPending == TRUE)
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);
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;
20096 + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
20097 + ar->user_key_ctrl = 0;
20101 + AR_DEBUG_PRINTF("%s(): WMI stopped\n", __func__);
20105 + AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n",
20106 + __func__, (unsigned int) ar, (unsigned int) ar->arWmi);
20108 + /* Shut down WMI if we have started it */
20109 + if(ar->arWmiEnabled == TRUE)
20111 + AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__);
20112 + wmi_shutdown(ar->arWmi);
20113 + ar->arWmiEnabled = FALSE;
20114 + ar->arWmi = NULL;
20119 + HTCStop(ar->arHtcTarget);
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);
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);
20132 + AR_DEBUG_PRINTF(" Host does not want target reset. \n");
20135 + /* Done with cookies */
20136 + ar6000_cookie_cleanup(ar);
20138 + /* Cleanup BMI */
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,
20151 + HTC_SERVICE_CONNECT_RESP response;
20155 + A_MEMZERO(&response,sizeof(response));
20157 + status = HTCConnectService(ar->arHtcTarget,
20161 + if (A_FAILED(status)) {
20162 + AR_DEBUG_PRINTF(" Failed to connect to %s service status:%d \n", pDesc, status);
20166 + if (WmiStreamID == WMI_NOT_MAPPED) {
20171 + /* set endpoint mapping for the WMI stream in the driver layer */
20172 + arSetWMIStream2EndpointIDMap(ar,WmiStreamID,response.Endpoint);
20179 +static void ar6000_TxDataCleanup(AR_SOFTC_T *ar)
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);
20198 +/* This function does one time initialization for the lifetime of the device */
20199 +int ar6000_init(struct net_device *dev)
20203 + A_INT32 timeleft;
20205 + if((ar = netdev_priv(dev)) == NULL)
20210 + /* Do we need to finish the BMI phase */
20211 + if(BMIDone(ar->arHifDevice) != A_OK)
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);
20226 + /* Indicate that WMI is enabled (although not ready yet) */
20227 + ar->arWmiEnabled = TRUE;
20228 + if ((ar->arWmi = wmi_init((void *) ar)) == NULL)
20230 + AR_DEBUG_PRINTF("%s() Failed to initialize WMI.\n", __func__);
20234 + AR_DEBUG_PRINTF("%s() Got WMI @ 0x%08x.\n", __func__,
20235 + (unsigned int) ar->arWmi);
20239 + HTC_SERVICE_CONNECT_REQ connect;
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,
20244 + status = HTCWaitTarget(ar->arHtcTarget);
20246 + if (A_FAILED(status)) {
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;
20270 + /* connect to control service */
20271 + connect.ServiceID = WMI_CONTROL_SVC;
20272 + status = ar6000_connectservice(ar,
20276 + if (A_FAILED(status)) {
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
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;
20290 + /* connect to best-effort service */
20291 + connect.ServiceID = WMI_DATA_BE_SVC;
20293 + status = ar6000_connectservice(ar,
20295 + WMI_BEST_EFFORT_PRI,
20297 + if (A_FAILED(status)) {
20301 + /* connect to back-ground
20302 + * map this to WMI LOW_PRI */
20303 + connect.ServiceID = WMI_DATA_BK_SVC;
20304 + status = ar6000_connectservice(ar,
20308 + if (A_FAILED(status)) {
20312 + /* connect to Video service, map this to
20314 + connect.ServiceID = WMI_DATA_VI_SVC;
20315 + status = ar6000_connectservice(ar,
20319 + if (A_FAILED(status)) {
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,
20333 + if (A_FAILED(status)) {
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);
20344 + if (A_FAILED(status)) {
20349 + * give our connected endpoints some buffers
20351 + ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_CONTROL_PRI));
20353 + ar6000_rx_refill(ar, arWMIStream2EndpointID(ar,WMI_BEST_EFFORT_PRI));
20356 + * We will post the receive buffers only for SPE testing and so we are
20357 + * making it conditional on the 'bypasswmi' flag.
20360 + ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_LOW_PRI));
20361 + ar6000_rx_refill(ar,arWMIStream2EndpointID(ar,WMI_HIGH_PRI));
20364 + /* setup credit distribution */
20365 + ar6000_setup_credit_dist(ar->arHtcTarget, &ar->arCreditStateInfo);
20367 + /* Since cookies are used for HTC transports, they should be */
20368 + /* initialized prior to enabling HTC. */
20369 + ar6000_cookie_init(ar);
20372 + status = HTCStart(ar->arHtcTarget);
20374 + if (status != A_OK) {
20375 + if (ar->arWmiEnabled == TRUE) {
20376 + wmi_shutdown(ar->arWmi);
20377 + ar->arWmiEnabled = FALSE;
20378 + ar->arWmi = NULL;
20380 + ar6000_cookie_cleanup(ar);
20384 + if (!bypasswmi) {
20385 + /* Wait for Wmi event to be ready */
20386 + timeleft = wait_event_interruptible_timeout(arEvent,
20387 + (ar->arWmiReady == TRUE), wmitimeout * HZ);
20389 + if(!timeleft || signal_pending(current))
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");
20399 + AR_DEBUG_PRINTF("%s() WMI is ready\n", __func__);
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");
20407 + ar->arNumDataEndPts = 1;
20414 +ar6000_bitrate_rx(void *devt, A_INT32 rateKbps)
20416 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
20418 + ar->arBitRate = rateKbps;
20419 + wake_up(&arEvent);
20423 +ar6000_ratemask_rx(void *devt, A_UINT16 ratemask)
20425 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
20427 + ar->arRateMask = ratemask;
20428 + wake_up(&arEvent);
20432 +ar6000_txPwr_rx(void *devt, A_UINT8 txPwr)
20434 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
20436 + ar->arTxPwr = txPwr;
20437 + wake_up(&arEvent);
20442 +ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList)
20444 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
20446 + A_MEMCPY(ar->arChannelList, chanList, numChan * sizeof (A_UINT16));
20447 + ar->arNumChannels = numChan;
20449 + wake_up(&arEvent);
20453 +ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, A_UINT32 * mapNo)
20455 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
20457 + ATH_MAC_HDR *macHdr;
20458 + A_UINT32 i, eptMap;
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;
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;
20475 + if ((eptMap == -1) && !ar->arNodeMap[i].txPending) {
20480 + if (eptMap == -1) {
20481 + eptMap = ar->arNodeNum;
20482 + ar->arNodeNum ++;
20483 + A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM);
20486 + A_MEMCPY(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN);
20488 + for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) {
20489 + if (!ar->arTxPending[i]) {
20490 + ar->arNodeMap[eptMap].epId = i;
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;
20503 + (*mapNo) = eptMap + 1;
20504 + ar->arNodeMap[eptMap].txPending ++;
20506 + return ar->arNodeMap[eptMap].epId;
20510 +static void ar6000_dump_skb(struct sk_buff *skb)
20513 + for (ch = A_NETBUF_DATA(skb);
20514 + (A_UINT32)ch < ((A_UINT32)A_NETBUF_DATA(skb) +
20515 + A_NETBUF_LEN(skb)); ch++)
20517 + AR_DEBUG_PRINTF("%2.2x ", *ch);
20519 + AR_DEBUG_PRINTF("\n");
20524 +ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
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;
20530 + struct ar_cookie *cookie;
20531 + A_BOOL checkAdHocPsMapping = FALSE;
20533 +#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,6,13)
20534 + skb->list = NULL;
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);
20549 + if (ar->arWmiReady == FALSE && bypasswmi == 0) {
20553 +#ifdef BLOCK_TX_PATH_FLAG
20557 +#endif /* BLOCK_TX_PATH_FLAG */
20559 + if (ar->arWmiEnabled) {
20560 + if (A_NETBUF_HEADROOM(skb) < dev->hard_header_len) {
20561 + struct sk_buff *newbuf;
20563 + * We really should have gotten enough headroom but sometimes
20564 + * we still get packets with not enough headroom. Copy the packet.
20566 + len = A_NETBUF_LEN(skb);
20567 + newbuf = A_NETBUF_ALLOC(len);
20568 + if (newbuf == NULL) {
20571 + A_NETBUF_PUT(newbuf, len);
20572 + A_MEMCPY(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len);
20573 + A_NETBUF_FREE(skb);
20575 + /* fall through and assemble header */
20578 + if (wmi_dix_2_dot3(ar->arWmi, skb) != A_OK) {
20579 + AR_DEBUG_PRINTF("ar6000_data_tx - wmi_dix_2_dot3 failed\n");
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");
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;
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));
20599 + streamID = WMI_BEST_EFFORT_PRI;
20604 + struct iphdr *ipHdr;
20606 + * the endpoint is directly based on the TOS field in the IP
20607 + * header **** only for testing ******
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);
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);
20628 + /* take the lock to protect driver data */
20629 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20633 + if (checkAdHocPsMapping) {
20634 + streamID = ar6000_ibss_map_epid(skb, dev, &mapNo);
20637 + A_ASSERT(streamID != WMI_NOT_MAPPED);
20639 + /* validate that the endpoint is connected */
20640 + if (arWMIStream2EndpointID(ar,streamID) == 0) {
20641 + AR_DEBUG_PRINTF("Stream %d is NOT mapped!\n",streamID);
20644 + /* allocate resource for this packet */
20645 + cookie = ar6000_alloc_cookie(ar);
20647 + if (cookie != NULL) {
20648 + /* update counts while the lock is held */
20649 + ar->arTxPending[streamID]++;
20650 + ar->arTotalTxDataPending++;
20655 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
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,
20662 + A_NETBUF_DATA(skb),
20663 + A_NETBUF_LEN(skb),
20664 + arWMIStream2EndpointID(ar,streamID),
20665 + AR6K_DATA_PKT_TAG);
20668 + if (debugdriver >= 3) {
20669 + ar6000_dump_skb(skb);
20672 + /* HTC interface is asynchronous, if this fails, cleanup will happen in
20673 + * the ar6000_tx_complete callback */
20674 + HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
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);
20685 +#ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
20687 +tvsub(register struct timeval *out, register struct timeval *in)
20689 + if((out->tv_usec -= in->tv_usec) < 0) {
20691 + out->tv_usec += 1000000;
20693 + out->tv_sec -= in->tv_sec;
20697 +applyAPTCHeuristics(AR_SOFTC_T *ar)
20699 + A_UINT32 duration;
20700 + A_UINT32 numbytes;
20701 + A_UINT32 throughput;
20702 + struct timeval ts;
20705 + AR6000_SPIN_LOCK(&ar->arLock, 0);
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;
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);
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;
20732 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20734 +#endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
20737 +ar6000_tx_queue_full(void *Context, HTC_ENDPOINT_ID Endpoint)
20739 + AR_SOFTC_T *ar = (AR_SOFTC_T *) Context;
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 */
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");
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);
20761 +ar6000_tx_queue_avail(void *Context, HTC_ENDPOINT_ID Endpoint)
20763 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
20765 + if (Endpoint == arWMIStream2EndpointID(ar,WMI_CONTROL_PRI)) {
20766 + /* FIXME: what do for it? */
20768 + /* Wake up interface, rescheduling prevented. */
20769 + if (ar->arConnected == TRUE || bypasswmi)
20770 + netif_wake_queue(ar->arNetDev);
20775 +ar6000_tx_complete(void *Context, HTC_PACKET *pPacket)
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;
20782 + struct ar_cookie * ar_cookie;
20783 + WMI_PRI_STREAM_ID streamID;
20784 + A_BOOL wakeEvent = FALSE;
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];
20793 + A_ASSERT(pPacket->pBuffer == A_NETBUF_DATA(skb));
20795 + if (A_SUCCESS(status)) {
20796 + A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(skb));
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,
20804 + /* lock the driver as we update internal state */
20805 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20807 + ar->arTxPending[streamID]--;
20809 + if ((streamID != WMI_CONTROL_PRI) || bypasswmi) {
20810 + ar->arTotalTxDataPending--;
20813 + if (streamID == WMI_CONTROL_PRI)
20815 + if (ar->arWMIControlEpFull) {
20816 + /* since this packet completed, the WMI EP is no longer full */
20817 + ar->arWMIControlEpFull = FALSE;
20820 + if (ar->arTxPending[streamID] == 0) {
20821 + wakeEvent = TRUE;
20825 + if (A_FAILED(status)) {
20826 + AR_DEBUG_PRINTF("%s() -TX ERROR, status: 0x%x\n", __func__,
20828 + AR6000_STAT_INC(ar, tx_errors);
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 */
20839 + // TODO this needs to be looked at
20840 + if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable
20841 + && (streamID != WMI_CONTROL_PRI) && mapNo)
20844 + ar->arNodeMap[mapNo].txPending --;
20846 + if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) {
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 --;
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))
20864 + ar6000_free_cookie(ar, cookie);
20867 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
20869 + /* lock is released, we can freely call other kernel APIs */
20871 + /* this indirectly frees the HTC_PACKET */
20872 + A_NETBUF_FREE(skb);
20875 + wake_up(&arEvent);
20880 + * Receive event handler. This is called by HTC when a packet is received
20884 +ar6000_rx(void *Context, HTC_PACKET *pPacket)
20886 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
20887 + struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext;
20889 + A_STATUS status = pPacket->Status;
20890 + WMI_PRI_STREAM_ID streamID = arEndpoint2WMIStreamID(ar,pPacket->Endpoint);
20891 + HTC_ENDPOINT_ID ept = pPacket->Endpoint;
20893 + A_ASSERT((status != A_OK) || (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN)));
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");
20901 + AR_DEBUG2_PRINTF("OK\n");
20904 + /* take lock to protect buffer counts
20905 + * and adaptive power throughput state */
20906 + AR6000_SPIN_LOCK(&ar->arLock, 0);
20908 + ar->arRxBuffers[streamID]--;
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 */
20918 + A_NETBUF_PUT(skb, pPacket->ActualLength + HTC_HEADER_LEN);
20919 + A_NETBUF_PULL(skb, HTC_HEADER_LEN);
20922 + if (debugdriver >= 2) {
20923 + ar6000_dump_skb(skb);
20925 +#endif /* DEBUG */
20928 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
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) {
20936 + * this is a wmi control msg
20938 + wmi_control_rx(ar->arWmi, skb);
20940 + WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb);
20941 + if (WMI_DATA_HDR_IS_MSG_TYPE(dhdr, CNTL_MSGTYPE)) {
20943 + * this is a wmi control msg
20945 + /* strip off WMI hdr */
20946 + wmi_data_hdr_remove(ar->arWmi, skb);
20947 + wmi_control_rx(ar->arWmi, skb);
20950 + * this is a wmi data packet
20952 + minHdrLen = sizeof (WMI_DATA_HDR) + sizeof(ATH_MAC_HDR) +
20953 + sizeof(ATH_LLC_SNAP_HDR);
20955 + if ((pPacket->ActualLength < minHdrLen) ||
20956 + (pPacket->ActualLength > AR6000_BUFFER_SIZE))
20959 + * packet is too short or too long
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);
20966 + if (ar->arWmmEnabled) {
20967 + wmi_implicit_create_pstream(ar->arWmi, skb,
20968 + DNLINK_TRAFFIC, UNDEFINED_PRI);
20971 + /* Access RSSI values here */
20972 + AR_DEBUG_PRINTF("RSSI %d\n",
20973 + ((WMI_DATA_HDR *) A_NETBUF_DATA(skb))->rssi);
20975 + wmi_data_hdr_remove(ar->arWmi, skb);
20976 + wmi_dot3_2_dix(ar->arWmi, skb);
20978 +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,0)
20980 + * extra push and memcpy, for eth_type_trans() of 2.4 kernel
20981 + * will pull out hard_header_len bytes of the skb.
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));
20987 + if ((ar->arNetDev->flags & IFF_UP) == IFF_UP)
20989 + skb->dev = ar->arNetDev;
20990 + skb->protocol = eth_type_trans(skb, ar->arNetDev);
20995 + A_NETBUF_FREE(skb);
21001 + if ((ar->arNetDev->flags & IFF_UP) == IFF_UP)
21003 + skb->dev = ar->arNetDev;
21004 + skb->protocol = eth_type_trans(skb, ar->arNetDev);
21009 + A_NETBUF_FREE(skb);
21013 + if (status != A_ECANCELED) {
21015 + * HTC provides A_ECANCELED status when it doesn't want to be refilled
21016 + * (probably due to a shutdown)
21018 + ar6000_rx_refill(Context, ept);
21025 +ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint)
21027 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
21030 + int buffersToRefill;
21031 + HTC_PACKET *pPacket;
21032 + WMI_PRI_STREAM_ID streamId = arEndpoint2WMIStreamID(ar,Endpoint);
21034 + buffersToRefill = (int)AR6000_MAX_RX_BUFFERS -
21035 + (int)ar->arRxBuffers[streamId];
21037 + if (buffersToRefill <= 0) {
21038 + /* fast return, nothing to fill */
21042 + AR_DEBUG2_PRINTF("ar6000_rx_refill: providing htc with %d buffers at eid=%d\n",
21043 + buffersToRefill, Endpoint);
21045 + for (RxBuffers = 0; RxBuffers < buffersToRefill; RxBuffers++) {
21046 + osBuf = A_NETBUF_ALLOC(AR6000_BUFFER_SIZE);
21047 + if (NULL == osBuf) {
21050 + /* the HTC packet wrapper is at the head of the reserved area
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);
21059 + /* update count */
21060 + AR6000_SPIN_LOCK(&ar->arLock, 0);
21061 + ar->arRxBuffers[streamId] += RxBuffers;
21062 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
21065 +static struct net_device_stats *
21066 +ar6000_get_stats(struct net_device *dev)
21068 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
21069 + return &ar->arNetStats;
21072 +static struct iw_statistics *
21073 +ar6000_get_iwstats(struct net_device * dev)
21075 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
21076 + TARGET_STATS *pStats = &ar->arTargetStats;
21077 + struct iw_statistics * pIwStats = &ar->arIwStats;
21079 + if ((ar->arWmiReady == FALSE)
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.
21087 +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,0)
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;
21101 + if (down_interruptible(&ar->arSem)) {
21102 + pIwStats->status = 0;
21107 + ar->statsUpdatePending = TRUE;
21109 + if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
21111 + pIwStats->status = 0;
21115 + wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
21117 + if (signal_pending(current)) {
21118 + AR_DEBUG_PRINTF("ar6000 : WMI get stats timeout \n");
21120 + pIwStats->status = 0;
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;
21135 +ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap)
21137 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
21138 + struct net_device *dev = ar->arNetDev;
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]);
21148 + ar->arPhyCapability = phyCap;
21152 +ar6000_iptos_to_userPriority(A_UINT8 *pkt)
21154 + struct iphdr *ipHdr = (struct iphdr *)pkt;
21155 + A_UINT8 userPriority;
21158 + * IP Tos format :
21159 + * (Refer Pg 57 WMM-test-plan-v1.2)
21161 + * : DSCP(6-bits) ECN(2-bits)
21162 + * : DSCP - P2 P1 P0 X X X
21163 + * where (P2 P1 P0) form 802.1D
21165 + userPriority = ipHdr->tos >> 5;
21166 + return (userPriority & 0x7);
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)
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)];
21183 + A_UINT8 key_op_ctrl;
21185 + A_MEMCPY(ar->arBssid, bssid, sizeof(ar->arBssid));
21186 + ar->arBssChannel = channel;
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");
21200 + A_PRINTF("Network: Adhoc (Joiner)\n");
21203 + A_PRINTF("Network: Infrastructure\n");
21206 + if (beaconIeLen && (sizeof(buf) > (9 + beaconIeLen * 2))) {
21207 + AR_DEBUG_PRINTF("\nBeaconIEs= ");
21209 + beacon_ie_pos = 0;
21210 + A_MEMZERO(buf, sizeof(buf));
21211 + sprintf(buf, "%s", beaconIetag);
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]);
21218 + AR_DEBUG_PRINTF("\n");
21220 + A_MEMZERO(&wrqu, sizeof(wrqu));
21221 + wrqu.data.length = strlen(buf);
21222 + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
21225 + if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2))))
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);
21234 + AR_DEBUG_PRINTF("\nAssocRespIEs= ");
21236 + * The Association Response Frame w.o. the WLAN header is delivered to
21237 + * the host, so skip over to the IEs
21239 + for (i = assoc_resp_ie_pos; i < assoc_resp_ie_pos + assocRespLen - 6; i++)
21241 + AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
21242 + sprintf(pos, "%2.2x", assocInfo[i]);
21245 + AR_DEBUG_PRINTF("\n");
21247 + A_MEMZERO(&wrqu, sizeof(wrqu));
21248 + wrqu.data.length = strlen(buf);
21249 + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
21252 + if (assocReqLen && (sizeof(buf) > (17 + (assocReqLen * 2)))) {
21254 + * assoc Request includes capability and listen interval. Skip these.
21256 + assoc_req_ie_pos = beaconIeLen +
21257 + sizeof(A_UINT16) + /* capinfo*/
21258 + sizeof(A_UINT16); /* listen interval */
21260 + A_MEMZERO(buf, sizeof(buf));
21261 + sprintf(buf, "%s", tag1);
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]);
21269 + AR_DEBUG_PRINTF("\n");
21271 + A_MEMZERO(&wrqu, sizeof(wrqu));
21272 + wrqu.data.length = strlen(buf);
21273 + wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
21277 + if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN &&
21278 + ar->user_saved_keys.keyOk == TRUE)
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;
21285 + key_op_ctrl |= KEY_OP_INIT_RSC;
21287 + ar6000_reinstall_keys(ar, key_op_ctrl);
21289 +#endif /* USER_KEYS */
21291 + /* flush data queues */
21292 + ar6000_TxDataCleanup(ar);
21294 + netif_start_queue(ar->arNetDev);
21296 + if ((OPEN_AUTH == ar->arDot11AuthMode) &&
21297 + (NONE_AUTH == ar->arAuthMode) &&
21298 + (WEP_CRYPT == ar->arPairwiseCrypto))
21300 + if (!ar->arConnected) {
21301 + ar6000_install_static_wep_keys(ar);
21305 + ar->arConnected = TRUE;
21306 + ar->arConnectPending = FALSE;
21308 + reconnect_flag = 0;
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;
21322 +void ar6000_set_numdataendpts(AR_SOFTC_T *ar, A_UINT32 num)
21324 + A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1));
21325 + ar->arNumDataEndPts = num;
21329 +ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
21330 + A_UINT8 assocRespLen, A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus)
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]);
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");
21349 + AR_DEBUG_PRINTF("%2.2x ", assocInfo[i]);
21351 + AR_DEBUG_PRINTF("\n");
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.
21358 + if( reason == DISCONNECT_CMD)
21360 + ar->arConnectPending = FALSE;
21362 + ar->arConnectPending = TRUE;
21363 + if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) ||
21364 + ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) {
21365 + ar->arConnected = TRUE;
21369 + ar->arConnected = FALSE;
21371 + if( (reason != CSERV_DISCONNECT) || (reconnect_flag != 1) ) {
21372 + reconnect_flag = 0;
21376 + if (reason != CSERV_DISCONNECT)
21378 + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
21379 + ar->user_key_ctrl = 0;
21381 +#endif /* USER_KEYS */
21383 + netif_stop_queue(ar->arNetDev);
21384 + A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
21385 + ar->arBssChannel = 0;
21386 + ar->arBeaconInterval = 0;
21388 + ar6000_TxDataCleanup(ar);
21392 +ar6000_regDomain_event(AR_SOFTC_T *ar, A_UINT32 regCode)
21394 + A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode);
21395 + ar->arRegCode = regCode;
21399 +ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info)
21401 + static const char *tag = "PRE-AUTH";
21403 + union iwreq_data wrqu;
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");
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 */
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",
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);
21431 +ar6000_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
21433 + static const char *tag = "MLME-MICHAELMICFAILURE.indication";
21435 + union iwreq_data wrqu;
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);
21447 +ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
21449 + AR_DEBUG_PRINTF("AR6000 scan complete: %d\n", status);
21451 + ar->scan_complete = 1;
21452 + wake_up_interruptible(&ar6000_scan_queue);
21456 +ar6000_targetStats_event(AR_SOFTC_T *ar, WMI_TARGET_STATS *pTarget)
21458 + TARGET_STATS *pStats = &ar->arTargetStats;
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);
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);
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;
21506 + pStats->power_save_failure_cnt += pTarget->pmStats.power_save_failure_cnt;
21507 + pStats->noise_floor_calibation = pTarget->noise_floor_calibation;
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;
21519 + pStats->lq_val = pTarget->lqVal;
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;
21526 + ar->statsUpdatePending = FALSE;
21527 + wake_up(&arEvent);
21531 +ar6000_rssiThreshold_event(AR_SOFTC_T *ar, WMI_RSSI_THRESHOLD_VAL newThreshold, A_INT16 rssi)
21533 + USER_RSSI_THOLD userRssiThold;
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));
21545 +ar6000_hbChallengeResp_event(AR_SOFTC_T *ar, A_UINT32 cookie, A_UINT32 source)
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));
21554 + /* This would ignore the replys that come in after their due time */
21555 + if (cookie == ar->arHBChallengeResp.seqNum) {
21556 + ar->arHBChallengeResp.outstanding = FALSE;
21563 +ar6000_reportError_event(AR_SOFTC_T *ar, WMI_TARGET_ERROR_VAL errorVal)
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"
21573 + A_PRINTF("AR6000 Error on Target. Error = 0x%x\n", errorVal);
21575 + /* One error is reported at a time, and errorval is a bitmask */
21576 + if(errorVal & (errorVal - 1))
21579 + A_PRINTF("AR6000 Error type = ");
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]);
21590 + A_PRINTF("INVALID\n");
21598 +ar6000_cac_event(AR_SOFTC_T *ar, A_UINT8 ac, A_UINT8 cacIndication,
21599 + A_UINT8 statusCode, A_UINT8 *tspecSuggestion)
21601 + WMM_TSPEC_IE *tspecIe;
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.
21609 + tspecIe = (WMM_TSPEC_IE *)tspecSuggestion;
21612 + * What do we do, if we get TSPEC rejection? One thought
21613 + * that comes to mind is implictly delete the pstream...
21615 + A_PRINTF("AR6000 CAC notification. "
21616 + "AC = %d, cacIndication = 0x%x, statusCode = 0x%x\n",
21617 + ac, cacIndication, statusCode);
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]); \
21627 +ar6000_roam_tbl_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_TBL *pTbl)
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"
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);
21652 +ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply)
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"));
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*/
21667 + /* If this event contains pattern information, display it*/
21668 + if (wow_reply->this_filter_num) {
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]);
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]);
21688 + * Report the Roaming related data collected on the target
21691 +ar6000_display_roam_time(WMI_TARGET_ROAM_TIME *p)
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);
21709 +ar6000_roam_data_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_DATA *p)
21711 + switch (p->roamDataType) {
21712 + case ROAM_DATA_TIME:
21713 + ar6000_display_roam_time(&p->u.roamTime);
21721 +ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len)
21723 + struct sk_buff *skb;
21724 + WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap;
21727 + if (!ar->arMgmtFilter) {
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)))
21738 + if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) {
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);
21752 +A_UINT32 wmiSendCmdNum;
21755 +ar6000_control_tx(void *devt, void *osbuf, WMI_PRI_STREAM_ID streamID)
21757 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
21758 + A_STATUS status = A_OK;
21759 + struct ar_cookie *cookie = NULL;
21762 + /* take lock to protect ar6000_alloc_cookie() */
21763 + AR6000_SPIN_LOCK(&ar->arLock, 0);
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);
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 */
21774 + AR_DEBUG_PRINTF(" WMI Control EP full, dropping packet : 0x%X, len:%d \n",
21775 + (A_UINT32)osbuf, A_NETBUF_LEN(osbuf));
21777 + cookie = ar6000_alloc_cookie(ar);
21780 + if (cookie == NULL) {
21781 + status = A_NO_MEMORY;
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]);
21796 + if (cookie != NULL) {
21797 + /* got a structure to send it out on */
21798 + ar->arTxPending[streamID]++;
21800 + if (streamID != WMI_CONTROL_PRI) {
21801 + ar->arTotalTxDataPending++;
21805 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
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,
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);
21825 +/* indicate tx activity or inactivity on a WMI stream */
21826 +void ar6000_indicate_tx_activity(void *devt, A_UINT8 TrafficClass, A_BOOL Active)
21828 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
21829 + WMI_PRI_STREAM_ID streamid;
21831 + if (ar->arWmiEnabled) {
21832 + streamid = wmi_get_stream_id(ar->arWmi, TrafficClass);
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;
21839 + /* notify HTC, this may cause credit distribution changes */
21841 + HTCIndicateActivityChange(ar->arHtcTarget,
21842 + arWMIStream2EndpointID(ar,streamid),
21847 +module_init(ar6000_init_module);
21848 +module_exit(ar6000_cleanup_module);
21850 +/* Init cookie queue */
21852 +ar6000_cookie_init(AR_SOFTC_T *ar)
21856 + ar->arCookieList = NULL;
21857 + A_MEMZERO(s_ar_cookie_mem, sizeof(s_ar_cookie_mem));
21859 + for (i = 0; i < MAX_COOKIE_NUM; i++) {
21860 + ar6000_free_cookie(ar, &s_ar_cookie_mem[i]);
21864 +/* cleanup cookie queue */
21866 +ar6000_cookie_cleanup(AR_SOFTC_T *ar)
21868 + /* It is gone .... */
21869 + ar->arCookieList = NULL;
21872 +/* Init cookie queue */
21874 +ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie)
21876 + /* Insert first */
21877 + A_ASSERT(ar != NULL);
21878 + A_ASSERT(cookie != NULL);
21879 + cookie->arc_list_next = ar->arCookieList;
21880 + ar->arCookieList = cookie;
21883 +/* cleanup cookie queue */
21884 +static struct ar_cookie *
21885 +ar6000_alloc_cookie(AR_SOFTC_T *ar)
21887 + struct ar_cookie *cookie;
21889 + cookie = ar->arCookieList;
21890 + if(cookie != NULL)
21892 + ar->arCookieList = cookie->arc_list_next;
21898 +#ifdef SEND_EVENT_TO_APP
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.
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)
21909 +#if (WIRELESS_EXT >= 15)
21911 +/* note: IWEVCUSTOM only exists in wireless extensions after version 15 */
21915 + union iwreq_data wrqu;
21917 + size = len + EVENT_ID_LEN;
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);
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);
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);
21944 +ar6000_tx_retry_err_event(void *devt)
21946 + AR_DEBUG2_PRINTF("Tx retries reach maximum!\n");
21950 +ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, A_UINT8 snr)
21952 + AR_DEBUG2_PRINTF("snr threshold range %d, snr %d\n", newThreshold, snr);
21956 +ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, A_UINT8 lq)
21958 + AR_DEBUG2_PRINTF("lq threshold range %d, lq %d\n", newThreshold, lq);
21964 +a_copy_to_user(void *to, const void *from, A_UINT32 n)
21966 + return(copy_to_user(to, from, n));
21970 +a_copy_from_user(void *to, const void *from, A_UINT32 n)
21972 + return(copy_from_user(to, from, n));
21977 +ar6000_get_driver_cfg(struct net_device *dev,
21978 + A_UINT16 cfgParam,
21982 + A_STATUS ret = 0;
21986 + case AR6000_DRIVER_CFG_GET_WLANNODECACHING:
21987 + *((A_UINT32 *)result) = wlanNodeCaching;
21989 + case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS:
21990 + *((A_UINT32 *)result) = logWmiRawMsgs;
22001 +ar6000_keepalive_rx(void *devt, A_UINT8 configured)
22003 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
22005 + ar->arKeepaliveConfigured = configured;
22006 + wake_up(&arEvent);
22010 +ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID, WMI_PMKID *pmkidList)
22014 + A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID);
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]);
22028 +ar6000_reinstall_keys(AR_SOFTC_T *ar, A_UINT8 key_op_ctrl)
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;
22035 + if (IEEE80211_CIPHER_CCKM_KRK != uik->ik_type) {
22036 + if (NONE_CRYPT == keyType) {
22037 + goto _reinstall_keys_out;
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);
22048 + status = wmi_add_krk_cmd(ar->arWmi, uik->ik_keydata);
22051 + if (IEEE80211_CIPHER_CCKM_KRK != bik->ik_type) {
22052 + if (NONE_CRYPT == keyType) {
22053 + goto _reinstall_keys_out;
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);
22063 + status = wmi_add_krk_cmd(ar->arWmi, bik->ik_keydata);
22066 +_reinstall_keys_out:
22067 + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
22068 + ar->user_key_ctrl = 0;
22072 +#endif /* USER_KEYS */
22076 +ar6000_dset_open_req(
22079 + A_UINT32 targHandle,
22080 + A_UINT32 targReplyFn,
22081 + A_UINT32 targReplyArg)
22086 +ar6000_dset_close(
22088 + A_UINT32 access_cookie)
22094 +ar6000_dset_data_req(
22096 + A_UINT32 accessCookie,
22099 + A_UINT32 targBuf,
22100 + A_UINT32 targReplyFn,
22101 + A_UINT32 targReplyArg)
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
22110 + * Copyright (c) 2004-2007 Atheros Communications Inc.
22111 + * All rights reserved.
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;
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.
22127 +#ifndef _AR6000_H_
22128 +#define _AR6000_H_
22130 +#include <linux/version.h>
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>
22149 +#include <a_config.h>
22150 +#include <athdefs.h>
22151 +#include "a_types.h"
22152 +#include "a_osapi.h"
22153 +#include "htc_api.h"
22155 +#include "a_drv.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"
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>
22173 +#include "targaddrs.h"
22174 +#include "dbglog_api.h"
22175 +#include "ar6000_diag.h"
22176 +#include "common_drv.h"
22179 +#define __dev_put(dev) dev_put(dev)
22184 +#define USER_SAVEDKEYS_STAT_INIT 0
22185 +#define USER_SAVEDKEYS_STAT_RUN 1
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;
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
22206 +#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING)
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;
22214 +#define AR_DEBUG_PRINTF(args...)
22215 +#define AR_DEBUG2_PRINTF(args...)
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);
22221 +#ifdef __cplusplus
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
22237 + DRV_HB_CHALLENGE = 0,
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;
22251 +#define RAW_HTC_READ_BUFFERS_NUM 4
22252 +#define RAW_HTC_WRITE_BUFFERS_NUM 4
22257 + unsigned char data[AR6000_BUFFER_SIZE];
22258 + HTC_PACKET HTCPacket;
22261 +#ifdef CONFIG_HOST_TCMD_SUPPORT
22263 + * add TCMD_MODE besides wmi and bypasswmi
22264 + * in TCMD_MODE, only few TCMD releated wmi commands
22265 + * counld be hanlder
22268 + AR6000_WMI_MODE = 0,
22269 + AR6000_BYPASS_MODE,
22270 + AR6000_TCMD_MODE,
22273 +#endif /* CONFIG_HOST_TCMD_SUPPORT */
22275 +struct ar_wep_key {
22276 + A_UINT8 arKeyIndex;
22277 + A_UINT8 arKeyLen;
22278 + A_UINT8 arKey[64];
22281 +struct ar_node_mapping {
22282 + A_UINT8 macAddress[6];
22284 + A_UINT8 txPending;
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;
22293 +struct ar_hb_chlng_resp {
22295 + A_UINT32 frequency;
22297 + A_BOOL outstanding;
22299 + A_UINT8 missThres;
22302 +typedef struct ar6_softc {
22303 + struct net_device *arNetDev; /* net_device pointer */
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];
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;
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;
22353 + A_UINT32 arTargetMode;
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];
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;
22394 + A_INT32 user_savedkeys_stat;
22395 + A_UINT32 user_key_ctrl;
22396 + struct USER_SAVEDKEYS user_saved_keys;
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)]
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)]
22414 +struct ar_giwscan_param {
22415 + char *current_ev;
22417 + A_BOOL firstPass;
22420 +#define AR6000_STAT_INC(ar, stat) (ar->arNetStats.stat++)
22422 +#define AR6000_SPIN_LOCK(lock, param) do { \
22423 + if (irqs_disabled()) { \
22424 + AR_DEBUG_PRINTF("IRQs disabled:AR6000_LOCK\n"); \
22426 + spin_lock_bh(lock); \
22429 +#define AR6000_SPIN_UNLOCK(lock, param) do { \
22430 + if (irqs_disabled()) { \
22431 + AR_DEBUG_PRINTF("IRQs disabled: AR6000_UNLOCK\n"); \
22433 + spin_unlock_bh(lock); \
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);
22446 +#ifdef HTC_RAW_INTERFACE
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);
22461 +#endif /* HTC_RAW_INTERFACE */
22463 +#ifdef __cplusplus
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
22474 + * Copyright (c) 2004-2007 Atheros Communications Inc.
22475 + * All rights reserved.
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;
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.
22491 +#include "ar6000_drv.h"
22493 +#ifdef HTC_RAW_INTERFACE
22496 +ar6000_htc_raw_read_cb(void *Context, HTC_PACKET *pPacket)
22498 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
22499 + raw_htc_buffer *busy;
22500 + HTC_RAW_STREAM_ID streamID;
22502 + busy = (raw_htc_buffer *)pPacket->pPktContext;
22503 + A_ASSERT(busy != NULL);
22505 + if (pPacket->Status == A_ECANCELED) {
22507 + * HTC provides A_ECANCELED status when it doesn't want to be refilled
22508 + * (probably due to a shutdown)
22513 + streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint);
22514 + A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED);
22517 + if (down_trylock(&ar->raw_htc_read_sem[streamID])) {
22519 + if (down_interruptible(&ar->raw_htc_read_sem[streamID])) {
22521 + AR_DEBUG2_PRINTF("Unable to down the semaphore\n");
22524 + A_ASSERT((pPacket->Status != A_OK) ||
22525 + (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN)));
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]);
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]);
22539 +ar6000_htc_raw_write_cb(void *Context, HTC_PACKET *pPacket)
22541 + AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
22542 + raw_htc_buffer *free;
22543 + HTC_RAW_STREAM_ID streamID;
22545 + free = (raw_htc_buffer *)pPacket->pPktContext;
22546 + A_ASSERT(free != NULL);
22548 + if (pPacket->Status == A_ECANCELED) {
22550 + * HTC provides A_ECANCELED status when it doesn't want to be refilled
22551 + * (probably due to a shutdown)
22556 + streamID = arEndpoint2RawStreamID(ar,pPacket->Endpoint);
22557 + A_ASSERT(streamID != HTC_RAW_STREAM_NOT_MAPPED);
22560 + if (down_trylock(&ar->raw_htc_write_sem[streamID])) {
22562 + if (down_interruptible(&ar->raw_htc_write_sem[streamID])) {
22564 + AR_DEBUG2_PRINTF("Unable to down the semaphore\n");
22567 + A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN));
22569 + free->length = 0;
22570 + ar->write_buffer_available[streamID] = TRUE;
22571 + up(&ar->raw_htc_write_sem[streamID]);
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]);
22578 +/* connect to a service */
22579 +static A_STATUS ar6000_connect_raw_service(AR_SOFTC_T *ar,
22580 + HTC_RAW_STREAM_ID StreamID)
22583 + HTC_SERVICE_CONNECT_RESP response;
22584 + A_UINT8 streamNo;
22585 + HTC_SERVICE_CONNECT_REQ connect;
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;
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;
22608 + A_MEMZERO(&response,sizeof(response));
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,
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");
22624 + /* set endpoint mapping for the RAW HTC streams */
22625 + arSetRawStream2EndpointIDMap(ar,StreamID,response.Endpoint);
22627 + AR_DEBUG_PRINTF("HTC RAW : stream ID: %d, endpoint: %d\n",
22628 + StreamID, arRawStream2EndpointID(ar,StreamID));
22635 +int ar6000_htc_raw_open(AR_SOFTC_T *ar)
22638 + int streamID, endPt, count2;
22639 + raw_htc_buffer *buffer;
22640 + HTC_SERVICE_ID servicepriority;
22642 + A_ASSERT(ar->arHtcTarget != NULL);
22644 + /* wait for target */
22645 + status = HTCWaitTarget(ar->arHtcTarget);
22647 + if (A_FAILED(status)) {
22648 + AR_DEBUG_PRINTF("HTCWaitTarget failed (%d)\n", status);
22652 + for (endPt = 0; endPt < ENDPOINT_MAX; endPt++) {
22653 + ar->arEp2RawMapping[endPt] = HTC_RAW_STREAM_NOT_MAPPED;
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]);
22663 + /* try to connect to the raw service */
22664 + status = ar6000_connect_raw_service(ar,streamID);
22666 + if (A_FAILED(status)) {
22670 + if (arRawStream2EndpointID(ar,streamID) == 0) {
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));
22681 + SET_HTC_PACKET_INFO_RX_REFILL(&buffer->HTCPacket,
22684 + AR6000_BUFFER_SIZE,
22685 + arRawStream2EndpointID(ar,streamID));
22687 + /* Queue buffers to HTC for receive */
22688 + if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != A_OK)
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));
22701 + ar->read_buffer_available[streamID] = FALSE;
22702 + ar->write_buffer_available[streamID] = TRUE;
22705 + if (A_FAILED(status)) {
22709 + AR_DEBUG_PRINTF("HTC RAW, number of streams the target supports: %d \n", streamID);
22711 + servicepriority = HTC_RAW_STREAMS_SVC; /* only 1 */
22713 + /* set callbacks and priority list */
22714 + HTCSetCreditDistribution(ar->arHtcTarget,
22716 + NULL, /* use default */
22717 + NULL, /* use default */
22718 + &servicepriority,
22721 + /* Start the HTC component */
22722 + if ((status = HTCStart(ar->arHtcTarget)) != A_OK) {
22727 + (ar)->arRawIfInit = TRUE;
22732 +int ar6000_htc_raw_close(AR_SOFTC_T *ar)
22734 + A_PRINTF("ar6000_htc_raw_close called \n");
22735 + HTCStop(ar->arHtcTarget);
22737 + /* reset the device */
22738 + ar6000_reset_device(ar->arHifDevice, ar->arTargetType);
22739 + /* Initialize the BMI component */
22746 +get_filled_buffer(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID)
22749 + raw_htc_buffer *busy;
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) {
22758 + if (busy->length) {
22759 + ar->read_buffer_available[StreamID] = TRUE;
22761 + ar->read_buffer_available[StreamID] = FALSE;
22767 +ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
22768 + char __user *buffer, size_t length)
22771 + raw_htc_buffer *busy;
22773 + if (arRawStream2EndpointID(ar,StreamID) == 0) {
22774 + AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID);
22778 + if (down_interruptible(&ar->raw_htc_read_sem[StreamID])) {
22779 + return -ERESTARTSYS;
22782 + busy = get_filled_buffer(ar,StreamID);
22783 + while (!ar->read_buffer_available[StreamID]) {
22784 + up(&ar->raw_htc_read_sem[StreamID]);
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]))
22793 + if (down_interruptible(&ar->raw_htc_read_sem[StreamID])) {
22794 + return -ERESTARTSYS;
22796 + busy = get_filled_buffer(ar,StreamID);
22799 + /* Read the data */
22800 + readPtr = busy->currPtr;
22801 + if (length > busy->length - HTC_HEADER_LEN) {
22802 + length = busy->length - HTC_HEADER_LEN;
22804 + if (copy_to_user(buffer, &busy->data[readPtr], length)) {
22805 + up(&ar->raw_htc_read_sem[StreamID]);
22809 + busy->currPtr += length;
22811 + //AR_DEBUG_PRINTF("raw read ioctl: currPTR : 0x%X 0x%X \n", busy->currPtr,busy->length);
22813 + if (busy->currPtr == busy->length)
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);
22821 + ar->read_buffer_available[StreamID] = FALSE;
22822 + up(&ar->raw_htc_read_sem[StreamID]);
22827 +static raw_htc_buffer *
22828 +get_free_buffer(AR_SOFTC_T *ar, HTC_ENDPOINT_ID StreamID)
22831 + raw_htc_buffer *free;
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) {
22840 + if (!free->length) {
22841 + ar->write_buffer_available[StreamID] = TRUE;
22843 + ar->write_buffer_available[StreamID] = FALSE;
22849 +ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
22850 + char __user *buffer, size_t length)
22853 + raw_htc_buffer *free;
22855 + if (arRawStream2EndpointID(ar,StreamID) == 0) {
22856 + AR_DEBUG_PRINTF("StreamID(%d) not connected! \n", StreamID);
22860 + if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) {
22861 + return -ERESTARTSYS;
22864 + /* Search for a free buffer */
22865 + free = get_free_buffer(ar,StreamID);
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]);
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]))
22878 + if (down_interruptible(&ar->raw_htc_write_sem[StreamID])) {
22879 + return -ERESTARTSYS;
22881 + free = get_free_buffer(ar,StreamID);
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;
22890 + if (copy_from_user(&free->data[writePtr], buffer, length)) {
22891 + up(&ar->raw_htc_read_sem[StreamID]);
22895 + free->length = length;
22897 + SET_HTC_PACKET_INFO_TX(&free->HTCPacket,
22899 + &free->data[writePtr],
22901 + arRawStream2EndpointID(ar,StreamID),
22902 + AR6K_DATA_PKT_TAG);
22904 + HTCSendPkt(ar->arHtcTarget,&free->HTCPacket);
22906 + ar->write_buffer_available[StreamID] = FALSE;
22907 + up(&ar->raw_htc_write_sem[StreamID]);
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
22916 +#ifndef _AR6XAPI_LINUX_H
22917 +#define _AR6XAPI_LINUX_H
22920 + * Copyright (c) 2004-2007 Atheros Communications Inc.
22921 + * All rights reserved.
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;
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.
22937 +#ifdef __cplusplus
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,
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,
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);
22974 +ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl);
22977 +ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p);
22980 +ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters,
22981 + WMI_GET_WOW_LIST_REPLY *wow_reply);
22983 +void ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID,
22984 + WMI_PMKID *pmkidList);
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);
22990 +void ar6000_dbglog_init_done(struct ar6_softc *ar);
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);
22996 +#ifdef CONFIG_HOST_TCMD_SUPPORT
22997 +void ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len);
23000 +void ar6000_tx_retry_err_event(void *devt);
23002 +void ar6000_snrThresholdEvent_rx(void *devt,
23003 + WMI_SNR_THRESHOLD_VAL newThreshold,
23006 +void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, A_UINT8 lqVal);
23009 +void ar6000_ratemask_rx(void *devt, A_UINT16 ratemask);
23011 +A_STATUS ar6000_get_driver_cfg(struct net_device *dev,
23012 + A_UINT16 cfgParam,
23014 +void ar6000_bssInfo_event_rx(struct ar6_softc *ar, A_UINT8 *data, int len);
23016 +void ar6000_dbglog_event(struct ar6_softc *ar, A_UINT32 dropped,
23017 + A_INT8 *buffer, A_UINT32 length);
23019 +int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar);
23021 +void ar6000_indicate_tx_activity(void *devt, A_UINT8 trafficClass, A_BOOL Active);
23023 +void ar6000_dset_open_req(void *devt,
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,
23033 + A_UINT32 targ_buf,
23034 + A_UINT32 targ_reply_fn,
23035 + A_UINT32 targ_reply_arg);
23039 +#ifdef __cplusplus
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
23049 + * Copyright (c) 2004-2006 Atheros Communications Inc.
23050 + * All rights reserved.
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;
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.
23067 +#ifndef _ATHDRV_LINUX_H
23068 +#define _ATHDRV_LINUX_H
23070 +#ifdef __cplusplus
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.
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)
23100 +/* ====WMI Ioctls==== */
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
23109 +#define AR6000_IOCTL_WMI_GETREV (SIOCIWFIRSTPRIV+10)
23112 + * ar6000_version *revision
23115 +#define AR6000_IOCTL_WMI_SETPWR (SIOCIWFIRSTPRIV+11)
23118 + * WMI_POWER_MODE_CMD pwrModeCmd (see include/wmi.h)
23119 + * uses: WMI_SET_POWER_MODE_CMDID
23122 +#define AR6000_IOCTL_WMI_SETSCAN (SIOCIWFIRSTPRIV+12)
23125 + * WMI_SCAN_PARAMS_CMD scanParams (see include/wmi.h)
23126 + * uses: WMI_SET_SCAN_PARAMS_CMDID
23129 +#define AR6000_IOCTL_WMI_SETLISTENINT (SIOCIWFIRSTPRIV+13)
23132 + * UINT32 listenInterval
23133 + * uses: WMI_SET_LISTEN_INT_CMDID
23136 +#define AR6000_IOCTL_WMI_SETBSSFILTER (SIOCIWFIRSTPRIV+14)
23139 + * WMI_BSS_FILTER filter (see include/wmi.h)
23140 + * uses: WMI_SET_BSS_FILTER_CMDID
23143 +#define AR6000_IOCTL_WMI_SET_CHANNELPARAMS (SIOCIWFIRSTPRIV+16)
23146 + * WMI_CHANNEL_PARAMS_CMD chParams
23147 + * uses: WMI_SET_CHANNEL_PARAMS_CMDID
23150 +#define AR6000_IOCTL_WMI_SET_PROBEDSSID (SIOCIWFIRSTPRIV+17)
23153 + * WMI_PROBED_SSID_CMD probedSsids (see include/wmi.h)
23154 + * uses: WMI_SETPROBED_SSID_CMDID
23157 +#define AR6000_IOCTL_WMI_SET_PMPARAMS (SIOCIWFIRSTPRIV+18)
23160 + * WMI_POWER_PARAMS_CMD powerParams (see include/wmi.h)
23161 + * uses: WMI_SET_POWER_PARAMS_CMDID
23164 +#define AR6000_IOCTL_WMI_SET_BADAP (SIOCIWFIRSTPRIV+19)
23167 + * WMI_ADD_BAD_AP_CMD badAPs (see include/wmi.h)
23168 + * uses: WMI_ADD_BAD_AP_CMDID
23171 +#define AR6000_IOCTL_WMI_GET_QOS_QUEUE (SIOCIWFIRSTPRIV+20)
23174 + * ar6000_queuereq queueRequest (see below)
23177 +#define AR6000_IOCTL_WMI_CREATE_QOS (SIOCIWFIRSTPRIV+21)
23180 + * WMI_CREATE_PSTREAM createPstreamCmd (see include/wmi.h)
23181 + * uses: WMI_CREATE_PSTREAM_CMDID
23184 +#define AR6000_IOCTL_WMI_DELETE_QOS (SIOCIWFIRSTPRIV+22)
23187 + * WMI_DELETE_PSTREAM_CMD deletePstreamCmd (see include/wmi.h)
23188 + * uses: WMI_DELETE_PSTREAM_CMDID
23191 +#define AR6000_IOCTL_WMI_SET_SNRTHRESHOLD (SIOCIWFIRSTPRIV+23)
23194 + * WMI_SNR_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h)
23195 + * uses: WMI_SNR_THRESHOLD_PARAMS_CMDID
23198 +#define AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK (SIOCIWFIRSTPRIV+24)
23201 + * WMI_TARGET_ERROR_REPORT_BITMASK errorReportBitMask (see include/wmi.h)
23202 + * uses: WMI_TARGET_ERROR_REPORT_BITMASK_CMDID
23205 +#define AR6000_IOCTL_WMI_GET_TARGET_STATS (SIOCIWFIRSTPRIV+25)
23208 + * TARGET_STATS *targetStats (see below)
23209 + * uses: WMI_GET_STATISTICS_CMDID
23212 +#define AR6000_IOCTL_WMI_SET_ASSOC_INFO (SIOCIWFIRSTPRIV+26)
23215 + * WMI_SET_ASSOC_INFO_CMD setAssocInfoCmd
23216 + * uses: WMI_SET_ASSOC_INFO_CMDID
23219 +#define AR6000_IOCTL_WMI_SET_ACCESS_PARAMS (SIOCIWFIRSTPRIV+27)
23222 + * WMI_SET_ACCESS_PARAMS_CMD setAccessParams (see include/wmi.h)
23223 + * uses: WMI_SET_ACCESS_PARAMS_CMDID
23226 +#define AR6000_IOCTL_WMI_SET_BMISS_TIME (SIOCIWFIRSTPRIV+28)
23229 + * UINT32 beaconMissTime
23230 + * uses: WMI_SET_BMISS_TIME_CMDID
23233 +#define AR6000_IOCTL_WMI_SET_DISC_TIMEOUT (SIOCIWFIRSTPRIV+29)
23236 + * WMI_DISC_TIMEOUT_CMD disconnectTimeoutCmd (see include/wmi.h)
23237 + * uses: WMI_SET_DISC_TIMEOUT_CMDID
23240 +#define AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS (SIOCIWFIRSTPRIV+30)
23243 + * WMI_IBSS_PM_CAPS_CMD ibssPowerMgmtCapsCmd
23244 + * uses: WMI_SET_IBSS_PM_CAPS_CMDID
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.
23253 +#define AR6000_IOCTL_EXTENDED (SIOCIWFIRSTPRIV+31)
23256 +/* ====BMI Extended Ioctls==== */
23258 +#define AR6000_XIOCTL_BMI_DONE 1
23261 + * UINT32 cmd (AR6000_XIOCTL_BMI_DONE)
23265 +#define AR6000_XIOCTL_BMI_READ_MEMORY 2
23270 + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_MEMORY)
23274 + * char results[length]
23276 + * uses: BMI_READ_MEMORY
23279 +#define AR6000_XIOCTL_BMI_WRITE_MEMORY 3
23282 + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_MEMORY)
23285 + * char data[length]
23286 + * uses: BMI_WRITE_MEMORY
23289 +#define AR6000_XIOCTL_BMI_EXECUTE 4
23292 + * UINT32 cmd (AR6000_XIOCTL_BMI_EXECUTE)
23293 + * UINT32 TargetAddress
23294 + * UINT32 parameter
23295 + * uses: BMI_EXECUTE
23298 +#define AR6000_XIOCTL_BMI_SET_APP_START 5
23301 + * UINT32 cmd (AR6000_XIOCTL_BMI_SET_APP_START)
23302 + * UINT32 TargetAddress
23303 + * uses: BMI_SET_APP_START
23306 +#define AR6000_XIOCTL_BMI_READ_SOC_REGISTER 6
23311 + * UINT32 cmd (AR6000_XIOCTL_BMI_READ_SOC_REGISTER)
23312 + * UINT32 TargetAddress, 32-bit aligned
23316 + * uses: BMI_READ_SOC_REGISTER
23319 +#define AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER 7
23323 + * UINT32 cmd (AR6000_XIOCTL_BMI_WRITE_SOC_REGISTER)
23324 + * UINT32 TargetAddress, 32-bit aligned
23325 + * UINT32 newValue
23327 + * uses: BMI_WRITE_SOC_REGISTER
23330 +#define AR6000_XIOCTL_BMI_TEST 8
23333 + * UINT32 cmd (AR6000_XIOCTL_BMI_TEST)
23341 +/* Historical Host-side DataSet support */
23342 +#define AR6000_XIOCTL_UNUSED9 9
23343 +#define AR6000_XIOCTL_UNUSED10 10
23344 +#define AR6000_XIOCTL_UNUSED11 11
23346 +/* ====Misc Extended Ioctls==== */
23348 +#define AR6000_XIOCTL_FORCE_TARGET_RESET 12
23351 + * UINT32 cmd (AR6000_XIOCTL_FORCE_TARGET_RESET)
23355 +#ifdef HTC_RAW_INTERFACE
23356 +/* HTC Raw Interface Ioctls */
23357 +#define AR6000_XIOCTL_HTC_RAW_OPEN 13
23360 + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_OPEN)
23363 +#define AR6000_XIOCTL_HTC_RAW_CLOSE 14
23366 + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_CLOSE)
23369 +#define AR6000_XIOCTL_HTC_RAW_READ 15
23374 + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_READ)
23375 + * UINT32 mailboxID
23378 + * results[length]
23382 +#define AR6000_XIOCTL_HTC_RAW_WRITE 16
23385 + * UINT32 cmd (AR6000_XIOCTL_HTC_RAW_WRITE)
23386 + * UINT32 mailboxID
23388 + * char buffer[length]
23390 +#endif /* HTC_RAW_INTERFACE */
23392 +#define AR6000_XIOCTL_CHECK_TARGET_READY 17
23395 + * UINT32 cmd (AR6000_XIOCTL_CHECK_TARGET_READY)
23400 +/* ====GPIO (General Purpose I/O) Extended Ioctls==== */
23402 +#define AR6000_XIOCTL_GPIO_OUTPUT_SET 18
23405 + * UINT32 cmd (AR6000_XIOCTL_GPIO_OUTPUT_SET)
23406 + * ar6000_gpio_output_set_cmd_s (see below)
23407 + * uses: WMIX_GPIO_OUTPUT_SET_CMDID
23410 +#define AR6000_XIOCTL_GPIO_INPUT_GET 19
23413 + * UINT32 cmd (AR6000_XIOCTL_GPIO_INPUT_GET)
23414 + * uses: WMIX_GPIO_INPUT_GET_CMDID
23417 +#define AR6000_XIOCTL_GPIO_REGISTER_SET 20
23420 + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_SET)
23421 + * ar6000_gpio_register_cmd_s (see below)
23422 + * uses: WMIX_GPIO_REGISTER_SET_CMDID
23425 +#define AR6000_XIOCTL_GPIO_REGISTER_GET 21
23428 + * UINT32 cmd (AR6000_XIOCTL_GPIO_REGISTER_GET)
23429 + * ar6000_gpio_register_cmd_s (see below)
23430 + * uses: WMIX_GPIO_REGISTER_GET_CMDID
23433 +#define AR6000_XIOCTL_GPIO_INTR_ACK 22
23436 + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_ACK)
23437 + * ar6000_cpio_intr_ack_cmd_s (see below)
23438 + * uses: WMIX_GPIO_INTR_ACK_CMDID
23441 +#define AR6000_XIOCTL_GPIO_INTR_WAIT 23
23444 + * UINT32 cmd (AR6000_XIOCTL_GPIO_INTR_WAIT)
23449 +/* ====more wireless commands==== */
23451 +#define AR6000_XIOCTL_SET_ADHOC_BSSID 24
23454 + * UINT32 cmd (AR6000_XIOCTL_SET_ADHOC_BSSID)
23455 + * WMI_SET_ADHOC_BSSID_CMD setAdHocBssidCmd (see include/wmi.h)
23458 +#define AR6000_XIOCTL_SET_OPT_MODE 25
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
23466 +#define AR6000_XIOCTL_OPT_SEND_FRAME 26
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
23474 +#define AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL 27
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
23483 +#define IEEE80211_IOCTL_SETAUTHALG 28
23486 +#define AR6000_XIOCTL_SET_VOICE_PKT_SIZE 29
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
23495 +#define AR6000_XIOCTL_SET_MAX_SP 30
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
23503 +#define AR6000_XIOCTL_WMI_GET_ROAM_TBL 31
23505 +#define AR6000_XIOCTL_WMI_SET_ROAM_CTRL 32
23507 +#define AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS 33
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
23517 +#define AR6000_XIOCTRL_WMI_GET_POWER_MODE 34
23520 + * UINT32 cmd (AR6000_XIOCTRL_WMI_GET_POWER_MODE)
23523 +#define AR6000_XIOCTRL_WMI_SET_WLAN_STATE 35
23527 +} AR6000_WLAN_STATE;
23533 +#define AR6000_XIOCTL_WMI_GET_ROAM_DATA 36
23535 +#define AR6000_XIOCTL_WMI_SETRETRYLIMITS 37
23538 + * WMI_SET_RETRY_LIMITS_CMD ibssSetRetryLimitsCmd
23539 + * uses: WMI_SET_RETRY_LIMITS_CMDID
23542 +#ifdef CONFIG_HOST_TCMD_SUPPORT
23543 +/* ====extended commands for radio test ==== */
23545 +#define AR6000_XIOCTL_TCMD_CONT_TX 38
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
23553 +#define AR6000_XIOCTL_TCMD_CONT_RX 39
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
23561 +#define AR6000_XIOCTL_TCMD_PM 40
23564 + * UINT32 cmd (AR6000_XIOCTL_TCMD_PM)
23565 + * WMI_TCMD_PM_CMD pmCmd (see include/wmi.h)
23566 + * uses: WMI_TCMD_PM_CMDID
23569 +#endif /* CONFIG_HOST_TCMD_SUPPORT */
23571 +#define AR6000_XIOCTL_WMI_STARTSCAN 41
23574 + * UINT32 cmd (AR6000_XIOCTL_WMI_STARTSCAN)
23576 + * UINT8 scanConnected
23577 + * A_BOOL forceFgScan
23578 + * uses: WMI_START_SCAN_CMDID
23581 +#define AR6000_XIOCTL_WMI_SETFIXRATES 42
23583 +#define AR6000_XIOCTL_WMI_GETFIXRATES 43
23586 +#define AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD 44
23589 + * WMI_RSSI_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h)
23590 + * uses: WMI_RSSI_THRESHOLD_PARAMS_CMDID
23593 +#define AR6000_XIOCTL_WMI_CLR_RSSISNR 45
23596 + * WMI_CLR_RSSISNR_CMD thresholdParams (see include/wmi.h)
23597 + * uses: WMI_CLR_RSSISNR_CMDID
23600 +#define AR6000_XIOCTL_WMI_SET_LQTHRESHOLD 46
23603 + * WMI_LQ_THRESHOLD_PARAMS_CMD thresholdParams (see include/wmi.h)
23604 + * uses: WMI_LQ_THRESHOLD_PARAMS_CMDID
23607 +#define AR6000_XIOCTL_WMI_SET_RTS 47
23610 + * WMI_SET_RTS_MODE_CMD (see include/wmi.h)
23611 + * uses: WMI_SET_RTS_MODE_CMDID
23614 +#define AR6000_XIOCTL_WMI_SET_LPREAMBLE 48
23616 +#define AR6000_XIOCTL_WMI_SET_AUTHMODE 49
23619 + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_AUTHMODE)
23621 + * uses: WMI_SET_RECONNECT_AUTH_MODE_CMDID
23624 +#define AR6000_XIOCTL_WMI_SET_REASSOCMODE 50
23628 + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_WMM)
23630 + * uses: WMI_SET_WMM_CMDID
23632 +#define AR6000_XIOCTL_WMI_SET_WMM 51
23636 + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS)
23637 + * UINT32 frequency
23638 + * UINT8 threshold
23640 +#define AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS 52
23644 + * UINT32 cmd (AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP)
23647 +#define AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP 53
23651 + * UINT32 cmd (AR6000_XIOCTL_WMI_GET_RD)
23652 + * UINT32 regDomain
23654 +#define AR6000_XIOCTL_WMI_GET_RD 54
23656 +#define AR6000_XIOCTL_DIAG_READ 55
23658 +#define AR6000_XIOCTL_DIAG_WRITE 56
23661 + * arguments cmd (AR6000_XIOCTL_SET_TXOP)
23662 + * WMI_TXOP_CFG txopEnable
23664 +#define AR6000_XIOCTL_WMI_SET_TXOP 57
23669 + * UINT32 cmd (AR6000_XIOCTL_USER_SETKEYS)
23670 + * UINT32 keyOpCtrl
23671 + * uses AR6000_USER_SETKEYS_INFO
23673 +#define AR6000_XIOCTL_USER_SETKEYS 58
23674 +#endif /* USER_KEYS */
23676 +#define AR6000_XIOCTL_WMI_SET_KEEPALIVE 59
23679 + * UINT8 cmd (AR6000_XIOCTL_WMI_SET_KEEPALIVE)
23680 + * UINT8 keepaliveInterval
23681 + * uses: WMI_SET_KEEPALIVE_CMDID
23684 +#define AR6000_XIOCTL_WMI_GET_KEEPALIVE 60
23687 + * UINT8 cmd (AR6000_XIOCTL_WMI_GET_KEEPALIVE)
23688 + * UINT8 keepaliveInterval
23689 + * A_BOOL configured
23690 + * uses: WMI_GET_KEEPALIVE_CMDID
23693 +/* ====ROM Patching Extended Ioctls==== */
23695 +#define AR6000_XIOCTL_BMI_ROMPATCH_INSTALL 61
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)
23706 + * A_UINT32 resulting rompatch ID
23708 + * uses: BMI_ROMPATCH_INSTALL
23711 +#define AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL 62
23715 + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL)
23716 + * UINT32 rompatch ID
23718 + * uses: BMI_ROMPATCH_UNINSTALL
23721 +#define AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE 63
23725 + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE)
23726 + * UINT32 rompatch count
23727 + * UINT32 rompatch IDs[rompatch count]
23729 + * uses: BMI_ROMPATCH_ACTIVATE
23732 +#define AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE 64
23736 + * UINT32 cmd (AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE)
23737 + * UINT32 rompatch count
23738 + * UINT32 rompatch IDs[rompatch count]
23740 + * uses: BMI_ROMPATCH_DEACTIVATE
23743 +#define AR6000_XIOCTL_WMI_SET_APPIE 65
23747 + * UINT32 cmd (AR6000_XIOCTL_WMI_SET_APPIE)
23748 + * UINT32 app_frmtype;
23749 + * UINT32 app_buflen;
23750 + * UINT8 app_buf[];
23753 +#define AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER 66
23756 + * A_UINT32 filter_type;
23759 +#define AR6000_XIOCTL_DBGLOG_CFG_MODULE 67
23761 +#define AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS 68
23763 +#define AR6000_XIOCTL_WMI_SET_WSC_STATUS 70
23766 + * A_UINT32 wsc_status;
23767 + * (WSC_REG_INACTIVE or WSC_REG_ACTIVE)
23773 + * A_UINT8 streamType;
23774 + * A_UINT8 status;
23776 + * uses: WMI_SET_BT_STATUS_CMDID
23778 +#define AR6000_XIOCTL_WMI_SET_BT_STATUS 71
23783 + * A_UINT8 paramType;
23785 + * A_UINT8 noSCOPkts;
23786 + * BT_PARAMS_A2DP a2dpParams;
23787 + * BT_COEX_REGS regs;
23790 + * uses: WMI_SET_BT_PARAM_CMDID
23792 +#define AR6000_XIOCTL_WMI_SET_BT_PARAMS 72
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
23802 +#define AR6000_XIOCTL_TARGET_INFO 78
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)
23811 +#define AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE 79
23817 +#define AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE 80
23819 + * This ioctl is used to emulate traffic activity
23820 + * timeouts. Activity/inactivity will trigger the driver
23821 + * to re-balance credits.
23824 + * ar6000_traffic_activity_change
23827 +#define AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS 81
23829 + * This ioctl is used to set the connect control flags
23832 + * A_UINT32 connectCtrlFlags
23835 +#define AR6000_XIOCTL_WMI_SET_AKMP_PARAMS 82
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.
23844 + * A_UINT32 akmpInfo;
23846 + * uses: WMI_SET_AKMP_PARAMS_CMD
23849 +#define AR6000_XIOCTL_WMI_GET_PMKID_LIST 83
23851 +#define AR6000_XIOCTL_WMI_SET_PMKID_LIST 84
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.
23860 + * A_UINT32 numPMKID;
23861 + * WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE];
23863 + * uses: WMI_SET_PMKIDLIST_CMD
23866 +/* Historical DSETPATCH support for INI patches */
23867 +#define AR6000_XIOCTL_UNUSED90 90
23871 +/* used by AR6000_IOCTL_WMI_GETREV */
23872 +struct ar6000_version {
23873 + A_UINT32 host_ver;
23874 + A_UINT32 target_ver;
23877 +/* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */
23878 +struct ar6000_queuereq {
23879 + A_UINT8 trafficClass;
23880 + A_UINT16 activeTsids;
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];
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;
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;
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;
23925 + A_UINT64 power_save_failure_cnt;
23926 + A_INT16 noise_floor_calibation;
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;
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;
23947 +typedef struct targetStats_cmd_t {
23948 + TARGET_STATS targetStats;
23950 +} TARGET_STATS_CMD;
23952 +/* used by AR6000_XIOCTL_USER_SETKEYS */
23955 + * Setting this bit to 1 doesnot initialize the RSC on the firmware
23957 +#define AR6000_XIOCTL_USER_SETKEYS_RSC_CTRL 1
23958 +#define AR6000_USER_SETKEYS_RSC_UNCHANGED 0x00000002
23961 + A_UINT32 keyOpCtrl; /* Bit Map of Key Mgmt Ctrl Flags */
23962 +} AR6000_USER_SETKEYS_INFO;
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;
23974 + * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET
23976 +struct ar6000_gpio_register_cmd_s {
23977 + A_UINT32 gpioreg_id;
23981 +/* used by AR6000_XIOCTL_GPIO_INTR_ACK */
23982 +struct ar6000_gpio_intr_ack_cmd_s {
23983 + A_UINT32 ack_mask;
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;
23992 +/* used by the AR6000_XIOCTL_DBGLOG_CFG_MODULE */
23993 +typedef struct ar6000_dbglog_module_config_s {
23999 +} DBGLOG_MODULE_CONFIG;
24001 +typedef struct user_rssi_thold_t {
24004 +} USER_RSSI_THOLD;
24006 +typedef struct user_rssi_params_t {
24008 + A_UINT32 pollTime;
24009 + USER_RSSI_THOLD tholds[12];
24010 +} USER_RSSI_PARAMS;
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.
24018 +#define AR6000_DRIVER_CFG_BASE 0x8000
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
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;
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) */
24037 +#ifdef __cplusplus
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
24046 + * $Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/include/athtypes_linux.h#1 $
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
24052 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
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;
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.
24068 +#ifndef _ATHTYPES_LINUX_H_
24069 +#define _ATHTYPES_LINUX_H_
24072 +#include <linux/types.h>
24075 +typedef int8_t A_INT8;
24076 +typedef int16_t A_INT16;
24077 +typedef int32_t A_INT32;
24078 +typedef int64_t A_INT64;
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;
24085 +typedef int A_BOOL;
24086 +typedef char A_CHAR;
24087 +typedef unsigned char A_UCHAR;
24088 +typedef unsigned long A_ATH_TIMER;
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
24097 + * Copyright (c) 2004-2007 Atheros Communications Inc.
24098 + * All rights reserved.
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;
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.
24114 +#ifndef _CONFIG_LINUX_H_
24115 +#define _CONFIG_LINUX_H_
24117 +#ifdef __cplusplus
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.
24126 +#define CONFIG_HOST_GPIO_SUPPORT
24129 + * Host side Test Command support
24131 +#define CONFIG_HOST_TCMD_SUPPORT
24133 +#define USE_4BYTE_REGISTER_ACCESS
24135 +#ifdef __cplusplus
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
24145 + * Copyright (c) 2004-2006 Atheros Communications Inc.
24146 + * All rights reserved.
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;
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.
24162 +#ifndef _DEBUG_LINUX_H_
24163 +#define _DEBUG_LINUX_H_
24165 +#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING)
24167 +extern A_UINT32 g_dbg_flags;
24169 +#define DBGFMT "%s() : "
24170 +#define DBGARG __func__
24171 +#define DBGFN A_PRINTF
24173 +/* ------- Debug related stuff ------- */
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,
24195 +#define A_DPRINTF(f, a) \
24196 + if(g_dbg_flags & (f)) \
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); \
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); \
24215 +#define AR_DEBUG_ASSERT(test) do { \
24217 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#test)); \
24220 +extern int debughtc;
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)
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
24236 + * Copyright (c) 2004-2007 Atheros Communications Inc.
24237 + * All rights reserved.
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;
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.
24253 +#include "ar6000_drv.h"
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;
24265 +ar6000_ioctl_get_roam_tbl(struct net_device *dev, struct ifreq *rq)
24267 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24269 + if (ar->arWmiReady == FALSE) {
24273 + if(wmi_get_roam_tbl_cmd(ar->arWmi) != A_OK) {
24281 +ar6000_ioctl_get_roam_data(struct net_device *dev, struct ifreq *rq)
24283 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24285 + if (ar->arWmiReady == FALSE) {
24290 + /* currently assume only roam times are required */
24291 + if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != A_OK) {
24300 +ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata)
24302 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24303 + WMI_SET_ROAM_CTRL_CMD cmd;
24304 + A_UINT8 size = sizeof(cmd);
24306 + if (ar->arWmiReady == FALSE) {
24311 + if (copy_from_user(&cmd, userdata, size)) {
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);
24321 + if (copy_from_user(&cmd, userdata, size)) {
24325 + if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != A_OK) {
24333 +ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata)
24335 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24336 + WMI_POWERSAVE_TIMERS_POLICY_CMD cmd;
24337 + A_UINT8 size = sizeof(cmd);
24339 + if (ar->arWmiReady == FALSE) {
24343 + if (copy_from_user(&cmd, userdata, size)) {
24347 + if (copy_from_user(&cmd, userdata, size)) {
24351 + if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != A_OK) {
24359 +ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq)
24361 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24362 + WMI_SET_WMM_CMD cmd;
24365 + if ((dev->flags & IFF_UP) != IFF_UP) {
24368 + if (ar->arWmiReady == FALSE) {
24372 + if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
24378 + if (cmd.status == WMI_WMM_ENABLED) {
24379 + ar->arWmmEnabled = TRUE;
24381 + ar->arWmmEnabled = FALSE;
24384 + ret = wmi_set_wmm_cmd(ar->arWmi, cmd.status);
24391 + case A_NO_MEMORY:
24400 +ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq)
24402 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24403 + WMI_SET_WMM_TXOP_CMD cmd;
24406 + if ((dev->flags & IFF_UP) != IFF_UP) {
24409 + if (ar->arWmiReady == FALSE) {
24413 + if (copy_from_user(&cmd, (char *)((unsigned int*)rq->ifr_data + 1),
24419 + ret = wmi_set_wmm_txop(ar->arWmi, cmd.txopEnable);
24426 + case A_NO_MEMORY:
24435 +ar6000_ioctl_get_rd(struct net_device *dev, struct ifreq *rq)
24437 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24438 + A_STATUS ret = 0;
24440 + if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == FALSE) {
24444 + if(copy_to_user((char *)((unsigned int*)rq->ifr_data + 1),
24445 + &ar->arRegCode, sizeof(ar->arRegCode)))
24452 +/* Get power mode command */
24454 +ar6000_ioctl_get_power_mode(struct net_device *dev, struct ifreq *rq)
24456 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24457 + WMI_POWER_MODE_CMD power_mode;
24460 + if (ar->arWmiReady == FALSE) {
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))) {
24474 +ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq)
24476 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24477 + WMI_CHANNEL_PARAMS_CMD cmd, *cmdp;
24480 + if (ar->arWmiReady == FALSE) {
24485 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24489 + if (cmd.numChannels > 1) {
24490 + cmdp = A_MALLOC(130);
24491 + if (copy_from_user(cmdp, rq->ifr_data,
24493 + ((cmd.numChannels - 1) * sizeof(A_UINT16))))
24502 + if ((ar->arPhyCapability == WMI_11G_CAPABILITY) &&
24503 + ((cmdp->phyMode == WMI_11A_MODE) || (cmdp->phyMode == WMI_11AG_MODE)))
24509 + (wmi_set_channelParams_cmd(ar->arWmi, cmdp->scanParam, cmdp->phyMode,
24510 + cmdp->numChannels, cmdp->channelList)
24516 + if (cmd.numChannels > 1) {
24524 +ar6000_ioctl_set_snr_threshold(struct net_device *dev, struct ifreq *rq)
24527 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24528 + WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
24531 + if (ar->arWmiReady == FALSE) {
24535 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24539 + if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != A_OK ) {
24547 +ar6000_ioctl_set_rssi_threshold(struct net_device *dev, struct ifreq *rq)
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; \
24559 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24560 + WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
24561 + USER_RSSI_PARAMS rssiParams;
24566 + if (ar->arWmiReady == FALSE) {
24570 + if (copy_from_user((char *)&rssiParams, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(USER_RSSI_PARAMS))) {
24573 + cmd.weight = rssiParams.weight;
24574 + cmd.pollTime = rssiParams.pollTime;
24576 + A_MEMCPY(rssi_map, &rssiParams.tholds, sizeof(rssi_map));
24578 + * only 6 elements, so use bubble sorting, in ascending order
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) {
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) {
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);
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;
24618 + if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != A_OK ) {
24626 +ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq)
24629 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24630 + WMI_LQ_THRESHOLD_PARAMS_CMD cmd;
24633 + if (ar->arWmiReady == FALSE) {
24637 + if (copy_from_user(&cmd, (char *)((unsigned int *)rq->ifr_data + 1), sizeof(cmd))) {
24641 + if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != A_OK ) {
24650 +ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq)
24652 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24653 + WMI_PROBED_SSID_CMD cmd;
24656 + if (ar->arWmiReady == FALSE) {
24660 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24664 + if (wmi_probedSsid_cmd(ar->arWmi, cmd.entryIndex, cmd.flag, cmd.ssidLength,
24665 + cmd.ssid) != A_OK)
24674 +ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq)
24676 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24677 + WMI_ADD_BAD_AP_CMD cmd;
24680 + if (ar->arWmiReady == FALSE) {
24685 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24689 + if (cmd.badApIndex > WMI_MAX_BAD_AP_INDEX) {
24693 + if (A_MEMCMP(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) {
24695 + * This is a delete badAP.
24697 + if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != A_OK) {
24701 + if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != A_OK) {
24710 +ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq)
24712 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24713 + WMI_CREATE_PSTREAM_CMD cmd;
24716 + if (ar->arWmiReady == FALSE) {
24721 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24725 + ret = wmi_verify_tspec_params(&cmd, tspecCompliance);
24727 + ret = wmi_create_pstream_cmd(ar->arWmi, &cmd);
24734 + case A_NO_MEMORY:
24743 +ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq)
24745 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24746 + WMI_DELETE_PSTREAM_CMD cmd;
24749 + if (ar->arWmiReady == FALSE) {
24753 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24757 + ret = wmi_delete_pstream_cmd(ar->arWmi, cmd.trafficClass, cmd.tsid);
24764 + case A_NO_MEMORY:
24773 +ar6000_ioctl_get_qos_queue(struct net_device *dev, struct ifreq *rq)
24775 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24776 + struct ar6000_queuereq qreq;
24779 + if (ar->arWmiReady == FALSE) {
24783 + if( copy_from_user(&qreq, rq->ifr_data,
24784 + sizeof(struct ar6000_queuereq)))
24787 + qreq.activeTsids = wmi_get_mapped_qos_queue(ar->arWmi, qreq.trafficClass);
24789 + if (copy_to_user(rq->ifr_data, &qreq,
24790 + sizeof(struct ar6000_queuereq)))
24798 +#ifdef CONFIG_HOST_TCMD_SUPPORT
24800 +ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
24801 + struct ifreq *rq, A_UINT8 *data, A_UINT32 len)
24803 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24807 + if (ar->arWmiReady == FALSE) {
24811 + if (down_interruptible(&ar->arSem)) {
24812 + return -ERESTARTSYS;
24814 + ar->tcmdRxReport = 0;
24815 + if (wmi_test_cmd(ar->arWmi, data, len) != A_OK) {
24820 + wait_event_interruptible_timeout(arEvent, ar->tcmdRxReport != 0, wmitimeout * HZ);
24822 + if (signal_pending(current)) {
24826 + buf[0] = ar->tcmdRxTotalPkt;
24827 + buf[1] = ar->tcmdRxRssi;
24828 + if (!ret && copy_to_user(rq->ifr_data, buf, sizeof(buf))) {
24838 +ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len)
24840 + AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
24841 + TCMD_CONT_RX * rx_rep = (TCMD_CONT_RX *)results;
24843 + ar->tcmdRxTotalPkt = rx_rep->u.report.totalPkt;
24844 + ar->tcmdRxRssi = rx_rep->u.report.rssiInDBm;
24845 + ar->tcmdRxReport = 1;
24847 + wake_up(&arEvent);
24849 +#endif /* CONFIG_HOST_TCMD_SUPPORT*/
24852 +ar6000_ioctl_set_error_report_bitmask(struct net_device *dev, struct ifreq *rq)
24854 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24855 + WMI_TARGET_ERROR_REPORT_BITMASK cmd;
24858 + if (ar->arWmiReady == FALSE) {
24862 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24866 + ret = wmi_set_error_report_bitmask(ar->arWmi, cmd.bitmask);
24868 + return (ret==0 ? ret : -EINVAL);
24872 +ar6000_clear_target_stats(struct net_device *dev)
24874 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24875 + TARGET_STATS *pStats = &ar->arTargetStats;
24878 + if (ar->arWmiReady == FALSE) {
24881 + AR6000_SPIN_LOCK(&ar->arLock, 0);
24882 + A_MEMZERO(pStats, sizeof(TARGET_STATS));
24883 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
24888 +ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
24890 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24891 + TARGET_STATS_CMD cmd;
24892 + TARGET_STATS *pStats = &ar->arTargetStats;
24895 + if (ar->arWmiReady == FALSE) {
24898 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24901 + if (down_interruptible(&ar->arSem)) {
24902 + return -ERESTARTSYS;
24905 + ar->statsUpdatePending = TRUE;
24907 + if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
24912 + wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
24914 + if (signal_pending(current)) {
24918 + if (!ret && copy_to_user(rq->ifr_data, pStats, sizeof(*pStats))) {
24922 + if (cmd.clearStats == 1) {
24923 + ret = ar6000_clear_target_stats(dev);
24932 +ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq)
24934 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24935 + WMI_SET_ACCESS_PARAMS_CMD cmd;
24938 + if (ar->arWmiReady == FALSE) {
24942 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24946 + if (wmi_set_access_params_cmd(ar->arWmi, cmd.txop, cmd.eCWmin, cmd.eCWmax,
24947 + cmd.aifsn) == A_OK)
24958 +ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq)
24960 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24961 + WMI_DISC_TIMEOUT_CMD cmd;
24964 + if (ar->arWmiReady == FALSE) {
24968 + if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
24972 + if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == A_OK)
24983 +ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char * userdata)
24985 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
24986 + WMI_SET_VOICE_PKT_SIZE_CMD cmd;
24989 + if (ar->arWmiReady == FALSE) {
24993 + if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
24997 + if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == A_OK)
25009 +ar6000_xioctl_set_max_sp_len(struct net_device *dev, char * userdata)
25011 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25012 + WMI_SET_MAX_SP_LEN_CMD cmd;
25015 + if (ar->arWmiReady == FALSE) {
25019 + if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
25023 + if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == A_OK)
25035 +ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char * userdata)
25037 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25038 + WMI_SET_BT_STATUS_CMD cmd;
25041 + if (ar->arWmiReady == FALSE) {
25045 + if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
25049 + if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == A_OK)
25060 +ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char * userdata)
25062 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25063 + WMI_SET_BT_PARAMS_CMD cmd;
25066 + if (ar->arWmiReady == FALSE) {
25070 + if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
25074 + if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == A_OK)
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 */
25092 +/* Host-side initialization for General Purpose I/O support */
25093 +void ar6000_gpio_init(void)
25095 + gpio_intr_available = FALSE;
25096 + gpio_data_available = FALSE;
25097 + gpio_ack_received = FALSE;
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.
25106 +ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values)
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);
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
25120 +ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value)
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);
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
25134 +ar6000_gpio_ack_rx(void)
25136 + gpio_ack_received = TRUE;
25137 + wake_up(&arEvent);
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)
25147 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25149 + gpio_ack_received = FALSE;
25150 + return wmi_gpio_output_set(ar->arWmi,
25151 + set_mask, clear_mask, enable_mask, disable_mask);
25155 +ar6000_gpio_input_get(struct net_device *dev)
25157 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25159 + *((volatile A_BOOL *)&gpio_data_available) = FALSE;
25160 + return wmi_gpio_input_get(ar->arWmi);
25164 +ar6000_gpio_register_set(struct net_device *dev,
25165 + A_UINT32 gpioreg_id,
25168 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25170 + gpio_ack_received = FALSE;
25171 + return wmi_gpio_register_set(ar->arWmi, gpioreg_id, value);
25175 +ar6000_gpio_register_get(struct net_device *dev,
25176 + A_UINT32 gpioreg_id)
25178 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25180 + *((volatile A_BOOL *)&gpio_data_available) = FALSE;
25181 + return wmi_gpio_register_get(ar->arWmi, gpioreg_id);
25185 +ar6000_gpio_intr_ack(struct net_device *dev,
25186 + A_UINT32 ack_mask)
25188 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
25190 + gpio_intr_available = FALSE;
25191 + return wmi_gpio_intr_ack(ar->arWmi, ack_mask);
25193 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
25195 +int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
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;
25204 + A_UINT32 connectCtrlFlags;
25207 + static WMI_SCAN_PARAMS_CMD scParams = {0, 0, 0, 0, 0,
25208 + WMI_SHORTSCANRATIO_DEFAULT,
25209 + DEFAULT_SCAN_CTRL_FLAGS,
25211 + WMI_SET_AKMP_PARAMS_CMD akmpParams;
25212 + WMI_SET_PMKID_LIST_CMD pmkidInfo;
25214 + if (cmd == AR6000_IOCTL_EXTENDED)
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.
25222 + get_user(cmd, (int *)rq->ifr_data);
25223 + userdata = (char *)(((unsigned int *)rq->ifr_data)+1);
25227 + userdata = (char *)rq->ifr_data;
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)))
25241 +#ifdef CONFIG_HOST_TCMD_SUPPORT
25242 + case AR6000_XIOCTL_TCMD_CONT_TX:
25244 + TCMD_CONT_TX txCmd;
25246 + if (ar->tcmdPm == TCMD_PM_SLEEP) {
25247 + A_PRINTF("Can NOT send tx tcmd when target is asleep! \n");
25251 + if(copy_from_user(&txCmd, userdata, sizeof(TCMD_CONT_TX)))
25253 + wmi_test_cmd(ar->arWmi,(A_UINT8 *)&txCmd, sizeof(TCMD_CONT_TX));
25256 + case AR6000_XIOCTL_TCMD_CONT_RX:
25258 + TCMD_CONT_RX rxCmd;
25260 + if (ar->tcmdPm == TCMD_PM_SLEEP) {
25261 + A_PRINTF("Can NOT send rx tcmd when target is asleep! \n");
25264 + if(copy_from_user(&rxCmd, userdata, sizeof(TCMD_CONT_RX)))
25266 + switch(rxCmd.act)
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));
25274 + case TCMD_CONT_RX_REPORT:
25275 + ar6000_ioctl_tcmd_get_rx_report(dev, rq,
25276 + (A_UINT8 *)&rxCmd, sizeof(TCMD_CONT_RX));
25279 + A_PRINTF("Unknown Cont Rx mode: %d\n",rxCmd.act);
25284 + case AR6000_XIOCTL_TCMD_PM:
25288 + if(copy_from_user(&pmCmd, userdata, sizeof(TCMD_PM)))
25290 + ar->tcmdPm = pmCmd.mode;
25291 + wmi_test_cmd(ar->arWmi, (A_UINT8*)&pmCmd, sizeof(TCMD_PM));
25294 +#endif /* CONFIG_HOST_TCMD_SUPPORT */
25296 + case AR6000_XIOCTL_BMI_DONE:
25299 + ret = ar6000_init(dev);
25303 + ret = BMIDone(hifDevice);
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)) {
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))
25336 + ret = BMIWriteMemory(hifDevice, address, buffer, length);
25344 + case AR6000_XIOCTL_BMI_TEST:
25345 + AR_DEBUG_PRINTF("No longer supported\n");
25346 + ret = -EOPNOTSUPP;
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",
25354 + ret = BMIExecute(hifDevice, address, ¶m);
25355 + put_user(param, (unsigned int *)rq->ifr_data); /* return value */
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);
25364 + case AR6000_XIOCTL_BMI_READ_SOC_REGISTER:
25365 + get_user(address, (unsigned int *)userdata);
25366 + ret = BMIReadSOCRegister(hifDevice, address, ¶m);
25367 + put_user(param, (unsigned int *)rq->ifr_data); /* return value */
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);
25376 +#ifdef HTC_RAW_INTERFACE
25377 + case AR6000_XIOCTL_HTC_RAW_OPEN:
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)) {
25386 + /* Terminate the BMI phase */
25387 + ret = BMIDone(hifDevice);
25388 + if (ret == A_OK) {
25389 + ret = ar6000_htc_raw_open(ar);
25394 + case AR6000_XIOCTL_HTC_RAW_CLOSE:
25395 + if (arRawIfEnabled(ar)) {
25396 + ret = ar6000_htc_raw_close(ar);
25397 + arRawIfEnabled(ar) = FALSE;
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,
25411 + put_user(ret, (unsigned int *)rq->ifr_data);
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,
25425 + put_user(ret, (unsigned int *)rq->ifr_data);
25430 +#endif /* HTC_RAW_INTERFACE */
25432 + case AR6000_IOCTL_WMI_GETREV:
25434 + if (copy_to_user(rq->ifr_data, &ar->arVersion,
25435 + sizeof(ar->arVersion)))
25441 + case AR6000_IOCTL_WMI_SETPWR:
25443 + WMI_POWER_MODE_CMD pwrModeCmd;
25445 + if (ar->arWmiReady == FALSE) {
25447 + } else if (copy_from_user(&pwrModeCmd, userdata,
25448 + sizeof(pwrModeCmd)))
25452 + if (wmi_powermode_cmd(ar->arWmi, pwrModeCmd.powerMode)
25460 + case AR6000_IOCTL_WMI_SET_IBSS_PM_CAPS:
25462 + WMI_IBSS_PM_CAPS_CMD ibssPmCaps;
25464 + if (ar->arWmiReady == FALSE) {
25466 + } else if (copy_from_user(&ibssPmCaps, userdata,
25467 + sizeof(ibssPmCaps)))
25471 + if (wmi_ibsspmcaps_cmd(ar->arWmi, ibssPmCaps.power_saving, ibssPmCaps.ttl,
25472 + ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != A_OK)
25476 + AR6000_SPIN_LOCK(&ar->arLock, 0);
25477 + ar->arIbssPsEnable = ibssPmCaps.power_saving;
25478 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
25482 + case AR6000_IOCTL_WMI_SET_PMPARAMS:
25484 + WMI_POWER_PARAMS_CMD pmParams;
25486 + if (ar->arWmiReady == FALSE) {
25488 + } else if (copy_from_user(&pmParams, userdata,
25489 + sizeof(pmParams)))
25493 + if (wmi_pmparams_cmd(ar->arWmi, pmParams.idle_period,
25494 + pmParams.pspoll_number,
25495 + pmParams.dtim_policy) != A_OK)
25502 + case AR6000_IOCTL_WMI_SETSCAN:
25504 + if (ar->arWmiReady == FALSE) {
25506 + } else if (copy_from_user(&scParams, userdata,
25507 + sizeof(scParams)))
25511 + if (CAN_SCAN_IN_CONNECT(scParams.scanCtrlFlags)) {
25512 + ar->arSkipScan = FALSE;
25514 + ar->arSkipScan = TRUE;
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)
25532 + case AR6000_IOCTL_WMI_SETLISTENINT:
25534 + WMI_LISTEN_INT_CMD listenCmd;
25536 + if (ar->arWmiReady == FALSE) {
25538 + } else if (copy_from_user(&listenCmd, userdata,
25539 + sizeof(listenCmd)))
25543 + if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != A_OK) {
25546 + AR6000_SPIN_LOCK(&ar->arLock, 0);
25547 + ar->arListenInterval = param;
25548 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
25554 + case AR6000_IOCTL_WMI_SET_BMISS_TIME:
25556 + WMI_BMISS_TIME_CMD bmissCmd;
25558 + if (ar->arWmiReady == FALSE) {
25560 + } else if (copy_from_user(&bmissCmd, userdata,
25561 + sizeof(bmissCmd)))
25565 + if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != A_OK) {
25571 + case AR6000_IOCTL_WMI_SETBSSFILTER:
25573 + if (ar->arWmiReady == FALSE) {
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) {
25586 + case AR6000_IOCTL_WMI_SET_SNRTHRESHOLD:
25588 + ret = ar6000_ioctl_set_snr_threshold(dev, rq);
25591 + case AR6000_XIOCTL_WMI_SET_RSSITHRESHOLD:
25593 + ret = ar6000_ioctl_set_rssi_threshold(dev, rq);
25596 + case AR6000_XIOCTL_WMI_CLR_RSSISNR:
25598 + if (ar->arWmiReady == FALSE) {
25601 + ret = wmi_clr_rssi_snr(ar->arWmi);
25604 + case AR6000_XIOCTL_WMI_SET_LQTHRESHOLD:
25606 + ret = ar6000_ioctl_set_lq_threshold(dev, rq);
25609 + case AR6000_XIOCTL_WMI_SET_LPREAMBLE:
25611 + WMI_SET_LPREAMBLE_CMD setLpreambleCmd;
25613 + if (ar->arWmiReady == FALSE) {
25615 + } else if (copy_from_user(&setLpreambleCmd, userdata,
25616 + sizeof(setLpreambleCmd)))
25620 + if (wmi_set_lpreamble_cmd(ar->arWmi, setLpreambleCmd.status)
25629 + case AR6000_XIOCTL_WMI_SET_RTS:
25631 + WMI_SET_RTS_CMD rtsCmd;
25633 + if (ar->arWmiReady == FALSE) {
25635 + } else if (copy_from_user(&rtsCmd, userdata,
25640 + if (wmi_set_rts_cmd(ar->arWmi, rtsCmd.threshold)
25649 + case AR6000_XIOCTL_WMI_SET_WMM:
25651 + ret = ar6000_ioctl_set_wmm(dev, rq);
25654 + case AR6000_XIOCTL_WMI_SET_TXOP:
25656 + ret = ar6000_ioctl_set_txop(dev, rq);
25659 + case AR6000_XIOCTL_WMI_GET_RD:
25661 + ret = ar6000_ioctl_get_rd(dev, rq);
25664 + case AR6000_IOCTL_WMI_SET_CHANNELPARAMS:
25666 + ret = ar6000_ioctl_set_channelParams(dev, rq);
25669 + case AR6000_IOCTL_WMI_SET_PROBEDSSID:
25671 + ret = ar6000_ioctl_set_probedSsid(dev, rq);
25674 + case AR6000_IOCTL_WMI_SET_BADAP:
25676 + ret = ar6000_ioctl_set_badAp(dev, rq);
25679 + case AR6000_IOCTL_WMI_CREATE_QOS:
25681 + ret = ar6000_ioctl_create_qos(dev, rq);
25684 + case AR6000_IOCTL_WMI_DELETE_QOS:
25686 + ret = ar6000_ioctl_delete_qos(dev, rq);
25689 + case AR6000_IOCTL_WMI_GET_QOS_QUEUE:
25691 + ret = ar6000_ioctl_get_qos_queue(dev, rq);
25694 + case AR6000_IOCTL_WMI_GET_TARGET_STATS:
25696 + ret = ar6000_ioctl_get_target_stats(dev, rq);
25699 + case AR6000_IOCTL_WMI_SET_ERROR_REPORT_BITMASK:
25701 + ret = ar6000_ioctl_set_error_report_bitmask(dev, rq);
25704 + case AR6000_IOCTL_WMI_SET_ASSOC_INFO:
25706 + WMI_SET_ASSOC_INFO_CMD cmd;
25707 + A_UINT8 assocInfo[WMI_MAX_ASSOC_INFO_LEN];
25709 + if (ar->arWmiReady == FALSE) {
25712 + get_user(cmd.ieType, userdata);
25713 + if (cmd.ieType >= WMI_MAX_ASSOC_INFO_TYPE) {
25716 + get_user(cmd.bufferSize, userdata + 1);
25717 + if (cmd.bufferSize > WMI_MAX_ASSOC_INFO_LEN) {
25721 + if (copy_from_user(assocInfo, userdata + 2,
25726 + if (wmi_associnfo_cmd(ar->arWmi, cmd.ieType,
25728 + assocInfo) != A_OK)
25737 + case AR6000_IOCTL_WMI_SET_ACCESS_PARAMS:
25739 + ret = ar6000_ioctl_set_access_params(dev, rq);
25742 + case AR6000_IOCTL_WMI_SET_DISC_TIMEOUT:
25744 + ret = ar6000_ioctl_set_disconnect_timeout(dev, rq);
25747 + case AR6000_XIOCTL_FORCE_TARGET_RESET:
25749 + if (ar->arHtcTarget)
25751 +// HTCForceReset(htcTarget);
25755 + AR_DEBUG_PRINTF("ar6000_ioctl cannot attempt reset.\n");
25759 + case AR6000_XIOCTL_TARGET_INFO:
25760 + case AR6000_XIOCTL_CHECK_TARGET_READY: /* backwards compatibility */
25762 + /* If we made it to here, then the Target exists and is ready. */
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)))
25770 + if (copy_to_user(((A_UINT32 *)rq->ifr_data)+1, &ar->arTargetType,
25771 + sizeof(ar->arTargetType)))
25778 + case AR6000_XIOCTL_WMI_SET_HB_CHALLENGE_RESP_PARAMS:
25780 + WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD hbparam;
25782 + if (copy_from_user(&hbparam, userdata, sizeof(hbparam)))
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;
25791 + if (hbparam.threshold) {
25792 + ar->arHBChallengeResp.missThres = hbparam.threshold;
25795 + /* Delete the pending timer and start a new one */
25796 + if (timer_pending(&ar->arHBChallengeResp.timer)) {
25797 + A_UNTIMEOUT(&ar->arHBChallengeResp.timer);
25799 + A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
25800 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
25804 + case AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP:
25808 + if (copy_from_user(&cookie, userdata, sizeof(cookie))) {
25812 + /* Send the challenge on the control channel */
25813 + if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != A_OK) {
25819 + case AR6000_XIOCTL_USER_SETKEYS:
25822 + ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_RUN;
25824 + if (copy_from_user(&ar->user_key_ctrl, userdata,
25825 + sizeof(ar->user_key_ctrl)))
25830 + A_PRINTF("ar6000 USER set key %x\n", ar->user_key_ctrl);
25833 +#endif /* USER_KEYS */
25835 +#ifdef CONFIG_HOST_GPIO_SUPPORT
25836 + case AR6000_XIOCTL_GPIO_OUTPUT_SET:
25838 + struct ar6000_gpio_output_set_cmd_s gpio_output_set_cmd;
25840 + if (ar->arWmiReady == FALSE) {
25843 + if (down_interruptible(&ar->arSem)) {
25844 + return -ERESTARTSYS;
25847 + if (copy_from_user(&gpio_output_set_cmd, userdata,
25848 + sizeof(gpio_output_set_cmd)))
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) {
25864 + case AR6000_XIOCTL_GPIO_INPUT_GET:
25866 + if (ar->arWmiReady == FALSE) {
25869 + if (down_interruptible(&ar->arSem)) {
25870 + return -ERESTARTSYS;
25873 + ret = ar6000_gpio_input_get(dev);
25874 + if (ret != A_OK) {
25879 + /* Wait for Target to respond. */
25880 + wait_event_interruptible(arEvent, gpio_data_available);
25881 + if (signal_pending(current)) {
25884 + A_ASSERT(gpio_reg_results.gpioreg_id == GPIO_ID_NONE);
25886 + if (copy_to_user(userdata, &gpio_reg_results.value,
25887 + sizeof(gpio_reg_results.value)))
25895 + case AR6000_XIOCTL_GPIO_REGISTER_SET:
25897 + struct ar6000_gpio_register_cmd_s gpio_register_cmd;
25899 + if (ar->arWmiReady == FALSE) {
25902 + if (down_interruptible(&ar->arSem)) {
25903 + return -ERESTARTSYS;
25906 + if (copy_from_user(&gpio_register_cmd, userdata,
25907 + sizeof(gpio_register_cmd)))
25911 + ret = ar6000_gpio_register_set(dev,
25912 + gpio_register_cmd.gpioreg_id,
25913 + gpio_register_cmd.value);
25914 + if (ret != A_OK) {
25918 + /* Wait for acknowledgement from Target */
25919 + wait_event_interruptible(arEvent, gpio_ack_received);
25920 + if (signal_pending(current)) {
25927 + case AR6000_XIOCTL_GPIO_REGISTER_GET:
25929 + struct ar6000_gpio_register_cmd_s gpio_register_cmd;
25931 + if (ar->arWmiReady == FALSE) {
25934 + if (down_interruptible(&ar->arSem)) {
25935 + return -ERESTARTSYS;
25938 + if (copy_from_user(&gpio_register_cmd, userdata,
25939 + sizeof(gpio_register_cmd)))
25943 + ret = ar6000_gpio_register_get(dev, gpio_register_cmd.gpioreg_id);
25944 + if (ret != A_OK) {
25949 + /* Wait for Target to respond. */
25950 + wait_event_interruptible(arEvent, gpio_data_available);
25951 + if (signal_pending(current)) {
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)))
25965 + case AR6000_XIOCTL_GPIO_INTR_ACK:
25967 + struct ar6000_gpio_intr_ack_cmd_s gpio_intr_ack_cmd;
25969 + if (ar->arWmiReady == FALSE) {
25972 + if (down_interruptible(&ar->arSem)) {
25973 + return -ERESTARTSYS;
25976 + if (copy_from_user(&gpio_intr_ack_cmd, userdata,
25977 + sizeof(gpio_intr_ack_cmd)))
25981 + ret = ar6000_gpio_intr_ack(dev, gpio_intr_ack_cmd.ack_mask);
25982 + if (ret != A_OK) {
25989 + case AR6000_XIOCTL_GPIO_INTR_WAIT:
25991 + /* Wait for Target to report an interrupt. */
25994 + wait_event_interruptible(arEvent, gpio_intr_available);
25998 + if (signal_pending(current)) {
26001 + if (copy_to_user(userdata, &gpio_intr_results,
26002 + sizeof(gpio_intr_results)))
26009 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
26011 + case AR6000_XIOCTL_DBGLOG_CFG_MODULE:
26013 + struct ar6000_dbglog_module_config_s config;
26015 + if (copy_from_user(&config, userdata, sizeof(config))) {
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)
26029 + case AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS:
26031 + /* Send the challenge on the control channel */
26032 + if (ar6000_dbglog_get_debug_logs(ar) != A_OK)
26039 + case AR6000_XIOCTL_SET_ADHOC_BSSID:
26041 + WMI_SET_ADHOC_BSSID_CMD adhocBssid;
26043 + if (ar->arWmiReady == FALSE) {
26045 + } else if (copy_from_user(&adhocBssid, userdata,
26046 + sizeof(adhocBssid)))
26049 + } else if (A_MEMCMP(adhocBssid.bssid, bcast_mac,
26050 + AR6000_ETH_ADDR_LEN) == 0)
26055 + A_MEMCPY(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid));
26060 + case AR6000_XIOCTL_SET_OPT_MODE:
26062 + WMI_SET_OPT_MODE_CMD optModeCmd;
26063 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
26065 + if (ar->arWmiReady == FALSE) {
26067 + } else if (copy_from_user(&optModeCmd, userdata,
26068 + sizeof(optModeCmd)))
26071 + } else if (ar->arConnected && optModeCmd.optMode == SPECIAL_ON) {
26074 + } else if (wmi_set_opt_mode_cmd(ar->arWmi, optModeCmd.optMode)
26082 + case AR6000_XIOCTL_OPT_SEND_FRAME:
26084 + WMI_OPT_TX_FRAME_CMD optTxFrmCmd;
26085 + A_UINT8 data[MAX_OPT_DATA_LEN];
26087 + if (ar->arWmiReady == FALSE) {
26089 + } else if (copy_from_user(&optTxFrmCmd, userdata,
26090 + sizeof(optTxFrmCmd)))
26093 + } else if (copy_from_user(data,
26094 + userdata+sizeof(WMI_OPT_TX_FRAME_CMD)-1,
26095 + optTxFrmCmd.optIEDataLen))
26099 + ret = wmi_opt_tx_frame_cmd(ar->arWmi,
26100 + optTxFrmCmd.frmType,
26101 + optTxFrmCmd.dstAddr,
26102 + optTxFrmCmd.bssid,
26103 + optTxFrmCmd.optIEDataLen,
26109 + case AR6000_XIOCTL_WMI_SETRETRYLIMITS:
26111 + WMI_SET_RETRY_LIMITS_CMD setRetryParams;
26113 + if (ar->arWmiReady == FALSE) {
26115 + } else if (copy_from_user(&setRetryParams, userdata,
26116 + sizeof(setRetryParams)))
26120 + if (wmi_set_retry_limits_cmd(ar->arWmi, setRetryParams.frameType,
26121 + setRetryParams.trafficClass,
26122 + setRetryParams.maxRetries,
26123 + setRetryParams.enableNotify) != A_OK)
26127 + AR6000_SPIN_LOCK(&ar->arLock, 0);
26128 + ar->arMaxRetries = setRetryParams.maxRetries;
26129 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
26134 + case AR6000_XIOCTL_SET_ADHOC_BEACON_INTVAL:
26136 + WMI_BEACON_INT_CMD bIntvlCmd;
26138 + if (ar->arWmiReady == FALSE) {
26140 + } else if (copy_from_user(&bIntvlCmd, userdata,
26141 + sizeof(bIntvlCmd)))
26144 + } else if (wmi_set_adhoc_bconIntvl_cmd(ar->arWmi, bIntvlCmd.beaconInterval)
26151 + case IEEE80211_IOCTL_SETAUTHALG:
26153 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
26154 + struct ieee80211req_authalg req;
26156 + if (ar->arWmiReady == FALSE) {
26158 + } else if (copy_from_user(&req, userdata,
26159 + sizeof(struct ieee80211req_authalg)))
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;
26174 + case AR6000_XIOCTL_SET_VOICE_PKT_SIZE:
26175 + ret = ar6000_xioctl_set_voice_pkt_size(dev, userdata);
26178 + case AR6000_XIOCTL_SET_MAX_SP:
26179 + ret = ar6000_xioctl_set_max_sp_len(dev, userdata);
26182 + case AR6000_XIOCTL_WMI_GET_ROAM_TBL:
26183 + ret = ar6000_ioctl_get_roam_tbl(dev, rq);
26185 + case AR6000_XIOCTL_WMI_SET_ROAM_CTRL:
26186 + ret = ar6000_ioctl_set_roam_ctrl(dev, userdata);
26188 + case AR6000_XIOCTRL_WMI_SET_POWERSAVE_TIMERS:
26189 + ret = ar6000_ioctl_set_powersave_timers(dev, userdata);
26191 + case AR6000_XIOCTRL_WMI_GET_POWER_MODE:
26192 + ret = ar6000_ioctl_get_power_mode(dev, rq);
26194 + case AR6000_XIOCTRL_WMI_SET_WLAN_STATE:
26195 + get_user(ar->arWlanState, (unsigned int *)userdata);
26196 + if (ar->arWmiReady == FALSE) {
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)
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)
26227 + ar->arConnectPending = FALSE;
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);
26237 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
26240 + if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0xFF, 0) != A_OK)
26246 + case AR6000_XIOCTL_WMI_GET_ROAM_DATA:
26247 + ret = ar6000_ioctl_get_roam_data(dev, rq);
26249 + case AR6000_XIOCTL_WMI_SET_BT_STATUS:
26250 + ret = ar6000_xioctl_set_bt_status_cmd(dev, userdata);
26252 + case AR6000_XIOCTL_WMI_SET_BT_PARAMS:
26253 + ret = ar6000_xioctl_set_bt_params_cmd(dev, userdata);
26255 + case AR6000_XIOCTL_WMI_STARTSCAN:
26257 + WMI_START_SCAN_CMD setStartScanCmd;
26259 + if (ar->arWmiReady == FALSE) {
26261 + } else if (copy_from_user(&setStartScanCmd, userdata,
26262 + sizeof(setStartScanCmd)))
26266 + if (wmi_startscan_cmd(ar->arWmi, setStartScanCmd.scanType,
26267 + setStartScanCmd.forceFgScan,
26268 + setStartScanCmd.isLegacy,
26269 + setStartScanCmd.homeDwellTime,
26270 + setStartScanCmd.forceScanInterval) != A_OK)
26277 + case AR6000_XIOCTL_WMI_SETFIXRATES:
26279 + WMI_FIX_RATES_CMD setFixRatesCmd;
26280 + A_STATUS returnStatus;
26282 + if (ar->arWmiReady == FALSE) {
26284 + } else if (copy_from_user(&setFixRatesCmd, userdata,
26285 + sizeof(setFixRatesCmd)))
26289 + returnStatus = wmi_set_fixrates_cmd(ar->arWmi, setFixRatesCmd.fixRateMask);
26290 + if (returnStatus == A_EINVAL)
26294 + else if(returnStatus != A_OK) {
26301 + case AR6000_XIOCTL_WMI_GETFIXRATES:
26303 + WMI_FIX_RATES_CMD getFixRatesCmd;
26304 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
26307 + if (ar->arWmiReady == FALSE) {
26311 + if (down_interruptible(&ar->arSem)) {
26312 + return -ERESTARTSYS;
26314 + /* Used copy_from_user/copy_to_user to access user space data */
26315 + if (copy_from_user(&getFixRatesCmd, userdata, sizeof(getFixRatesCmd))) {
26318 + ar->arRateMask = 0xFFFF;
26320 + if (wmi_get_ratemask_cmd(ar->arWmi) != A_OK) {
26325 + wait_event_interruptible_timeout(arEvent, ar->arRateMask != 0xFFFF, wmitimeout * HZ);
26327 + if (signal_pending(current)) {
26332 + getFixRatesCmd.fixRateMask = ar->arRateMask;
26335 + if(copy_to_user(userdata, &getFixRatesCmd, sizeof(getFixRatesCmd))) {
26343 + case AR6000_XIOCTL_WMI_SET_AUTHMODE:
26345 + WMI_SET_AUTH_MODE_CMD setAuthMode;
26347 + if (ar->arWmiReady == FALSE) {
26349 + } else if (copy_from_user(&setAuthMode, userdata,
26350 + sizeof(setAuthMode)))
26354 + if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != A_OK)
26361 + case AR6000_XIOCTL_WMI_SET_REASSOCMODE:
26363 + WMI_SET_REASSOC_MODE_CMD setReassocMode;
26365 + if (ar->arWmiReady == FALSE) {
26367 + } else if (copy_from_user(&setReassocMode, userdata,
26368 + sizeof(setReassocMode)))
26372 + if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != A_OK)
26379 + case AR6000_XIOCTL_DIAG_READ:
26381 + A_UINT32 addr, data;
26382 + get_user(addr, (unsigned int *)userdata);
26383 + if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != A_OK) {
26386 + put_user(data, (unsigned int *)userdata + 1);
26389 + case AR6000_XIOCTL_DIAG_WRITE:
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) {
26399 + case AR6000_XIOCTL_WMI_SET_KEEPALIVE:
26401 + WMI_SET_KEEPALIVE_CMD setKeepAlive;
26402 + if (ar->arWmiReady == FALSE) {
26404 + } else if (copy_from_user(&setKeepAlive, userdata,
26405 + sizeof(setKeepAlive))){
26408 + if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != A_OK) {
26414 + case AR6000_XIOCTL_WMI_GET_KEEPALIVE:
26416 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
26417 + WMI_GET_KEEPALIVE_CMD getKeepAlive;
26419 + if (ar->arWmiReady == FALSE) {
26422 + if (down_interruptible(&ar->arSem)) {
26423 + return -ERESTARTSYS;
26425 + if (copy_from_user(&getKeepAlive, userdata,sizeof(getKeepAlive))) {
26428 + getKeepAlive.keepaliveInterval = wmi_get_keepalive_cmd(ar->arWmi);
26429 + ar->arKeepaliveConfigured = 0xFF;
26430 + if (wmi_get_keepalive_configured(ar->arWmi) != A_OK){
26434 + wait_event_interruptible_timeout(arEvent, ar->arKeepaliveConfigured != 0xFF, wmitimeout * HZ);
26435 + if (signal_pending(current)) {
26440 + getKeepAlive.configured = ar->arKeepaliveConfigured;
26442 + if (copy_to_user(userdata, &getKeepAlive, sizeof(getKeepAlive))) {
26449 + case AR6000_XIOCTL_WMI_SET_APPIE:
26451 + WMI_SET_APPIE_CMD appIEcmd;
26452 + A_UINT8 appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN];
26453 + A_UINT32 fType,ieLen;
26455 + if (ar->arWmiReady == FALSE) {
26458 + get_user(fType, (A_UINT32 *)userdata);
26459 + appIEcmd.mgmtFrmType = fType;
26460 + if (appIEcmd.mgmtFrmType >= IEEE80211_APPIE_NUM_OF_FRAME) {
26463 + get_user(ieLen, (A_UINT32 *)(userdata + 4));
26464 + appIEcmd.ieLen = ieLen;
26465 + if (appIEcmd.ieLen > IEEE80211_APPIE_FRAME_MAX_LEN) {
26469 + if (copy_from_user(appIeInfo, userdata + 8, appIEcmd.ieLen)) {
26472 + if (wmi_set_appie_cmd(ar->arWmi, appIEcmd.mgmtFrmType,
26473 + appIEcmd.ieLen, appIeInfo) != A_OK)
26481 + case AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER:
26483 + WMI_BSS_FILTER_CMD cmd;
26484 + A_UINT32 filterType;
26486 + if (copy_from_user(&filterType, userdata, sizeof(A_UINT32)))
26490 + if (filterType & (IEEE80211_FILTER_TYPE_BEACON |
26491 + IEEE80211_FILTER_TYPE_PROBE_RESP))
26493 + cmd.bssFilter = ALL_BSS_FILTER;
26495 + cmd.bssFilter = NONE_BSS_FILTER;
26497 + if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != A_OK) {
26501 + AR6000_SPIN_LOCK(&ar->arLock, 0);
26502 + ar->arMgmtFilter = filterType;
26503 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
26506 + case AR6000_XIOCTL_WMI_SET_WSC_STATUS:
26508 + A_UINT32 wsc_status;
26510 + if (copy_from_user(&wsc_status, userdata, sizeof(A_UINT32)))
26514 + if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != A_OK) {
26519 + case AR6000_XIOCTL_BMI_ROMPATCH_INSTALL:
26521 + A_UINT32 ROM_addr;
26522 + A_UINT32 RAM_addr;
26524 + A_UINT32 do_activate;
26525 + A_UINT32 rompatch_id;
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 */
26541 + case AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL:
26543 + A_UINT32 rompatch_id;
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);
26551 + case AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE:
26552 + case AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE:
26554 + A_UINT32 rompatch_count;
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))
26565 + if (cmd == AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) {
26566 + ret = BMIrompatchActivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
26568 + ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
26579 + case AR6000_XIOCTL_WMI_SET_HOST_SLEEP_MODE:
26581 + WMI_SET_HOST_SLEEP_MODE_CMD setHostSleepMode;
26583 + if (ar->arWmiReady == FALSE) {
26585 + } else if (copy_from_user(&setHostSleepMode, userdata,
26586 + sizeof(setHostSleepMode)))
26590 + if (wmi_set_host_sleep_mode_cmd(ar->arWmi,
26591 + &setHostSleepMode) != A_OK)
26598 + case AR6000_XIOCTL_WMI_SET_WOW_MODE:
26600 + WMI_SET_WOW_MODE_CMD setWowMode;
26602 + if (ar->arWmiReady == FALSE) {
26604 + } else if (copy_from_user(&setWowMode, userdata,
26605 + sizeof(setWowMode)))
26609 + if (wmi_set_wow_mode_cmd(ar->arWmi,
26610 + &setWowMode) != A_OK)
26617 + case AR6000_XIOCTL_WMI_GET_WOW_LIST:
26619 + WMI_GET_WOW_LIST_CMD getWowList;
26621 + if (ar->arWmiReady == FALSE) {
26623 + } else if (copy_from_user(&getWowList, userdata,
26624 + sizeof(getWowList)))
26628 + if (wmi_get_wow_list_cmd(ar->arWmi,
26629 + &getWowList) != A_OK)
26636 + case AR6000_XIOCTL_WMI_ADD_WOW_PATTERN:
26638 +#define WOW_PATTERN_SIZE 64
26639 +#define WOW_MASK_SIZE 64
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};
26645 + if (ar->arWmiReady == FALSE) {
26649 + if(copy_from_user(&cmd, userdata,
26650 + sizeof(WMI_ADD_WOW_PATTERN_CMD)))
26652 + if (copy_from_user(pattern_data,
26654 + cmd.filter_size)){
26658 + if (copy_from_user(mask_data,
26659 + (userdata + 3 + cmd.filter_size),
26660 + cmd.filter_size)){
26664 + if (wmi_add_wow_pattern_cmd(ar->arWmi,
26665 + &cmd, pattern_data, mask_data, cmd.filter_size) != A_OK){
26670 +#undef WOW_PATTERN_SIZE
26671 +#undef WOW_MASK_SIZE
26674 + case AR6000_XIOCTL_WMI_DEL_WOW_PATTERN:
26676 + WMI_DEL_WOW_PATTERN_CMD delWowPattern;
26678 + if (ar->arWmiReady == FALSE) {
26680 + } else if (copy_from_user(&delWowPattern, userdata,
26681 + sizeof(delWowPattern)))
26685 + if (wmi_del_wow_pattern_cmd(ar->arWmi,
26686 + &delWowPattern) != A_OK)
26693 + case AR6000_XIOCTL_DUMP_HTC_CREDIT_STATE:
26694 + if (ar->arHtcTarget != NULL) {
26695 + HTCDumpCreditStates(ar->arHtcTarget);
26698 + case AR6000_XIOCTL_TRAFFIC_ACTIVITY_CHANGE:
26699 + if (ar->arHtcTarget != NULL) {
26700 + struct ar6000_traffic_activity_change data;
26702 + if (copy_from_user(&data, userdata, sizeof(data)))
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);
26713 + case AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS:
26714 + if (ar->arWmiReady == FALSE) {
26716 + } else if (copy_from_user(&connectCtrlFlags, userdata,
26717 + sizeof(connectCtrlFlags)))
26721 + ar->arConnectCtrlFlags = connectCtrlFlags;
26724 + case AR6000_XIOCTL_WMI_SET_AKMP_PARAMS:
26725 + if (ar->arWmiReady == FALSE) {
26727 + } else if (copy_from_user(&akmpParams, userdata,
26728 + sizeof(WMI_SET_AKMP_PARAMS_CMD)))
26732 + if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != A_OK) {
26737 + case AR6000_XIOCTL_WMI_SET_PMKID_LIST:
26738 + if (ar->arWmiReady == FALSE) {
26741 + if (copy_from_user(&pmkidInfo.numPMKID, userdata,
26742 + sizeof(pmkidInfo.numPMKID)))
26747 + if (copy_from_user(&pmkidInfo.pmkidList,
26748 + userdata + sizeof(pmkidInfo.numPMKID),
26749 + pmkidInfo.numPMKID * sizeof(WMI_PMKID)))
26754 + if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != A_OK) {
26759 + case AR6000_XIOCTL_WMI_GET_PMKID_LIST:
26760 + if (ar->arWmiReady == FALSE) {
26763 + if (wmi_get_pmkid_list_cmd(ar->arWmi) != A_OK) {
26769 + ret = -EOPNOTSUPP;
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
26781 + * Copyright (c) 2004-2007 Atheros Communications Inc.
26782 + * All rights reserved.
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;
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.
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"
26805 +#define AR6000_DATA_OFFSET 64
26807 +void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt)
26809 + skb_queue_tail((struct sk_buff_head *) q, (struct sk_buff *) pkt);
26812 +void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt)
26814 + skb_queue_head((struct sk_buff_head *) q, (struct sk_buff *) pkt);
26817 +void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q)
26819 + return((void *) skb_dequeue((struct sk_buff_head *) q));
26822 +int a_netbuf_queue_size(A_NETBUF_QUEUE_T *q)
26824 + return(skb_queue_len((struct sk_buff_head *) q));
26827 +int a_netbuf_queue_empty(A_NETBUF_QUEUE_T *q)
26829 + return(skb_queue_empty((struct sk_buff_head *) q));
26832 +void a_netbuf_queue_init(A_NETBUF_QUEUE_T *q)
26834 + skb_queue_head_init((struct sk_buff_head *) q);
26838 +a_netbuf_alloc(int size)
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);
26847 + * Allocate an SKB w.o. any encapsulation requirement.
26850 +a_netbuf_alloc_raw(int size)
26852 + struct sk_buff *skb;
26854 + skb = dev_alloc_skb(size);
26856 + return ((void *)skb);
26860 +a_netbuf_free(void *bufPtr)
26862 + struct sk_buff *skb = (struct sk_buff *)bufPtr;
26864 + dev_kfree_skb(skb);
26868 +a_netbuf_to_len(void *bufPtr)
26870 + return (((struct sk_buff *)bufPtr)->len);
26874 +a_netbuf_to_data(void *bufPtr)
26876 + return (((struct sk_buff *)bufPtr)->data);
26880 + * Add len # of bytes to the beginning of the network buffer
26881 + * pointed to by bufPtr
26884 +a_netbuf_push(void *bufPtr, A_INT32 len)
26886 + skb_push((struct sk_buff *)bufPtr, len);
26892 + * Add len # of bytes to the beginning of the network buffer
26893 + * pointed to by bufPtr and also fill with data
26896 +a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len)
26898 + skb_push((struct sk_buff *) bufPtr, len);
26899 + A_MEMCPY(((struct sk_buff *)bufPtr)->data, srcPtr, len);
26905 + * Add len # of bytes to the end of the network buffer
26906 + * pointed to by bufPtr
26909 +a_netbuf_put(void *bufPtr, A_INT32 len)
26911 + skb_put((struct sk_buff *)bufPtr, len);
26917 + * Add len # of bytes to the end of the network buffer
26918 + * pointed to by bufPtr and also fill with data
26921 +a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len)
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);
26933 + * Trim the network buffer pointed to by bufPtr to len # of bytes
26936 +a_netbuf_setlen(void *bufPtr, A_INT32 len)
26938 + skb_trim((struct sk_buff *)bufPtr, len);
26944 + * Chop of len # of bytes from the end of the buffer.
26947 +a_netbuf_trim(void *bufPtr, A_INT32 len)
26949 + skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
26955 + * Chop of len # of bytes from the end of the buffer and return the data.
26958 +a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len)
26960 + char *start = ((struct sk_buff *)bufPtr)->data +
26961 + (((struct sk_buff *)bufPtr)->len - len);
26963 + A_MEMCPY(dstPtr, start, len);
26964 + skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
26971 + * Returns the number of bytes available to a a_netbuf_push()
26974 +a_netbuf_headroom(void *bufPtr)
26976 + return (skb_headroom((struct sk_buff *)bufPtr));
26980 + * Removes specified number of bytes from the beginning of the buffer
26983 +a_netbuf_pull(void *bufPtr, A_INT32 len)
26985 + skb_pull((struct sk_buff *)bufPtr, len);
26991 + * Removes specified number of bytes from the beginning of the buffer
26992 + * and return the data
26995 +a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len)
26997 + A_MEMCPY(dstPtr, ((struct sk_buff *)bufPtr)->data, len);
26998 + skb_pull((struct sk_buff *)bufPtr, len);
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
27008 + * $Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/include/osapi_linux.h#1 $
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
27014 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
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;
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.
27030 +#ifndef _OSAPI_LINUX_H_
27031 +#define _OSAPI_LINUX_H_
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>
27044 +#include <linux/timer.h>
27045 +#include <linux/delay.h>
27046 +#include <linux/wait.h>
27048 +#include <asm/arch/irq.h>
27049 +#include <asm/irq.h>
27053 +#define __ATTRIB_PACK __attribute__ ((packed))
27054 +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2)))
27055 +#define __ATTRIB_NORETURN __attribute__ ((noreturn))
27057 +#define INLINE __inline__
27059 +#else /* Not GCC */
27060 +#define __ATTRIB_PACK
27061 +#define __ATTRIB_PRINTF
27062 +#define __ATTRIB_NORETURN
27064 +#define INLINE __inline
27066 +#endif /* End __GNUC__ */
27069 +#define POSTPACK __ATTRIB_PACK
27072 + * Endianes macros
27074 +#define A_BE2CPU8(x) ntohb(x)
27075 +#define A_BE2CPU16(x) ntohs(x)
27076 +#define A_BE2CPU32(x) ntohl(x)
27078 +#define A_LE2CPU8(x) (x)
27079 +#define A_LE2CPU16(x) (x)
27080 +#define A_LE2CPU32(x) (x)
27082 +#define A_CPU2BE8(x) htonb(x)
27083 +#define A_CPU2BE16(x) htons(x)
27084 +#define A_CPU2BE32(x) htonl(x)
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)
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.. */
27102 +/* Get current time in ms adding a constant offset (in ms) */
27103 +#define A_GET_MS(offset) \
27104 + (jiffies + ((offset) / 1000) * HZ)
27107 + * Timer Functions
27109 +#define A_MDELAY(msecs) mdelay(msecs)
27110 +typedef struct timer_list A_TIMER;
27112 +#define A_INIT_TIMER(pTimer, pFunction, pArg) do { \
27113 + init_timer(pTimer); \
27114 + (pTimer)->function = (pFunction); \
27115 + (pTimer)->data = (unsigned long)(pArg); \
27119 + * Start a Timer that elapses after 'periodMSec' milli-seconds
27120 + * Support is provided for a one-shot timer. The 'repeatFlag' is
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"); \
27128 + mod_timer((pTimer), jiffies + HZ * (periodMSec) / 1000); \
27132 + * Cancel the Timer.
27134 +#define A_UNTIMEOUT(pTimer) do { \
27135 + del_timer((pTimer)); \
27138 +#define A_DELETE_TIMER(pTimer) do { \
27142 + * Wait Queue related functions
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) \
27149 + wait_queue_t __wait; \
27150 + init_waitqueue_entry(&__wait, current); \
27152 + add_wait_queue(&wq, &__wait); \
27154 + set_current_state(TASK_INTERRUPTIBLE); \
27157 + if (!signal_pending(current)) { \
27158 + ret = schedule_timeout(ret); \
27163 + ret = -ERESTARTSYS; \
27166 + current->state = TASK_RUNNING; \
27167 + remove_wait_queue(&wq, &__wait); \
27170 +#define wait_event_interruptible_timeout(wq, condition, timeout) \
27172 + long __ret = timeout; \
27173 + if (!(condition)) \
27174 + __wait_event_interruptible_timeout(wq, condition, __ret); \
27177 +#endif /* wait_event_interruptible_timeout */
27179 +#define A_WAIT_EVENT_INTERRUPTIBLE_TIMEOUT(head, condition, timeout) do { \
27180 + wait_event_interruptible_timeout(head, condition, timeout); \
27183 +#define A_WAKE_UP(head) wake_up(head)
27186 +#define A_ASSERT(expr) \
27188 + printk(KERN_ALERT "\n" __FILE__ ":%d: Assertion " #expr " failed!\n",__LINE__); \
27193 +#define A_ASSERT(expr)
27194 +#endif /* DEBUG */
27197 + * Initialization of the network buffer subsystem
27199 +#define A_NETBUF_INIT()
27202 + * Network buffer queue support
27204 +typedef struct sk_buff_head A_NETBUF_QUEUE_T;
27206 +#define A_NETBUF_QUEUE_INIT(q) \
27207 + a_netbuf_queue_init(q)
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)
27221 + * Network buffer support
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)
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)
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)
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)
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)
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)
27266 +/* return the beginning of the headroom for the buffer */
27267 +#define A_NETBUF_HEAD(bufPtr) \
27268 + ((((struct sk_buff *)(bufPtr))->head))
27271 + * OS specific network buffer access routines
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);
27297 + * Kernel v.s User space functions
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);
27302 +#else /* __KERNEL__ */
27305 +#define __ATTRIB_PACK __attribute__ ((packed))
27306 +#define __ATTRIB_PRINTF __attribute__ ((format (printf, 1, 2)))
27307 +#define __ATTRIB_NORETURN __attribute__ ((noreturn))
27309 +#define INLINE __inline__
27311 +#else /* Not GCC */
27312 +#define __ATTRIB_PACK
27313 +#define __ATTRIB_PRINTF
27314 +#define __ATTRIB_NORETURN
27316 +#define INLINE __inline
27318 +#endif /* End __GNUC__ */
27321 +#define POSTPACK __ATTRIB_PACK
27323 +#endif /* __KERNEL__ */
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
27332 + * Copyright (c) 2004-2007 Atheros Communications Inc.
27333 + * All rights reserved.
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;
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.
27349 +#include "ar6000_drv.h"
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;
27358 + * Encode a WPA or RSN information element as a custom
27359 + * element using the hostap format.
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)
27369 + if (bufsize < leader_len)
27372 + memcpy(p, leader, leader_len);
27373 + bufsize -= 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);
27381 +ar6000_scan_node(void *arg, bss_t *ni)
27383 + struct iw_event iwe;
27384 +#if WIRELESS_EXT > 14
27385 + char buf[64*2 + 30];
27387 + struct ar_giwscan_param *param;
27388 + A_CHAR *current_ev;
27390 + struct ieee80211_common_ie *cie;
27391 + struct iw_request_info info;
27396 + param = (struct ar_giwscan_param *)arg;
27398 + if (param->current_ev >= param->end_buf) {
27401 + if ((param->firstPass == TRUE) &&
27402 + ((ni->ni_cie.ie_wpa == NULL) && (ni->ni_cie.ie_rsn == NULL))) {
27404 + * Only forward wpa bss's in first pass
27409 + if ((param->firstPass == FALSE) &&
27410 + ((ni->ni_cie.ie_wpa != NULL) || (ni->ni_cie.ie_rsn != NULL))) {
27412 + * Only forward non-wpa bss's in 2nd pass
27417 + current_ev = param->current_ev;
27418 + end_buf = param->end_buf;
27420 + cie = &ni->ni_cie;
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,
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]);
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,
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,
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,
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;
27463 + iwe.u.data.flags = IW_ENCODE_DISABLED;
27465 + iwe.u.data.length = 0;
27466 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe, "");
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);
27474 + if (cie->ie_wpa != NULL) {
27475 + static const char wpa_leader[] = "wpa_ie=";
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);
27483 + if (iwe.u.data.length != 0) {
27484 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
27489 + if (cie->ie_rsn != NULL && cie->ie_rsn[0] == IEEE80211_ELEMID_RSN) {
27490 + static const char rsn_leader[] = "rsn_ie=";
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);
27498 + if (iwe.u.data.length != 0) {
27499 + current_ev = iwe_stream_add_point(&info, current_ev, end_buf, &iwe,
27504 + if (cie->ie_wmm != NULL) {
27505 + static const char wmm_leader[] = "wmm_ie=";
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,
27518 + if (cie->ie_ath != NULL) {
27519 + static const char ath_leader[] = "ath_ie=";
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,
27532 + param->current_ev = current_ev;
27536 +ar6000_ioctl_giwscan(struct net_device *dev,
27537 + struct iw_request_info *info,
27538 + struct iw_point *data, char *extra)
27540 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27541 + struct ar_giwscan_param param;
27544 + if (ar->arWlanState == WLAN_DISABLED) {
27548 + if (ar->arWmiReady == FALSE) {
27552 + param.current_ev = extra;
27553 + param.end_buf = extra + IW_SCAN_MAX_DATA;
27554 + param.firstPass = TRUE;
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.
27565 + for (i = 0; i < 2; i++) {
27567 + * Translate data to WE format.
27569 + wmi_iterate_nodes(ar->arWmi, ar6000_scan_node, ¶m);
27570 + param.firstPass = FALSE;
27571 + if (param.current_ev >= param.end_buf) {
27572 + data->length = param.current_ev - extra;
27577 + data->length = param.current_ev - extra;
27581 +extern int reconnect_flag;
27582 +/* SIOCSIWESSID */
27584 +ar6000_ioctl_siwessid(struct net_device *dev,
27585 + struct iw_request_info *info,
27586 + struct iw_point *data, char *ssid)
27588 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27590 + A_UINT8 arNetworkType;
27592 + if (ar->arWlanState == WLAN_DISABLED) {
27596 + if (ar->arWmiReady == FALSE) {
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.
27605 + if (data->flags && (!data->length || data->length >= sizeof(ar->arSsid))) {
27607 + * ssid is invalid
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.
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])))
27625 + if (down_interruptible(&ar->arSem)) {
27626 + return -ERESTARTSYS;
27629 + if (ar->arTxPending[WMI_CONTROL_PRI]) {
27631 + * sleep until the command queue drains
27633 + wait_event_interruptible_timeout(arEvent,
27634 + ar->arTxPending[WMI_CONTROL_PRI] == 0, wmitimeout * HZ);
27635 + if (signal_pending(current)) {
27640 + if (!data->flags) {
27641 + arNetworkType = ar->arNetworkType;
27642 + ar6000_init_profile_info(ar);
27643 + ar->arNetworkType = arNetworkType;
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
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.)
27655 + * The "1 ||" makes sure we always disconnect or reconnect. The WMI doesn't
27656 + * seem to mind being sent multiple disconnects.
27658 + if (1 || (ar->arSsidLen) || (!data->flags))
27660 + if ((!data->flags) ||
27661 + (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
27662 + (ar->arSsidLen != (data->length)))
27665 + * SSID set previously or essid off has been issued.
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
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));
27680 + if (!data->flags) {
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
27696 + if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE))
27698 + reconnect_flag = TRUE;
27699 + status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
27700 + ar->arChannelHint);
27702 + if (status != A_OK) {
27709 + * Dont return if connect is pending.
27711 + if(!(ar->arConnectPending)) {
27719 + ar->arSsidLen = data->length;
27720 + A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
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.
27725 + if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) )
27727 + AR6000_SPIN_LOCK(&ar->arLock, 0);
27728 + if (SHARED_AUTH == ar->arDot11AuthMode) {
27729 + ar6000_install_static_wep_keys(ar);
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);
27750 + if (status != A_OK) {
27753 + ar->arConnectPending = TRUE;
27760 +/* SIOCGIWESSID */
27762 +ar6000_ioctl_giwessid(struct net_device *dev,
27763 + struct iw_request_info *info,
27764 + struct iw_point *data, char *essid)
27766 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27768 + if (ar->arWlanState == WLAN_DISABLED) {
27773 + data->length = ar->arSsidLen;
27774 + A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
27780 +void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
27783 + A_UINT8 keyUsage;
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;
27791 + wmi_addKey_cmd(ar->arWmi,
27795 + ar->arWepKeyList[index].arKeyLen,
27797 + ar->arWepKeyList[index].arKey, KEY_OP_INIT_VAL,
27798 + NO_SYNC_WMIFLAG);
27804 +ar6000_ioctl_delkey(struct net_device *dev, struct iw_request_info *info,
27805 + void *w, char *extra)
27811 +ar6000_ioctl_setmlme(struct net_device *dev, struct iw_request_info *info,
27812 + void *w, char *extra)
27814 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27815 + struct ieee80211req_mlme *mlme = (struct ieee80211req_mlme *)extra;
27817 + if ((ar->arWmiReady == FALSE) || (ar->arConnected != TRUE))
27820 + switch (mlme->im_op) {
27821 + case IEEE80211_MLME_DISASSOC:
27822 + case IEEE80211_MLME_DEAUTH:
27823 + /* Not Supported */
27833 +ar6000_ioctl_setwmmparams(struct net_device *dev, struct iw_request_info *info,
27834 + void *w, char *extra)
27836 + return -EIO; /* for now */
27840 +ar6000_ioctl_getwmmparams(struct net_device *dev, struct iw_request_info *info,
27841 + void *w, char *extra)
27843 + return -EIO; /* for now */
27846 +int ar6000_ioctl_setoptie(struct net_device *dev, struct iw_request_info *info,
27847 + struct iw_point *data, char *extra)
27849 + /* The target generates the WPA/RSN IE */
27854 +ar6000_ioctl_setauthalg(struct net_device *dev, struct iw_request_info *info,
27855 + void *w, char *extra)
27857 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27858 + struct ieee80211req_authalg *req = (struct ieee80211req_authalg *)extra;
27862 + AR6000_SPIN_LOCK(&ar->arLock, 0);
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;
27874 + AR6000_SPIN_UNLOCK(&ar->arLock, 0);
27879 +ar6000_ioctl_addpmkid(struct net_device *dev, struct iw_request_info *info,
27880 + void *w, char *extra)
27882 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27883 + struct ieee80211req_addpmkid *req = (struct ieee80211req_addpmkid *)extra;
27886 + if (ar->arWlanState == WLAN_DISABLED) {
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],
27895 + status = wmi_setPmkid_cmd(ar->arWmi, req->pi_bssid, req->pi_pmkid,
27898 + if (status != A_OK) {
27909 +ar6000_ioctl_siwrate(struct net_device *dev,
27910 + struct iw_request_info *info,
27911 + struct iw_param *rrq, char *extra)
27913 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27916 + if (rrq->fixed) {
27917 + kbps = rrq->value / 1000; /* rrq->value is in bps */
27919 + kbps = -1; /* -1 indicates auto rate */
27921 + if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps) == A_EINVAL)
27923 + AR_DEBUG_PRINTF("BitRate is not Valid %d\n", kbps);
27926 + ar->arBitRate = kbps;
27927 + if(ar->arWmiReady == TRUE)
27929 + if (wmi_set_bitrate_cmd(ar->arWmi, kbps) != A_OK) {
27940 +ar6000_ioctl_giwrate(struct net_device *dev,
27941 + struct iw_request_info *info,
27942 + struct iw_param *rrq, char *extra)
27944 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27947 + if (down_interruptible(&ar->arSem)) {
27948 + return -ERESTARTSYS;
27950 + if(ar->arWmiReady == TRUE)
27952 + ar->arBitRate = 0xFFFF;
27953 + if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
27957 + wait_event_interruptible_timeout(arEvent, ar->arBitRate != 0xFFFF, wmitimeout * HZ);
27958 + if (signal_pending(current)) {
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 */
27965 + if (ar->arBitRate == -1) {
27966 + rrq->fixed = TRUE;
27969 + rrq->value = ar->arBitRate * 1000;
27982 +ar6000_ioctl_siwtxpow(struct net_device *dev,
27983 + struct iw_request_info *info,
27984 + struct iw_param *rrq, char *extra)
27986 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
27989 + if (ar->arWlanState == WLAN_DISABLED) {
27993 + if (ar->arRadioSwitch == WLAN_ENABLED
27994 + && rrq->disabled) {
27995 + if (wmi_switch_radio(ar->arWmi, WLAN_DISABLED) < 0)
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)
28002 + ar->arRadioSwitch = WLAN_ENABLED;
28005 + if (rrq->fixed) {
28006 + if (rrq->flags != IW_TXPOW_DBM) {
28007 + return -EOPNOTSUPP;
28009 + ar->arTxPwr= dbM = rrq->value;
28010 + ar->arTxPwrSet = TRUE;
28012 + ar->arTxPwr = dbM = 0;
28013 + ar->arTxPwrSet = FALSE;
28015 + if(ar->arWmiReady == TRUE)
28017 + AR_DEBUG_PRINTF("Set tx pwr cmd %d dbM\n", dbM);
28018 + wmi_set_txPwr_cmd(ar->arWmi, dbM);
28027 +ar6000_ioctl_giwtxpow(struct net_device *dev,
28028 + struct iw_request_info *info,
28029 + struct iw_param *rrq, char *extra)
28031 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28034 + if (ar->arWlanState == WLAN_DISABLED) {
28038 + if (ar->arRadioSwitch == WLAN_DISABLED) {
28039 + rrq->disabled = 1;
28043 + if (down_interruptible(&ar->arSem)) {
28044 + return -ERESTARTSYS;
28046 + if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE))
28050 + if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
28055 + wait_event_interruptible_timeout(arEvent, ar->arTxPwr != 0, wmitimeout * HZ);
28057 + if (signal_pending(current)) {
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 */
28065 + if (ar->arTxPwrSet == TRUE) {
28066 + rrq->fixed = TRUE;
28068 + rrq->value = ar->arTxPwr;
28069 + rrq->flags = IW_TXPOW_DBM;
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.
28083 +ar6000_ioctl_siwretry(struct net_device *dev,
28084 + struct iw_request_info *info,
28085 + struct iw_param *rrq, char *extra)
28087 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28089 + if (ar->arWlanState == WLAN_DISABLED) {
28093 + if (rrq->disabled) {
28094 + return -EOPNOTSUPP;
28097 + if ((rrq->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT) {
28098 + return -EOPNOTSUPP;
28101 + if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
28104 + if(ar->arWmiReady == TRUE)
28106 + if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
28107 + rrq->value, 0) != A_OK){
28111 + ar->arMaxRetries = rrq->value;
28119 +ar6000_ioctl_giwretry(struct net_device *dev,
28120 + struct iw_request_info *info,
28121 + struct iw_param *rrq, char *extra)
28123 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28125 + if (ar->arWlanState == WLAN_DISABLED) {
28129 + rrq->disabled = 0;
28130 + switch (rrq->flags & IW_RETRY_TYPE) {
28131 + case IW_RETRY_LIFETIME:
28132 + return -EOPNOTSUPP;
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;
28141 + case IW_RETRY_MAX:
28142 + rrq->flags |= IW_RETRY_MAX;
28143 + rrq->value = ar->arMaxRetries;
28155 +ar6000_ioctl_siwencode(struct net_device *dev,
28156 + struct iw_request_info *info,
28157 + struct iw_point *erq, char *keybuf)
28159 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28161 + A_INT32 auth = ar->arDot11AuthMode;
28163 + if (ar->arWlanState == WLAN_DISABLED) {
28167 + index = erq->flags & IW_ENCODE_INDEX;
28169 + if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
28170 + ((index - 1) > WMI_MAX_KEY_INDEX)))
28175 + if (erq->flags & IW_ENCODE_DISABLED) {
28177 + * Encryption disabled
28181 + * If key index was specified then clear the specified key
28184 + A_MEMZERO(ar->arWepKeyList[index].arKey,
28185 + sizeof(ar->arWepKeyList[index].arKey));
28186 + ar->arWepKeyList[index].arKeyLen = 0;
28188 + ar->arDot11AuthMode = OPEN_AUTH;
28189 + ar->arPairwiseCrypto = NONE_CRYPT;
28190 + ar->arGroupCrypto = NONE_CRYPT;
28191 + ar->arAuthMode = NONE_AUTH;
28194 + * Enabling WEP encryption
28197 + index--; /* keyindex is off base 1 in iwconfig */
28200 + if (erq->flags & IW_ENCODE_OPEN) {
28201 + auth = OPEN_AUTH;
28202 + } else if (erq->flags & IW_ENCODE_RESTRICTED) {
28203 + auth = SHARED_AUTH;
28206 + if (erq->length) {
28207 + if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(erq->length)) {
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;
28216 + if (ar->arWepKeyList[index].arKeyLen == 0) {
28219 + ar->arDefTxKeyIndex = index;
28222 + ar->arPairwiseCrypto = WEP_CRYPT;
28223 + ar->arGroupCrypto = WEP_CRYPT;
28224 + ar->arDot11AuthMode = auth;
28225 + ar->arAuthMode = NONE_AUTH;
28229 + * profile has changed. Erase ssid to signal change
28231 + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
28232 + ar->arSsidLen = 0;
28238 +ar6000_ioctl_giwencode(struct net_device *dev,
28239 + struct iw_request_info *info,
28240 + struct iw_point *erq, char *key)
28242 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28243 + A_UINT8 keyIndex;
28244 + struct ar_wep_key *wk;
28246 + if (ar->arWlanState == WLAN_DISABLED) {
28250 + if (ar->arPairwiseCrypto == NONE_CRYPT) {
28252 + erq->flags = IW_ENCODE_DISABLED;
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))
28261 + keyIndex = WMI_MIN_KEY_INDEX;
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;
28271 + if (wk->arKeyLen) {
28272 + A_MEMCPY(key, wk->arKey, erq->length);
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;
28284 +static int ar6000_ioctl_siwpower(struct net_device *dev,
28285 + struct iw_request_info *info,
28286 + union iwreq_data *wrqu, char *extra)
28288 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28289 + WMI_POWER_MODE power_mode;
28291 + if (wrqu->power.disabled)
28292 + power_mode = MAX_PERF_POWER;
28294 + power_mode = REC_POWER;
28296 + if (wmi_powermode_cmd(ar->arWmi, power_mode) < 0)
28302 +static int ar6000_ioctl_giwpower(struct net_device *dev,
28303 + struct iw_request_info *info,
28304 + union iwreq_data *wrqu, char *extra)
28306 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
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.
28315 + if (ar->arWlanState == WLAN_DISABLED || ar->arWmiReady == FALSE)
28318 + return wmi_get_power_mode_cmd(ar->arWmi);
28321 +static int ar6000_ioctl_siwgenie(struct net_device *dev,
28322 + struct iw_request_info *info,
28323 + struct iw_point *dwrq,
28326 + /* The target does that for us */
28330 +static int ar6000_ioctl_giwgenie(struct net_device *dev,
28331 + struct iw_request_info *info,
28332 + struct iw_point *dwrq,
28338 +static int ar6000_ioctl_siwauth(struct net_device *dev,
28339 + struct iw_request_info *info,
28340 + struct iw_param *param,
28343 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
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;
28351 + if (param->value & IW_AUTH_WPA_VERSION_WPA) {
28352 + ar->arAuthMode = WPA_AUTH;
28354 + if (param->value & IW_AUTH_WPA_VERSION_WPA2) {
28355 + ar->arAuthMode = WPA2_AUTH;
28360 + case IW_AUTH_CIPHER_PAIRWISE:
28361 + if (param->value & IW_AUTH_CIPHER_NONE) {
28362 + ar->arPairwiseCrypto = NONE_CRYPT;
28364 + if (param->value & IW_AUTH_CIPHER_WEP40) {
28365 + ar->arPairwiseCrypto = WEP_CRYPT;
28367 + if (param->value & IW_AUTH_CIPHER_TKIP) {
28368 + ar->arPairwiseCrypto = TKIP_CRYPT;
28370 + if (param->value & IW_AUTH_CIPHER_CCMP) {
28371 + ar->arPairwiseCrypto = AES_CRYPT;
28376 + case IW_AUTH_CIPHER_GROUP:
28377 + if (param->value & IW_AUTH_CIPHER_NONE) {
28378 + ar->arGroupCrypto = NONE_CRYPT;
28380 + if (param->value & IW_AUTH_CIPHER_WEP40) {
28381 + ar->arGroupCrypto = WEP_CRYPT;
28383 + if (param->value & IW_AUTH_CIPHER_TKIP) {
28384 + ar->arGroupCrypto = TKIP_CRYPT;
28386 + if (param->value & IW_AUTH_CIPHER_CCMP) {
28387 + ar->arGroupCrypto = AES_CRYPT;
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;
28404 + case IW_AUTH_TKIP_COUNTERMEASURES:
28405 + if (ar->arWmiReady == FALSE) {
28408 + wmi_set_tkip_countermeasures_cmd(ar->arWmi, param->value);
28411 + case IW_AUTH_DROP_UNENCRYPTED:
28414 + case IW_AUTH_80211_AUTH_ALG:
28415 + if (param->value & IW_AUTH_ALG_OPEN_SYSTEM) {
28416 + ar->arDot11AuthMode = OPEN_AUTH;
28418 + if (param->value & IW_AUTH_ALG_SHARED_KEY) {
28419 + ar->arDot11AuthMode = SHARED_AUTH;
28421 + if (param->value & IW_AUTH_ALG_LEAP) {
28422 + ar->arDot11AuthMode = LEAP_AUTH;
28423 + ar->arPairwiseCrypto = WEP_CRYPT;
28424 + ar->arGroupCrypto = WEP_CRYPT;
28430 + case IW_AUTH_WPA_ENABLED:
28434 + case IW_AUTH_RX_UNENCRYPTED_EAPOL:
28437 + case IW_AUTH_PRIVACY_INVOKED:
28441 + printk("%s(): Unknown flag 0x%x\n", __FUNCTION__, param->flags);
28442 + return -EOPNOTSUPP;
28446 + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
28447 + ar->arSsidLen = 0;
28453 +static int ar6000_ioctl_giwauth(struct net_device *dev,
28454 + struct iw_request_info *info,
28455 + struct iw_param *dwrq,
28461 +static int ar6000_ioctl_siwencodeext(struct net_device *dev,
28462 + struct iw_request_info *info,
28463 + union iwreq_data *wrqu,
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;
28471 + if (ar->arWlanState == WLAN_DISABLED) {
28475 + /* Determine and validate the key index */
28476 + idx = (encoding->flags & IW_ENCODE_INDEX) - 1;
28478 + if (idx < 0 || idx > 3)
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;
28488 + ar->user_saved_keys.keyOk = FALSE;
28490 + if (alg == IW_ENCODE_ALG_TKIP) {
28491 + key_type = TKIP_CRYPT;
28492 + ik.ik_type = IEEE80211_CIPHER_TKIP;
28494 + key_type = AES_CRYPT;
28495 + ik.ik_type = IEEE80211_CIPHER_AES_CCM;
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;
28506 + if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
28507 + memcpy(&ik.ik_keyrsc, ext->rx_seq, 8);
28510 + memcpy(ik.ik_keydata, ext->key, ext->key_len);
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));
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));
28525 + status = wmi_addKey_cmd(ar->arWmi, ik.ik_keyix, key_type,
28526 + key_usage, ik.ik_keylen,
28527 + (A_UINT8 *)&ik.ik_keyrsc,
28529 + KEY_OP_INIT_VAL, SYNC_BEFORE_WMIFLAG);
28534 + ar->user_saved_keys.keyOk = TRUE;
28539 + /* WEP falls back to SIWENCODE */
28540 + return -EOPNOTSUPP;
28547 +static int ar6000_ioctl_giwencodeext(struct net_device *dev,
28548 + struct iw_request_info *info,
28549 + struct iw_point *dwrq,
28557 +ar6000_ioctl_setparam(struct net_device *dev,
28558 + struct iw_request_info *info,
28559 + void *erq, char *extra)
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];
28566 + A_BOOL profChanged = FALSE;
28568 + if (ar->arWlanState == WLAN_DISABLED) {
28573 + case IEEE80211_PARAM_WPA:
28575 + case WPA_MODE_WPA1:
28576 + ar->arAuthMode = WPA_AUTH;
28577 + profChanged = TRUE;
28579 + case WPA_MODE_WPA2:
28580 + ar->arAuthMode = WPA2_AUTH;
28581 + profChanged = TRUE;
28583 + case WPA_MODE_NONE:
28584 + ar->arAuthMode = NONE_AUTH;
28585 + profChanged = TRUE;
28588 + printk("IEEE80211_PARAM_WPA: Unknown value %d\n", value);
28591 + case IEEE80211_PARAM_AUTHMODE:
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;
28601 + AR_DEBUG_PRINTF("Error - Setting PSK mode when WPA "\
28602 + "param was set to %d\n",
28607 + case IEEE80211_AUTH_WPA_CCKM:
28608 + if (WPA2_AUTH == ar->arAuthMode) {
28609 + ar->arAuthMode = WPA2_AUTH_CCKM;
28611 + ar->arAuthMode = WPA_AUTH_CCKM;
28618 + case IEEE80211_PARAM_UCASTCIPHER:
28620 + case IEEE80211_CIPHER_AES_CCM:
28621 + ar->arPairwiseCrypto = AES_CRYPT;
28622 + profChanged = TRUE;
28624 + case IEEE80211_CIPHER_TKIP:
28625 + ar->arPairwiseCrypto = TKIP_CRYPT;
28626 + profChanged = TRUE;
28628 + case IEEE80211_CIPHER_WEP:
28629 + ar->arPairwiseCrypto = WEP_CRYPT;
28630 + profChanged = TRUE;
28632 + case IEEE80211_CIPHER_NONE:
28633 + ar->arPairwiseCrypto = NONE_CRYPT;
28634 + profChanged = TRUE;
28638 + case IEEE80211_PARAM_UCASTKEYLEN:
28639 + if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
28642 + ar->arPairwiseCryptoLen = value;
28645 + case IEEE80211_PARAM_MCASTCIPHER:
28647 + case IEEE80211_CIPHER_AES_CCM:
28648 + ar->arGroupCrypto = AES_CRYPT;
28649 + profChanged = TRUE;
28651 + case IEEE80211_CIPHER_TKIP:
28652 + ar->arGroupCrypto = TKIP_CRYPT;
28653 + profChanged = TRUE;
28655 + case IEEE80211_CIPHER_WEP:
28656 + ar->arGroupCrypto = WEP_CRYPT;
28657 + profChanged = TRUE;
28659 + case IEEE80211_CIPHER_NONE:
28660 + ar->arGroupCrypto = NONE_CRYPT;
28661 + profChanged = TRUE;
28665 + case IEEE80211_PARAM_MCASTKEYLEN:
28666 + if (!IEEE80211_IS_VALID_WEP_CIPHER_LEN(value)) {
28669 + ar->arGroupCryptoLen = value;
28672 + case IEEE80211_PARAM_COUNTERMEASURES:
28673 + if (ar->arWmiReady == FALSE) {
28676 + wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
28682 + if (profChanged == TRUE) {
28684 + * profile has changed. Erase ssid to signal change
28686 + A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
28687 + ar->arSsidLen = 0;
28694 +ar6000_ioctl_getparam(struct net_device *dev, struct iw_request_info *info,
28695 + void *w, char *extra)
28697 + return -EIO; /* for now */
28701 +ar6000_ioctl_setkey(struct net_device *dev, struct iw_request_info *info,
28702 + void *w, char *extra)
28704 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28705 + struct ieee80211req_key *ik = (struct ieee80211req_key *)extra;
28706 + KEY_USAGE keyUsage;
28708 + CRYPTO_TYPE keyType = NONE_CRYPT;
28710 + if (ar->arWlanState == WLAN_DISABLED) {
28714 + ar->user_saved_keys.keyOk = FALSE;
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));
28722 + keyUsage = PAIRWISE_USAGE;
28723 + A_MEMCPY(&ar->user_saved_keys.ucast_ik, ik,
28724 + sizeof(struct ieee80211req_key));
28727 + switch (ik->ik_type) {
28728 + case IEEE80211_CIPHER_WEP:
28729 + keyType = WEP_CRYPT;
28731 + case IEEE80211_CIPHER_TKIP:
28732 + keyType = TKIP_CRYPT;
28734 + case IEEE80211_CIPHER_AES_CCM:
28735 + keyType = AES_CRYPT;
28740 + ar->user_saved_keys.keyType = keyType;
28742 + if (IEEE80211_CIPHER_CCKM_KRK != ik->ik_type) {
28743 + if (NONE_CRYPT == keyType) {
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);
28752 + if (status != A_OK) {
28756 + status = wmi_add_krk_cmd(ar->arWmi, ik->ik_keydata);
28759 + ar->user_saved_keys.keyOk = TRUE;
28769 +ar6000_ioctl_giwname(struct net_device *dev,
28770 + struct iw_request_info *info,
28771 + char *name, char *extra)
28773 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28775 + if (ar->arWlanState == WLAN_DISABLED) {
28779 + switch (ar->arPhyCapability) {
28780 + case (WMI_11A_CAPABILITY):
28781 + strncpy(name, "AR6000 802.11a", IFNAMSIZ);
28783 + case (WMI_11G_CAPABILITY):
28784 + strncpy(name, "AR6000 802.11g", IFNAMSIZ);
28786 + case (WMI_11AG_CAPABILITY):
28787 + strncpy(name, "AR6000 802.11ag", IFNAMSIZ);
28790 + strncpy(name, "AR6000 802.11", IFNAMSIZ);
28801 +ar6000_ioctl_siwfreq(struct net_device *dev,
28802 + struct iw_request_info *info,
28803 + struct iw_freq *freq, char *extra)
28805 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28807 + if (ar->arWlanState == WLAN_DISABLED) {
28812 + * We support limiting the channels via wmiconfig.
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
28818 + if (freq->e > 1) {
28820 + } else if (freq->e == 1) {
28821 + ar->arChannelHint = freq->m / 100000;
28823 + ar->arChannelHint = wlan_ieee2freq(freq->m);
28826 + A_PRINTF("channel hint set to %d\n", ar->arChannelHint);
28834 +ar6000_ioctl_giwfreq(struct net_device *dev,
28835 + struct iw_request_info *info,
28836 + struct iw_freq *freq, char *extra)
28838 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28840 + if (ar->arWlanState == WLAN_DISABLED) {
28844 + if (ar->arConnected != TRUE) {
28848 + freq->m = ar->arBssChannel * 100000;
28858 +ar6000_ioctl_siwmode(struct net_device *dev,
28859 + struct iw_request_info *info,
28860 + __u32 *mode, char *extra)
28862 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28864 + if (ar->arWlanState == WLAN_DISABLED) {
28869 + case IW_MODE_INFRA:
28870 + ar->arNetworkType = INFRA_NETWORK;
28872 + case IW_MODE_ADHOC:
28873 + ar->arNetworkType = ADHOC_NETWORK;
28886 +ar6000_ioctl_giwmode(struct net_device *dev,
28887 + struct iw_request_info *info,
28888 + __u32 *mode, char *extra)
28890 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28892 + if (ar->arWlanState == WLAN_DISABLED) {
28896 + switch (ar->arNetworkType) {
28897 + case INFRA_NETWORK:
28898 + *mode = IW_MODE_INFRA;
28900 + case ADHOC_NETWORK:
28901 + *mode = IW_MODE_ADHOC;
28913 +ar6000_ioctl_siwsens(struct net_device *dev,
28914 + struct iw_request_info *info,
28915 + struct iw_param *sens, char *extra)
28924 +ar6000_ioctl_giwsens(struct net_device *dev,
28925 + struct iw_request_info *info,
28926 + struct iw_param *sens, char *extra)
28938 +ar6000_ioctl_giwrange(struct net_device *dev,
28939 + struct iw_request_info *info,
28940 + struct iw_point *data, char *extra)
28942 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
28943 + struct iw_range *range = (struct iw_range *) extra;
28946 + if (ar->arWmiReady == FALSE) {
28950 + if (ar->arWlanState == WLAN_DISABLED) {
28954 + if (down_interruptible(&ar->arSem)) {
28955 + return -ERESTARTSYS;
28957 + ar->arNumChannels = -1;
28958 + A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
28960 + if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
28965 + wait_event_interruptible_timeout(arEvent, ar->arNumChannels != -1, wmitimeout * HZ);
28967 + if (signal_pending(current)) {
28972 + data->length = sizeof(struct iw_range);
28973 + A_MEMZERO(range, sizeof(struct iw_range));
28975 + range->txpower_capa = IW_TXPOW_DBM;
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;
28985 + range->we_version_compiled = WIRELESS_EXT;
28986 + range->we_version_source = 13;
28988 + range->retry_capa = IW_RETRY_LIMIT;
28989 + range->retry_flags = IW_RETRY_LIMIT;
28990 + range->min_retry = 0;
28991 + range->max_retry = 255;
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;
28999 + * Linux supports max of 32 channels, bail out once you
29002 + if (i == IW_MAX_FREQUENCIES) {
29007 + /* Max quality is max field value minus noise floor */
29008 + range->max_qual.qual = 0xff - 161;
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.
29017 + range->max_qual.level = 0;
29018 + range->max_qual.noise = 0;
29020 + range->sensitivity = 3;
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 */
29029 + range->num_bitrates = 0;
29031 + /* estimated maximum TCP throughput values (bps) */
29032 + range->throughput = 22000000;
29034 + range->min_rts = 0;
29035 + range->max_rts = 2347;
29036 + range->min_frag = 256;
29037 + range->max_frag = 2346;
29047 + * This ioctl is used to set the desired bssid for the connect command.
29050 +ar6000_ioctl_siwap(struct net_device *dev,
29051 + struct iw_request_info *info,
29052 + struct sockaddr *ap_addr, char *extra)
29054 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
29056 + if (ar->arWlanState == WLAN_DISABLED) {
29060 + if (ap_addr->sa_family != ARPHRD_ETHER) {
29064 + if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
29065 + A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
29067 + A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data, sizeof(ar->arReqBssid));
29077 +ar6000_ioctl_giwap(struct net_device *dev,
29078 + struct iw_request_info *info,
29079 + struct sockaddr *ap_addr, char *extra)
29081 + AR_SOFTC_T *ar = (AR_SOFTC_T *)netdev_priv(dev);
29083 + if (ar->arWlanState == WLAN_DISABLED) {
29087 + if (ar->arConnected != TRUE) {
29091 + A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
29092 + ap_addr->sa_family = ARPHRD_ETHER;
29101 +ar6000_ioctl_iwaplist(struct net_device *dev,
29102 + struct iw_request_info *info,
29103 + struct iw_point *data, char *extra)
29105 + return -EIO; /* for now */
29112 +ar6000_ioctl_siwscan(struct net_device *dev,
29113 + struct iw_request_info *info,
29114 + struct iw_point *data, char *extra)
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);
29122 + if (ar->arWmiReady == FALSE) {
29126 + if (ar->arWlanState == WLAN_DISABLED) {
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");
29136 + if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \
29137 + HOME_TXDRAIN_TIME, SCAN_INT) != A_OK) {
29141 + ar->scan_complete = 0;
29142 + wait_event_interruptible_timeout(ar6000_scan_queue, ar->scan_complete,
29145 + if (wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0) != A_OK) {
29146 + printk("Couldn't set filtering\n");
29151 +#undef ACT_DWELLTIME_DEFAULT
29152 +#undef HOME_TXDRAIN_TIME
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.
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.
29170 + * NB: various calculations are based on the orinoco/wavelan
29171 + * drivers for compatibility
29174 +ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
29182 + /* NB: max is 94 because noise is hardcoded to 161 */
29183 + if (iq->qual > 94)
29186 + iq->noise = 161; /* -95dBm */
29187 + iq->level = iq->noise + iq->qual;
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 */
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 */
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))
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"},
29295 +void ar6000_ioctl_iwsetup(struct iw_handler_def *def)
29297 + def->private_args = (struct iw_priv_args *)ar6000_priv_args;
29298 + def->num_private_args = ARRAY_SIZE(ar6000_priv_args);
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),
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
29314 + * Copyright (c) 2004-2007 Atheros Communications Inc.
29315 + * All rights reserved.
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;
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.
29333 +#include "htc_api.h"
29334 +#include "bmi_internal.h"
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
29345 +/* APIs visible to the driver */
29353 +BMIDone(HIF_DEVICE *device)
29359 + AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
29363 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
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"));
29372 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
29378 +BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
29384 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29388 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
29389 + cid = BMI_GET_TARGET_INFO;
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"));
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"));
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"));
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.
29417 + A_ASSERT(targ_info->target_info_byte_count == sizeof(*targ_info));
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));
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.
29434 + targ_info->target_info_byte_count = sizeof(targ_info);
29435 + targ_info->target_type = TARGET_TYPE_AR6001;
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);
29447 +BMIReadMemory(HIF_DEVICE *device,
29448 + A_UINT32 address,
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));
29460 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
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));
29468 + cid = BMI_READ_MEMORY;
29470 + remaining = length;
29472 + while (remaining)
29474 + rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
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);
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"));
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"));
29493 + A_MEMCPY(&buffer[length - remaining], data, rxlen);
29494 + remaining -= rxlen; address += rxlen;
29497 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
29502 +BMIWriteMemory(HIF_DEVICE *device,
29503 + A_UINT32 address,
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);
29516 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
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));
29524 + cid = BMI_WRITE_MEMORY;
29526 + remaining = length;
29527 + while (remaining)
29529 + txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
29530 + remaining : (BMI_DATASZ_MAX - header);
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);
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"));
29545 + remaining -= txlen; address += txlen;
29548 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
29554 +BMIExecute(HIF_DEVICE *device,
29555 + A_UINT32 address,
29561 + static A_UCHAR data[sizeof(cid) + sizeof(address) + sizeof(*param)];
29562 + memset (&data, 0, sizeof(cid) + sizeof(address) + sizeof(*param));
29565 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29569 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29570 + ("BMI Execute: Enter (device: 0x%p, address: 0x%x, param: %d)\n",
29571 + device, address, *param));
29573 + cid = BMI_EXECUTE;
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"));
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"));
29594 + A_MEMCPY(param, data, sizeof(*param));
29596 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
29601 +BMISetAppStart(HIF_DEVICE *device,
29602 + A_UINT32 address)
29607 + static A_UCHAR data[sizeof(cid) + sizeof(address)];
29608 + memset (&data, 0, sizeof(cid) + sizeof(address));
29611 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29615 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29616 + ("BMI Set App Start: Enter (device: 0x%p, address: 0x%x)\n",
29617 + device, address));
29619 + cid = BMI_SET_APP_START;
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"));
29632 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
29637 +BMIReadSOCRegister(HIF_DEVICE *device,
29638 + A_UINT32 address,
29644 + static A_UCHAR data[sizeof(cid) + sizeof(address)];
29645 + memset (&data, 0, sizeof(cid) + sizeof(address));
29648 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29652 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29653 + ("BMI Read SOC Register: Enter (device: 0x%p, address: 0x%x)\n",
29654 + device, address));
29656 + cid = BMI_READ_SOC_REGISTER;
29659 + A_MEMCPY(&data[offset], &cid, sizeof(cid));
29660 + offset += sizeof(cid);
29661 + A_MEMCPY(&data[offset], &address, sizeof(address));
29662 + offset += sizeof(address);
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"));
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"));
29675 + A_MEMCPY(param, data, sizeof(*param));
29677 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
29682 +BMIWriteSOCRegister(HIF_DEVICE *device,
29683 + A_UINT32 address,
29689 + static A_UCHAR data[sizeof(cid) + sizeof(address) + sizeof(param)];
29691 + memset (&data, 0, sizeof(cid) + sizeof(address) + sizeof(param));
29694 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
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));
29702 + cid = BMI_WRITE_SOC_REGISTER;
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], ¶m, 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"));
29717 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
29722 +BMIrompatchInstall(HIF_DEVICE *device,
29723 + A_UINT32 ROM_addr,
29724 + A_UINT32 RAM_addr,
29726 + A_UINT32 do_activate,
29727 + A_UINT32 *rompatch_id)
29732 + static A_UCHAR data[sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
29733 + sizeof(nbytes) + sizeof(do_activate)];
29735 + memset (&data, 0, sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
29736 + sizeof(nbytes) + sizeof(do_activate));
29739 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
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));
29747 + cid = BMI_ROMPATCH_INSTALL;
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"));
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"));
29772 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
29777 +BMIrompatchUninstall(HIF_DEVICE *device,
29778 + A_UINT32 rompatch_id)
29783 + static A_UCHAR data[sizeof(cid) + sizeof(rompatch_id)];
29784 + memset (&data, 0, sizeof(cid) + sizeof(rompatch_id));
29787 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29791 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29792 + ("BMI rompatch Uninstall: Enter (device: 0x%p, rompatch_id: %d)\n",
29793 + device, rompatch_id));
29795 + cid = BMI_ROMPATCH_UNINSTALL;
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"));
29808 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
29813 +_BMIrompatchChangeActivation(HIF_DEVICE *device,
29814 + A_UINT32 rompatch_count,
29815 + A_UINT32 *rompatch_list,
29816 + A_UINT32 do_activate)
29821 + static A_UCHAR data[BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)];
29824 + memset (&data, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
29827 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
29831 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI,
29832 + ("BMI Change rompatch Activation: Enter (device: 0x%p, count: %d)\n",
29833 + device, rompatch_count));
29835 + cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
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"));
29851 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
29857 +BMIrompatchActivate(HIF_DEVICE *device,
29858 + A_UINT32 rompatch_count,
29859 + A_UINT32 *rompatch_list)
29861 + return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
29865 +BMIrompatchDeactivate(HIF_DEVICE *device,
29866 + A_UINT32 rompatch_count,
29867 + A_UINT32 *rompatch_list)
29869 + return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
29872 +/* BMI Access routines */
29874 +bmiBufferSend(HIF_DEVICE *device,
29879 + A_UINT32 timeout;
29880 + A_UINT32 address;
29881 + static A_UINT32 cmdCredits;
29882 + A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
29884 + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
29885 + &mboxAddress, sizeof(mboxAddress));
29888 + timeout = BMI_COMMUNICATION_TIMEOUT;
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"));
29902 + /* the counter is only 8=bits, ignore anything in the upper 3 bytes */
29903 + cmdCredits &= 0xFF;
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"));
29915 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI Communication timeout\n"));
29923 +bmiBufferReceive(HIF_DEVICE *device,
29928 + A_UINT32 address;
29929 + A_UINT32 timeout;
29930 + static A_UINT32 cmdCredits;
29931 + A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
29933 + HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
29934 + &mboxAddress, sizeof(mboxAddress));
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"));
29950 + /* we did a 4-byte read to the same count register so mask off upper bytes */
29951 + cmdCredits &= 0xFF;
29952 + status = A_ERROR;
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"));
29964 + AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Communication timeout\n"));
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
29974 +#ifndef BMI_INTERNAL_H
29975 +#define BMI_INTERNAL_H
29978 + * Copyright (c) 2004-2007 Atheros Communications Inc.
29979 + * All rights reserved.
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;
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.
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"
30003 +#define BMI_COMMUNICATION_TIMEOUT 100000
30005 +/* ------ Global Variable Declarations ------- */
30009 +bmiBufferSend(HIF_DEVICE *device,
30011 + A_UINT32 length);
30014 +bmiBufferReceive(HIF_DEVICE *device,
30016 + A_UINT32 length);
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
30024 + * hif2.c - HIF layer re-implementation for the Linux SDIO stack
30026 + * Copyright (C) 2008, 2009 by OpenMoko, Inc.
30027 + * Written by Werner Almesberger <werner@openmoko.org>
30028 + * All Rights Reserved
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;
30036 + * @abstract: HIF layer reference implementation for Atheros SDIO stack
30037 + * @notice: Copyright (c) 2004-2006 Atheros Communications Inc.
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>
30052 +#include "athdefs.h"
30053 +#include "a_types.h"
30057 +/* @@@ Hack - this wants cleaning up */
30059 +#ifdef CONFIG_MACH_NEO1973_GTA02
30061 +#include <mach/gta02-pm-wlan.h>
30063 +#else /* CONFIG_MACH_NEO1973_GTA02 */
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()
30070 +#endif /* !CONFIG_MACH_NEO1973_GTA02 */
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
30082 + * Differences from Atheros' HIFs:
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.
30089 + * - request queue locking seems unnecessarily complex in the Atheros HIFs.
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.
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.
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.
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.
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)
30120 +struct hif_device {
30121 + void *htc_handle;
30122 + struct sdio_func *func;
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.
30128 + struct list_head queue;
30129 + spinlock_t queue_lock;
30130 + struct task_struct *io_task;
30131 + wait_queue_head_t wait;
30134 + * activate_lock protects "active" and the activation/deactivation
30135 + * process itself.
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.
30142 + struct mutex activate_lock;
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);
30153 + unsigned long addr;
30155 + A_STATUS (*completion)(void *context, A_STATUS status);
30160 +static HTC_CALLBACKS htcCallbacks;
30163 + * shutdown_lock prevents recursion through HIFShutDownDevice
30165 +static DEFINE_MUTEX(shutdown_lock);
30168 +/* ----- Request processing ------------------------------------------------ */
30171 +static A_STATUS process_request(struct hif_request *req)
30176 + dev_dbg(&req->func->dev, "process_request(req %p)\n", req);
30177 + sdio_claim_host(req->func);
30179 + ret = req->read(req->func, req->buf, req->addr, req->len);
30181 + ret = req->write(req->func, req->addr, req->buf, req->len);
30183 + sdio_release_host(req->func);
30184 + status = ret ? A_ERROR : A_OK;
30185 + if (req->completion)
30186 + req->completion(req->context, status);
30192 +static void enqueue_request(struct hif_device *hif, struct hif_request *req)
30194 + unsigned long flags;
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);
30204 +static struct hif_request *dequeue_request(struct hif_device *hif)
30206 + struct hif_request *req;
30207 + unsigned long flags;
30209 + spin_lock_irqsave(&hif->queue_lock, flags);
30210 + if (list_empty(&hif->queue))
30213 + req = list_first_entry(&hif->queue,
30214 + struct hif_request, list);
30215 + list_del(&req->list);
30217 + spin_unlock_irqrestore(&hif->queue_lock, flags);
30222 +static void wait_queue_empty(struct hif_device *hif)
30224 + unsigned long flags;
30228 + spin_lock_irqsave(&hif->queue_lock, flags);
30229 + empty = list_empty(&hif->queue);
30230 + spin_unlock_irqrestore(&hif->queue_lock, flags);
30239 +static int io(void *data)
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;
30247 + sched_setscheduler(current, SCHED_FIFO, ¶m);
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.
30257 + prepare_to_wait(&hif->wait, &wait, TASK_INTERRUPTIBLE);
30258 + if (kthread_should_stop()) {
30259 + finish_wait(&hif->wait, &wait);
30262 + req = dequeue_request(hif);
30267 + finish_wait(&hif->wait, &wait);
30269 + (void) process_request(req);
30275 +A_STATUS HIFReadWrite(HIF_DEVICE *hif, A_UINT32 address, A_UCHAR *buffer,
30276 + A_UINT32 length, A_UINT32 request, void *context)
30278 + struct device *dev = HIFGetOSDevice(hif);
30279 + struct hif_request *req;
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);
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));
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
30295 + address += HIF_MBOX_WIDTH-length;
30298 + req = kzalloc(sizeof(*req), GFP_ATOMIC);
30300 + if (request & HIF_ASYNCHRONOUS)
30301 + htcCallbacks.rwCompletionHandler(context, A_ERROR);
30305 + req->func = hif->func;
30306 + req->addr = address;
30307 + req->buf = buffer;
30308 + req->len = length;
30310 + if (request & HIF_READ) {
30311 + if (request & HIF_FIXED_ADDRESS)
30312 + req->read = sdio_readsb;
30314 + req->read = sdio_memcpy_fromio;
30316 + if (request & HIF_FIXED_ADDRESS)
30317 + req->write = sdio_writesb;
30319 + req->write = sdio_memcpy_toio;
30322 + if (!(request & HIF_ASYNCHRONOUS))
30323 + return process_request(req);
30325 + req->completion = htcCallbacks.rwCompletionHandler;
30326 + req->context = context;
30327 + enqueue_request(hif, req);
30333 +/* ----- Interrupt handling ------------------------------------------------ */
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.
30339 + * Warning: this story changes if going SMP/SMT.
30342 +static volatile int masked = 1;
30343 +static volatile int pending;
30344 +static volatile int in_interrupt;
30347 +static void ar6000_do_irq(struct sdio_func *func)
30349 + HIF_DEVICE *hif = sdio_get_drvdata(func);
30350 + struct device *dev = HIFGetOSDevice(hif);
30353 + dev_dbg(dev, "ar6000_do_irq -> %p\n", htcCallbacks.dsrHandler);
30355 + status = htcCallbacks.dsrHandler(hif->htc_handle);
30356 + BUG_ON(status != A_OK);
30360 +static void sdio_ar6000_irq(struct sdio_func *func)
30362 + HIF_DEVICE *hif = sdio_get_drvdata(func);
30363 + struct device *dev = HIFGetOSDevice(hif);
30365 + dev_dbg(dev, "sdio_ar6000_irq\n");
30367 + in_interrupt = 1;
30369 + in_interrupt = 0;
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:
30377 + * 1) Break the call chain by calling the callback from a workqueue.
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.
30385 + * Solution 2) is probably the best for now. Will try it later.
30387 + sdio_release_host(func);
30388 + ar6000_do_irq(func);
30389 + sdio_claim_host(func);
30390 + in_interrupt = 0;
30394 +void HIFAckInterrupt(HIF_DEVICE *hif)
30396 + struct device *dev = HIFGetOSDevice(hif);
30398 + dev_dbg(dev, "HIFAckInterrupt\n");
30403 +void HIFUnMaskInterrupt(HIF_DEVICE *hif)
30405 + struct device *dev = HIFGetOSDevice(hif);
30407 + dev_dbg(dev, "HIFUnMaskInterrupt\n");
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. */
30422 +void HIFMaskInterrupt(HIF_DEVICE *hif)
30424 + struct device *dev = HIFGetOSDevice(hif);
30426 + dev_dbg(dev, "HIFMaskInterrupt\n");
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.
30433 + * Note: this may be a bit on the paranoid side - the callers may
30434 + * actually be nice enough to disable scheduling. Check later.
30437 + while (in_interrupt)
30442 +/* ----- HIF API glue functions -------------------------------------------- */
30445 +struct device *HIFGetOSDevice(HIF_DEVICE *hif)
30447 + return &hif->func->dev;
30451 +void HIFSetHandle(void *hif_handle, void *handle)
30453 + HIF_DEVICE *hif = (HIF_DEVICE *) hif_handle;
30455 + hif->htc_handle = handle;
30459 +/* ----- Device configuration (HIF side) ----------------------------------- */
30462 +A_STATUS HIFConfigureDevice(HIF_DEVICE *hif,
30463 + HIF_DEVICE_CONFIG_OPCODE opcode, void *config, A_UINT32 configLen)
30465 + struct device *dev = HIFGetOSDevice(hif);
30466 + HIF_DEVICE_IRQ_PROCESSING_MODE *ipm_cfg = config;
30467 + A_UINT32 *mbs_cfg = config;
30470 + dev_dbg(dev, "HIFConfigureDevice\n");
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;
30477 + case HIF_DEVICE_GET_MBOX_ADDR:
30478 + for (i = 0; i != MBOXES; i++)
30479 + mbs_cfg[i] = HIF_MBOX_START_ADDR(i);
30481 + case HIF_DEVICE_GET_IRQ_PROC_MODE:
30482 + *ipm_cfg = HIF_DEVICE_IRQ_SYNC_ONLY;
30483 +// *ipm_cfg = HIF_DEVICE_IRQ_ASYNC_SYNC;
30492 +/* ----- Device probe and removal (Linux side) ----------------------------- */
30495 +static int ar6000_do_activate(struct hif_device *hif)
30497 + struct sdio_func *func = hif->func;
30498 + struct device *dev = &func->dev;
30501 + dev_dbg(dev, "ar6000_do_activate\n");
30503 + sdio_claim_host(func);
30504 + sdio_enable_func(func);
30506 + INIT_LIST_HEAD(&hif->queue);
30507 + init_waitqueue_head(&hif->wait);
30508 + spin_lock_init(&hif->queue_lock);
30510 + ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
30512 + dev_err(dev, "sdio_set_block_size returns %d\n", ret);
30513 + goto out_enabled;
30515 + ret = sdio_claim_irq(func, sdio_ar6000_irq);
30517 + dev_err(dev, "sdio_claim_irq returns %d\n", ret);
30518 + goto out_enabled;
30520 + /* Set SDIO_BUS_CD_DISABLE in SDIO_CCCR_IF ? */
30522 + sdio_f0_writeb(func, SDIO_CCCR_CAP_E4MI, SDIO_CCCR_CAPS, &ret);
30524 + dev_err(dev, "sdio_f0_writeb(SDIO_CCCR_CAPS) returns %d\n",
30526 + goto out_got_irq;
30529 + if (0) /* avoid warning */
30530 + goto out_got_irq;
30533 + sdio_release_host(func);
30535 + hif->io_task = kthread_run(io, hif, "ar6000_io");
30536 + ret = IS_ERR(hif->io_task);
30538 + dev_err(dev, "kthread_run(ar6000_io): %d\n", ret);
30539 + goto out_func_ready;
30542 + ret = htcCallbacks.deviceInsertedHandler(hif);
30546 + dev_err(dev, "deviceInsertedHandler: %d\n", ret);
30548 + ret = kthread_stop(hif->io_task);
30550 + dev_err(dev, "kthread_stop (ar6000_io): %d\n", ret);
30553 + sdio_claim_host(func);
30556 + sdio_release_irq(func);
30559 + sdio_disable_func(func);
30560 + sdio_release_host(func);
30566 +static void ar6000_do_deactivate(struct hif_device *hif)
30568 + struct sdio_func *func = hif->func;
30569 + struct device *dev = &func->dev;
30572 + dev_dbg(dev, "ar6000_do_deactivate\n");
30573 + if (!hif->active)
30576 + if (mutex_trylock(&shutdown_lock)) {
30578 + * Funny, Atheros' HIF does this call, but this just puts us in
30579 + * a recursion through HTCShutDown/HIFShutDown if unloading the
30582 + * However, we need it for suspend/resume. See the comment at
30583 + * HIFShutDown, below.
30585 + ret = htcCallbacks.deviceRemovedHandler(hif->htc_handle, A_OK);
30587 + dev_err(dev, "deviceRemovedHandler: %d\n", ret);
30588 + mutex_unlock(&shutdown_lock);
30590 + wait_queue_empty(hif);
30591 + ret = kthread_stop(hif->io_task);
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);
30601 +static int ar6000_activate(struct hif_device *hif)
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);
30610 + printk(KERN_ERR "%s: Failed to activate %d\n",
30617 + mutex_unlock(&hif->activate_lock);
30622 +static void ar6000_deactivate(struct hif_device *hif)
30624 + dev_dbg(&hif->func->dev, "ar6000_deactivate\n");
30625 + mutex_lock(&hif->activate_lock);
30626 + if (hif->active) {
30627 + ar6000_do_deactivate(hif);
30630 + mutex_unlock(&hif->activate_lock);
30634 +static int ar6000_rfkill_cb(void *data, int on)
30636 + struct hif_device *hif = data;
30637 + struct sdio_func *func = hif->func;
30638 + struct device *dev = &func->dev;
30640 + dev_dbg(dev, "ar6000_rfkill_cb: on %d\n", on);
30642 + return ar6000_activate(hif);
30643 + ar6000_deactivate(hif);
30648 +static int sdio_ar6000_probe(struct sdio_func *func,
30649 + const struct sdio_device_id *id)
30651 + struct device *dev = &func->dev;
30652 + struct hif_device *hif;
30655 + dev_dbg(dev, "sdio_ar6000_probe\n");
30656 + BUG_ON(!htcCallbacks.deviceInsertedHandler);
30658 + hif = kzalloc(sizeof(*hif), GFP_KERNEL);
30662 + sdio_set_drvdata(func, hif);
30663 + hif->func = func;
30664 + mutex_init(&hif->activate_lock);
30667 + if (gta02_wlan_query_rfkill_lock())
30668 + ret = ar6000_activate(hif);
30670 + gta02_wlan_set_rfkill_cb(ar6000_rfkill_cb, hif);
30673 + gta02_wlan_query_rfkill_unlock();
30674 + sdio_set_drvdata(func, NULL);
30680 +static void sdio_ar6000_remove(struct sdio_func *func)
30682 + struct device *dev = &func->dev;
30683 + HIF_DEVICE *hif = sdio_get_drvdata(func);
30685 + dev_dbg(dev, "sdio_ar6000_remove\n");
30686 + gta02_wlan_clear_rfkill_cb();
30687 + ar6000_deactivate(hif);
30688 + sdio_set_drvdata(func, NULL);
30693 +/* ----- Device registration/unregistration (called by HIF) ---------------- */
30696 +#define ATHEROS_SDIO_DEVICE(id, offset) \
30697 + SDIO_DEVICE(SDIO_VENDOR_ID_ATHEROS, SDIO_DEVICE_ID_ATHEROS_##id | (offset))
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 */ },
30709 +MODULE_DEVICE_TABLE(sdio, sdio_ar6000_ids);
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,
30720 +int HIFInit(HTC_CALLBACKS *callbacks)
30724 + BUG_ON(!callbacks);
30726 + printk(KERN_DEBUG "HIFInit\n");
30727 + htcCallbacks = *callbacks;
30729 + ret = sdio_register_driver(&sdio_ar6000_driver);
30732 + "sdio_register_driver(sdio_ar6000_driver): %d\n", ret);
30741 + * We have four possible call chains here:
30743 + * System shutdown/reboot:
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
30750 + * This is roughly the same sequence as suspend, described below.
30752 + * Module removal:
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
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.
30764 + * device_suspend ...> s3cmci_suspend ...> sdio_bus_remove ->
30765 + * sdio_ar6000_remove -> ar6000_deactivate -> ar6000_do_deactivate ->
30766 + * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice
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.
30776 + * rfkill_state_store -> rfkill_toggle_radio -> gta02_wlan_toggle_radio ->
30777 + * ar6000_rfkill_cb -> ar6000_deactivate -> ar6000_do_deactivate ->
30778 + * deviceRemovedHandler (HTCTargetRemovedHandler) -> HIFShutDownDevice
30780 + * This is similar to suspend - only the entry point changes.
30783 +void HIFShutDownDevice(HIF_DEVICE *hif)
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);
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
30798 + * @abstract: HIF layer reference implementation for Atheros SDIO stack
30800 + * @notice: Copyright (c) 2004-2006 Atheros Communications Inc.
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;
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.
30816 +#include "hif_internal.h"
30818 +/* ------ Static Variables ------ */
30820 +/* ------ Global Variable Declarations ------- */
30821 +SD_PNP_INFO Ids[] = {
30823 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xB,
30824 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30825 + .SDIO_FunctionClass = FUNCTION_CLASS,
30826 + .SDIO_FunctionNo = 1
30829 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0xA,
30830 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30831 + .SDIO_FunctionClass = FUNCTION_CLASS,
30832 + .SDIO_FunctionNo = 1
30835 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x9,
30836 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30837 + .SDIO_FunctionClass = FUNCTION_CLASS,
30838 + .SDIO_FunctionNo = 1
30841 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6001_BASE | 0x8,
30842 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30843 + .SDIO_FunctionClass = FUNCTION_CLASS,
30844 + .SDIO_FunctionNo = 1
30847 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x0,
30848 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30849 + .SDIO_FunctionClass = FUNCTION_CLASS,
30850 + .SDIO_FunctionNo = 1
30853 + .SDIO_ManufacturerID = MANUFACTURER_ID_AR6002_BASE | 0x1,
30854 + .SDIO_ManufacturerCode = MANUFACTURER_CODE,
30855 + .SDIO_FunctionClass = FUNCTION_CLASS,
30856 + .SDIO_FunctionNo = 1
30859 + } //list is null termintaed
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,
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;
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);\
30895 +#define AR_DEBUG_PRINTF(lvl, args)
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);
30903 +/* ------ Functions ------ */
30904 +int HIFInit(HTC_CALLBACKS *callbacks)
30906 + SDIO_STATUS status;
30907 + DBG_ASSERT(callbacks != NULL);
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;
30918 + CriticalSectionInit(&lock);
30920 + /* Register with bus driver core */
30921 + status = SDIO_RegisterFunction(&FunctionContext.function);
30922 + DBG_ASSERT(SDIO_SUCCESS(status));
30928 +HIFReadWrite(HIF_DEVICE *device,
30929 + A_UINT32 address,
30932 + A_UINT32 request,
30940 + SDREQUEST *sdrequest;
30941 + SDIO_STATUS sdiostatus;
30942 + BUS_REQUEST *busrequest;
30943 + A_STATUS status = A_OK;
30945 + DBG_ASSERT(device != NULL);
30946 + DBG_ASSERT(device->handle != NULL);
30948 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device));
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;
30958 + sdrequest = busrequest->request;
30959 + busrequest->context = context;
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"));
30974 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
30975 + ("Invalid execution mode: 0x%08x\n", request));
30976 + status = A_EINVAL;
30980 + if (request & HIF_EXTENDED_IO) {
30981 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Command type: CMD53\n"));
30982 + sdrequest->Command = CMD53;
30984 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
30985 + ("Invalid command type: 0x%08x\n", request));
30986 + status = A_EINVAL;
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));
31007 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31008 + ("Invalid data mode: 0x%08x\n", request));
31009 + status = A_EINVAL;
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);
31021 + if ((address >= HIF_MBOX_START_ADDR(0)) &&
31022 + (address <= HIF_MBOX_END_ADDR(3)))
31025 + DBG_ASSERT(length <= HIF_MBOX_WIDTH);
31028 + * Mailbox write. Adjust the address so that the last byte
31029 + * falls on the EOM address.
31031 + address += (HIF_MBOX_WIDTH - length);
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) {
31042 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Direction: Read\n"));
31044 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31045 + ("Invalid direction: 0x%08x\n", request));
31046 + status = A_EINVAL;
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"));
31057 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31058 + ("Invalid address mode: 0x%08x\n", request));
31059 + status = A_EINVAL;
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);
31068 + /* Send the command out */
31069 + sdiostatus = SDDEVICE_CALL_REQUEST_FUNC(device->handle, sdrequest);
31071 + if (!SDIO_SUCCESS(sdiostatus)) {
31072 + status = A_ERROR;
31077 + if (A_FAILED(status) || (request & HIF_SYNCHRONOUS)) {
31078 + if (busrequest != NULL) {
31079 + hifFreeBusRequest(busrequest);
31083 + if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
31084 + /* call back async handler on failure */
31085 + htcCallbacks.rwCompletionHandler(context, status);
31092 +HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
31093 + void *config, A_UINT32 configLen)
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;
31105 + case HIF_DEVICE_GET_MBOX_ADDR:
31106 + for (count = 0; count < 4; count ++) {
31107 + ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count);
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;
31115 + AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
31116 + ("Unsupported configuration opcode: %d\n", opcode));
31124 +HIFShutDownDevice(HIF_DEVICE *device)
31128 + SDIO_STATUS status;
31129 + SDCONFIG_BUS_MODE_DATA busSettings;
31130 + SDCONFIG_FUNC_ENABLE_DISABLE_DATA fData;
31132 + if (device != NULL) {
31133 + DBG_ASSERT(device->handle != NULL);
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));
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));
31147 + /* Perform a soft I/O reset */
31148 + data = SDIO_IO_RESET;
31149 + status = SDLIB_IssueCMD52(device->handle, 0, SDIO_IO_ABORT_REG,
31151 + DBG_ASSERT(SDIO_SUCCESS(status));
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.
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);
31166 + /* Issue config request to change the bus width to 4 bit */
31167 + status = SDLIB_IssueConfig(device->handle, SDCONFIG_BUS_MODE_CTRL,
31169 + sizeof(SDCONFIG_BUS_MODE_DATA));
31170 + DBG_ASSERT(SDIO_SUCCESS(status));
31173 + /* Free the bus requests */
31174 + for (count = 0; count < BUS_REQUEST_MAX_NUM; count ++) {
31175 + SDDeviceFreeRequest(device->handle, busRequest[count].request);
31177 + /* Clean up the queue */
31178 + s_busRequestFreeQueue = NULL;
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
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));
31194 +hifRWCompletionHandler(SDREQUEST *request)
31198 + BUS_REQUEST *busrequest;
31200 + if (SDIO_SUCCESS(request->Status)) {
31203 + status = A_ERROR;
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
31213 + hifFreeBusRequest(busrequest);
31214 + htcCallbacks.rwCompletionHandler(context, status);
31218 +hifIRQHandler(void *context)
31221 + HIF_DEVICE *device;
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);
31230 +hifDeviceInserted(SDFUNCTION *function, SDDEVICE *handle)
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;
31245 + DBG_ASSERT(function != NULL);
31246 + DBG_ASSERT(handle != NULL);
31248 + device = addHifDevice(handle);
31249 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device: %p\n", device));
31250 + functionContext = (TARGET_FUNCTION_CONTEXT *)function->pContext;
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.
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"));
31273 + /* Get current bus flags */
31274 + ZERO_OBJECT(busSettings);
31276 + busSettings.BusModeFlags = SDDEVICE_GET_BUSMODE_FLAGS(handle);
31277 + if (onebitmode) {
31278 + SDCONFIG_SET_BUS_WIDTH(busSettings.BusModeFlags,
31279 + SDCONFIG_BUS_WIDTH_1_BIT);
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
31286 + currentBusClock = SDDEVICE_GET_OPER_CLOCK(handle);
31287 + busSettings.ClockRate = currentBusClock;
31289 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31290 + ("HIF currently running at: %d \n",currentBusClock));
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));
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"));
31308 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31309 + ("Configured clock: %d, Maximum clock: %d\n",
31310 + busSettings.ActualClockRate,
31311 + SDDEVICE_GET_MAX_CLOCK(handle)));
31315 + * Check if the target supports block mode. This result of this check
31316 + * can be used to implement the HIFReadWrite API.
31318 + if (SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle)) {
31319 + /* Limit block size to operational block limit or card function
31321 + maxBlockSize = min(SDDEVICE_GET_OPER_BLOCK_LEN(handle),
31322 + SDDEVICE_GET_SDIO_FUNC_MAXBLKSIZE(handle));
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"));
31328 + /* Limit block size to max byte basis */
31329 + maxBlockSize = min(maxBlockSize,
31330 + (A_UINT16)SDIO_MAX_LENGTH_BYTE_BASIS);
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));
31343 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
31344 + ("Bytes Per Block: %d bytes, Block Count:%d \n",
31345 + maxBlockSize, maxBlocks));
31347 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31348 + ("Function does not support Block Mode!\n"));
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));
31366 + /* Enable the dragon function */
31369 + fData.TimeOut = 1;
31370 + fData.EnableFlags = SDCONFIG_ENABLE_FUNC;
31371 + while ((count++ < SDWLAN_ENABLE_DISABLE_TIMEOUT) && !enabled)
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"));
31382 + /* Mark the status as enabled */
31386 + /* Check if we were succesful in enabling the target */
31388 + AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
31389 + ("Failed to communicate with the target\n"));
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 */
31401 + hifFreeBusRequest(&busRequest[count]);
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));
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
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.
31419 + if (SDIO_SUCCESS(SDLIB_OSCreateHelper(&device->insert_helper,
31420 + insert_helper_func,
31422 + device->helper_started = TRUE;
31428 +static THREAD_RETURN insert_helper_func(POSKERNEL_HELPER pHelper)
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
31446 + if ((htcCallbacks.deviceInsertedHandler(SD_GET_OS_HELPER_CONTEXT(pHelper))) != A_OK) {
31447 + AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("Device rejected\n"));
31454 +HIFAckInterrupt(HIF_DEVICE *device)
31456 + SDIO_STATUS status;
31457 + DBG_ASSERT(device != NULL);
31458 + DBG_ASSERT(device->handle != NULL);
31460 + /* Acknowledge our function IRQ */
31461 + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_ACK_IRQ,
31463 + DBG_ASSERT(SDIO_SUCCESS(status));
31467 +HIFUnMaskInterrupt(HIF_DEVICE *device)
31469 + SDIO_STATUS status;
31471 + DBG_ASSERT(device != NULL);
31472 + DBG_ASSERT(device->handle != NULL);
31474 + /* Register the IRQ Handler */
31475 + SDDEVICE_SET_IRQ_HANDLER(device->handle, hifIRQHandler, device);
31477 + /* Unmask our function IRQ */
31478 + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_UNMASK_IRQ,
31480 + DBG_ASSERT(SDIO_SUCCESS(status));
31483 +void HIFMaskInterrupt(HIF_DEVICE *device)
31485 + SDIO_STATUS status;
31486 + DBG_ASSERT(device != NULL);
31487 + DBG_ASSERT(device->handle != NULL);
31489 + /* Mask our function IRQ */
31490 + status = SDLIB_IssueConfig(device->handle, SDCONFIG_FUNC_MASK_IRQ,
31492 + DBG_ASSERT(SDIO_SUCCESS(status));
31494 + /* Unregister the IRQ Handler */
31495 + SDDEVICE_SET_IRQ_HANDLER(device->handle, NULL, NULL);
31498 +static BUS_REQUEST *hifAllocateBusRequest(void)
31500 + BUS_REQUEST *busrequest;
31502 + /* Acquire lock */
31503 + CriticalSectionAcquire(&lock);
31505 + /* Remove first in list */
31506 + if((busrequest = s_busRequestFreeQueue) != NULL)
31508 + s_busRequestFreeQueue = busrequest->next;
31511 + /* Release lock */
31512 + CriticalSectionRelease(&lock);
31514 + return busrequest;
31518 +hifFreeBusRequest(BUS_REQUEST *busrequest)
31520 + DBG_ASSERT(busrequest != NULL);
31522 + /* Acquire lock */
31523 + CriticalSectionAcquire(&lock);
31525 + /* Insert first in list */
31526 + busrequest->next = s_busRequestFreeQueue;
31527 + s_busRequestFreeQueue = busrequest;
31529 + /* Release lock */
31530 + CriticalSectionRelease(&lock);
31534 +hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *handle)
31537 + HIF_DEVICE *device;
31538 + DBG_ASSERT(function != NULL);
31539 + DBG_ASSERT(handle != NULL);
31541 + device = getHifDevice(handle);
31542 + status = htcCallbacks.deviceRemovedHandler(device->htc_handle, A_OK);
31544 + /* cleanup the helper thread */
31545 + if (device->helper_started) {
31546 + SDLIB_OSDeleteHelper(&device->insert_helper);
31547 + device->helper_started = FALSE;
31550 + delHifDevice(handle);
31551 + DBG_ASSERT(status == A_OK);
31555 +addHifDevice(SDDEVICE *handle)
31557 + DBG_ASSERT(handle != NULL);
31558 + hifDevice[0].handle = handle;
31559 + return &hifDevice[0];
31563 +getHifDevice(SDDEVICE *handle)
31565 + DBG_ASSERT(handle != NULL);
31566 + return &hifDevice[0];
31570 +delHifDevice(SDDEVICE *handle)
31572 + DBG_ASSERT(handle != NULL);
31573 + hifDevice[0].handle = NULL;
31577 +HIFGetOSDevice(HIF_DEVICE *device)
31579 + return &device->handle->Device->dev;
31582 +static void ResetAllCards(void)
31585 + SDIO_STATUS status;
31588 + data = SDIO_IO_RESET;
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,
31605 + TRUE); /* write */
31611 +void HIFSetHandle(void *hif_handle, void *handle)
31613 + HIF_DEVICE *device = (HIF_DEVICE *) hif_handle;
31615 + device->htc_handle = handle;
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
31624 + * @file: hif_internal.h
31626 + * @abstract: internal header file for hif layer
31628 + * @notice: Copyright (c) 2004-2006 Atheros Communications Inc.
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;
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.
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"
31654 +#define MANUFACTURER_ID_AR6001_BASE 0x100
31655 +#define MANUFACTURER_ID_AR6002_BASE 0x200
31656 +#define FUNCTION_CLASS 0x0
31657 +#define MANUFACTURER_CODE 0x271
31659 +#define BUS_REQUEST_MAX_NUM 64
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
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
31674 +#define HIF_MBOX_START_ADDR(mbox) \
31675 + HIF_MBOX_BASE_ADDR + mbox * HIF_MBOX_WIDTH
31677 +#define HIF_MBOX_END_ADDR(mbox) \
31678 + HIF_MBOX_START_ADDR(mbox) + HIF_MBOX_WIDTH - 1
31680 +struct hif_device {
31681 + SDDEVICE *handle;
31682 + void *htc_handle;
31683 + OSKERNEL_HELPER insert_helper;
31684 + BOOL helper_started;
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;
31693 +typedef struct bus_request {
31694 + struct bus_request *next;
31695 + SDREQUEST *request;
31700 +hifDeviceInserted(SDFUNCTION *function, SDDEVICE *device);
31703 +hifDeviceRemoved(SDFUNCTION *function, SDDEVICE *device);
31706 +hifAllocateDeviceRequest(SDDEVICE *device);
31709 +hifFreeDeviceRequest(SDREQUEST *request);
31712 +hifRWCompletionHandler(SDREQUEST *request);
31715 +hifIRQHandler(void *context);
31718 +addHifDevice(SDDEVICE *handle);
31721 +getHifDevice(SDDEVICE *handle);
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
31730 + * AR6K device layer that handles register level I/O
31732 + * Copyright (c) 2007 Atheros Communications Inc.
31733 + * All rights reserved.
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;
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.
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"
31755 +#include "htc_packet.h"
31758 +#define MAILBOX_FOR_BLOCK_SIZE 1
31760 +extern A_UINT32 resetok;
31762 +static A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
31763 +static A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
31765 +#define LOCK_AR6K(p) A_MUTEX_LOCK(&(p)->Lock);
31766 +#define UNLOCK_AR6K(p) A_MUTEX_UNLOCK(&(p)->Lock);
31768 +void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket)
31771 + HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket);
31772 + UNLOCK_AR6K(pDev);
31775 +HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev)
31777 + HTC_PACKET *pPacket;
31780 + pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList);
31781 + UNLOCK_AR6K(pDev);
31786 +A_STATUS DevSetup(AR6K_DEVICE *pDev)
31788 + A_UINT32 mailboxaddrs[AR6K_MAILBOXES];
31789 + A_UINT32 blocksizes[AR6K_MAILBOXES];
31790 + A_STATUS status = A_OK;
31793 + AR_DEBUG_ASSERT(AR6K_IRQ_PROC_REGS_SIZE == 16);
31794 + AR_DEBUG_ASSERT(AR6K_IRQ_ENABLE_REGS_SIZE == 4);
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);
31803 + /* get the addresses for all 4 mailboxes */
31804 + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
31805 + mailboxaddrs, sizeof(mailboxaddrs));
31807 + if (status != A_OK) {
31808 + AR_DEBUG_ASSERT(FALSE);
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,
31818 + pDev->RegIOBuffers[i].Buffer,
31819 + AR6K_REG_IO_BUFFER_SIZE,
31820 + 0); /* don't care */
31821 + AR6KFreeIOPacket(pDev,pIOPacket);
31824 + /* get the address of the mailbox we are using */
31825 + pDev->MailboxAddress = mailboxaddrs[HTC_MAILBOX];
31827 + /* get the block sizes */
31828 + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
31829 + blocksizes, sizeof(blocksizes));
31831 + if (status != A_OK) {
31832 + AR_DEBUG_ASSERT(FALSE);
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);
31843 + /* assemble mask, used for padding to a block */
31844 + pDev->BlockMask = pDev->BlockSize - 1;
31846 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("BlockSize: %d, MailboxAddress:0x%X \n",
31847 + pDev->BlockSize, pDev->MailboxAddress));
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));
31856 + /* assume we can process HIF interrupt events asynchronously */
31857 + pDev->HifIRQProcessingMode = HIF_DEVICE_IRQ_ASYNC_SYNC;
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));
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"));
31869 + case HIF_DEVICE_IRQ_ASYNC_SYNC:
31870 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n"));
31873 + AR_DEBUG_ASSERT(FALSE);
31876 + pDev->HifMaskUmaskRecvEvent = NULL;
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));
31884 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF special overrides : 0x%X , 0x%X\n",
31885 + (A_UINT32)pDev->GetPendingEventsFunc, (A_UINT32)pDev->HifMaskUmaskRecvEvent));
31887 + status = DevDisableInterrupts(pDev);
31891 + if (A_FAILED(status)) {
31892 + /* make sure handle is cleared */
31893 + HIFSetHandle(pDev->HIFDevice, NULL);
31900 +static A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev)
31903 + AR6K_IRQ_ENABLE_REGISTERS regs;
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);
31912 + if (NULL == pDev->GetPendingEventsFunc) {
31913 + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
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
31921 + pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
31925 + /* Set up the CPU Interrupt Status Register */
31926 + pDev->IrqEnableRegisters.cpu_int_status_enable = CPU_INT_STATUS_ENABLE_BIT_SET(0x00);
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);
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);
31937 + /* copy into our temp area */
31938 + A_MEMCPY(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
31940 + UNLOCK_AR6K(pDev);
31942 + /* always synchronous */
31943 + status = HIFReadWrite(pDev->HIFDevice,
31944 + INT_STATUS_ENABLE_ADDRESS,
31945 + ®s.int_status_enable,
31946 + AR6K_IRQ_ENABLE_REGS_SIZE,
31947 + HIF_WR_SYNC_BYTE_INC,
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));
31960 +static A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev)
31962 + AR6K_IRQ_ENABLE_REGISTERS regs;
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(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
31973 + UNLOCK_AR6K(pDev);
31975 + /* always synchronous */
31976 + return HIFReadWrite(pDev->HIFDevice,
31977 + INT_STATUS_ENABLE_ADDRESS,
31978 + ®s.int_status_enable,
31979 + AR6K_IRQ_ENABLE_REGS_SIZE,
31980 + HIF_WR_SYNC_BYTE_INC,
31984 +/* enable device interrupts */
31985 +A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev)
31987 + /* Unmask the host controller interrupts */
31988 + HIFUnMaskInterrupt(pDev->HIFDevice);
31990 + return DevEnableInterrupts(pDev);
31993 +/* disable all device interrupts */
31994 +A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev)
31998 + status = DevDisableInterrupts(pDev);
32000 + if (A_SUCCESS(status)) {
32001 + /* Disable the interrupt at the HIF layer */
32002 + HIFMaskInterrupt(pDev->HIFDevice);
32008 +/* callback when our fetch to enable/disable completes */
32009 +static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacket)
32011 + AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
32013 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev));
32015 + if (A_FAILED(pPacket->Status)) {
32016 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
32017 + (" Failed to disable receiver, status:%d \n", pPacket->Status));
32019 + /* free this IO packet */
32020 + AR6KFreeIOPacket(pDev,pPacket);
32021 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDoEnableDisableRecvAsyncHandler \n"));
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)
32029 + A_STATUS status = A_OK;
32030 + HTC_PACKET *pIOPacket = NULL;
32032 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n",
32033 + EnableRecv,AsyncMode));
32039 + pIOPacket = AR6KAllocIOPacket(pDev);
32041 + if (NULL == pIOPacket) {
32042 + status = A_NO_MEMORY;
32043 + AR_DEBUG_ASSERT(FALSE);
32047 + /* stick in our completion routine when the I/O operation completes */
32048 + pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
32049 + pIOPacket->pContext = pDev;
32051 + /* call the HIF layer override and do this asynchronously */
32052 + status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
32053 + EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
32058 + /* if we get here we are doing it synchronously */
32059 + status = pDev->HifMaskUmaskRecvEvent(pDev->HIFDevice,
32060 + EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
32065 + if (A_FAILED(status) && (pIOPacket != NULL)) {
32066 + AR6KFreeIOPacket(pDev,pIOPacket);
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)
32077 + A_STATUS status = A_OK;
32078 + HTC_PACKET *pIOPacket = NULL;
32079 + AR6K_IRQ_ENABLE_REGISTERS regs;
32081 + /* take the lock to protect interrupt enable shadows */
32084 + if (EnableRecv) {
32085 + pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
32087 + pDev->IrqEnableRegisters.int_status_enable &= ~INT_STATUS_ENABLE_MBOX_DATA_SET(0x01);
32090 + /* copy into our temp area */
32091 + A_MEMCPY(®s,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
32092 + UNLOCK_AR6K(pDev);
32098 + pIOPacket = AR6KAllocIOPacket(pDev);
32100 + if (NULL == pIOPacket) {
32101 + status = A_NO_MEMORY;
32102 + AR_DEBUG_ASSERT(FALSE);
32106 + /* copy values to write to our async I/O buffer */
32107 + A_MEMCPY(pIOPacket->pBuffer,®s,AR6K_IRQ_ENABLE_REGS_SIZE);
32109 + /* stick in our completion routine when the I/O operation completes */
32110 + pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
32111 + pIOPacket->pContext = pDev;
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,
32123 + /* if we get here we are doing it synchronously */
32125 + status = HIFReadWrite(pDev->HIFDevice,
32126 + INT_STATUS_ENABLE_ADDRESS,
32127 + ®s.int_status_enable,
32128 + AR6K_IRQ_ENABLE_REGS_SIZE,
32129 + HIF_WR_SYNC_BYTE_INC,
32134 + if (A_FAILED(status) && (pIOPacket != NULL)) {
32135 + AR6KFreeIOPacket(pDev,pIOPacket);
32142 +A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
32144 + if (NULL == pDev->HifMaskUmaskRecvEvent) {
32145 + return DevDoEnableDisableRecvNormal(pDev,FALSE,AsyncMode);
32147 + return DevDoEnableDisableRecvOverride(pDev,FALSE,AsyncMode);
32151 +A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
32153 + if (NULL == pDev->HifMaskUmaskRecvEvent) {
32154 + return DevDoEnableDisableRecvNormal(pDev,TRUE,AsyncMode);
32156 + return DevDoEnableDisableRecvOverride(pDev,TRUE,AsyncMode);
32160 +void DevDumpRegisters(AR6K_IRQ_PROC_REGISTERS *pIrqProcRegs,
32161 + AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs)
32164 + AR_DEBUG_PRINTF(ATH_DEBUG_DUMP, ("\n<------- Register Table -------->\n"));
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]));
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"));
32195 +#ifdef MBOXHW_UNIT_TEST
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
32202 + * the unit test has the following constraints:
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 :
32207 + * 1 buffer - 128 bytes
32208 + * 1 buffer - 256 bytes
32209 + * 1 buffer - 512 bytes
32210 + * 1 buffer - 1024 bytes
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.
32217 + * Note: To simplifythe test , we assume that the chosen buffer sizes
32218 + * will fall on a nice block pad
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.
32226 +#define A_ROUND_UP_PWR2(x, align) (((int) (x) + ((align)-1)) & ~((align)-1))
32228 +#define BUFFER_BLOCK_PAD 128
32231 +#define BUFFER1 128
32232 +#define BUFFER2 256
32233 +#define BUFFER3 512
32234 +#define BUFFER4 1024
32238 +#define BUFFER1 80
32239 +#define BUFFER2 200
32240 +#define BUFFER3 444
32241 +#define BUFFER4 800
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) )
32249 +#define TEST_BYTES (BUFFER1 + BUFFER2 + BUFFER3 + BUFFER4)
32251 +#define TEST_CREDITS_RECV_TIMEOUT 100
32253 +static A_UINT8 g_Buffer[TOTAL_BYTES];
32254 +static A_UINT32 g_MailboxAddrs[AR6K_MAILBOXES];
32255 +static A_UINT32 g_BlockSizes[AR6K_MAILBOXES];
32257 +#define BUFFER_PROC_LIST_DEPTH 4
32259 +typedef struct _BUFFER_PROC_LIST{
32260 + A_UINT8 *pBuffer;
32262 +}BUFFER_PROC_LIST;
32265 +#define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \
32267 + (pList)->pBuffer = (pCurrpos); \
32268 + (pList)->length = (len); \
32269 + (pCurrpos) += (len); \
32273 +/* a simple and crude way to send different "message" sizes */
32274 +static void AssembleBufferList(BUFFER_PROC_LIST *pList)
32276 + A_UINT8 *pBuffer = g_Buffer;
32278 +#if BUFFER_PROC_LIST_DEPTH < 4
32279 +#error "Buffer processing list depth is not deep enough!!"
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);
32289 +#define FILL_ZERO TRUE
32290 +#define FILL_COUNTING FALSE
32291 +static void InitBuffers(A_BOOL Zero)
32293 + A_UINT16 *pBuffer16 = (A_UINT16 *)g_Buffer;
32296 + /* fill buffer with 16 bit counting pattern or zeros */
32297 + for (i = 0; i < (TOTAL_BYTES / 2) ; i++) {
32299 + pBuffer16[i] = (A_UINT16)i;
32301 + pBuffer16[i] = 0;
32307 +static A_BOOL CheckOneBuffer(A_UINT16 *pBuffer16, int Length)
32310 + A_UINT16 startCount;
32311 + A_BOOL success = TRUE;
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) {
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]));
32333 +static A_BOOL CheckBuffers(void)
32336 + A_BOOL success = TRUE;
32337 + BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
32339 + /* assemble the list */
32340 + AssembleBufferList(checkList);
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);
32346 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n",
32347 + (A_UINT32)checkList[i].pBuffer, checkList[i].length));
32355 + /* find the end marker for the last buffer we will be sending */
32356 +static A_UINT16 GetEndMarker(void)
32358 + A_UINT8 *pBuffer;
32359 + BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
32361 + /* fill up buffers with the normal counting pattern */
32362 + InitBuffers(FILL_COUNTING);
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]);
32369 + /* the last count in the last buffer is the marker */
32370 + return (A_UINT16)pBuffer[0] | ((A_UINT16)pBuffer[1] << 8);
32373 +#define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR
32375 +/* send the ordered buffers to the target */
32376 +static A_STATUS SendBuffers(AR6K_DEVICE *pDev, int mbox)
32378 + A_STATUS status = A_OK;
32379 + A_UINT32 request = HIF_WR_SYNC_BLOCK_INC;
32380 + BUFFER_PROC_LIST sendList[BUFFER_PROC_LIST_DEPTH];
32382 + int totalBytes = 0;
32383 + int paddedLength;
32384 + int totalwPadding = 0;
32386 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sending buffers on mailbox : %d \n",mbox));
32388 + /* fill buffer with counting pattern */
32389 + InitBuffers(FILL_COUNTING);
32391 + /* assemble the order in which we send */
32392 + AssembleBufferList(sendList);
32394 + for (i = 0; i < BUFFER_PROC_LIST_DEPTH; i++) {
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));
32400 + /* send each buffer synchronously */
32401 + status = HIFReadWrite(pDev->HIFDevice,
32402 + g_MailboxAddrs[mbox],
32403 + sendList[i].pBuffer,
32407 + if (status != A_OK) {
32410 + totalBytes += sendList[i].length;
32411 + totalwPadding += paddedLength;
32414 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Sent %d bytes (%d padded bytes) to mailbox : %d \n",totalBytes,totalwPadding,mbox));
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)
32422 + A_STATUS status = A_OK;
32423 + int timeout = TEST_CREDITS_RECV_TIMEOUT;
32424 + A_UINT8 credits = 0;
32425 + A_UINT32 address;
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;
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;
32453 + /* delay a little, target may not be ready */
32458 + if (status == A_OK) {
32459 + *pCredits = credits;
32466 +/* wait for the buffers to come back */
32467 +static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
32469 + A_STATUS status = A_OK;
32470 + A_UINT32 request = HIF_RD_SYNC_BLOCK_INC;
32471 + BUFFER_PROC_LIST recvList[BUFFER_PROC_LIST_DEPTH];
32475 + int totalBytes = 0;
32476 + int paddedLength;
32477 + int totalwPadding = 0;
32479 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for buffers on mailbox : %d \n",mbox));
32481 + /* zero the buffers */
32482 + InitBuffers(FILL_ZERO);
32484 + /* assemble the order in which we should receive */
32485 + AssembleBufferList(recvList);
32489 + while (curBuffer < BUFFER_PROC_LIST_DEPTH) {
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);
32495 + if (status != A_OK) {
32499 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got %d messages on mailbox : %d \n",credits, mbox));
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));
32509 + status = HIFReadWrite(pDev->HIFDevice,
32510 + g_MailboxAddrs[mbox],
32511 + recvList[curBuffer].pBuffer,
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]));
32521 + totalwPadding += paddedLength;
32522 + totalBytes += recvList[curBuffer].length;
32526 + if (status != A_OK) {
32529 + /* go back and get some more */
32533 + if (totalBytes != TEST_BYTES) {
32534 + AR_DEBUG_ASSERT(FALSE);
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));
32545 +static A_STATUS DoOneMboxHWTest(AR6K_DEVICE *pDev, int mbox)
32550 + /* send out buffers */
32551 + status = SendBuffers(pDev,mbox);
32553 + if (status != A_OK) {
32554 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox));
32558 + /* go get them, this will block */
32559 + status = RecvBuffers(pDev, mbox);
32561 + if (status != A_OK) {
32562 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox));
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;
32573 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox));
32580 +/* here is where the test starts */
32581 +A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
32586 + A_UINT8 params[4];
32592 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START - \n"));
32595 + /* get the addresses for all 4 mailboxes */
32596 + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
32597 + g_MailboxAddrs, sizeof(g_MailboxAddrs));
32599 + if (status != A_OK) {
32600 + AR_DEBUG_ASSERT(FALSE);
32604 + /* get the block sizes */
32605 + status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
32606 + g_BlockSizes, sizeof(g_BlockSizes));
32608 + if (status != A_OK) {
32609 + AR_DEBUG_ASSERT(FALSE);
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
32616 + g_BlockSizes[0] = g_BlockSizes[1];
32617 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Block Size to use: %d \n",g_BlockSizes[0]));
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));
32625 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Waiting for target.... \n"));
32627 + /* the target lets us know it is ready by giving us 1 credit on
32629 + status = GetCredits(pDev, 0, &credits);
32631 + if (status != A_OK) {
32632 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n"));
32636 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Target is ready ...\n"));
32638 + /* read the first 4 scratch registers */
32639 + status = HIFReadWrite(pDev->HIFDevice,
32643 + HIF_RD_SYNC_BYTE_INC,
32646 + if (status != A_OK) {
32647 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n"));
32651 + numBufs = params[0];
32652 + bufferSize = (int)(((A_UINT16)params[2] << 8) | (A_UINT16)params[1]);
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));
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;
32665 + temp = GetEndMarker();
32667 + status = HIFReadWrite(pDev->HIFDevice,
32668 + SCRATCH_ADDRESS + 4,
32669 + (A_UINT8 *)&temp,
32671 + HIF_WR_SYNC_BYTE_INC,
32674 + if (status != A_OK) {
32675 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n"));
32679 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp));
32681 + temp = (A_UINT16)g_BlockSizes[1];
32682 + /* convert to a mask */
32684 + status = HIFReadWrite(pDev->HIFDevice,
32685 + SCRATCH_ADDRESS + 6,
32686 + (A_UINT8 *)&temp,
32688 + HIF_WR_SYNC_BYTE_INC,
32691 + if (status != A_OK) {
32692 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n"));
32696 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Set Block Mask: 0x%X \n",temp));
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) {
32708 + if (status == A_OK) {
32709 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! - \n"));
32711 + AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! - \n"));
32713 + /* don't let HTC_Start continue, the target is actually not running any HTC code */
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
32725 + * AR6K Driver layer event handling (i.e. interrupts, message polling)
32727 + * Copyright (c) 2007 Atheros Communications Inc.
32728 + * All rights reserved.
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;
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.
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"
32750 +#include "htc_packet.h"
32753 +extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
32754 +extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
32756 +static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev);
32758 +#define DELAY_PER_INTERVAL_MS 10 /* 10 MS delay per polling interval */
32760 +/* completion routine for ALL HIF layer async I/O */
32761 +A_STATUS DevRWCompletionHandler(void *context, A_STATUS status)
32763 + HTC_PACKET *pPacket = (HTC_PACKET *)context;
32765 + COMPLETE_HTC_PACKET(pPacket,status);
32770 +/* mailbox recv message polling */
32771 +A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
32772 + A_UINT32 *pLookAhead,
32775 + A_STATUS status = A_OK;
32776 + int timeout = TimeoutMS/DELAY_PER_INTERVAL_MS;
32778 + AR_DEBUG_ASSERT(timeout > 0);
32780 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n"));
32784 + if (pDev->GetPendingEventsFunc != NULL)
32787 + HIF_PENDING_EVENTS_INFO events;
32789 + /* the HIF layer uses a special mechanism to get events, do this
32790 + * synchronously */
32791 + status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
32794 + if (A_FAILED(status))
32796 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n"));
32800 + if (events.Events & HIF_RECV_MSG_AVAIL)
32802 + /* there is a message available, the lookahead should be valid now */
32803 + *pLookAhead = events.LookAhead;
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,
32820 + if (A_FAILED(status))
32822 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n"));
32826 + /* check for MBOX data and valid lookahead */
32827 + if (pDev->IrqProcRegisters.host_int_status & (1 << HTC_MAILBOX))
32829 + if (pDev->IrqProcRegisters.rx_lookahead_valid & (1 << HTC_MAILBOX))
32831 + /* mailbox has a message and the look ahead is valid */
32832 + *pLookAhead = pDev->IrqProcRegisters.rx_lookahead[HTC_MAILBOX];
32841 + if (timeout <= 0)
32843 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Timeout waiting for recv message \n"));
32844 + status = A_ERROR;
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);
32856 + /* delay a little */
32857 + msleep(DELAY_PER_INTERVAL_MS);
32858 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,(" Retry Mbox Poll : %d \n",timeout));
32861 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevPollMboxMsgRecv \n"));
32866 +static A_STATUS DevServiceCPUInterrupt(AR6K_DEVICE *pDev)
32869 + A_UINT8 cpu_int_status;
32870 + A_UINT8 regBuffer[4];
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));
32880 + /* Clear the interrupt */
32881 + pDev->IrqProcRegisters.cpu_int_status &= ~cpu_int_status; /* W1C */
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 */
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;
32894 + status = HIFReadWrite(pDev->HIFDevice,
32895 + CPU_INT_STATUS_ADDRESS,
32898 + HIF_WR_SYNC_BYTE_FIX,
32901 + AR_DEBUG_ASSERT(status == A_OK);
32906 +static A_STATUS DevServiceErrorInterrupt(AR6K_DEVICE *pDev)
32909 + A_UINT8 error_int_status;
32910 + A_UINT8 regBuffer[4];
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));
32919 + if (ERROR_INT_STATUS_WAKEUP_GET(error_int_status)) {
32921 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error : Wakeup\n"));
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"));
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"));
32934 + /* Clear the interrupt */
32935 + pDev->IrqProcRegisters.error_int_status &= ~error_int_status; /* W1C */
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 */
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;
32948 + status = HIFReadWrite(pDev->HIFDevice,
32949 + ERROR_INT_STATUS_ADDRESS,
32952 + HIF_WR_SYNC_BYTE_FIX,
32955 + AR_DEBUG_ASSERT(status == A_OK);
32959 +static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev)
32964 + /* Send a target failure event to the application */
32965 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n"));
32967 + if (pDev->TargetFailureCallback != NULL) {
32968 + pDev->TargetFailureCallback(pDev->HTCContext);
32971 + /* clear the interrupt , the debug error interrupt is
32973 + /* read counter to clear interrupt */
32974 + status = HIFReadWrite(pDev->HIFDevice,
32975 + COUNT_DEC_ADDRESS,
32976 + (A_UINT8 *)&dummy,
32978 + HIF_RD_SYNC_BYTE_INC,
32981 + AR_DEBUG_ASSERT(status == A_OK);
32985 +static A_STATUS DevServiceCounterInterrupt(AR6K_DEVICE *pDev)
32987 + A_UINT8 counter_int_status;
32989 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n"));
32991 + counter_int_status = pDev->IrqProcRegisters.counter_int_status &
32992 + pDev->IrqEnableRegisters.counter_int_status_enable;
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));
32999 + /* Check if the debug interrupt is pending */
33000 + if (counter_int_status & AR6K_TARGET_DEBUG_INTR_MASK) {
33001 + return DevServiceDebugInterrupt(pDev);
33007 +/* callback when our fetch to get interrupt status registers completes */
33008 +static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
33010 + AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
33011 + A_UINT32 lookAhead = 0;
33012 + A_BOOL otherInts = FALSE;
33014 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%X)\n", (A_UINT32)pDev));
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 */
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"));
33034 + if (pEvents->Events & HIF_OTHER_EVENTS) {
33035 + otherInts = TRUE;
33038 + /* standard interrupt table handling.... */
33039 + AR6K_IRQ_PROC_REGISTERS *pReg = (AR6K_IRQ_PROC_REGISTERS *)pPacket->pBuffer;
33040 + A_UINT8 host_int_status;
33042 + host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable;
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"));
33055 + if (host_int_status) {
33056 + /* there are other interrupts to handle */
33057 + otherInts = TRUE;
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);
33070 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
33071 + (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n",
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);
33080 + /* free this IO packet */
33081 + AR6KFreeIOPacket(pDev,pPacket);
33082 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGetEventAsyncHandler \n"));
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)
33089 + AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
33090 + A_STATUS status = A_OK;
33091 + HTC_PACKET *pIOPacket;
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 */
33096 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevCheckPendingRecvMsgsAsync: (dev: 0x%X)\n", (A_UINT32)pDev));
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 */
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);
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);
33119 + /* stick in our completion routine when the I/O operation completes */
33120 + pIOPacket->Completion = DevGetEventAsyncHandler;
33121 + pIOPacket->pContext = pDev;
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,
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,
33139 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n"));
33142 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n"));
33147 +/* process pending interrupts synchronously */
33148 +static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pASyncProcessing)
33150 + A_STATUS status = A_OK;
33151 + A_UINT8 host_int_status = 0;
33152 + A_UINT32 lookAhead = 0;
33154 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%X)\n", (A_UINT32)pDev));
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.
33163 + if (pDev->GetPendingEventsFunc != NULL) {
33164 + HIF_PENDING_EVENTS_INFO events;
33166 + /* the HIF layer uses a special mechanism to get events
33167 + * get this synchronously */
33168 + status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
33172 + if (A_FAILED(status)) {
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"));
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 */
33191 + /* otherwise fall through and read the register table */
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
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);
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,
33214 + if (A_FAILED(status)) {
33218 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_IRQ)) {
33219 + DevDumpRegisters(&pDev->IrqProcRegisters,
33220 + &pDev->IrqEnableRegisters);
33223 + /* Update only those registers that are enabled */
33224 + host_int_status = pDev->IrqProcRegisters.host_int_status &
33225 + pDev->IrqEnableRegisters.int_status_enable;
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"));
33243 + /* not valid to check if the HIF has another mechanism for reading mailbox pending status*/
33244 + host_int_status &= ~(1 << HTC_MAILBOX);
33252 + /* did the interrupt status fetches succeed? */
33253 + if (A_FAILED(status)) {
33257 + if ((0 == host_int_status) && (0 == lookAhead)) {
33258 + /* nothing to process, the caller can use this to break out of a loop */
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
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)) {
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));
33281 + if (HOST_INT_STATUS_CPU_GET(host_int_status)) {
33282 + /* CPU Interrupt */
33283 + status = DevServiceCPUInterrupt(pDev);
33284 + if (A_FAILED(status)){
33289 + if (HOST_INT_STATUS_ERROR_GET(host_int_status)) {
33290 + /* Error Interrupt */
33291 + status = DevServiceErrorInterrupt(pDev);
33292 + if (A_FAILED(status)){
33297 + if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) {
33298 + /* Counter Interrupt */
33299 + status = DevServiceCounterInterrupt(pDev);
33300 + if (A_FAILED(status)){
33307 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n",
33308 + *pDone, *pASyncProcessing, status));
33314 +/* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/
33315 +A_STATUS DevDsrHandler(void *context)
33317 + AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
33318 + A_STATUS status = A_OK;
33319 + A_BOOL done = FALSE;
33320 + A_BOOL asyncProc = FALSE;
33322 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%X)\n", (A_UINT32)pDev));
33326 + status = ProcessPendingIRQs(pDev, &done, &asyncProc);
33327 + if (A_FAILED(status)) {
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) */
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 */
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);
33357 + AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevDsrHandler \n"));
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
33368 + * Copyright (c) 2007 Atheros Communications Inc.
33369 + * All rights reserved.
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;
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.
33388 +#define AR6K_MAILBOXES 4
33390 +/* HTC runs over mailbox 0 */
33391 +#define HTC_MAILBOX 0
33393 +#define AR6K_TARGET_DEBUG_INTR_MASK 0x01
33395 +#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \
33396 + INT_STATUS_ENABLE_CPU_MASK | \
33397 + INT_STATUS_ENABLE_COUNTER_MASK)
33399 +//#define MBOXHW_UNIT_TEST 1
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;
33410 + A_UINT32 rx_lookahead[2];
33411 +} POSTPACK AR6K_IRQ_PROC_REGISTERS;
33413 +#define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS)
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;
33424 +#include "athendpack.h"
33426 +#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(AR6K_IRQ_ENABLE_REGISTERS)
33428 +#define AR6K_REG_IO_BUFFER_SIZE 32
33429 +#define AR6K_MAX_REG_IO_BUFFERS 8
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;
33437 +typedef struct _AR6K_DEVICE {
33439 + AR6K_IRQ_PROC_REGISTERS IrqProcRegisters;
33440 + AR6K_IRQ_ENABLE_REGISTERS IrqEnableRegisters;
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;
33455 +#define IS_DEV_IRQ_PROCESSING_ASYNC_ALLOWED(pDev) ((pDev)->HifIRQProcessingMode != HIF_DEVICE_IRQ_SYNC_ONLY)
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,
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);
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);
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;
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);
33493 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
33494 + ("DevSendPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n",
33496 + pDev->MailboxAddress,
33497 + sync ? "SYNC" : "ASYNC"));
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 */
33507 + pPacket->Status = status;
33513 +static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 RecvLength) {
33514 + A_UINT32 paddedLength;
33516 + A_BOOL sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
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);
33532 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
33533 + ("DevRecvPacket, Padded Length: %d Mbox:0x%X (mode:%s)\n",
33535 + pDev->MailboxAddress,
33536 + sync ? "SYNC" : "ASYNC"));
33538 + status = HIFReadWrite(pDev->HIFDevice,
33539 + pDev->MailboxAddress,
33540 + pPacket->pBuffer,
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 */
33546 + pPacket->Status = status;
33552 +#ifdef MBOXHW_UNIT_TEST
33553 +A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev);
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
33563 + * Copyright (c) 2007 Atheros Communications Inc.
33564 + * All rights reserved.
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;
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.
33580 +#include "htc_internal.h"
33583 +static HTC_INIT_INFO HTCInitInfo = {NULL,NULL,NULL};
33584 +static A_BOOL HTCInitialized = FALSE;
33586 +static A_STATUS HTCTargetInsertedHandler(void *hif_handle);
33587 +static A_STATUS HTCTargetRemovedHandler(void *handle, A_STATUS status);
33588 +static void HTCReportFailure(void *Context);
33590 +/* Initializes the HTC layer */
33591 +A_STATUS HTCInit(HTC_INIT_INFO *pInitInfo)
33593 + HTC_CALLBACKS htcCallbacks;
33595 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Enter\n"));
33596 + if (HTCInitialized) {
33597 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Exit\n"));
33601 + A_MEMCPY(&HTCInitInfo,pInitInfo,sizeof(HTC_INIT_INFO));
33603 + A_MEMZERO(&htcCallbacks, sizeof(HTC_CALLBACKS));
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;
33614 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCInit: Exit\n"));
33618 +void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList)
33620 + LOCK_HTC(target);
33621 + HTC_PACKET_ENQUEUE(pList,pPacket);
33622 + UNLOCK_HTC(target);
33625 +HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList)
33627 + HTC_PACKET *pPacket;
33629 + LOCK_HTC(target);
33630 + pPacket = HTC_PACKET_DEQUEUE(pList);
33631 + UNLOCK_HTC(target);
33636 +/* cleanup the HTC instance */
33637 +static void HTCCleanup(HTC_TARGET *target)
33639 + if (A_IS_MUTEX_VALID(&target->HTCLock)) {
33640 + A_MUTEX_DELETE(&target->HTCLock);
33643 + if (A_IS_MUTEX_VALID(&target->HTCRxLock)) {
33644 + A_MUTEX_DELETE(&target->HTCRxLock);
33647 + if (A_IS_MUTEX_VALID(&target->HTCTxLock)) {
33648 + A_MUTEX_DELETE(&target->HTCTxLock);
33650 + /* free our instance */
33654 +/* registered target arrival callback from the HIF layer */
33655 +static A_STATUS HTCTargetInsertedHandler(void *hif_handle)
33657 + HTC_TARGET *target = NULL;
33661 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Enter\n"));
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;
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);
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;
33691 + /* setup device layer */
33692 + status = DevSetup(&target->Device);
33694 + if (A_FAILED(status)) {
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,
33704 + target->HTCControlBuffers[i].Buffer,
33705 + HTC_CONTROL_BUFFER_SIZE,
33707 + HTC_FREE_CONTROL_RX(target,pControlPacket);
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);
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);
33726 + if (target != NULL) {
33727 + HTCCleanup(target);
33731 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("htcTargetInserted - Exit\n"));
33736 +/* registered removal callback from the HIF layer */
33737 +static A_STATUS HTCTargetRemovedHandler(void *handle, A_STATUS status)
33739 + HTC_TARGET *target;
33741 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCTargetRemovedHandler handle:0x%X \n",(A_UINT32)handle));
33743 + if (NULL == handle) {
33744 + /* this could be NULL in the event that target initialization failed */
33748 + target = ((AR6K_DEVICE *)handle)->HTCContext;
33750 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" removing target:0x%X instance:0x%X ... \n",
33751 + (A_UINT32)target, (A_UINT32)target->pInstanceContext));
33753 + if (target->pInstanceContext != NULL) {
33754 + /* let upper layer know, it needs to call HTCStop() */
33755 + HTCInitInfo.DeleteInstance(target->pInstanceContext);
33758 + HIFShutDownDevice(target->Device.HIFDevice);
33760 + HTCCleanup(target);
33761 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCTargetRemovedHandler \n"));
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)
33769 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33770 + return target->Device.HIFDevice;
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)
33777 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33779 + target->pInstanceContext = Instance;
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)
33786 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33788 + HTC_PACKET *pPacket = NULL;
33789 + HTC_READY_MSG *pRdyMsg;
33790 + HTC_SERVICE_CONNECT_REQ connect;
33791 + HTC_SERVICE_CONNECT_RESP resp;
33793 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%X) \n", (A_UINT32)target));
33797 +#ifdef MBOXHW_UNIT_TEST
33799 + status = DoMboxHWTest(&target->Device);
33801 + if (status != A_OK) {
33807 + /* we should be getting 1 control message that the target is ready */
33808 + status = HTCWaitforControlMessage(target, &pPacket);
33810 + if (A_FAILED(status)) {
33811 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n"));
33815 + /* we controlled the buffer creation so it has to be properly aligned */
33816 + pRdyMsg = (HTC_READY_MSG *)pPacket->pBuffer;
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;
33826 + if (pRdyMsg->CreditCount == 0 || pRdyMsg->CreditSize == 0) {
33827 + /* this message is not valid */
33828 + AR_DEBUG_ASSERT(FALSE);
33829 + status = A_EPROTO;
33833 + target->TargetCredits = pRdyMsg->CreditCount;
33834 + target->TargetCreditSize = pRdyMsg->CreditSize;
33836 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, (" Target Ready: credits: %d credit size: %d\n",
33837 + target->TargetCredits, target->TargetCreditSize));
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;
33851 + /* connect fake service */
33852 + status = HTCConnectService((HTC_HANDLE)target,
33856 + if (!A_FAILED(status)) {
33862 + if (pPacket != NULL) {
33863 + HTC_FREE_CONTROL_RX(target,pPacket);
33866 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Exit\n"));
33873 +/* Start HTC, enable interrupts and let the target know host has finished setup */
33874 +A_STATUS HTCStart(HTC_HANDLE HTCHandle)
33876 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33877 + HTC_PACKET *pPacket;
33880 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n"));
33882 + /* now that we are starting, push control receive buffers into the
33883 + * HTC control endpoint */
33886 + pPacket = HTC_ALLOC_CONTROL_RX(target);
33887 + if (NULL == pPacket) {
33890 + HTCAddReceivePkt((HTC_HANDLE)target,pPacket);
33895 + AR_DEBUG_ASSERT(target->InitCredits != NULL);
33896 + AR_DEBUG_ASSERT(target->EpCreditDistributionListHead != NULL);
33897 + AR_DEBUG_ASSERT(target->EpCreditDistributionListHead->pNext != NULL);
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);
33906 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
33907 + DumpCreditDistStates(target);
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);
33914 + if (A_FAILED(status)) {
33918 + /* unmask interrupts */
33919 + status = DevUnmaskInterrupts(&target->Device);
33921 + if (A_FAILED(status)) {
33927 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n"));
33932 +/* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
33933 +void HTCStop(HTC_HANDLE HTCHandle)
33935 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33936 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n"));
33938 + /* mark that we are shutting down .. */
33939 + target->HTCStateFlags |= HTC_STATE_STOPPING;
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);
33945 + /* flush all send packets */
33946 + HTCFlushSendPkts(target);
33947 + /* flush all recv buffers */
33948 + HTCFlushRecvBuffers(target);
33950 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
33953 +/* undo what was done in HTCInit() */
33954 +void HTCShutDown(void)
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"));
33963 +void HTCDumpCreditStates(HTC_HANDLE HTCHandle)
33965 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
33967 + LOCK_HTC_TX(target);
33969 + DumpCreditDistStates(target);
33971 + UNLOCK_HTC_TX(target);
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)
33978 + HTC_TARGET *target = (HTC_TARGET *)Context;
33980 + target->TargetFailure = TRUE;
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);
33988 +void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription)
33990 + A_CHAR stream[60];
33992 + A_UINT16 offset, count;
33994 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<---------Dumping %d Bytes : %s ------>\n", length, pDescription));
33998 + for(i = 0; i < length; i++) {
33999 + sprintf(stream + offset, "%2.2X ", buffer[i]);
34003 + if(count == 16) {
34006 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("[H]: %s\n", stream));
34007 + A_MEMZERO(stream, 60);
34011 + if(offset != 0) {
34012 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("[H]: %s\n", stream));
34015 + AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("<------------------------------------------------->\n"));
34018 +A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle,
34019 + HTC_ENDPOINT_ID Endpoint,
34020 + HTC_ENDPOINT_STAT_ACTION Action,
34021 + HTC_ENDPOINT_STATS *pStats)
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;
34029 + switch (Action) {
34030 + case HTC_EP_STAT_SAMPLE :
34033 + case HTC_EP_STAT_SAMPLE_AND_CLEAR :
34035 + clearStats = TRUE;
34037 + case HTC_EP_STAT_CLEAR :
34038 + clearStats = TRUE;
34044 + A_ASSERT(Endpoint < ENDPOINT_MAX);
34046 + /* lock out TX and RX while we sample and/or clear */
34047 + LOCK_HTC_TX(target);
34048 + LOCK_HTC_RX(target);
34051 + A_ASSERT(pStats != NULL);
34052 + /* return the stats to the caller */
34053 + A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
34056 + if (clearStats) {
34057 + /* reset stats */
34058 + A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
34061 + UNLOCK_HTC_RX(target);
34062 + UNLOCK_HTC_TX(target);
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
34073 +#ifndef HTC_DEBUG_H_
34074 +#define HTC_DEBUG_H_
34077 + * Copyright (c) 2004-2007 Atheros Communications Inc.
34078 + * All rights reserved.
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;
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.
34094 +/* ------- Debug related stuff ------- */
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,
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); \
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); \
34122 +#define AR_DEBUG_ASSERT(test) do { \
34124 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Debug Assert Caught, File %s, Line: %d, Test:%s \n",__FILE__, __LINE__,#test)); \
34127 +extern int debughtc;
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
34135 +void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
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
34144 + * Copyright (c) 2007 Atheros Communications Inc.
34145 + * All rights reserved.
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;
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.
34161 +#ifndef _HTC_INTERNAL_H_
34162 +#define _HTC_INTERNAL_H_
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
34168 +//#define HTC_EP_STAT_PROFILING
34170 +#ifdef __cplusplus
34172 +#endif /* __cplusplus */
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"
34181 +#include "htc_api.h"
34182 +#include "bmi_msg.h"
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
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 */
34207 +#ifdef HTC_EP_STAT_PROFILING
34208 +#define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count);
34210 +#define INC_HTC_EP_STAT(p,stat,count)
34213 +#define HTC_SERVICE_TX_PACKET_TAG HTC_TX_PACKET_TAG_INTERNAL
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)
34219 +#define HTC_CONTROL_BUFFER_SIZE (HTC_MAX_CONTROL_MESSAGE_LENGTH + HTC_HDR_LENGTH)
34221 +typedef struct HTC_CONTROL_BUFFER {
34222 + HTC_PACKET HtcPacket;
34223 + A_UINT8 Buffer[HTC_CONTROL_BUFFER_SIZE];
34224 +} HTC_CONTROL_BUFFER;
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;
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);
34263 +#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd))
34264 +#define HTC_RECYCLE_RX_PKT(target,p) \
34266 + HTC_PACKET_RESET_RX(pPacket); \
34267 + HTCAddReceivePkt((HTC_HANDLE)(target),(p)); \
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);
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;
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) \
34301 + HTC_PACKET_RESET_RX(p); \
34302 + HTCFreeControlBuffer((t),(p),&(t)->ControlBufferRXFreeList); \
34305 +#ifdef __cplusplus
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
34316 + * Copyright (c) 2007 Atheros Communications Inc.
34317 + * All rights reserved.
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;
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.
34333 +#include "htc_internal.h"
34335 +#define HTCIssueRecv(t, p) \
34336 + DevRecvPacket(&(t)->Device, \
34338 + (p)->ActualLength)
34340 +#define DO_RCV_COMPLETION(t,p,e) \
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, \
34348 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, (" recycling empty packet \n")); \
34349 + HTC_RECYCLE_RX_PKT((t), (p)); \
34353 +#ifdef HTC_EP_STAT_PROFILING
34354 +#define HTC_RX_STAT_PROFILE(t,ep,lookAhead) \
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); \
34361 + UNLOCK_HTC_RX((t)); \
34364 +#define HTC_RX_STAT_PROFILE(t,ep,lookAhead)
34367 +static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
34368 + A_UINT8 *pBuffer,
34370 + A_UINT32 *pNextLookAhead,
34371 + HTC_ENDPOINT_ID FromEndpoint)
34373 + HTC_RECORD_HDR *pRecord;
34374 + A_UINT8 *pRecordBuf;
34375 + HTC_LOOKAHEAD_REPORT *pLookAhead;
34376 + A_UINT8 *pOrigBuffer;
34380 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length));
34382 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
34383 + AR_DEBUG_PRINTBUF(pBuffer,Length,"Recv Trailer");
34386 + pOrigBuffer = pBuffer;
34387 + origLength = Length;
34390 + while (Length > 0) {
34392 + if (Length < sizeof(HTC_RECORD_HDR)) {
34393 + status = A_EPROTO;
34396 + /* these are byte aligned structs */
34397 + pRecord = (HTC_RECORD_HDR *)pBuffer;
34398 + Length -= sizeof(HTC_RECORD_HDR);
34399 + pBuffer += sizeof(HTC_RECORD_HDR);
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;
34409 + /* start of record follows the header */
34410 + pRecordBuf = pBuffer;
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)),
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)) {
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));
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];
34437 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
34438 + DebugDumpBytes((A_UINT8 *)pNextLookAhead,4,"Next Look Ahead");
34443 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" unhandled record: id:%d length:%d \n",
34444 + pRecord->RecordID, pRecord->Length));
34448 + if (A_FAILED(status)) {
34452 + /* advance buffer past this record for next time around */
34453 + pBuffer += pRecord->Length;
34454 + Length -= pRecord->Length;
34457 + if (A_FAILED(status)) {
34458 + DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer");
34461 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessTrailer \n"));
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)
34472 + A_STATUS status = A_OK;
34473 + A_UINT16 payloadLen;
34474 + A_UINT32 lookAhead;
34476 + pBuf = pPacket->pBuffer;
34478 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessRecvHeader \n"));
34480 + if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
34481 + AR_DEBUG_PRINTBUF(pBuf,pPacket->ActualLength,"HTC Recv PKT");
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);
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];
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,
34509 + status = A_EPROTO;
34514 + temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, Flags);
34516 + if (temp & HTC_FLAGS_RECV_TRAILER) {
34517 + /* this packet has a trailer */
34519 + /* extract the trailer length in control byte 0 */
34520 + temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, ControlBytes[0]);
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;
34530 + /* process trailer data that follows HDR + application payload */
34531 + status = HTCProcessTrailer(target,
34532 + (pBuf + HTC_HDR_LENGTH + payloadLen - temp),
34535 + pPacket->Endpoint);
34537 + if (A_FAILED(status)) {
34541 +#ifdef HTC_CAPTURE_LAST_FRAME
34542 + A_MEMCPY(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp);
34543 + target->LastTrailerLength = temp;
34545 + /* trim length by trailer bytes */
34546 + pPacket->ActualLength -= temp;
34548 +#ifdef HTC_CAPTURE_LAST_FRAME
34550 + target->LastTrailerLength = 0;
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;
34561 + if (A_FAILED(status)) {
34562 + /* dump the whole packet */
34563 + DebugDumpBytes(pBuf,pPacket->ActualLength,"BAD HTC Recv PKT");
34565 +#ifdef HTC_CAPTURE_LAST_FRAME
34566 + A_MEMCPY(&target->LastFrameHdr,pBuf,sizeof(HTC_FRAME_HDR));
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");
34575 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCProcessRecvHeader \n"));
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)
34583 + HTC_TARGET *target = (HTC_TARGET *)Context;
34584 + HTC_ENDPOINT *pEndpoint;
34585 + A_UINT32 nextLookAhead = 0;
34588 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (status:%d, ep:%d) \n",
34589 + pPacket->Status, pPacket->Endpoint));
34591 + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
34592 + pEndpoint = &target->EndPoint[pPacket->Endpoint];
34593 + pPacket->Completion = NULL;
34595 + /* get completion status */
34596 + status = pPacket->Status;
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));
34604 + /* process the header for any trailer data */
34605 + status = HTCProcessRecvHeader(target,pPacket,&nextLookAhead);
34607 + if (A_FAILED(status)) {
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",
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,
34624 + "BAD lookahead from lookahead report");
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);
34636 + HTC_RX_STAT_PROFILE(target,pEndpoint,nextLookAhead);
34637 + DO_RCV_COMPLETION(target,pPacket,pEndpoint);
34641 + if (A_FAILED(status)) {
34642 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34643 + ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n",
34645 + /* recyle this packet */
34646 + HTC_RECYCLE_RX_PKT(target, pPacket);
34649 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("-HTCRecvCompleteHandler\n"));
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)
34658 + A_UINT32 lookAhead;
34659 + HTC_PACKET *pPacket = NULL;
34660 + HTC_FRAME_HDR *pHdr;
34662 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n"));
34666 + *ppControlPacket = NULL;
34668 + /* call the polling function to see if we have a message */
34669 + status = DevPollMboxMsgRecv(&target->Device,
34671 + HTC_TARGET_RESPONSE_TIMEOUT);
34673 + if (A_FAILED(status)) {
34677 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
34678 + ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead));
34680 + /* check the lookahead */
34681 + pHdr = (HTC_FRAME_HDR *)&lookAhead;
34683 + if (pHdr->EndpointID != ENDPOINT_0) {
34684 + /* unexpected endpoint number, should be zero */
34685 + AR_DEBUG_ASSERT(FALSE);
34686 + status = A_EPROTO;
34690 + if (A_FAILED(status)) {
34691 + /* bad message */
34692 + AR_DEBUG_ASSERT(FALSE);
34693 + status = A_EPROTO;
34697 + pPacket = HTC_ALLOC_CONTROL_RX(target);
34699 + if (pPacket == NULL) {
34700 + AR_DEBUG_ASSERT(FALSE);
34701 + status = A_NO_MEMORY;
34705 + pPacket->HTCReserved = lookAhead;
34706 + pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
34708 + if (pPacket->ActualLength > pPacket->BufferLength) {
34709 + AR_DEBUG_ASSERT(FALSE);
34710 + status = A_EPROTO;
34714 + /* we want synchronous operation */
34715 + pPacket->Completion = NULL;
34717 + /* get the message from the device, this will block */
34718 + status = HTCIssueRecv(target, pPacket);
34720 + if (A_FAILED(status)) {
34724 + /* process receive header */
34725 + status = HTCProcessRecvHeader(target,pPacket,NULL);
34727 + pPacket->Status = status;
34729 + if (A_FAILED(status)) {
34730 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
34731 + ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n",
34736 + /* give the caller this control message packet, they are responsible to free */
34737 + *ppControlPacket = pPacket;
34741 + if (A_FAILED(status)) {
34742 + if (pPacket != NULL) {
34743 + /* cleanup buffer on error */
34744 + HTC_FREE_CONTROL_RX(target,pPacket);
34748 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCWaitforControlMessage \n"));
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)
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;
34763 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCRecvMessagePendingHandler LookAhead:0x%X \n",LookAhead));
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;
34772 + if (pAsyncProc != NULL) {
34773 + /* indicate to caller how we decided to process this */
34774 + *pAsyncProc = asyncProc;
34779 + pHdr = (HTC_FRAME_HDR *)&LookAhead;
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;
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;
34795 + pEndpoint = &target->EndPoint[pHdr->EndpointID];
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;
34804 + /* lock RX to get a buffer */
34805 + LOCK_HTC_RX(target);
34807 + /* get a packet from the endpoint recv queue */
34808 + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
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 */
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;
34831 + UNLOCK_HTC_RX(target);
34833 + if (A_FAILED(status)) {
34838 + AR_DEBUG_ASSERT(pPacket->Endpoint == pHdr->EndpointID);
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;
34849 + pPacket->HTCReserved = LookAhead; /* set expected look ahead */
34850 + /* set the amount of data to fetch */
34851 + pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
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;
34859 + /* fully synchronous */
34860 + pPacket->Completion = NULL;
34863 + /* go fetch the packet */
34864 + status = HTCIssueRecv(target, pPacket);
34866 + if (A_FAILED(status)) {
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 */
34877 + /* in the sync case, we process the packet, check lookaheads and then repeat */
34880 + status = HTCProcessRecvHeader(target,pPacket,&LookAhead);
34882 + if (A_FAILED(status)) {
34886 + HTC_RX_STAT_PROFILE(target,pEndpoint,LookAhead);
34887 + DO_RCV_COMPLETION(target,pPacket,pEndpoint);
34891 + if (0 == LookAhead) {
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);
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);
34914 + AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCRecvMessagePendingHandler \n"));
34919 +/* Makes a buffer available to the HTC module */
34920 +A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
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;
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));
34933 + if (HTC_STOPPING(target)) {
34934 + status = A_ECANCELED;
34938 + AR_DEBUG_ASSERT(pPacket->Endpoint < ENDPOINT_MAX);
34940 + pEndpoint = &target->EndPoint[pPacket->Endpoint];
34942 + LOCK_HTC_RX(target);
34944 + /* store receive packet */
34945 + HTC_PACKET_ENQUEUE(&pEndpoint->RxBuffers, pPacket);
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;
34958 + UNLOCK_HTC_RX(target);
34960 + if (unblockRecv && !HTC_STOPPING(target)) {
34961 + /* TODO : implement a buffer threshold count? */
34962 + DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
34970 +static void HTCFlushEndpointRX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
34972 + HTC_PACKET *pPacket;
34974 + LOCK_HTC_RX(target);
34977 + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->RxBuffers);
34978 + if (NULL == pPacket) {
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,
34989 + LOCK_HTC_RX(target);
34992 + UNLOCK_HTC_RX(target);
34997 +void HTCFlushRecvBuffers(HTC_TARGET *target)
34999 + HTC_ENDPOINT *pEndpoint;
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.. */
35010 + HTCFlushEndpointRX(target,pEndpoint);
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
35023 + * Copyright (c) 2007 Atheros Communications Inc.
35024 + * All rights reserved.
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;
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.
35040 +#include "htc_internal.h"
35042 +#define DO_EP_TX_COMPLETION(ep,p) \
35044 + (p)->Completion = NULL; \
35045 + (ep)->EpCallBacks.EpTxComplete((ep)->EpCallBacks.pContext,(p)); \
35049 +/* call the distribute credits callback with the distribution */
35050 +#define DO_DISTRIBUTION(t,reason,description,pList) \
35052 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, \
35053 + (" calling distribute function (%s) (dfn:0x%X, ctxt:0x%X, dist:0x%X) \n", \
35055 + (A_UINT32)(t)->DistributeCredits, \
35056 + (A_UINT32)(t)->pCredDistContext, \
35057 + (A_UINT32)pList)); \
35058 + (t)->DistributeCredits((t)->pCredDistContext, \
35063 +/* our internal send packet completion handler when packets are submited to the AR6K device
35065 +static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket)
35067 + HTC_TARGET *target = (HTC_TARGET *)Context;
35068 + HTC_ENDPOINT *pEndpoint = &target->EndPoint[pPacket->Endpoint];
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));
35076 + /* first, fixup the head room we allocated */
35077 + pPacket->pBuffer += HTC_HDR_LENGTH;
35078 + /* do completion */
35079 + DO_EP_TX_COMPLETION(pEndpoint,pPacket);
35082 +A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket, A_UINT8 SendFlags)
35085 + A_UINT8 *pHdrBuf;
35086 + A_BOOL sync = FALSE;
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);
35096 + if (pPacket->Completion == NULL) {
35097 + /* mark that this request was synchronously issued */
35101 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
35102 + ("+-HTCIssueSend: transmit length : %d (%s) \n",
35103 + pPacket->ActualLength + HTC_HDR_LENGTH,
35104 + sync ? "SYNC" : "ASYNC" ));
35106 + /* send message to device */
35107 + status = DevSendPacket(&target->Device,
35109 + pPacket->ActualLength + HTC_HDR_LENGTH);
35112 + /* use local sync variable. If this was issued asynchronously, pPacket is no longer
35113 + * safe to access. */
35114 + pPacket->pBuffer += HTC_HDR_LENGTH;
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 */
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)
35129 + HTC_PACKET *pPacket;
35130 + HTC_ENDPOINT *pEndpoint;
35131 + int creditsRequired;
35132 + A_UINT8 sendFlags;
35134 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HTCTrySend (pPkt:0x%X)\n",(A_UINT32)pPacketToSend));
35136 + pEndpoint = &target->EndPoint[ep];
35138 + LOCK_HTC_TX(target);
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++;
35147 + /* now drain the TX queue for transmission as long as we have enough
35152 + if (HTC_QUEUE_EMPTY(&pEndpoint->TxQueue)) {
35153 + /* nothing in the queue */
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));
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;
35169 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,(" Creds Required:%d Got:%d\n",
35170 + creditsRequired, pEndpoint->CreditDist.TxCredits));
35172 + if (pEndpoint->CreditDist.TxCredits < creditsRequired) {
35174 + /* not enough credits */
35176 + if (pPacket->Endpoint == ENDPOINT_0) {
35177 + /* leave it in the queue */
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
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,
35191 + &pEndpoint->CreditDist);
35193 + pEndpoint->CreditDist.TxCreditsSeek = 0;
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));
35205 + pEndpoint->CreditDist.TxCredits -= creditsRequired;
35206 + INC_HTC_EP_STAT(pEndpoint, TxCreditsConsummed, creditsRequired);
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"));
35215 + /* now we can fully dequeue */
35216 + pPacket = HTC_PACKET_DEQUEUE(&pEndpoint->TxQueue);
35217 + pEndpoint->CurrentTxQueueDepth--;
35219 + INC_HTC_EP_STAT(pEndpoint, TxIssued, 1);
35221 + UNLOCK_HTC_TX(target);
35223 + HTCIssueSend(target, pPacket, sendFlags);
35225 + LOCK_HTC_TX(target);
35227 + /* go back and check for more messages */
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);
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);
35246 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend: \n"));
35249 +/* HTC API - HTCSendPkt */
35250 +A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
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;
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));
35261 + ep = pPacket->Endpoint;
35262 + AR_DEBUG_ASSERT(ep < ENDPOINT_MAX);
35263 + pEndpoint = &target->EndPoint[ep];
35267 + if (HTC_STOPPING(target)) {
35268 + status = A_ECANCELED;
35269 + pPacket->Status = status;
35270 + DO_EP_TX_COMPLETION(pEndpoint,pPacket);
35273 + /* everything sent through this interface is asynchronous */
35274 + /* fill in HTC completion routines */
35275 + pPacket->Completion = HTCSendPktCompletionHandler;
35276 + pPacket->pContext = target;
35278 + HTCTrySend(target, pPacket, ep);
35282 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPkt \n"));
35288 +/* check TX queues to drain because of credit distribution update */
35289 +static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
35291 + HTC_ENDPOINT *pEndpoint;
35292 + HTC_ENDPOINT_CREDIT_DIST *pDistItem;
35294 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n"));
35295 + pDistItem = target->EpCreditDistributionListHead;
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;
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
35311 + HTCTrySend(target, NULL, pDistItem->Endpoint);
35314 + pDistItem = pDistItem->pNext;
35317 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCCheckEndpointTxQueues \n"));
35320 +/* process credit reports and call distribution function */
35321 +void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
35324 + HTC_ENDPOINT *pEndpoint;
35325 + int totalCredits = 0;
35326 + A_BOOL doDist = FALSE;
35328 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries));
35330 + /* lock out TX while we update credits */
35331 + LOCK_HTC_TX(target);
35333 + for (i = 0; i < NumEntries; i++, pRpt++) {
35334 + if (pRpt->EndpointID >= ENDPOINT_MAX) {
35335 + AR_DEBUG_ASSERT(FALSE);
35339 + pEndpoint = &target->EndPoint[pRpt->EndpointID];
35341 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Endpoint %d got %d credits \n",
35342 + pRpt->EndpointID, pRpt->Credits));
35345 +#ifdef HTC_EP_STAT_PROFILING
35347 + INC_HTC_EP_STAT(pEndpoint, TxCreditRpts, 1);
35348 + INC_HTC_EP_STAT(pEndpoint, TxCreditsReturned, pRpt->Credits);
35350 + if (FromEndpoint == pRpt->EndpointID) {
35351 + /* this credit report arrived on the same endpoint indicating it arrived in an RX
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);
35360 + /* arrived on another endpoint */
35361 + INC_HTC_EP_STAT(pEndpoint, TxCreditsFromOther, pRpt->Credits);
35362 + INC_HTC_EP_STAT(pEndpoint, TxCreditRptsFromOther, 1);
35367 + if (ENDPOINT_0 == pRpt->EndpointID) {
35368 + /* always give endpoint 0 credits back */
35369 + pEndpoint->CreditDist.TxCredits += pRpt->Credits;
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 */
35378 + totalCredits += pRpt->Credits;
35381 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Report indicated %d credits to distribute \n", totalCredits));
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,
35389 + target->EpCreditDistributionListHead->pNext);
35392 + UNLOCK_HTC_TX(target);
35394 + if (totalCredits) {
35395 + HTCCheckEndpointTxQueues(target);
35398 + AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCProcessCreditRpt \n"));
35401 +/* flush endpoint TX queue */
35402 +static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag)
35404 + HTC_PACKET *pPacket;
35405 + HTC_PACKET_QUEUE discardQueue;
35407 + /* initialize the discard queue */
35408 + INIT_HTC_PACKET_QUEUE(&discardQueue);
35410 + LOCK_HTC_TX(target);
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) {
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--;
35426 + UNLOCK_HTC_TX(target);
35428 + /* empty the discard queue */
35430 + pPacket = HTC_PACKET_DEQUEUE(&discardQueue);
35431 + if (NULL == pPacket) {
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);
35442 +void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist)
35445 + HTC_ENDPOINT *pEndpoint = (HTC_ENDPOINT *)pEPDist->pHTCReserved;
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"));
35465 +void DumpCreditDistStates(HTC_TARGET *target)
35467 + HTC_ENDPOINT_CREDIT_DIST *pEPList = target->EpCreditDistributionListHead;
35469 + while (pEPList != NULL) {
35470 + DumpCreditDist(pEPList);
35471 + pEPList = pEPList->pNext;
35474 + if (target->DistributeCredits != NULL) {
35475 + DO_DISTRIBUTION(target,
35476 + HTC_DUMP_CREDIT_STATE,
35482 +/* flush all send packets from all endpoint queues */
35483 +void HTCFlushSendPkts(HTC_TARGET *target)
35485 + HTC_ENDPOINT *pEndpoint;
35488 + DumpCreditDistStates(target);
35490 + for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
35491 + pEndpoint = &target->EndPoint[i];
35492 + if (pEndpoint->ServiceID == 0) {
35493 + /* not in use.. */
35496 + HTCFlushEndpointTX(target,pEndpoint,HTC_TX_PACKET_TAG_ALL);
35501 +/* HTC API to flush an endpoint's TX queue*/
35502 +void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag)
35504 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
35505 + HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
35507 + if (pEndpoint->ServiceID == 0) {
35508 + AR_DEBUG_ASSERT(FALSE);
35509 + /* not in use.. */
35513 + HTCFlushEndpointTX(target, pEndpoint, Tag);
35516 +/* HTC API to indicate activity to the credit distribution function */
35517 +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
35518 + HTC_ENDPOINT_ID Endpoint,
35521 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
35522 + HTC_ENDPOINT *pEndpoint = &target->EndPoint[Endpoint];
35523 + A_BOOL doDist = FALSE;
35525 + if (pEndpoint->ServiceID == 0) {
35526 + AR_DEBUG_ASSERT(FALSE);
35527 + /* not in use.. */
35531 + LOCK_HTC_TX(target);
35534 + if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) {
35535 + /* mark active now */
35536 + pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE;
35540 + if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
35541 + /* mark inactive now */
35542 + pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE;
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);
35556 + UNLOCK_HTC_TX(target);
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
35565 + * Copyright (c) 2007 Atheros Communications Inc.
35566 + * All rights reserved.
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;
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.
35582 +#include "htc_internal.h"
35584 +void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket)
35586 + /* not implemented
35587 + * we do not send control TX frames during normal runtime, only during setup */
35588 + AR_DEBUG_ASSERT(FALSE);
35591 + /* callback when a control message arrives on this endpoint */
35592 +void HTCControlRecv(void *Context, HTC_PACKET *pPacket)
35594 + AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0);
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));
35602 + /* dump header and message */
35603 + DebugDumpBytes(pPacket->pBuffer - HTC_HDR_LENGTH,
35604 + pPacket->ActualLength + HTC_HDR_LENGTH,
35605 + "Unexpected ENDPOINT 0 Message");
35607 + HTC_RECYCLE_RX_PKT((HTC_TARGET*)Context,pPacket);
35610 +A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
35612 + HTC_PACKET *pSendPacket = NULL;
35614 + HTC_SETUP_COMPLETE_MSG *pSetupComplete;
35617 + /* allocate a packet to send to the target */
35618 + pSendPacket = HTC_ALLOC_CONTROL_TX(target);
35620 + if (NULL == pSendPacket) {
35621 + status = A_NO_MEMORY;
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;
35630 + SET_HTC_PACKET_INFO_TX(pSendPacket,
35632 + (A_UINT8 *)pSetupComplete,
35633 + sizeof(HTC_SETUP_COMPLETE_MSG),
35635 + HTC_SERVICE_TX_PACKET_TAG);
35637 + /* we want synchronous operation */
35638 + pSendPacket->Completion = NULL;
35639 + /* send the message */
35640 + status = HTCIssueSend(target,pSendPacket,0);
35644 + if (pSendPacket != NULL) {
35645 + HTC_FREE_CONTROL_TX(target,pSendPacket);
35652 +A_STATUS HTCConnectService(HTC_HANDLE HTCHandle,
35653 + HTC_SERVICE_CONNECT_REQ *pConnectReq,
35654 + HTC_SERVICE_CONNECT_RESP *pConnectResp)
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;
35666 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%X SvcID:0x%X \n",
35667 + (A_UINT32)target, pConnectReq->ServiceID));
35671 + AR_DEBUG_ASSERT(pConnectReq->ServiceID != 0);
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;
35678 + /* allocate a packet to send to the target */
35679 + pSendPacket = HTC_ALLOC_CONTROL_TX(target);
35681 + if (NULL == pSendPacket) {
35682 + AR_DEBUG_ASSERT(FALSE);
35683 + status = A_NO_MEMORY;
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;
35703 + SET_HTC_PACKET_INFO_TX(pSendPacket,
35705 + (A_UINT8 *)pConnectMsg,
35706 + sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength,
35708 + HTC_SERVICE_TX_PACKET_TAG);
35710 + /* we want synchronous operation */
35711 + pSendPacket->Completion = NULL;
35713 + status = HTCIssueSend(target,pSendPacket,0);
35715 + if (A_FAILED(status)) {
35719 + /* wait for response */
35720 + status = HTCWaitforControlMessage(target, &pRecvPacket);
35722 + if (A_FAILED(status)) {
35725 + /* we controlled the buffer creation so it has to be properly aligned */
35726 + pResponseMsg = (HTC_CONNECT_SERVICE_RESPONSE_MSG *)pRecvPacket->pBuffer;
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;
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;
35746 + assignedEndpoint = pResponseMsg->EndpointID;
35747 + maxMsgSize = pResponseMsg->MaxMsgSize;
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),
35758 + pConnectResp->ActualLength = copyLength;
35763 + /* the rest of these are parameter checks so set the error status */
35764 + status = A_EPROTO;
35766 + if (assignedEndpoint >= ENDPOINT_MAX) {
35767 + AR_DEBUG_ASSERT(FALSE);
35771 + if (0 == maxMsgSize) {
35772 + AR_DEBUG_ASSERT(FALSE);
35776 + pEndpoint = &target->EndPoint[assignedEndpoint];
35778 + if (pEndpoint->ServiceID != 0) {
35779 + /* endpoint already in use! */
35780 + AR_DEBUG_ASSERT(FALSE);
35784 + /* return assigned endpoint to caller */
35785 + pConnectResp->Endpoint = assignedEndpoint;
35786 + pConnectResp->MaxMsgLength = maxMsgSize;
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;
35804 + if (0 == pEndpoint->CreditDist.TxCreditsPerMaxMsg) {
35805 + pEndpoint->CreditDist.TxCreditsPerMaxMsg = 1;
35812 + if (pSendPacket != NULL) {
35813 + HTC_FREE_CONTROL_TX(target,pSendPacket);
35816 + if (pRecvPacket != NULL) {
35817 + HTC_FREE_CONTROL_RX(target,pRecvPacket);
35820 + AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCConnectService \n"));
35825 +static void AddToEndpointDistList(HTC_TARGET *target, HTC_ENDPOINT_CREDIT_DIST *pEpDist)
35827 + HTC_ENDPOINT_CREDIT_DIST *pCurEntry,*pLastEntry;
35829 + if (NULL == target->EpCreditDistributionListHead) {
35830 + target->EpCreditDistributionListHead = pEpDist;
35831 + pEpDist->pNext = NULL;
35832 + pEpDist->pPrev = NULL;
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;
35840 + while (pCurEntry) {
35841 + pLastEntry = pCurEntry;
35842 + pCurEntry = pCurEntry->pNext;
35845 + pLastEntry->pNext = pEpDist;
35846 + pEpDist->pPrev = pLastEntry;
35847 + pEpDist->pNext = NULL;
35852 +/* default credit init callback */
35853 +static void HTCDefaultCreditInit(void *Context,
35854 + HTC_ENDPOINT_CREDIT_DIST *pEPList,
35855 + int TotalCredits)
35857 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
35858 + int totalEps = 0;
35859 + int creditsPerEndpoint;
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;
35868 + /* even distribution */
35869 + creditsPerEndpoint = TotalCredits/totalEps;
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) {
35876 + if (creditsPerEndpoint < pCurEpDist->TxCreditsPerMaxMsg) {
35877 + /* too many endpoints and not enough credits */
35878 + AR_DEBUG_ASSERT(FALSE);
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;
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)
35900 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
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;
35911 + pCurEpDist = pCurEpDist->pNext;
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 */
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[],
35926 + HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
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;
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;
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);
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);
35962 + AR_DEBUG_ASSERT(ep < ENDPOINT_MAX);
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
35970 +#ifndef _A_CONFIG_H_
35971 +#define _A_CONFIG_H_
35973 + * Copyright (c) 2004-2005 Atheros Communications Inc.
35974 + * All rights reserved.
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;
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.
35991 + * This file contains software configuration options that enables
35992 + * specific software "features"
35994 +#include "../ar6000/config_linux.h"
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
36001 +#ifndef _A_DEBUG_H_
36002 +#define _A_DEBUG_H_
36004 + * Copyright (c) 2004-2006 Atheros Communications Inc.
36005 + * All rights reserved.
36007 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36008 + * All rights reserved.
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;
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.
36024 +#include <a_types.h>
36025 +#include <a_osapi.h>
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
36037 +#define DBG_DEFAULTS (DBG_ERROR|DBG_WARNING)
36039 +#include "../ar6000/debug_linux.h"
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
36046 +#ifndef _A_DRV_API_H_
36047 +#define _A_DRV_API_H_
36049 + * Copyright (c) 2004-2006 Atheros Communications Inc.
36050 + * All rights reserved.
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;
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.
36066 +#ifdef __cplusplus
36070 +/****************************************************************************/
36071 +/****************************************************************************/
36073 +/** WMI related hooks **/
36075 +/****************************************************************************/
36076 +/****************************************************************************/
36078 +#include <ar6000_api.h>
36080 +#define A_WMI_CHANNELLIST_RX(devt, numChan, chanList) \
36081 + ar6000_channelList_rx((devt), (numChan), (chanList))
36083 +#define A_WMI_SET_NUMDATAENDPTS(devt, num) \
36084 + ar6000_set_numdataendpts((devt), (num))
36086 +#define A_WMI_CONTROL_TX(devt, osbuf, streamID) \
36087 + ar6000_control_tx((devt), (osbuf), (streamID))
36089 +#define A_WMI_TARGETSTATS_EVENT(devt, pStats) \
36090 + ar6000_targetStats_event((devt), (pStats))
36092 +#define A_WMI_SCANCOMPLETE_EVENT(devt, status) \
36093 + ar6000_scanComplete_event((devt), (status))
36095 +#ifdef CONFIG_HOST_DSET_SUPPORT
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))
36100 +#define A_WMI_DSET_CLOSE(devt, access_cookie) \
36101 + ar6000_dset_close((devt), (access_cookie))
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))
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))
36111 +#define A_WMI_REGDOMAIN_EVENT(devt, regCode) \
36112 + ar6000_regDomain_event((devt), (regCode))
36114 +#define A_WMI_NEIGHBORREPORT_EVENT(devt, numAps, info) \
36115 + ar6000_neighborReport_event((devt), (numAps), (info))
36117 +#define A_WMI_DISCONNECT_EVENT(devt, reason, bssid, assocRespLen, assocInfo, protocolReasonStatus) \
36118 + ar6000_disconnect_event((devt), (reason), (bssid), (assocRespLen), (assocInfo), (protocolReasonStatus))
36120 +#define A_WMI_TKIP_MICERR_EVENT(devt, keyid, ismcast) \
36121 + ar6000_tkip_micerr_event((devt), (keyid), (ismcast))
36123 +#define A_WMI_BITRATE_RX(devt, rateKbps) \
36124 + ar6000_bitrate_rx((devt), (rateKbps))
36126 +#define A_WMI_TXPWR_RX(devt, txPwr) \
36127 + ar6000_txPwr_rx((devt), (txPwr))
36129 +#define A_WMI_READY_EVENT(devt, datap, phyCap) \
36130 + ar6000_ready_event((devt), (datap), (phyCap))
36132 +#define A_WMI_DBGLOG_INIT_DONE(ar) \
36133 + ar6000_dbglog_init_done(ar);
36135 +#define A_WMI_RSSI_THRESHOLD_EVENT(devt, newThreshold, rssi) \
36136 + ar6000_rssiThreshold_event((devt), (newThreshold), (rssi))
36138 +#define A_WMI_REPORT_ERROR_EVENT(devt, errorVal) \
36139 + ar6000_reportError_event((devt), (errorVal))
36141 +#define A_WMI_ROAM_TABLE_EVENT(devt, pTbl) \
36142 + ar6000_roam_tbl_event((devt), (pTbl))
36144 +#define A_WMI_ROAM_DATA_EVENT(devt, p) \
36145 + ar6000_roam_data_event((devt), (p))
36147 +#define A_WMI_WOW_LIST_EVENT(devt, num_filters, wow_filters) \
36148 + ar6000_wow_list_event((devt), (num_filters), (wow_filters))
36150 +#define A_WMI_CAC_EVENT(devt, ac, cac_indication, statusCode, tspecSuggestion) \
36151 + ar6000_cac_event((devt), (ac), (cac_indication), (statusCode), (tspecSuggestion))
36153 +#define A_WMI_IPTOS_TO_USERPRIORITY(pkt) \
36154 + ar6000_iptos_to_userPriority((pkt))
36156 +#define A_WMI_PMKID_LIST_EVENT(devt, num_pmkid, pmkid_list) \
36157 + ar6000_pmkid_list_event((devt), (num_pmkid), (pmkid_list))
36159 +#ifdef CONFIG_HOST_GPIO_SUPPORT
36161 +#define A_WMI_GPIO_INTR_RX(intr_mask, input_values) \
36162 + ar6000_gpio_intr_rx((intr_mask), (input_values))
36164 +#define A_WMI_GPIO_DATA_RX(reg_id, value) \
36165 + ar6000_gpio_data_rx((reg_id), (value))
36167 +#define A_WMI_GPIO_ACK_RX() \
36168 + ar6000_gpio_ack_rx()
36172 +#ifdef SEND_EVENT_TO_APP
36174 +#define A_WMI_SEND_EVENT_TO_APP(ar, eventId, datap, len) \
36175 + ar6000_send_event_to_app((ar), (eventId), (datap), (len))
36179 +#define A_WMI_SEND_EVENT_TO_APP(ar, eventId, datap, len)
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))
36188 +#define A_WMI_HBCHALLENGERESP_EVENT(devt, cookie, source) \
36189 + ar6000_hbChallengeResp_event((devt), (cookie), (source))
36191 +#define A_WMI_TX_RETRY_ERR_EVENT(devt) \
36192 + ar6000_tx_retry_err_event((devt))
36194 +#define A_WMI_SNR_THRESHOLD_EVENT_RX(devt, newThreshold, snr) \
36195 + ar6000_snrThresholdEvent_rx((devt), (newThreshold), (snr))
36197 +#define A_WMI_LQ_THRESHOLD_EVENT_RX(devt, range, lqVal) \
36198 + ar6000_lqThresholdEvent_rx((devt), (range), (lqVal))
36200 +#define A_WMI_RATEMASK_RX(devt, ratemask) \
36201 + ar6000_ratemask_rx((devt), (ratemask))
36203 +#define A_WMI_KEEPALIVE_RX(devt, configured) \
36204 + ar6000_keepalive_rx((devt), (configured))
36206 +#define A_WMI_BSSINFO_EVENT_RX(ar, datp, len) \
36207 + ar6000_bssInfo_event_rx((ar), (datap), (len))
36209 +#define A_WMI_DBGLOG_EVENT(ar, dropped, buffer, length) \
36210 + ar6000_dbglog_event((ar), (dropped), (buffer), (length));
36212 +#define A_WMI_STREAM_TX_ACTIVE(devt,trafficClass) \
36213 + ar6000_indicate_tx_activity((devt),(trafficClass), TRUE)
36215 +#define A_WMI_STREAM_TX_INACTIVE(devt,trafficClass) \
36216 + ar6000_indicate_tx_activity((devt),(trafficClass), FALSE)
36218 +/****************************************************************************/
36219 +/****************************************************************************/
36221 +/** HTC related hooks **/
36223 +/****************************************************************************/
36224 +/****************************************************************************/
36226 +#ifdef __cplusplus
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
36238 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/a_drv.h#1 $
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
36244 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
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;
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.
36260 +#include "../ar6000/athdrv_linux.h"
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
36267 +#ifndef _A_OSAPI_H_
36268 +#define _A_OSAPI_H_
36270 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/a_osapi.h#1 $
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
36276 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
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;
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.
36292 +#include "../ar6000/osapi_linux.h"
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
36299 +#ifndef _AR6000_API_H_
36300 +#define _AR6000_API_H_
36302 + * Copyright (c) 2004-2005 Atheros Communications Inc.
36303 + * All rights reserved.
36305 + * This file contains the API to access the OS dependent atheros host driver
36306 + * by the WMI or WLAN generic modules.
36308 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/ar6000_api.h#1 $
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;
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.
36324 +#include "../ar6000/ar6xapi_linux.h"
36326 +#endif /* _AR6000_API_H */
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
36334 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36335 + * All rights reserved.
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;
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.
36351 +#ifndef AR6000_DIAG_H_
36352 +#define AR6000_DIAG_H_
36356 +ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
36359 +ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
36362 +ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
36363 + A_UCHAR *data, A_UINT32 length);
36366 +ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
36367 + A_UCHAR *data, A_UINT32 length);
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
36375 + * Copyright (c) 2006 Atheros Communications Inc.
36376 + * All rights reserved.
36378 + * $ATH_LICENSE_HOSTSDK0_C$
36382 +#ifndef __AR6000_REGDUMP_H__
36383 +#define __AR6000_REGDUMP_H__
36385 +#if !defined(__ASSEMBLER__)
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.
36392 +struct MIPS_exception_frame_s {
36393 + A_UINT32 pc; /* Program Counter */
36394 + A_UINT32 at; /* MIPS General Purpose registers */
36425 + A_UINT32 cause; /* Selected coprocessor regs */
36428 +typedef struct MIPS_exception_frame_s CPU_exception_frame_t;
36433 + * Offsets into MIPS_exception_frame structure, for use in assembler code
36434 + * MUST MATCH C STRUCTURE ABOVE
36468 +#define RD_cause 32
36469 +#define RD_status 33
36471 +#define RD_SIZE (34*4) /* Space for this number of words */
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
36479 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36480 + * All rights reserved.
36482 + * $ATH_LICENSE_HOSTSDK0_C$
36484 + * This file contains the definitions for AR6001 registers
36485 + * that may be directly manipulated by Host software.
36488 +#ifndef __AR6KHWREG_H__
36489 +#define __AR6KHWREG_H__
36491 +#ifdef __cplusplus
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
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
36620 +#ifdef __cplusplus
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
36629 +#define __VER_MAJOR_ 2
36630 +#define __VER_MINOR_ 0
36631 +#define __VER_PATCH_ 0
36635 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36636 + * All rights reserved.
36638 + * $ATH_LICENSE_HOSTSDK0_C$
36640 + * The makear6ksdk script (used for release builds) modifies the following line.
36642 +#define __BUILD_NUMBER_ 18
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
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.
36660 + * DO NOT split the following macro into multiple lines as this may confuse the build scripts.
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 ) )
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
36669 +#define __VER_MAJOR_ 2
36670 +#define __VER_MINOR_ 0
36671 +#define __VER_PATCH_ 0
36675 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36676 + * All rights reserved.
36678 + * $ATH_LICENSE_HOSTSDK0_C$
36680 + * The makear6ksdk script (used for release builds) modifies the following line.
36682 +#define __BUILD_NUMBER_ 18
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
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.
36700 + * DO NOT split the following macro into multiple lines as this may confuse the build scripts.
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 ) )
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
36709 +#ifndef __ATHDEFS_H__
36710 +#define __ATHDEFS_H__
36713 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36714 + * All rights reserved.
36716 + * $ATH_LICENSE_HOSTSDK0_C$
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.
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.
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 */
36764 +#define A_SUCCESS(x) (x == A_OK)
36765 +#define A_FAILED(x) (!A_SUCCESS(x))
36776 + * The following definition is WLAN specific definition
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,
36788 + WLAN_11A_CAPABILITY = 1,
36789 + WLAN_11G_CAPABILITY = 2,
36790 + WLAN_11AG_CAPABILITY = 3,
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
36799 + * Copyright (c) 2004-2006 Atheros Communications Inc.
36800 + * All rights reserved.
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;
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.
36817 +#ifndef _ATHDRV_H_
36818 +#define _ATHDRV_H_
36820 +#ifdef __cplusplus
36825 +#ifdef __cplusplus
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
36834 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36835 + * @file: athendpack.h
36837 + * @abstract: end compiler-specific structure packing
36839 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36840 + * All rights reserved.
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;
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.
36856 +#endif /* VXWORKS */
36859 +#endif /* LINUX */
36865 +#include "integrity/athendpack_integrity.h"
36866 +#endif /* INTEGRITY */
36869 +#endif /* NUCLEUS */
36872 +#include "../os/wince/include/athendpack_wince.h"
36873 +#endif /* WINCE */
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
36879 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
36880 + * @file: athstartpack.h
36882 + * @abstract: start compiler-specific structure packing
36884 + * Copyright (c) 2004-2007 Atheros Communications Inc.
36885 + * All rights reserved.
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;
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.
36902 +#endif /* VXWORKS */
36905 +#endif /* LINUX */
36911 +#include "integrity/athstartpack_integrity.h"
36912 +#endif /* INTEGRITY */
36915 +#endif /* NUCLEUS */
36918 +#include "../os/wince/include/athstartpack_wince.h"
36919 +#endif /* WINCE */
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
36925 +#ifndef _A_TYPES_H_
36926 +#define _A_TYPES_H_
36928 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/a_types.h#1 $
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
36934 + * Copyright 2003-2005 Atheros Communications, Inc., All Rights Reserved.
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;
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.
36950 +#include "../ar6000/athtypes_linux.h"
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
36960 + * Copyright (c) 2004-2005 Atheros Communications Inc.
36961 + * All rights reserved.
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;
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.
36975 + * BMI declarations and prototypes
36978 +#ifdef __cplusplus
36980 +#endif /* __cplusplus */
36982 +/* Header files */
36983 +#include "a_config.h"
36984 +#include "athdefs.h"
36985 +#include "a_types.h"
36987 +#include "a_osapi.h"
36988 +#include "bmi_msg.h"
36994 +BMIDone(HIF_DEVICE *device);
36997 +BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info);
37000 +BMIReadMemory(HIF_DEVICE *device,
37001 + A_UINT32 address,
37003 + A_UINT32 length);
37006 +BMIWriteMemory(HIF_DEVICE *device,
37007 + A_UINT32 address,
37009 + A_UINT32 length);
37012 +BMIExecute(HIF_DEVICE *device,
37013 + A_UINT32 address,
37014 + A_UINT32 *param);
37017 +BMISetAppStart(HIF_DEVICE *device,
37018 + A_UINT32 address);
37021 +BMIReadSOCRegister(HIF_DEVICE *device,
37022 + A_UINT32 address,
37023 + A_UINT32 *param);
37026 +BMIWriteSOCRegister(HIF_DEVICE *device,
37027 + A_UINT32 address,
37031 +BMIrompatchInstall(HIF_DEVICE *device,
37032 + A_UINT32 ROM_addr,
37033 + A_UINT32 RAM_addr,
37035 + A_UINT32 do_activate,
37036 + A_UINT32 *patch_id);
37039 +BMIrompatchUninstall(HIF_DEVICE *device,
37040 + A_UINT32 rompatch_id);
37043 +BMIrompatchActivate(HIF_DEVICE *device,
37044 + A_UINT32 rompatch_count,
37045 + A_UINT32 *rompatch_list);
37048 +BMIrompatchDeactivate(HIF_DEVICE *device,
37049 + A_UINT32 rompatch_count,
37050 + A_UINT32 *rompatch_list);
37052 +#ifdef __cplusplus
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
37061 +#ifndef __BMI_MSG_H__
37062 +#define __BMI_MSG_H__
37065 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37066 + * All rights reserved.
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;
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.
37083 + * Bootloader Messaging Interface (BMI)
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.
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.
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.
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).
37106 + * BMI handles all required Target-side cache flushing.
37110 +/* Maximum data size used for BMI transfers */
37111 +#define BMI_DATASZ_MAX 32
37113 +/* BMI Commands */
37115 +#define BMI_NO_COMMAND 0
37117 +#define BMI_DONE 1
37119 + * Semantics: Host is done using BMI
37120 + * Request format:
37121 + * A_UINT32 command (BMI_DONE)
37122 + * Response format: none
37125 +#define BMI_READ_MEMORY 2
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]
37136 +#define BMI_WRITE_MEMORY 3
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
37147 +#define BMI_EXECUTE 4
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
37158 +#define BMI_SET_APP_START 5
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
37167 +#define BMI_READ_SOC_REGISTER 6
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:
37177 +#define BMI_WRITE_SOC_REGISTER 7
37179 + * Semantics: Write a 32-bit Target SOC register.
37180 + * Request format:
37181 + * A_UINT32 command (BMI_WRITE_REGISTER)
37182 + * A_UINT32 address
37185 + * Response format: none
37188 +#define BMI_GET_TARGET_ID 8
37189 +#define BMI_GET_TARGET_INFO 8
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;
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 */
37206 +#define TARGET_VERSION_SENTINAL 0xffffffff
37207 +#define TARGET_TYPE_AR6001 1
37208 +#define TARGET_TYPE_AR6002 2
37211 +#define BMI_ROMPATCH_INSTALL 9
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
37225 +#define BMI_ROMPATCH_UNINSTALL 10
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
37233 + * Response format: none
37236 +#define BMI_ROMPATCH_ACTIVATE 11
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]
37244 + * Response format: none
37247 +#define BMI_ROMPATCH_DEACTIVATE 12
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]
37255 + * Response format: none
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
37266 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37267 + * All rights reserved.
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;
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.
37284 +#ifndef COMMON_DRV_H_
37285 +#define COMMON_DRV_H_
37288 +#include "htc_packet.h"
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;
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)
37307 +#ifdef __cplusplus
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);
37320 +#ifdef __cplusplus
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
37329 +#ifndef _DBGLOG_API_H_
37330 +#define _DBGLOG_API_H_
37332 + * Copyright (c) 2004-2006 Atheros Communications Inc.
37333 + * All rights reserved.
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;
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.
37347 + * This file contains host side debug primitives.
37350 +#ifdef __cplusplus
37354 +#include "dbglog.h"
37356 +#define DBGLOG_HOST_LOG_BUFFER_SIZE DBGLOG_LOG_BUFFER_SIZE
37358 +#define DBGLOG_GET_DBGID(arg) \
37359 + ((arg & DBGLOG_DBGID_MASK) >> DBGLOG_DBGID_OFFSET)
37361 +#define DBGLOG_GET_MODULEID(arg) \
37362 + ((arg & DBGLOG_MODULEID_MASK) >> DBGLOG_MODULEID_OFFSET)
37364 +#define DBGLOG_GET_NUMARGS(arg) \
37365 + ((arg & DBGLOG_NUM_ARGS_MASK) >> DBGLOG_NUM_ARGS_OFFSET)
37367 +#define DBGLOG_GET_TIMESTAMP(arg) \
37368 + ((arg & DBGLOG_TIMESTAMP_MASK) >> DBGLOG_TIMESTAMP_OFFSET)
37370 +#ifdef __cplusplus
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
37380 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37381 + * All rights reserved.
37383 + * $ATH_LICENSE_HOSTSDK0_C$
37385 + * This file contains the definitions and data structures associated with
37386 + * the log based debug mechanism.
37390 +#ifndef _DBGLOG_H_
37391 +#define _DBGLOG_H_
37393 +#ifdef __cplusplus
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 */
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 */
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.
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
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 */
37430 +#define DBGLOG_MODULE_LOG_ENABLE_OFFSET 0
37431 +#define DBGLOG_MODULE_LOG_ENABLE_MASK 0x0000FFFF
37433 +#define DBGLOG_REPORTING_ENABLED_OFFSET 16
37434 +#define DBGLOG_REPORTING_ENABLED_MASK 0x00010000
37436 +#define DBGLOG_TIMESTAMP_RESOLUTION_OFFSET 17
37437 +#define DBGLOG_TIMESTAMP_RESOLUTION_MASK 0x000E0000
37439 +#define DBGLOG_REPORT_SIZE_OFFSET 20
37440 +#define DBGLOG_REPORT_SIZE_MASK 0x3FF00000
37442 +#define DBGLOG_LOG_BUFFER_SIZE 1500
37443 +#define DBGLOG_DBGID_DEFINITION_LEN_MAX 64
37445 +struct dbglog_buf_s {
37446 + struct dbglog_buf_s *next;
37448 + A_UINT32 bufsize;
37454 +struct dbglog_hdr_s {
37455 + struct dbglog_buf_s *dbuf;
37456 + A_UINT32 dropped;
37459 +struct dbglog_config_s {
37460 + A_UINT32 cfgvalid; /* Mask with valid config bits */
37462 + /* TODO: Take care of endianness */
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;
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
37481 +#ifdef __cplusplus
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
37492 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37493 + * All rights reserved.
37495 + * $ATH_LICENSE_HOSTSDK0_C$
37497 + * This file contains the definitions of the debug identifiers for different
37502 +#ifndef _DBGLOG_ID_H_
37503 +#define _DBGLOG_ID_H_
37505 +#ifdef __cplusplus
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.
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
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
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
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
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
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
37704 +/* PM (Power Module) debug identifier definitions */
37705 +#define PM_DBGID_DEFINITION_START
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
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
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
37792 +#ifdef __cplusplus
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
37803 + * Double-link list definitions (adapted from Atheros SDIO stack)
37805 + * Copyright (c) 2007 Atheros Communications Inc.
37806 + * All rights reserved.
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;
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.
37821 +#ifndef __DL_LIST_H___
37822 +#define __DL_LIST_H___
37824 +#define A_CONTAINING_STRUCT(address, struct_type, field_name)\
37825 + ((struct_type *)((A_UINT32)(address) - (A_UINT32)(&((struct_type *)0)->field_name)))
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;
37834 + * DL_LIST_INIT , initialize doubly linked list
37836 +#define DL_LIST_INIT(pList)\
37837 + {(pList)->pPrev = pList; (pList)->pNext = pList;}
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
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
37847 +#define ITERATE_OVER_LIST(pStart, pTemp) \
37848 + for((pTemp) =(pStart)->pNext; pTemp != (pStart); (pTemp) = (pTemp)->pNext)
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
37854 +#define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset) \
37856 + PDL_LIST pTemp; \
37857 + pTemp = (pStart)->pNext; \
37858 + while (pTemp != (pStart)) { \
37859 + (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset); \
37860 + pTemp = pTemp->pNext; \
37862 +#define ITERATE_END }}
37865 + * DL_ListInsertTail - insert pAdd to the end of the list
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;
37877 + * DL_ListInsertHead - insert pAdd into the head of the list
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;
37888 +#define DL_ListAdd(pList,pItem) DL_ListInsertHead((pList),(pItem))
37890 + * DL_ListRemove - remove pDel from list
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;
37902 + * DL_ListRemoveItemFromHead - get a list item from the head
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);
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
37920 + * Copyright (c) 2004-2006 Atheros Communications Inc.
37921 + * All rights reserved.
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;
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.
37935 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/dset_api.h#1 $
37937 + * Host-side DataSet API.
37941 +#ifndef _DSET_API_H_
37942 +#define _DSET_API_H_
37944 +#ifdef __cplusplus
37946 +#endif /* __cplusplus */
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.
37953 +#ifndef CONFIG_HOST_DSET_SUPPORT
37954 +#define CONFIG_HOST_DSET_SUPPORT 1
37957 +/* Called to send a DataSet Open Reply back to the Target. */
37958 +A_STATUS wmi_dset_open_reply(struct wmi_t *wmip,
37960 + A_UINT32 access_cookie,
37962 + A_UINT32 version,
37963 + A_UINT32 targ_handle,
37964 + A_UINT32 targ_reply_fn,
37965 + A_UINT32 targ_reply_arg);
37967 +/* Called to send a DataSet Data Reply back to the Target. */
37968 +A_STATUS wmi_dset_data_reply(struct wmi_t *wmip,
37970 + A_UINT8 *host_buf,
37972 + A_UINT32 targ_buf,
37973 + A_UINT32 targ_reply_fn,
37974 + A_UINT32 targ_reply_arg);
37976 +#ifdef __cplusplus
37978 +#endif /* __cplusplus */
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
37987 + * Copyright (c) 2004-2007 Atheros Communications Inc.
37988 + * All rights reserved.
37990 + * $ATH_LICENSE_HOSTSDK0_C$
37994 +#ifndef __DSETID_H__
37995 +#define __DSETID_H__
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 */
38004 +#define DSETID_ANALOG_CONTROL_DATA_START 0x00000005
38005 +#define DSETID_ANALOG_CONTROL_DATA_END 0x00000025
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.
38013 +#define ANALOG_CONTROL_DATA_DSETID(refclk) \
38014 + (DSETID_ANALOG_CONTROL_DATA_START + 3*refclk)
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.
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
38027 +#define DSETID_WOW_CONFIG 0x00000090 /* WoW Configuration */
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
38034 +#define DSETID_VENDOR_START 0x00010000 /* Vendor-defined DataSets */
38036 +#define DSETID_INDEX_END 0xfffffffe /* Reserved to indicate the
38037 + end of a memory-based
38039 +#define DSETID_INDEX_FREE 0xffffffff /* An unused index entry */
38042 + * PATCH DataSet format:
38043 + * A list of patches, terminated by a patch with
38044 + * address=PATCH_END.
38046 + * This allows for patches to be stored in flash.
38049 + A_UINT32 *address;
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.
38060 +#define PATCH_SKIP ((A_UINT32 *)0x00000000)
38063 + * Execute code at the address specified by "data".
38064 + * The address of the patch structure is passed as
38065 + * the one parameter.
38067 +#define PATCH_CODE_ABS ((A_UINT32 *)0x00000001)
38070 + * Same as PATCH_CODE_ABS, but treat "data" as an
38071 + * offset from the start of the patch word.
38073 +#define PATCH_CODE_REL ((A_UINT32 *)0x00000002)
38075 +/* Mark the end of this patch DataSet. */
38076 +#define PATCH_END ((A_UINT32 *)0xffffffff)
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.
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".
38090 + * NB: There are some implementation-induced restrictions
38091 + * on which DataSets can be BPatched.
38093 +#define DSETID_BPATCH_FLAG 0x80000000
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
38101 + * Copyright (c) 2007 Atheros Communications Inc.
38102 + * All rights reserved.
38104 + * $ATH_LICENSE_HOSTSDK0_C$
38108 +#ifndef __DSET_INTERNAL_H__
38109 +#define __DSET_INTERNAL_H__
38112 + * Internal dset definitions, common for DataSet layer.
38115 +#define DSET_TYPE_STANDARD 0
38116 +#define DSET_TYPE_BPATCHED 1
38117 +#define DSET_TYPE_COMPRESSED 2
38119 +/* Dataset descriptor */
38121 +typedef struct dset_descriptor_s {
38122 + struct dset_descriptor_s *next; /* List link. NULL only at the last
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
38130 + A_UINT32 data_type; /* DSET_TYPE_*, above */
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;
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
38143 +#ifndef _GPIO_API_H_
38144 +#define _GPIO_API_H_
38146 + * Copyright 2005 Atheros Communications, Inc., All Rights Reserved.
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;
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.
38163 + * Host-side General Purpose I/O API.
38165 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/gpio_api.h#1 $
38169 + * Send a command to the Target in order to change output on GPIO pins.
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);
38178 + * Send a command to the Target requesting input state of GPIO pins.
38180 +A_STATUS wmi_gpio_input_get(struct wmi_t *wmip);
38183 + * Send a command to the Target to change the value of a GPIO register.
38185 +A_STATUS wmi_gpio_register_set(struct wmi_t *wmip,
38186 + A_UINT32 gpioreg_id,
38190 + * Send a command to the Target to fetch the value of a GPIO register.
38192 +A_STATUS wmi_gpio_register_get(struct wmi_t *wmip, A_UINT32 gpioreg_id);
38195 + * Send a command to the Target, acknowledging some GPIO interrupts.
38197 +A_STATUS wmi_gpio_intr_ack(struct wmi_t *wmip, A_UINT32 ack_mask);
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
38205 + * Copyright (c) 2005 Atheros Communications Inc.
38206 + * All rights reserved.
38208 + * $ATH_LICENSE_HOSTSDK0_C$
38212 +#if defined(AR6001)
38213 +#define GPIO_PIN_COUNT 18
38215 +#define GPIO_PIN_COUNT 18
38219 + * Possible values for WMIX_GPIO_SET_REGISTER_CMDID.
38220 + * NB: These match hardware order, so that addresses can
38221 + * easily be computed.
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))
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
38243 + * Copyright (c) 2004-2007 Atheros Communications Inc.
38244 + * All rights reserved.
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;
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.
38258 + * HIF specific declarations and prototypes
38264 +#ifdef __cplusplus
38266 +#endif /* __cplusplus */
38268 +/* Header files */
38269 +#include "a_config.h"
38270 +#include "athdefs.h"
38271 +#include "a_types.h"
38272 +#include "a_osapi.h"
38274 +typedef struct htc_callbacks HTC_CALLBACKS;
38275 +typedef struct hif_device HIF_DEVICE;
38278 + * direction - Direction of transfer (HIF_READ/HIF_WRITE).
38280 +#define HIF_READ 0x00000001
38281 +#define HIF_WRITE 0x00000002
38282 +#define HIF_DIR_MASK (HIF_READ | HIF_WRITE)
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.
38289 +#define HIF_BASIC_IO 0x00000004
38290 +#define HIF_EXTENDED_IO 0x00000008
38291 +#define HIF_TYPE_MASK (HIF_BASIC_IO | HIF_EXTENDED_IO)
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.
38304 +#define HIF_SYNCHRONOUS 0x00000010
38305 +#define HIF_ASYNCHRONOUS 0x00000020
38306 +#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS)
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.
38318 +#define HIF_BYTE_BASIS 0x00000040
38319 +#define HIF_BLOCK_BASIS 0x00000080
38320 +#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS)
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).
38327 +#define HIF_FIXED_ADDRESS 0x00000100
38328 +#define HIF_INCREMENTAL_ADDRESS 0x00000200
38329 +#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS)
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)
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;
38369 + * HIF CONFIGURE definitions:
38371 + * HIF_DEVICE_GET_MBOX_BLOCK_SIZE
38373 + * output : array of 4 A_UINT32s
38374 + * notes: block size is returned for each mailbox (4)
38376 + * HIF_DEVICE_GET_MBOX_ADDR
38378 + * output : array of 4 A_UINT32
38379 + * notes: address is returned for each mailbox (4) in the array
38381 + * HIF_DEVICE_GET_PENDING_EVENTS_FUNC
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.
38389 + * HIF_DEVICE_GET_IRQ_PROC_MODE
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).
38396 + * HIF_DEVICE_GET_RECV_EVENT_MASK_UNMASK_FUNC
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).
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
38412 +} HIF_DEVICE_IRQ_PROCESSING_MODE;
38414 +#define HIF_MAX_DEVICES 1
38416 +struct htc_callbacks {
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);
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 */
38433 +typedef struct _HIF_PENDING_EVENTS_INFO {
38435 + A_UINT32 LookAhead;
38436 +} HIF_PENDING_EVENTS_INFO;
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);
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,
38449 + void *AsyncContext);
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.
38461 +int HIFInit(HTC_CALLBACKS *callbacks);
38464 + * This API is used to provide the read/write interface over the specific bus
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
38472 + * length - Amount of data to be transmitted or received.
38473 + * request - Characterizes the attributes of the command.
38476 +HIFReadWrite(HIF_DEVICE *device,
38477 + A_UINT32 address,
38480 + A_UINT32 request,
38484 + * This can be initiated from the unload driver context ie when the HTCShutdown
38485 + * routine is called.
38487 +void HIFShutDownDevice(HIF_DEVICE *device);
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.
38496 +void HIFAckInterrupt(HIF_DEVICE *device);
38498 +void HIFMaskInterrupt(HIF_DEVICE *device);
38500 +void HIFUnMaskInterrupt(HIF_DEVICE *device);
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.
38508 +int HIFInsertEventNotify(void);
38510 +int HIFRemoveEventNotify(void);
38512 +int HIFIRQEventNotify(void);
38514 +int HIFRWCompleteEventNotify(void);
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.
38521 +void HIFSetHandle(void *hif_handle, void *handle);
38524 +HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
38525 + void *config, A_UINT32 configLen);
38530 +HIFGetOSDevice(HIF_DEVICE *device);
38533 +#ifdef __cplusplus
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
38542 +#ifndef _HOST_VERSION_H_
38543 +#define _HOST_VERSION_H_
38545 + * Copyright (c) 2004-2005 Atheros Communications Inc.
38546 + * All rights reserved.
38548 + * This file contains version information for the sample host driver for the
38551 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/host_version.h#2 $
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;
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.
38567 +#ifdef __cplusplus
38571 +#include <AR6K_version.h>
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
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
38586 +#ifdef __cplusplus
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
38597 + * Copyright (c) 2007 Atheros Communications Inc.
38598 + * All rights reserved.
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;
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.
38614 +#ifndef _HTC_API_H_
38615 +#define _HTC_API_H_
38618 +#include <htc_services.h>
38619 +#include "htc_packet.h"
38621 +#ifdef __cplusplus
38623 +#endif /* __cplusplus */
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
38631 +/* ------ Endpoint IDS ------ */
38634 + ENDPOINT_UNUSED = -1,
38645 +} HTC_ENDPOINT_ID;
38647 +/* this is the amount of header room required by users of HTC */
38648 +#define HTC_HEADER_LEN HTC_HDR_LENGTH
38650 +typedef void *HTC_HANDLE;
38652 +typedef A_UINT16 HTC_SERVICE_ID;
38654 +typedef struct _HTC_INIT_INFO {
38655 + void (*AddInstance)(HTC_HANDLE);
38656 + void (*DeleteInstance)(void *Instance);
38657 + void (*TargetFailure)(void *Instance, A_STATUS Status);
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 *);
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.
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
38673 +typedef void (*HTC_EP_RECV_REFILL)(void *, HTC_ENDPOINT_ID Endpoint);
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);
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;
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;
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;
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;
38745 +#define HTC_EP_ACTIVE (1 << 31)
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
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;
38763 +typedef void (*HTC_CREDIT_DIST_CALLBACK)(void *Context,
38764 + HTC_ENDPOINT_CREDIT_DIST *pEPList,
38765 + HTC_CREDIT_DIST_REASON Reason);
38767 +typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context,
38768 + HTC_ENDPOINT_CREDIT_DIST *pEPList,
38769 + int TotalCredits);
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;
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
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;
38797 +/* ------ Function Prototypes ------ */
38798 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38799 + @desc: Initialize HTC
38800 + @function name: HTCInit
38801 + @input: pInfo - initialization information
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).
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
38816 + @return: opaque HIF device handle usable in HIF API calls.
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
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.
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
38845 + ListLength - number of elements in ServicePriorityOrder
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.
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[],
38862 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38863 + @desc: Wait for the target to indicate the HTC layer is ready
38864 + @function name: HTCWaitTarget
38865 + @input: HTCHandle - HTC handle
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
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
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.
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
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()
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
38911 + @notes: Service connections must be performed before HTCStart. User provides callback handlers
38912 + for various endpoint events.
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
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.
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
38939 + @notes: HTC communications is halted. All receive and pending TX packets will
38943 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38944 +void HTCStop(HTC_HANDLE HTCHandle);
38945 +/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
38946 + @desc: Shutdown HTC
38947 + @function name: HTCShutdown
38951 + @notes: This cleans up all resources allocated by HTCInit().
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
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.
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
38976 + @notes: This dumps all credit distribution information to the debugger
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
38989 + @notes: This triggers the registered credit distribution function to
38990 + re-adjust credits for active/inactive endpoints.
38993 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
38994 +void HTCIndicateActivityChange(HTC_HANDLE HTCHandle,
38995 + HTC_ENDPOINT_ID Endpoint,
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
39005 + pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR)
39007 + @return: TRUE if statistics profiling is enabled, otherwise FALSE.
39009 + @notes: Statistics is a compile-time option and this function may return FALSE
39010 + if HTC is not compiled with profiling.
39012 + The caller can specify the statistic "action" to take when sampling
39013 + the statistics. This includes:
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
39018 + HTC_EP_STAT_CLEA : the statistics are cleared, the called can pass a NULL value for
39023 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
39024 +A_BOOL HTCGetEndpointStatistics(HTC_HANDLE HTCHandle,
39025 + HTC_ENDPOINT_ID Endpoint,
39026 + HTC_ENDPOINT_STAT_ACTION Action,
39027 + HTC_ENDPOINT_STATS *pStats);
39029 +#ifdef __cplusplus
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
39039 + * Copyright (c) 2007 Atheros Communications Inc.
39040 + * All rights reserved.
39042 + * $ATH_LICENSE_HOSTSDK0_C$
39050 +#ifndef ATH_TARGET
39051 +#include "athstartpack.h"
39054 +#define A_OFFSETOF(type,field) (int)(&(((type *)NULL)->field))
39056 +#define ASSEMBLE_UNALIGNED_UINT16(p,highbyte,lowbyte) \
39057 + (((A_UINT16)(((A_UINT8 *)(p))[(highbyte)])) << 8 | (A_UINT16)(((A_UINT8 *)(p))[(lowbyte)]))
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))
39067 +#define A_SET_UINT16_FIELD(p,type,field,value) \
39069 + ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (A_UINT8)(value); \
39070 + ((A_UINT8 *)(p))[A_OFFSETOF(type,field) + 1] = (A_UINT8)((value) >> 8); \
39073 +#define A_GET_UINT8_FIELD(p,type,field) \
39074 + ((A_UINT8 *)(p))[A_OFFSETOF(type,field)]
39076 +#define A_SET_UINT8_FIELD(p,type,field,value) \
39077 + ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (value)
39079 +/****** DANGER DANGER ***************
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.
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.
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;
39097 + A_UINT16 PayloadLen; /* length of data (including trailer) that follows the header */
39099 + /***** end of 4-byte lookahead ****/
39101 + A_UINT8 ControlBytes[2];
39103 + /* message payload starts after the header */
39105 +} POSTPACK HTC_FRAME_HDR;
39107 +/* frame header flags */
39108 +#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0)
39109 +#define HTC_FLAGS_RECV_TRAILER (1 << 1)
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))
39116 +/* HTC control message IDs */
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,
39124 +#define HTC_MAX_CONTROL_MESSAGE_LENGTH 256
39126 +/* base message ID header */
39127 +typedef PREPACK struct {
39128 + A_UINT16 MessageID;
39129 +} POSTPACK HTC_UNKNOWN_MSG;
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 */
39139 +} POSTPACK HTC_READY_MSG;
39141 +#define HTC_SERVICE_META_DATA_MAX_LENGTH 128
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 */
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
39158 + A_UINT8 ServiceMetaLength; /* length of meta data that follows */
39161 + /* service-specific meta data starts after the header */
39163 +} POSTPACK HTC_CONNECT_SERVICE_MSG;
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 */
39176 + /* service-specific meta data starts after the header */
39178 +} POSTPACK HTC_CONNECT_SERVICE_RESPONSE_MSG;
39180 +typedef PREPACK struct {
39181 + A_UINT16 MessageID;
39182 + /* currently, no other fields */
39183 +} POSTPACK HTC_SETUP_COMPLETE_MSG;
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
39194 +/* report record IDs */
39196 + HTC_RECORD_NULL = 0,
39197 + HTC_RECORD_CREDITS = 1,
39198 + HTC_RECORD_LOOKAHEAD = 2,
39201 +typedef PREPACK struct {
39202 + A_UINT8 RecordID; /* Record ID */
39203 + A_UINT8 Length; /* Length of record */
39204 +} POSTPACK HTC_RECORD_HDR;
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;
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 */
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 */
39219 +} POSTPACK HTC_LOOKAHEAD_REPORT;
39221 +#ifndef ATH_TARGET
39222 +#include "athendpack.h"
39226 +#endif /* __HTC_H__ */
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
39234 + * Copyright (c) 2007 Atheros Communications Inc.
39235 + * All rights reserved.
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;
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.
39251 +#ifndef HTC_PACKET_H_
39252 +#define HTC_PACKET_H_
39255 +#include "dl_list.h"
39257 +struct _HTC_PACKET;
39259 +typedef void (* HTC_PACKET_COMPLETION)(void *,struct _HTC_PACKET *);
39261 +typedef A_UINT16 HTC_TX_TAG;
39263 +typedef struct _HTC_TX_PACKET_INFO {
39264 + HTC_TX_TAG Tag; /* tag used to selective flush packets */
39265 +} HTC_TX_PACKET_INFO;
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 */
39271 +typedef struct _HTC_RX_PACKET_INFO {
39272 + A_UINT32 Unused; /* for future use and to make compilers happy */
39273 +} HTC_RX_PACKET_INFO;
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 */
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 */
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
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 */
39299 + HTC_TX_PACKET_INFO AsTx; /* Tx Packet specific info */
39300 + HTC_RX_PACKET_INFO AsRx; /* Rx Packet specific info */
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 */
39311 +#define COMPLETE_HTC_PACKET(p,status) \
39313 + (p)->Status = (status); \
39314 + (p)->Completion((p)->pContext,(p)); \
39317 +#define INIT_HTC_PACKET_INFO(p,b,len) \
39319 + (p)->pBufferStart = (b); \
39320 + (p)->BufferLength = (len); \
39323 +/* macro to set an initial RX packet for refilling HTC */
39324 +#define SET_HTC_PACKET_INFO_RX_REFILL(p,c,b,len,ep) \
39326 + (p)->pPktContext = (c); \
39327 + (p)->pBuffer = (b); \
39328 + (p)->pBufferStart = (b); \
39329 + (p)->BufferLength = (len); \
39330 + (p)->Endpoint = (ep); \
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
39337 +/* macro to set packet parameters for TX */
39338 +#define SET_HTC_PACKET_INFO_TX(p,c,b,len,ep,tag) \
39340 + (p)->pPktContext = (c); \
39341 + (p)->pBuffer = (b); \
39342 + (p)->ActualLength = (len); \
39343 + (p)->Endpoint = (ep); \
39344 + (p)->PktInfo.AsTx.Tag = (tag); \
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)
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);
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
39375 + * Copyright (c) 2007 Atheros Communications Inc.
39376 + * All rights reserved.
39378 + * $ATH_LICENSE_HOSTSDK0_C$
39382 +#ifndef __HTC_SERVICES_H__
39383 +#define __HTC_SERVICES_H__
39385 +/* Current service IDs */
39388 + RSVD_SERVICE_GROUP = 0,
39389 + WMI_SERVICE_GROUP = 1,
39391 + HTC_TEST_GROUP = 254,
39392 + HTC_SERVICE_GROUP_LAST = 255
39393 +}HTC_SERVICE_GROUP_IDS;
39395 +#define MAKE_SERVICE_ID(group,index) \
39396 + (int)(((int)group << 8) | (int)(index))
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
39407 +/* raw stream service (i.e. flash, tcmd, calibration apps) */
39408 +#define HTC_RAW_STREAMS_SVC MAKE_SERVICE_ID(HTC_TEST_GROUP,0)
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
39416 + * Copyright (c) 2001 Atsushi Onoe
39417 + * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
39418 + * Copyright (c) 2006 Atheros Communications, Inc.
39420 + * Wireless Network driver for Atheros AR6001
39421 + * All rights reserved.
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.
39435 +#ifndef _NET80211_IEEE80211_H_
39436 +#define _NET80211_IEEE80211_H_
39438 +#include "athstartpack.h"
39441 + * 802.11 protocol definitions.
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)
39450 +#define IEEE80211_KEYBUF_SIZE 16
39451 +#define IEEE80211_MICBUF_SIZE (8+8) /* space for both tx and rx */
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.
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 */
39466 +#define IEEE80211_CIPHER_MAX (IEEE80211_CIPHER_NONE+1)
39468 +#define IEEE80211_IS_VALID_WEP_CIPHER_LEN(len) \
39469 + (((len) == 5) || ((len) == 13) || ((len) == 16))
39474 + * generic definitions for IEEE 802.11 frames
39476 +PREPACK struct ieee80211_frame {
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]; */
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
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
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 */
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
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
39547 +#define IEEE80211_NWID_LEN 32
39550 + * 802.11 rate set.
39552 +#define IEEE80211_RATE_SIZE 8 /* 802.11 standard */
39553 +#define IEEE80211_RATE_MAXSIZE 15 /* max rates we'll handle */
39555 +#define WMM_NUM_AC 4 /* 4 AC categories */
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 */
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 : \
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 : \
39578 + * Management information element payloads.
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 */
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
39615 +#define WPA_OUI 0xf25000
39616 +#define WPA_OUI_TYPE 0x01
39617 +#define WPA_VERSION 1 /* current supported version */
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
39625 +#define WPA_ASE_NONE 0x00
39626 +#define WPA_ASE_8021X_UNSPEC 0x01
39627 +#define WPA_ASE_8021X_PSK 0x02
39629 +#define RSN_OUI 0xac0f00
39630 +#define RSN_VERSION 1 /* current supported version */
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
39639 +#define RSN_ASE_NONE 0x00
39640 +#define RSN_ASE_8021X_UNSPEC 0x01
39641 +#define RSN_ASE_8021X_PSK 0x02
39643 +#define RSN_CAP_PREAUTH 0x01
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
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 */
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
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;
39677 + * WMM/802.11e Tspec Element
39679 +typedef PREPACK struct wmm_tspec_ie_t {
39680 + A_UINT8 elementId;
39684 + A_UINT8 ouiSubType;
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;
39702 + A_UINT16 mediumTime;
39703 +} POSTPACK WMM_TSPEC_IE;
39707 + * BEACON management packets
39709 + * octet timestamp[8]
39710 + * octet beacon interval[2]
39711 + * octet capability information[2]
39712 + * information element
39715 + * octet information[length]
39718 +#define IEEE80211_BEACON_INTERVAL(beacon) \
39719 + ((beacon)[8] | ((beacon)[9] << 8))
39720 +#define IEEE80211_BEACON_CAPABILITY(beacon) \
39721 + ((beacon)[10] | ((beacon)[11] << 8))
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 */
39739 + * Authentication Modes
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 */
39754 +#include "athendpack.h"
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
39762 + * Copyright (c) 2004-2005 Atheros Communications Inc.
39763 + * All rights reserved.
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;
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.
39778 + * $Id: //depot/sw/releases/olca2.0-GPL/host/os/linux/include/ieee80211_ioctl.h#1 $
39781 +#ifndef _IEEE80211_IOCTL_H_
39782 +#define _IEEE80211_IOCTL_H_
39784 +#ifdef __cplusplus
39789 + * Extracted from the MADWIFI net80211/ieee80211_ioctl.h
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.
39802 +struct ieee80211req_key {
39803 + u_int8_t ik_type; /* key/cipher type */
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];
39817 + * Delete a key either by index or address. Set the index
39818 + * to IEEE80211_KEYIX_NONE when deleting a unicast key.
39820 +struct ieee80211req_del_key {
39821 + u_int8_t idk_keyix; /* key index */
39822 + u_int8_t idk_macaddr[IEEE80211_ADDR_LEN];
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).
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];
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];
39847 +#define AUTH_ALG_OPEN_SYSTEM 0x01
39848 +#define AUTH_ALG_SHARED_KEY 0x02
39849 +#define AUTH_ALG_LEAP 0x04
39851 +struct ieee80211req_authalg {
39852 + u_int8_t auth_alg;
39856 + * Request to add an IE to a Management Frame
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
39868 + * The Maximum length of the IE that can be added to a Management frame
39870 +#define IEEE80211_APPIE_FRAME_MAX_LEN 78
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[];
39879 + * The following definitions are used by an application to set filter
39880 + * for receiving management frames
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 */
39894 +struct ieee80211req_set_filter {
39895 + u_int32_t app_filterype; /* management frame filter type */
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 */
39912 + * Values for IEEE80211_PARAM_WPA
39914 +#define WPA_MODE_WPA1 1
39915 +#define WPA_MODE_WPA2 2
39916 +#define WPA_MODE_AUTO 3
39917 +#define WPA_MODE_NONE 4
39919 +#ifdef __cplusplus
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
39929 + * Copyright (c) 2001 Atsushi Onoe
39930 + * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
39931 + * Copyright (c) 2006 Atheros Communications, Inc.
39933 + * Wireless Network driver for Atheros AR6001
39934 + * All rights reserved.
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.
39948 +#ifndef _IEEE80211_NODE_H_
39949 +#define _IEEE80211_NODE_H_
39952 + * Node locking definitions.
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)
39963 + * Node reference counting definitions.
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)
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)
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)
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.
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 */
40002 +#define WLAN_NODE_INACT_TIMEOUT_MSEC 10000
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
40010 + * Copyright (c) 2004-2007 Atheros Communications Inc.
40011 + * All rights reserved.
40013 + * $ATH_LICENSE_HOSTSDK0_C$
40016 +#ifndef _INI_DSET_H_
40017 +#define _INI_DSET_H_
40020 + * Each of these represents a WHAL INI table, which consists
40021 + * of an "address column" followed by 1 or more "value columns".
40023 + * Software uses the base WHAL_INI_DATA_ID+column to access a
40024 + * DataSet that holds a particular column of data.
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 */
40039 + WHAL_INI_DATA_ID_MAX =25
40040 +} WHAL_INI_DATA_ID;
40042 +typedef PREPACK struct {
40043 + A_UINT16 freqIndex; // 1 - A mode 2 - B or G mode 0 - common
40045 + A_UINT32 newValue;
40046 +} POSTPACK INI_DSET_REG_OVERRIDE;
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
40054 + * Copyright (c) 2005 Atheros Communications, Inc.
40055 + * All rights reserved.
40058 + * $ATH_LICENSE_HOSTSDK0_C$
40060 + * This module contains the header files for regulatory module,
40061 + * which include the DB schema and DB values.
40065 +#ifndef __REG_DB_H__
40066 +#define __REG_DB_H__
40068 +#include "./regulatory/reg_dbschema.h"
40069 +#include "./regulatory/reg_dbvalues.h"
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
40076 +#ifndef __REGDUMP_H__
40077 +#define __REGDUMP_H__
40079 + * Copyright (c) 2004-2007 Atheros Communications Inc.
40080 + * All rights reserved.
40082 + * $ATH_LICENSE_HOSTSDK0_C$
40085 +#if defined(AR6001)
40086 +#include "AR6001/AR6001_regdump.h"
40088 +#if defined(AR6002)
40089 +#include "AR6002/AR6002_regdump.h"
40092 +#if !defined(__ASSEMBLER__)
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.
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 */
40105 + /* Could copy top of stack here, too.... */
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
40114 + * Copyright (c) 2004-2007 Atheros Communications Inc.
40115 + * All rights reserved.
40117 + * $ATH_LICENSE_HOSTSDK0_C$
40121 +#ifndef __TARGADDRS_H__
40122 +#define __TARGADDRS_H__
40123 +#if defined(AR6001)
40124 +#include "AR6001/addrs.h"
40126 +#if defined(AR6002)
40127 +#include "AR6002/addrs.h"
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.
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 */
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).
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.
40153 +#define AR6001_HOST_INTEREST_ADDRESS 0x80000600
40154 +#define AR6002_HOST_INTEREST_ADDRESS 0x00500400
40156 +#define HOST_INTEREST_MAX_SIZE 0x100
40158 +#if !defined(__ASSEMBLER__)
40159 +struct register_dump_s;
40160 +struct dbglog_hdr_s;
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!
40168 + * Types for each item must be fixed size across
40169 + * target and host platforms.
40171 + * More items may be added at the end.
40173 +struct host_interest_s {
40175 + * Pointer to application-defined area, if any.
40176 + * Set by Target application during startup.
40178 + A_UINT32 hi_app_host_interest; /* 0x00 */
40180 + /* Pointer to register dump area, valid after Target crash. */
40181 + A_UINT32 hi_failure_state; /* 0x04 */
40183 + /* Pointer to debug logging header */
40184 + A_UINT32 hi_dbglog_hdr; /* 0x08 */
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
40194 + A_UINT32 hi_flash_is_present; /* 0x0c */
40197 + * General-purpose flag bits, similar to AR6000_OPTION_* flags.
40198 + * Can be used by application rather than by OS.
40200 + A_UINT32 hi_option_flag; /* 0x10 */
40203 + * Boolean that determines whether or not to
40204 + * display messages on the serial port.
40206 + A_UINT32 hi_serial_enable; /* 0x14 */
40208 + /* Start address of Flash DataSet index, if any */
40209 + A_UINT32 hi_dset_list_head; /* 0x18 */
40211 + /* Override Target application start address */
40212 + A_UINT32 hi_app_start; /* 0x1c */
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 */
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.)
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 */
40236 + /* Pointer to Board Data */
40237 + A_UINT32 hi_board_data; /* 0x54 */
40238 + A_UINT32 hi_board_data_initialized; /* 0x58 */
40240 + A_UINT32 hi_dset_RAM_index_table; /* 0x5c */
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 */
40247 + A_UINT32 hi_num_bpatch_streams; /* 0x70 */
40248 + A_UINT32 hi_mbox_isr_yield_limit; /* 0x74 */
40250 + A_UINT32 hi_refclk_hz; /* 0x78 */
40253 +/* Bits defined in hi_option_flag */
40254 +#define HI_OPTION_TIMER_WAR 1 /* not really used */
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);
40261 +#define AR6001_HOST_INTEREST_ITEM_ADDRESS(item) \
40262 + ((A_UINT32)&((((struct host_interest_s *)(AR6001_HOST_INTEREST_ADDRESS))->item)))
40264 +#define AR6002_HOST_INTEREST_ITEM_ADDRESS(item) \
40265 + ((A_UINT32)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item)))
40268 +#endif /* !__ASSEMBLER__ */
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
40276 + * Copyright (c) 2004-2005 Atheros Communications Inc.
40277 + * All rights reserved.
40280 + * $ATH_LICENSE_HOSTSDK0_C$
40284 +#ifndef TESTCMD_H_
40285 +#define TESTCMD_H_
40287 +#ifdef __cplusplus
40292 + ZEROES_PATTERN = 0,
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
40317 + txPwr: Tx power in dBm[5 -11] for unmod Tx, [5-14] for mod Tx
40318 +antenna: 1 - one antenna
40320 +Note : Enable/disable continuous tx test cmd works only when target is awake.
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;
40331 +typedef PREPACK struct {
40332 + A_UINT32 testCmdId;
40335 + A_UINT32 dataRate;
40337 + A_UINT32 antenna;
40339 + A_UINT32 scramblerOff;
40342 + A_UINT16 txPattern;
40343 +} POSTPACK TCMD_CONT_TX;
40345 +#define TCMD_TXPATTERN_ZERONE 0x1
40346 +#define TCMD_TXPATTERN_ZERONE_DIS_SCRAMBLE 0x2
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
40357 + TCMD_CONT_RX_SETMAC - set MacAddr mode (sets the MAC address for the
40358 + target. This Overrides
40359 + the default MAC address.)
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;
40369 +typedef PREPACK struct {
40370 + A_UINT32 testCmdId;
40374 + struct PREPACK TCMD_CONT_RX_PARA {
40376 + A_UINT32 antenna;
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];
40386 +} POSTPACK TCMD_CONT_RX;
40388 +/* Force sleep/wake test cmd
40389 + mode: TCMD_PM_WAKEUP - Wakeup the target
40390 + TCMD_PM_SLEEP - Force the target to sleep.
40393 + TCMD_PM_WAKEUP = 1, /* be consistent with target */
40397 +typedef PREPACK struct {
40398 + A_UINT32 testCmdId;
40400 +} POSTPACK TCMD_PM;
40408 +typedef PREPACK union {
40409 + TCMD_CONT_TX contTx;
40410 + TCMD_CONT_RX contRx;
40412 +} POSTPACK TEST_CMD;
40414 +#ifdef __cplusplus
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
40423 +#ifndef _HOST_WLAN_API_H_
40424 +#define _HOST_WLAN_API_H_
40426 + * Copyright (c) 2004-2005 Atheros Communications Inc.
40427 + * All rights reserved.
40429 + * This file contains the API for the host wlan module
40431 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/wlan_api.h#1 $
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;
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.
40447 +#ifdef __cplusplus
40451 +struct ieee80211_node_table;
40452 +struct ieee80211_frame;
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;
40465 + A_UINT16 ie_capInfo;
40466 + A_UINT16 ie_beaconInt;
40468 + A_UINT8 *ie_chswitch;
40473 +typedef struct bss {
40474 + A_UINT8 ni_macaddr[6];
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;
40483 + struct ieee80211_node_table *ni_table;
40484 + A_UINT32 ni_refcnt;
40486 + A_UINT32 ni_tstamp;
40489 +typedef void wlan_node_iter_func(void *arg, bss_t *);
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,
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);
40505 +A_STATUS wlan_parse_beacon(A_UINT8 *buf, int framelen,
40506 + struct ieee80211_common_ie *cie);
40508 +A_UINT16 wlan_ieee2freq(int chan);
40509 +A_UINT32 wlan_freq2ieee(A_UINT16 freq);
40513 +wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
40514 + A_UINT32 ssidLength, A_BOOL bIsWPA2);
40517 +wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni);
40519 +#ifdef __cplusplus
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
40529 + * Copyright (c) 2007 Atheros Communications, Inc.
40530 + * All rights reserved.
40533 + * $ATH_LICENSE_HOSTSDK0_C$
40537 +#ifndef __WLAN_DSET_H__
40538 +#define __WKAN_DSET_H__
40540 +typedef PREPACK struct wow_config_dset {
40542 + A_UINT8 valid_dset;
40543 + A_UINT8 gpio_enable;
40544 + A_UINT16 gpio_pin;
40545 +} POSTPACK WOW_CONFIG_DSET;
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
40552 +#ifndef _WMI_API_H_
40553 +#define _WMI_API_H_
40555 + * Copyright (c) 2004-2006 Atheros Communications Inc.
40556 + * All rights reserved.
40558 + * This file contains the definitions for the Wireless Module Interface (WMI).
40560 + * $Id: //depot/sw/releases/olca2.0-GPL/host/include/wmi_api.h#2 $
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;
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.
40576 +#ifdef __cplusplus
40581 + * IP QoS Field definitions according to 802.1p
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
40592 +#define UNDEFINED_PRI (0xff)
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
40599 +#define IP_TOS_TO_WMI_PRI(tos) \
40600 + ((WMI_PRI_STREAM_ID)(((tos) >> 1) & 0x03))
40602 +#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000 /* 5 seconds */
40607 +void *wmi_init(void *devt);
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);
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);
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 */
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,
40648 + A_UINT16 channel,
40649 + A_UINT32 ctrl_flags);
40650 +A_STATUS wmi_reconnect_cmd(struct wmi_t *wmip,
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);
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);
40699 +A_STATUS wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 bitmask);
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,
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,
40728 +A_STATUS wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT16 txop,
40729 + A_UINT8 eCWmin, A_UINT8 eCWmax,
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);
40735 +void wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid);
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,
40741 +A_STATUS wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
40742 + WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
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,
40748 + A_UINT8 *dstMacAddr,
40750 + A_UINT16 optIEDataLen,
40751 + A_UINT8 *optIEData);
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);
40760 +#ifdef CONFIG_HOST_TCMD_SUPPORT
40761 +A_STATUS wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32 len);
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);
40769 + * This function is used to configure the fix rates mask to the target.
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);
40774 +A_STATUS wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
40776 +A_STATUS wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
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);
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);
40785 +A_STATUS wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType,
40786 + A_UINT8 ieLen,A_UINT8 *ieInfo);
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);
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);
40802 +wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
40803 + A_UINT32 ssidLength, A_BOOL bIsWPA2);
40806 +wmi_node_return (struct wmi_t *wmip, bss_t *bss);
40807 +#ifdef __cplusplus
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
40817 + * Copyright (c) 2004-2006 Atheros Communications Inc.
40818 + * All rights reserved.
40821 + * $ATH_LICENSE_HOSTSDK0_C$
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.
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.
40837 +#ifndef ATH_TARGET
40838 +#include "athstartpack.h"
40843 +#ifdef __cplusplus
40847 +#define WMI_PROTOCOL_VERSION 0x0002
40848 +#define WMI_PROTOCOL_REVISION 0x0000
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}
40857 +#define IP_ETHERTYPE 0x0800
40859 +#define WMI_IMPLICIT_PSTREAM 0xFF
40860 +#define WMI_MAX_THINSTREAM 15
40862 +struct host_app_area_s {
40863 + A_UINT32 wmi_protocol_ver;
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;
40875 +typedef PREPACK struct {
40879 + A_UINT8 orgCode[3];
40880 + A_UINT16 etherType;
40881 +} POSTPACK ATH_LLC_SNAP_HDR;
40884 + DATA_MSGTYPE = 0x0,
40890 +typedef PREPACK struct {
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;
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))
40908 +typedef PREPACK struct {
40909 + A_UINT16 commandId;
40910 +} POSTPACK WMI_CMD_HDR; /* used for commands and events */
40913 + * List of Commnands
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,
40974 + WMI_SET_BT_STATUS_CMDID,
40975 + WMI_SET_BT_PARAMS_CMDID,
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,
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,
40995 + * Developer commands starts at 0xF000
40997 + WMI_SET_BITRATE_CMDID = 0xF000,
40998 + WMI_GET_BITRATE_CMDID,
40999 + WMI_SET_WHALPARAM_CMDID,
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;
41016 + * Connect Command
41019 + INFRA_NETWORK = 0x01,
41020 + ADHOC_NETWORK = 0x02,
41021 + ADHOC_CREATOR = 0x04,
41025 + OPEN_AUTH = 0x01,
41026 + SHARED_AUTH = 0x02,
41027 + LEAP_AUTH = 0x04, /* different from IEEE_AUTH_MODE definitions */
41028 +} DOT11_AUTH_MODE;
41031 + NONE_AUTH = 0x01,
41033 + WPA_PSK_AUTH = 0x03,
41034 + WPA2_AUTH = 0x04,
41035 + WPA2_PSK_AUTH = 0x05,
41036 + WPA_AUTH_CCKM = 0x06,
41037 + WPA2_AUTH_CCKM = 0x07,
41041 + NONE_CRYPT = 0x01,
41042 + WEP_CRYPT = 0x02,
41043 + TKIP_CRYPT = 0x03,
41044 + AES_CRYPT = 0x04,
41047 +#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT
41048 +#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1)
41050 +#define WMI_MIN_KEY_INDEX 0
41051 +#define WMI_MAX_KEY_INDEX 3
41053 +#define WMI_MAX_KEY_LEN 32
41055 +#define WMI_MAX_SSID_LEN 32
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;
41066 +#define DEFAULT_CONNECT_CTRL_FLAGS (CONNECT_CSA_FOLLOW_BSS)
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;
41084 + * WMI_RECONNECT_CMDID
41086 +typedef PREPACK struct {
41087 + A_UINT16 channel; /* hint */
41088 + A_UINT8 bssid[ATH_MAC_LEN]; /* mandatory if set */
41089 +} POSTPACK WMI_RECONNECT_CMD;
41092 + * WMI_ADD_CIPHER_KEY_CMDID
41095 + PAIRWISE_USAGE = 0x00,
41096 + GROUP_USAGE = 0x01,
41097 + TX_USAGE = 0x02, /* default Tx Key - Static WEP only */
41102 + * Bit 0 - Initialise TSC - default is Initialize
41104 +#define KEY_OP_INIT_TSC 0x01
41105 +#define KEY_OP_INIT_RSC 0x02
41107 +#define KEY_OP_INIT_VAL 0x03 /* Default Initialise the TSC & RSC */
41108 +#define KEY_OP_VALID_MASK 0x03
41110 +typedef PREPACK struct {
41111 + A_UINT8 keyIndex;
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;
41121 + * WMI_DELETE_CIPHER_KEY_CMDID
41123 +typedef PREPACK struct {
41124 + A_UINT8 keyIndex;
41125 +} POSTPACK WMI_DELETE_CIPHER_KEY_CMD;
41127 +#define WMI_KRK_LEN 16
41129 + * WMI_ADD_KRK_CMDID
41131 +typedef PREPACK struct {
41132 + A_UINT8 krk[WMI_KRK_LEN];
41133 +} POSTPACK WMI_ADD_KRK_CMD;
41136 + * WMI_SET_TKIP_COUNTERMEASURES_CMDID
41139 + WMI_TKIP_CM_DISABLE = 0x0,
41140 + WMI_TKIP_CM_ENABLE = 0x1,
41141 +} WMI_TKIP_CM_CONTROL;
41143 +typedef PREPACK struct {
41144 + A_UINT8 cm_en; /* WMI_TKIP_CM_CONTROL */
41145 +} POSTPACK WMI_SET_TKIP_COUNTERMEASURES_CMD;
41148 + * WMI_SET_PMKID_CMDID
41151 +#define WMI_PMKID_LEN 16
41154 + PMKID_DISABLE = 0,
41155 + PMKID_ENABLE = 1,
41156 +} PMKID_ENABLE_FLG;
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;
41165 + * WMI_START_SCAN_CMD
41168 + WMI_LONG_SCAN = 0,
41169 + WMI_SHORT_SCAN = 1,
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;
41181 + * WMI_SET_SCAN_PARAMS_CMDID
41183 +#define WMI_SHORTSCANRATIO_DEFAULT 3
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 */
41195 +} WMI_SCAN_CTRL_FLAGS_BITS;
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)
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)
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;
41221 + * WMI_SET_BSS_FILTER_CMDID
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 */
41234 +typedef PREPACK struct {
41235 + A_UINT8 bssFilter; /* see WMI_BSS_FILTER */
41237 +} POSTPACK WMI_BSS_FILTER_CMD;
41240 + * WMI_SET_PROBED_SSID_CMDID
41242 +#define MAX_PROBED_SSID_INDEX 5
41245 + DISABLE_SSID_FLAG = 0, /* disables entry */
41246 + SPECIFIC_SSID_FLAG = 0x01, /* probes specified ssid */
41247 + ANY_SSID_FLAG = 0x02, /* probes for any ssid */
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;
41258 + * WMI_SET_LISTEN_INT_CMDID
41259 + * The Listen interval is between 15 and 3000 TUs
41261 +#define MIN_LISTEN_INTERVAL 15
41262 +#define MAX_LISTEN_INTERVAL 5000
41263 +#define MIN_LISTEN_BEACONS 1
41264 +#define MAX_LISTEN_BEACONS 50
41266 +typedef PREPACK struct {
41267 + A_UINT16 listenInterval;
41268 + A_UINT16 numBeacons;
41269 +} POSTPACK WMI_LISTEN_INT_CMD;
41272 + * WMI_SET_BEACON_INT_CMDID
41274 +typedef PREPACK struct {
41275 + A_UINT16 beaconInterval;
41276 +} POSTPACK WMI_BEACON_INT_CMD;
41279 + * WMI_SET_BMISS_TIME_CMDID
41280 + * valid values are between 1000 and 5000 TUs
41283 +#define MIN_BMISS_TIME 1000
41284 +#define MAX_BMISS_TIME 5000
41285 +#define MIN_BMISS_BEACONS 1
41286 +#define MAX_BMISS_BEACONS 50
41288 +typedef PREPACK struct {
41289 + A_UINT16 bmissTime;
41290 + A_UINT16 numBeacons;
41291 +} POSTPACK WMI_BMISS_TIME_CMD;
41294 + * WMI_SET_POWER_MODE_CMDID
41297 + REC_POWER = 0x01,
41301 +typedef PREPACK struct {
41302 + A_UINT8 powerMode; /* WMI_POWER_MODE */
41303 +} POSTPACK WMI_POWER_MODE_CMD;
41306 + * WMI_SET_POWER_PARAMS_CMDID
41309 + IGNORE_DTIM = 0x01,
41310 + NORMAL_DTIM = 0x02,
41311 + STICK_DTIM = 0x03,
41312 +} WMI_DTIM_POLICY;
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;
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;
41328 + * WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID
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;
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;
41345 + * WMI_SET_VOICE_PKT_SIZE_CMDID
41347 +typedef PREPACK struct {
41348 + A_UINT16 voicePktSize;
41349 +} POSTPACK WMI_SET_VOICE_PKT_SIZE_CMD;
41352 + * WMI_SET_MAX_SP_LEN_CMDID
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;
41361 +typedef PREPACK struct {
41362 + A_UINT8 maxSPLen;
41363 +} POSTPACK WMI_SET_MAX_SP_LEN_CMD;
41366 + * WMI_SET_DISC_TIMEOUT_CMDID
41368 +typedef PREPACK struct {
41369 + A_UINT8 disconnectTimeout; /* seconds */
41370 +} POSTPACK WMI_DISC_TIMEOUT_CMD;
41373 + UPLINK_TRAFFIC = 0,
41374 + DNLINK_TRAFFIC = 1,
41375 + BIDIR_TRAFFIC = 2,
41379 + DISABLE_FOR_THIS_AC = 0,
41380 + ENABLE_FOR_THIS_AC = 1,
41381 + ENABLE_FOR_ALL_AC = 2,
41382 +} VOICEPS_CAP_TYPE;
41385 + TRAFFIC_TYPE_APERIODIC = 0,
41386 + TRAFFIC_TYPE_PERIODIC = 1,
41390 + * WMI_CREATE_PSTREAM_CMDID
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 */
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 */
41413 + A_UINT8 userPriority; /* 802.1D user priority */
41414 +} POSTPACK WMI_CREATE_PSTREAM_CMD;
41417 + * WMI_DELETE_PSTREAM_CMDID
41419 +typedef PREPACK struct {
41420 + A_UINT8 trafficClass;
41422 +} POSTPACK WMI_DELETE_PSTREAM_CMD;
41425 + * WMI_SET_CHANNEL_PARAMS_CMDID
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,
41435 +#define WMI_MAX_CHANNELS 32
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;
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)
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;
41473 + * WMI_SNR_THRESHOLD_PARAMS_CMDID
41474 + * Setting the polltime to 0 would disable polling.
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;
41492 + * WMI_LQ_THRESHOLD_PARAMS_CMDID
41494 +typedef PREPACK struct WMI_LQ_THRESHOLD_PARAMS {
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;
41508 + WMI_LPREAMBLE_DISABLED = 0,
41509 + WMI_LPREAMBLE_ENABLED
41510 +} WMI_LPREAMBLE_STATUS;
41512 +typedef PREPACK struct {
41514 +}POSTPACK WMI_SET_LPREAMBLE_CMD;
41516 +typedef PREPACK struct {
41517 + A_UINT16 threshold;
41518 +}POSTPACK WMI_SET_RTS_CMD;
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.
41526 +typedef PREPACK struct {
41527 + A_UINT32 bitmask;
41528 +} POSTPACK WMI_TARGET_ERROR_REPORT_BITMASK;
41531 + * WMI_SET_TX_PWR_CMDID
41533 +typedef PREPACK struct {
41534 + A_UINT8 dbM; /* in dbM units */
41535 +} POSTPACK WMI_SET_TX_PWR_CMD, WMI_TX_PWR_REPLY;
41538 + * WMI_SET_ASSOC_INFO_CMDID
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.
41543 +#define WMI_MAX_ASSOC_INFO_TYPE 2
41544 +#define WMI_CCX_VER_IE 2 /* ieType to set CCX Version IE */
41546 +#define WMI_MAX_ASSOC_INFO_LEN 240
41548 +typedef PREPACK struct {
41550 + A_UINT8 bufferSize;
41551 + A_UINT8 assocInfo[1]; /* up to WMI_MAX_ASSOC_INFO_LEN */
41552 +} POSTPACK WMI_SET_ASSOC_INFO_CMD;
41556 + * WMI_GET_TX_PWR_CMDID does not take any parameters
41560 + * WMI_ADD_BAD_AP_CMDID
41562 +#define WMI_MAX_BAD_AP_INDEX 1
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;
41570 + * WMI_DELETE_BAD_AP_CMDID
41572 +typedef PREPACK struct {
41573 + A_UINT8 badApIndex; /* 0 to WMI_MAX_BAD_AP_INDEX */
41574 +} POSTPACK WMI_DELETE_BAD_AP_CMD;
41577 + * WMI_SET_ACCESS_PARAMS_CMDID
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 */
41590 +} POSTPACK WMI_SET_ACCESS_PARAMS_CMD;
41594 + * WMI_SET_RETRY_LIMITS_CMDID
41596 + * This command is used to customize the number of retries the
41597 + * wlan device will perform on a given frame.
41599 +#define WMI_MIN_RETRIES 2
41600 +#define WMI_MAX_RETRIES 13
41602 + MGMT_FRAMETYPE = 0,
41603 + CONTROL_FRAMETYPE = 1,
41604 + DATA_FRAMETYPE = 2
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;
41615 + * WMI_SET_ROAM_CTRL_CMDID
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
41623 + * Different types of Roam Control
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;
41633 +#define WMI_MIN_ROAM_CTRL_TYPE WMI_FORCE_ROAM
41634 +#define WMI_MAX_ROAM_CTRL_TYPE WMI_SET_LOWRSSI_SCAN_PARAMS
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 */
41647 + * BSS HOST BIAS INFO
41650 +typedef PREPACK struct {
41651 + A_UINT8 bssid[ATH_MAC_LEN];
41653 +} POSTPACK WMI_BSS_BIAS;
41655 +typedef PREPACK struct {
41657 + WMI_BSS_BIAS bssBias[1];
41658 +} POSTPACK WMI_BSS_BIAS_INFO;
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;
41668 +typedef PREPACK struct {
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;
41675 + A_UINT8 roamCtrlType ;
41676 +} POSTPACK WMI_SET_ROAM_CTRL_CMD;
41679 + * WMI_ENABLE_RM_CMDID
41681 +typedef PREPACK struct {
41682 + A_BOOL enable_radio_measurements;
41683 +} POSTPACK WMI_ENABLE_RM_CMD;
41686 + * WMI_SET_MAX_OFFHOME_DURATION_CMDID
41688 +typedef PREPACK struct {
41689 + A_UINT8 max_offhome_duration;
41690 +} POSTPACK WMI_SET_MAX_OFFHOME_DURATION_CMD;
41692 +typedef PREPACK struct {
41693 + A_UINT32 frequency;
41694 + A_UINT8 threshold;
41695 +} POSTPACK WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD;
41698 + BT_STREAM_UNDEF = 0,
41699 + BT_STREAM_SCO, /* SCO stream */
41700 + BT_STREAM_A2DP, /* A2DP stream */
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 */
41713 + BT_STATUS_UNDEF = 0,
41716 + BT_STATUS_RESUME,
41717 + BT_STATUS_SUSPEND,
41719 +} BT_STREAM_STATUS;
41721 +typedef PREPACK struct {
41722 + A_UINT8 streamType;
41724 +} POSTPACK WMI_SET_BT_STATUS_CMD;
41726 +typedef PREPACK struct {
41727 + A_UINT8 noSCOPkts;
41728 + A_UINT8 pspollTimeout;
41730 +} POSTPACK BT_PARAMS_SCO;
41732 +typedef PREPACK struct {
41734 + A_UINT32 dutycycle;
41736 +} POSTPACK BT_PARAMS_A2DP;
41738 +typedef PREPACK struct {
41740 + A_UINT32 scoWghts;
41741 + A_UINT32 a2dpWghts;
41742 + A_UINT32 genWghts;
41745 +} POSTPACK BT_COEX_REGS;
41748 + WLAN_PROTECT_POLICY = 1,
41749 + WLAN_COEX_CTRL_FLAGS
41750 +} BT_PARAMS_MISC_TYPE;
41753 + WLAN_PROTECT_PER_STREAM = 0x01, /* default */
41754 + WLAN_PROTECT_ANY_TX = 0x02
41755 +} WLAN_PROTECT_FLAGS;
41758 +#define WLAN_DISABLE_COEX_IN_DISCONNECT 0x01 /* default */
41759 +#define WLAN_KEEP_COEX_IN_DISCONNECT 0x02
41760 +#define WLAN_STOMPBT_IN_DISCONNECT 0x04
41762 +#define WLAN_DISABLE_COEX_IN_ROAM 0x10 /* default */
41763 +#define WLAN_KEEP_COEX_IN_ROAM 0x20
41764 +#define WLAN_STOMPBT_IN_ROAM 0x40
41766 +#define WLAN_DISABLE_COEX_IN_SCAN 0x100 /* default */
41767 +#define WLAN_KEEP_COEX_IN_SCAN 0x200
41768 +#define WLAN_STOMPBT_IN_SCAN 0x400
41770 +#define WLAN_DISABLE_COEX_BT_OFF 0x1000 /* default */
41771 +#define WLAN_KEEP_COEX_BT_OFF 0x2000
41772 +#define WLAN_STOMPBT_BT_OFF 0x4000
41774 +typedef PREPACK struct {
41776 + A_UINT32 dutycycle;
41779 +} POSTPACK WLAN_PROTECT_POLICY_TYPE;
41781 +typedef PREPACK struct {
41783 + WLAN_PROTECT_POLICY_TYPE protectParams;
41784 + A_UINT16 wlanCtrlFlags;
41786 + A_UINT8 paramType;
41787 +} POSTPACK BT_PARAMS_MISC;
41789 +typedef PREPACK struct {
41791 + BT_PARAMS_SCO scoParams;
41792 + BT_PARAMS_A2DP a2dpParams;
41793 + BT_PARAMS_MISC miscParams;
41794 + BT_COEX_REGS regs;
41796 + A_UINT8 paramType;
41797 +} POSTPACK WMI_SET_BT_PARAMS_CMD;
41800 + * Command Replies
41804 + * WMI_GET_CHANNEL_LIST_CMDID reply
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;
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;
41822 + * List of Events (target to host)
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,
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
41853 + WMI_11A_CAPABILITY = 1,
41854 + WMI_11G_CAPABILITY = 2,
41855 + WMI_11AG_CAPABILITY = 3,
41856 +} WMI_PHY_CAPABILITY;
41858 +typedef PREPACK struct {
41859 + A_UINT8 macaddr[ATH_MAC_LEN];
41860 + A_UINT8 phyCapability; /* WMI_PHY_CAPABILITY */
41861 +} POSTPACK WMI_READY_EVENT;
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;
41879 + * Disconnect Event
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;
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;
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.
41909 + BEACON_FTYPE = 0x1,
41911 + ACTION_MGMT_FTYPE,
41915 + BSS_ELEMID_CHANSWITCH = 0x01,
41916 + BSS_ELEMID_ATHEROS = 0x02,
41919 +typedef PREPACK struct {
41920 + A_UINT16 channel;
41921 + A_UINT8 frameType; /* see WMI_BI_FTYPE */
41924 + A_UINT8 bssid[ATH_MAC_LEN];
41926 +} POSTPACK WMI_BSS_INFO_HDR;
41929 + * Command Error Event
41932 + INVALID_PARAM = 0x01,
41933 + ILLEGAL_STATE = 0x02,
41934 + INTERNAL_ERROR = 0x03,
41937 +typedef PREPACK struct {
41938 + A_UINT16 commandId;
41939 + A_UINT8 errorCode;
41940 +} POSTPACK WMI_CMD_ERROR_EVENT;
41943 + * New Regulatory Domain Event
41945 +typedef PREPACK struct {
41946 + A_UINT32 regDomain;
41947 +} POSTPACK WMI_REG_DOMAIN_EVENT;
41949 +typedef PREPACK struct {
41950 + A_UINT8 trafficClass;
41951 +} POSTPACK WMI_PSTREAM_TIMEOUT_EVENT;
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
41959 + * The bssid and bssFlags information repeats according to the number
41960 + * or APs reported.
41963 + WMI_DEFAULT_BSS_FLAGS = 0x00,
41964 + WMI_PREAUTH_CAPABLE_BSS = 0x01,
41965 + WMI_PMKID_VALID_BSS = 0x02,
41968 +typedef PREPACK struct {
41969 + A_UINT8 bssid[ATH_MAC_LEN];
41970 + A_UINT8 bssFlags; /* see WMI_BSS_FLAGS */
41971 +} POSTPACK WMI_NEIGHBOR_INFO;
41973 +typedef PREPACK struct {
41974 + A_INT8 numberOfAps;
41975 + WMI_NEIGHBOR_INFO neighbor[1];
41976 +} POSTPACK WMI_NEIGHBOR_REPORT_EVENT;
41979 + * TKIP MIC Error Event
41981 +typedef PREPACK struct {
41984 +} POSTPACK WMI_TKIP_MICERR_EVENT;
41987 + * WMI_SCAN_COMPLETE_EVENTID - no parameters (old), staus parameter (new)
41989 +typedef PREPACK struct {
41991 +} POSTPACK WMI_SCAN_COMPLETE_EVENT;
41993 +#define MAX_OPT_DATA_LEN 1400
41996 + * WMI_SET_ADHOC_BSSID_CMDID
41998 +typedef PREPACK struct {
41999 + A_UINT8 bssid[ATH_MAC_LEN];
42000 +} POSTPACK WMI_SET_ADHOC_BSSID_CMD;
42003 + * WMI_SET_OPT_MODE_CMDID
42010 +typedef PREPACK struct {
42012 +} POSTPACK WMI_SET_OPT_MODE_CMD;
42015 + * WMI_TX_OPT_FRAME_CMDID
42018 + OPT_PROBE_REQ = 0x01,
42019 + OPT_PROBE_RESP = 0x02,
42020 + OPT_CPPP_START = 0x03,
42021 + OPT_CPPP_STOP = 0x04,
42024 +typedef PREPACK struct {
42025 + A_UINT16 optIEDataLen;
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;
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.
42039 +typedef PREPACK struct {
42040 + A_UINT16 channel;
42041 + A_UINT8 frameType; /* see WMI_OPT_FTYPE */
42043 + A_UINT8 srcAddr[ATH_MAC_LEN];
42044 + A_UINT8 bssid[ATH_MAC_LEN];
42045 +} POSTPACK WMI_OPT_RX_INFO_HDR;
42048 + * Reporting statistics.
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];
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;
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;
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;
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;
42098 +typedef PREPACK struct {
42099 + A_UINT32 power_save_failure_cnt;
42100 +}POSTPACK pm_stats_t;
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;
42111 + A_UINT8 cs_aveBeacon_snr;
42112 + A_UINT8 cs_lastRoam_msec;
42113 +} POSTPACK cserv_stats_t;
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;
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;
42128 +typedef PREPACK struct {
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;
42138 + * WMI_RSSI_THRESHOLD_EVENTID.
42139 + * Indicate the RSSI events to host. Events are indicated when we breach a
42140 + * thresold value.
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;
42157 +typedef PREPACK struct {
42160 +}POSTPACK WMI_RSSI_THRESHOLD_EVENT;
42163 + * WMI_ERROR_REPORT_EVENTID
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;
42175 +typedef PREPACK struct {
42176 + A_UINT32 errorVal;
42177 +}POSTPACK WMI_TARGET_ERROR_REPORT_EVENT;
42179 +typedef PREPACK struct {
42181 +}POSTPACK WMI_TX_RETRY_ERR_EVENT;
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;
42194 +typedef PREPACK struct {
42195 + A_UINT8 range; /* WMI_SNR_THRESHOLD_VAL */
42197 +}POSTPACK WMI_SNR_THRESHOLD_EVENT;
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;
42210 +typedef PREPACK struct {
42212 + A_UINT8 range; /* WMI_LQ_THRESHOLD_VAL */
42213 +}POSTPACK WMI_LQ_THRESHOLD_EVENT;
42215 + * WMI_REPORT_ROAM_TBL_EVENTID
42217 +#define MAX_ROAM_TBL_CAND 5
42219 +typedef PREPACK struct {
42220 + A_INT32 roam_util;
42221 + A_UINT8 bssid[ATH_MAC_LEN];
42224 + A_INT8 last_rssi;
42227 + A_UINT8 reserved; /* For alignment */
42228 +} POSTPACK WMI_BSS_ROAM_INFO;
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;
42238 + * WMI_CAC_EVENTID
42241 + CAC_INDICATION_ADMISSION = 0x00,
42242 + CAC_INDICATION_ADMISSION_RESP = 0x01,
42243 + CAC_INDICATION_DELETE = 0x02,
42244 + CAC_INDICATION_NO_RESP = 0x03,
42247 +#define WMM_TSPEC_IE_LEN 63
42249 +typedef PREPACK struct {
42251 + A_UINT8 cac_indication;
42252 + A_UINT8 statusCode;
42253 + A_UINT8 tspecSuggestion[WMM_TSPEC_IE_LEN];
42254 +}POSTPACK WMI_CAC_EVENT;
42257 + * WMI_APLIST_EVENTID
42264 +typedef PREPACK struct {
42265 + A_UINT8 bssid[ATH_MAC_LEN];
42266 + A_UINT16 channel;
42267 +} POSTPACK WMI_AP_INFO_V1;
42269 +typedef PREPACK union {
42270 + WMI_AP_INFO_V1 apInfoV1;
42271 +} POSTPACK WMI_AP_INFO;
42273 +typedef PREPACK struct {
42274 + A_UINT8 apListVer;
42276 + WMI_AP_INFO apList[1];
42277 +} POSTPACK WMI_APLIST_EVENT;
42280 + * developer commands
42284 + * WMI_SET_BITRATE_CMDID
42286 + * Get bit rate cmd uses same definition as set bit rate cmd
42304 +typedef PREPACK struct {
42305 + A_INT8 rateIndex; /* see WMI_BIT_RATE */
42306 +} POSTPACK WMI_BIT_RATE_CMD, WMI_BIT_RATE_REPLY;
42309 + * WMI_SET_FIXRATES_CMDID
42311 + * Get fix rates cmd uses same definition as set fix rates cmd
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;
42328 +typedef PREPACK struct {
42329 + A_UINT16 fixRateMask; /* see WMI_BIT_RATE */
42330 +} POSTPACK WMI_FIX_RATES_CMD, WMI_FIX_RATES_REPLY;
42333 + * WMI_SET_RECONNECT_AUTH_MODE_CMDID
42335 + * Set authentication mode
42338 + RECONN_DO_AUTH = 0x00,
42339 + RECONN_NOT_AUTH = 0x01
42342 +typedef PREPACK struct {
42344 +} POSTPACK WMI_SET_AUTH_MODE_CMD;
42347 + * WMI_SET_REASSOC_MODE_CMDID
42349 + * Set authentication mode
42352 + REASSOC_DO_DISASSOC = 0x00,
42353 + REASSOC_DONOT_DISASSOC = 0x01
42354 +} WMI_REASSOC_MODE;
42356 +typedef PREPACK struct {
42358 +}POSTPACK WMI_SET_REASSOC_MODE_CMD;
42361 + ROAM_DATA_TIME = 1, /* Get The Roam Time Data */
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;
42377 +typedef PREPACK struct {
42379 + WMI_TARGET_ROAM_TIME roamTime;
42381 + A_UINT8 roamDataType ;
42382 +} POSTPACK WMI_TARGET_ROAM_DATA;
42385 + WMI_WMM_DISABLED = 0,
42389 +typedef PREPACK struct {
42391 +}POSTPACK WMI_SET_WMM_CMD;
42394 + WMI_TXOP_DISABLED = 0,
42398 +typedef PREPACK struct {
42399 + A_UINT8 txopEnable;
42400 +}POSTPACK WMI_SET_WMM_TXOP_CMD;
42402 +typedef PREPACK struct {
42403 + A_UINT8 keepaliveInterval;
42404 +} POSTPACK WMI_SET_KEEPALIVE_CMD;
42406 +typedef PREPACK struct {
42407 + A_BOOL configured;
42408 + A_UINT8 keepaliveInterval;
42409 +} POSTPACK WMI_GET_KEEPALIVE_CMD;
42412 + * Add Application specified IE to a management frame
42414 +#define WMI_MAX_IE_LEN 78
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;
42423 + * Notify the WSC registration status to the target
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 */
42430 + WHAL_SETCABTO_CMDID = 1,
42433 +typedef PREPACK struct {
42434 + A_UINT8 cabTimeOut;
42435 +} POSTPACK WHAL_SETCABTO_PARAM;
42437 +typedef PREPACK struct {
42438 + A_UINT8 whalCmdId;
42440 +} POSTPACK WHAL_PARAMCMD;
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
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;
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;
42466 +typedef PREPACK struct {
42469 +} POSTPACK WMI_SET_HOST_SLEEP_MODE_CMD;
42471 +typedef PREPACK struct {
42472 + A_BOOL enable_wow;
42473 +} POSTPACK WMI_SET_WOW_MODE_CMD;
42475 +typedef PREPACK struct {
42476 + A_UINT8 filter_list_id;
42477 +} POSTPACK WMI_GET_WOW_LIST_CMD;
42480 + * WMI_GET_WOW_LIST_CMD reply
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;
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;
42497 +typedef PREPACK struct {
42498 + A_UINT16 filter_list_id;
42499 + A_UINT16 filter_id;
42500 +} POSTPACK WMI_DEL_WOW_PATTERN_CMD;
42502 +typedef PREPACK struct {
42503 + A_UINT8 macaddr[ATH_MAC_LEN];
42504 +} POSTPACK WMI_SET_MAC_ADDRESS_CMD;
42507 + * WMI_SET_AKMP_PARAMS_CMD
42510 +#define WMI_AKMP_MULTI_PMKID_EN 0x000001
42512 +typedef PREPACK struct {
42513 + A_UINT32 akmpInfo;
42514 +} POSTPACK WMI_SET_AKMP_PARAMS_CMD;
42516 +typedef PREPACK struct {
42517 + A_UINT8 pmkid[WMI_PMKID_LEN];
42518 +} POSTPACK WMI_PMKID;
42521 + * WMI_SET_PMKID_LIST_CMD
42523 +#define WMI_MAX_PMKID_CACHE 8
42525 +typedef PREPACK struct {
42526 + A_UINT32 numPMKID;
42527 + WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE];
42528 +} POSTPACK WMI_SET_PMKID_LIST_CMD;
42531 + * WMI_GET_PMKID_LIST_CMD Reply
42532 + * Following the Number of PMKIDs is the list of PMKIDs
42534 +typedef PREPACK struct {
42535 + A_UINT32 numPMKID;
42536 + WMI_PMKID pmkidList[1];
42537 +} POSTPACK WMI_PMKID_LIST_REPLY;
42539 +/* index used for priority streams */
42541 + WMI_NOT_MAPPED = -1,
42542 + WMI_CONTROL_PRI = 0,
42543 + WMI_BEST_EFFORT_PRI = 1,
42545 + WMI_HIGH_PRI = 3,
42547 + WMI_PRI_MAX_COUNT
42548 +} WMI_PRI_STREAM_ID;
42550 +#ifndef ATH_TARGET
42551 +#include "athendpack.h"
42554 +#ifdef __cplusplus
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
42564 + * Copyright (c) 2004-2005 Atheros Communications Inc.
42565 + * All rights reserved.
42568 + * $ATH_LICENSE_HOSTSDK0_C$
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.
42577 + * Extended WMIX commands are encapsulated in a WMI message with
42578 + * cmd=WMI_EXTENSION_CMD.
42585 +#ifdef __cplusplus
42589 +#ifndef ATH_TARGET
42590 +#include "athstartpack.h"
42593 +#include "dbglog.h"
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.
42603 +typedef PREPACK struct {
42604 + A_UINT32 commandId;
42605 +} POSTPACK WMIX_CMD_HDR;
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;
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,
42631 + * =============DataSet support=================
42635 + * WMIX_DSETOPENREQ_EVENTID
42636 + * DataSet Open Request Event
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;
42646 + * WMIX_DSETCLOSE_EVENTID
42647 + * DataSet Close Event
42649 +typedef PREPACK struct {
42650 + A_UINT32 access_cookie;
42651 +} POSTPACK WMIX_DSETCLOSE_EVENT;
42654 + * WMIX_DSETDATAREQ_EVENTID
42655 + * DataSet Data Request Event
42657 +typedef PREPACK struct {
42658 + A_UINT32 access_cookie;
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;
42666 +typedef PREPACK struct {
42668 + A_UINT32 targ_dset_handle;
42669 + A_UINT32 targ_reply_fn;
42670 + A_UINT32 targ_reply_arg;
42671 + A_UINT32 access_cookie;
42673 + A_UINT32 version;
42674 +} POSTPACK WMIX_DSETOPEN_REPLY_CMD;
42676 +typedef PREPACK struct {
42678 + A_UINT32 targ_buf;
42679 + A_UINT32 targ_reply_fn;
42680 + A_UINT32 targ_reply_arg;
42683 +} POSTPACK WMIX_DSETDATA_REPLY_CMD;
42687 + * =============GPIO support=================
42688 + * All masks are 18-bit masks with bit N operating on GPIO pin N.
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.
42699 + * If a request is made to simultaneously set/clear or set/disable or
42700 + * clear/disable or disable/enable, results are undefined.
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;
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.
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;
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;
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.
42729 +typedef PREPACK struct {
42730 + A_UINT32 ack_mask; /* interrupts to acknowledge */
42731 +} POSTPACK WMIX_GPIO_INTR_ACK_CMD;
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.
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;
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
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.
42759 +typedef PREPACK struct {
42762 +} POSTPACK WMIX_GPIO_DATA_EVENT;
42765 + * =============Error Detection support=================
42769 + * WMIX_HB_CHALLENGE_RESP_CMDID
42770 + * Heartbeat Challenge Response command
42772 +typedef PREPACK struct {
42775 +} POSTPACK WMIX_HB_CHALLENGE_RESP_CMD;
42778 + * WMIX_HB_CHALLENGE_RESP_EVENTID
42779 + * Heartbeat Challenge Response Event
42781 +#define WMIX_HB_CHALLENGE_RESP_EVENT WMIX_HB_CHALLENGE_RESP_CMD
42783 +typedef PREPACK struct {
42784 + struct dbglog_config_s config;
42785 +} POSTPACK WMIX_DBGLOG_CFG_MODULE_CMD;
42787 +#ifndef ATH_TARGET
42788 +#include "athendpack.h"
42791 +#ifdef __cplusplus
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
42800 +config AR6000_WLAN
42801 + tristate "AR6000 wireless networking over SDIO"
42803 + select WIRELESS_EXT
42808 +config AR6000_WLAN_DEBUG
42809 + bool "Enable retrieval of firmware debugging information"
42810 + depends on AR6000_WLAN
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.
42817 + If in doubt, say N.
42819 +config AR6000_WLAN_RESET
42820 + bool "Soft-reset when shutting down"
42821 + depends on AR6000_WLAN
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
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
42837 +PWD := $(shell pwd)
42839 +EXTRA_CFLAGS += -I$(src)/include
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 \
42848 +EXTRA_CFLAGS += -DKERNEL_2_6
42850 +obj-$(CONFIG_AR6000_WLAN) += ar6000.o
42852 +ar6000-objs += htc/ar6k.o \
42853 + htc/ar6k_events.o \
42856 + htc/htc_services.o \
42860 + ar6000/ar6000_drv.o \
42861 + ar6000/ar6000_raw_if.o \
42862 + ar6000/netbuf.o \
42863 + ar6000/wireless_ext.o \
42865 + miscdrv/common_drv.o \
42866 + miscdrv/credit_dist.o \
42868 + wlan/wlan_node.o \
42869 + wlan/wlan_recv_beacon.o \
42870 + wlan/wlan_utils.o
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
42880 + * Copyright (c) 2004-2007 Atheros Communications Inc.
42881 + * All rights reserved.
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;
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.
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"
42904 +#include "htc_api.h"
42906 +#include "bmi_msg.h"
42907 +#include "common_drv.h"
42908 +#include "a_debug.h"
42909 +#include "targaddrs.h"
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))
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. */
42923 +#ifdef USE_4BYTE_REGISTER_ACCESS
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)
42929 + A_UINT8 addrValue[4];
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 */
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];
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,
42948 + HIF_WR_SYNC_BYTE_FIX,
42950 + if (status != A_OK) {
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));
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,
42966 + (A_UCHAR *)(&Address),
42968 + HIF_WR_SYNC_BYTE_INC,
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));
42986 + /* set the window address register */
42987 +A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
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,
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));
43006 + /* write the LSB of the register, this initiates the operation */
43007 + status = HIFReadWrite(hifDevice,
43009 + (A_UCHAR *)(&Address),
43011 + HIF_WR_SYNC_BYTE_INC,
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));
43026 + * Read from the AR6000 through its diagnostic window.
43027 + * No cooperation from the Target is required for this.
43030 +ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
43034 + /* set window register to start read cycle */
43035 + status = ar6000_SetAddressWindowRegister(hifDevice,
43036 + WINDOW_READ_ADDR_ADDRESS,
43039 + if (status != A_OK) {
43043 + /* read the data */
43044 + status = HIFReadWrite(hifDevice,
43045 + WINDOW_DATA_ADDRESS,
43047 + sizeof(A_UINT32),
43048 + HIF_RD_SYNC_BYTE_INC,
43050 + if (status != A_OK) {
43051 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
43060 + * Write to the AR6000 through its diagnostic window.
43061 + * No cooperation from the Target is required for this.
43064 +ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
43068 + /* set write data */
43069 + status = HIFReadWrite(hifDevice,
43070 + WINDOW_DATA_ADDRESS,
43072 + sizeof(A_UINT32),
43073 + HIF_WR_SYNC_BYTE_INC,
43075 + if (status != A_OK) {
43076 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data));
43080 + /* set window register, which starts the write cycle */
43081 + return ar6000_SetAddressWindowRegister(hifDevice,
43082 + WINDOW_WRITE_ADDR_ADDRESS,
43087 +ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
43088 + A_UCHAR *data, A_UINT32 length)
43091 + A_STATUS status = A_OK;
43093 + for (count = 0; count < length; count += 4, address += 4) {
43094 + if ((status = ar6000_ReadRegDiag(hifDevice, &address,
43095 + (A_UINT32 *)&data[count])) != A_OK)
43105 +ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
43106 + A_UCHAR *data, A_UINT32 length)
43109 + A_STATUS status = A_OK;
43111 + for (count = 0; count < length; count += 4, address += 4) {
43112 + if ((status = ar6000_WriteRegDiag(hifDevice, &address,
43113 + (A_UINT32 *)&data[count])) != A_OK)
43123 +ar6000_reset_device_skipflash(HIF_DEVICE *hifDevice)
43126 + struct forceROM_s {
43130 + struct forceROM_s *ForceROM;
43132 + A_UINT32 instruction;
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 */
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 */
43144 + {LOCAL_COUNT_ADDRESS+0x10, 0}, /* clear BMI credit counter */
43146 + {RESET_CONTROL_ADDRESS, RESET_CONTROL_WARM_RST_MASK},
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},
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.
43162 + (void)ar6000_ReadDataDiag(hifDevice, 0x01000040,
43163 + (A_UCHAR *)&instruction, 4);
43165 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("instruction=0x%x\n", instruction));
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"));
43173 + ForceROM = ForceROM_NEW;
43174 + szForceROM = sizeof(ForceROM_NEW)/sizeof(*ForceROM);
43175 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Using NEW method\n"));
43178 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Force Target to execute from ROM....\n"));
43179 + for (i = 0; i < szForceROM; i++)
43181 + if (ar6000_WriteRegDiag(hifDevice,
43182 + &ForceROM[i].addr,
43183 + &ForceROM[i].data) != A_OK)
43185 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot force Target to execute ROM!\n"));
43190 + msleep(50); /* delay to allow dragon to come to BMI phase */
43194 +/* reset device */
43195 +A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
43198 +#if !defined(DWSIM)
43199 + A_STATUS status = A_OK;
43200 + A_UINT32 address;
43205 + // address = RESET_CONTROL_ADDRESS;
43206 + data = RESET_CONTROL_COLD_RST_MASK;
43208 + /* Hardcode the address of RESET_CONTROL_ADDRESS based on the target type */
43209 + if (TargetType == TARGET_TYPE_AR6001) {
43210 + address = 0x0C000000;
43212 + if (TargetType == TARGET_TYPE_AR6002) {
43213 + address = 0x00004000;
43219 + status = ar6000_WriteRegDiag(hifDevice, &address, &data);
43221 + if (A_FAILED(status)) {
43226 + * Read back the RESET CAUSE register to ensure that the cold reset
43229 + msleep(2000); /* 2 second delay to allow things to settle down */
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;
43237 + if (TargetType == TARGET_TYPE_AR6002) {
43238 + address = 0x000040C0;
43245 + status = ar6000_ReadRegDiag(hifDevice, &address, &data);
43247 + if (A_FAILED(status)) {
43251 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Reset Cause readback: 0x%X \n",data));
43252 + data &= RESET_CAUSE_LAST_MASK;
43254 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Unable to cold reset the target \n"));
43259 + if (A_FAILED(status)) {
43260 + AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
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 */
43270 +#if REG_DUMP_COUNT_AR6001 <= REG_DUMP_COUNT_AR6002
43271 +#define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6002
43273 +#define REGISTER_DUMP_LEN_MAX REG_DUMP_COUNT_AR6001
43276 +void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
43278 + A_UINT32 address;
43279 + A_UINT32 regDumpArea = 0;
43281 + A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
43282 + A_UINT32 regDumpCount = 0;
43287 + /* the reg dump pointer is copied to the host interest area */
43288 + address = HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_failure_state);
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;
43296 + } else if (TargetType == TARGET_TYPE_AR6002) {
43298 + regDumpCount = REG_DUMP_COUNT_AR6002;
43304 + /* read RAM location through diagnostic window */
43305 + status = ar6000_ReadRegDiag(hifDevice, &address, ®DumpArea);
43307 + if (A_FAILED(status)) {
43308 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
43312 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Location of register dump data: 0x%X \n",regDumpArea));
43314 + if (regDumpArea == 0) {
43315 + /* no reg dump */
43319 + if (TargetType == TARGET_TYPE_AR6001) {
43320 + regDumpArea &= 0x0FFFFFFF; /* convert to physical address in target memory */
43323 + /* fetch register dump data */
43324 + status = ar6000_ReadDataDiag(hifDevice,
43326 + (A_UCHAR *)®DumpValues[0],
43327 + regDumpCount * (sizeof(A_UINT32)));
43329 + if (A_FAILED(status)) {
43330 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
43334 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Register Dump: \n"));
43336 + for (i = 0; i < regDumpCount; i++) {
43337 + AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" %d : 0x%8.8X \n",i, regDumpValues[i]));
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
43351 + * Copyright (c) 2004-2007 Atheros Communications Inc.
43352 + * All rights reserved.
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;
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.
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"
43376 +/********* CREDIT DISTRIBUTION FUNCTIONS ******************************************/
43378 +#define NO_VO_SERVICE 1 /* currently WMI only uses 3 data streams, so we leave VO service inactive */
43380 +#ifdef NO_VO_SERVICE
43381 +#define DATA_SVCS_USED 3
43383 +#define DATA_SVCS_USED 4
43386 +static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
43387 + HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
43389 +static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
43390 + HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
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,
43399 + /* set the new limit */
43400 + pEpDist->TxCreditsAssigned = Limit;
43402 + if (pEpDist->TxCredits <= Limit) {
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;
43413 +/* give an endpoint some credits from the free credit pool */
43414 +#define GiveCredits(pCredInfo,pEpDist,credits) \
43416 + (pEpDist)->TxCredits += (credits); \
43417 + (pEpDist)->TxCreditsAssigned += (credits); \
43418 + (pCredInfo)->CurrentFreeCredits -= (credits); \
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)
43429 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
43431 + COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
43433 + pCredInfo->CurrentFreeCredits = TotalCredits;
43434 + pCredInfo->TotalAvailableCredits = TotalCredits;
43436 + pCurEpDist = pEPList;
43438 + /* run through the list and initialize */
43439 + while (pCurEpDist != NULL) {
43441 + /* set minimums for each endpoint */
43442 + pCurEpDist->TxCreditsMin = pCurEpDist->TxCreditsPerMaxMsg;
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;
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.
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;
43465 + if (pCredInfo->CurrentFreeCredits <= 0) {
43466 + AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit distributions \n", TotalCredits));
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;
43479 + /* for the remaining data endpoints, we assume that each TxCreditsPerMaxMsg are
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.
43485 + count = (pCredInfo->CurrentFreeCredits/pCurEpDist->TxCreditsPerMaxMsg) * pCurEpDist->TxCreditsPerMaxMsg;
43486 + count = count >> 1;
43487 + count = max(count,pCurEpDist->TxCreditsPerMaxMsg);
43489 + pCurEpDist->TxCreditsNorm = count;
43492 + pCurEpDist = pCurEpDist->pNext;
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.
43505 +static void ar6000_credit_distribute(void *Context,
43506 + HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
43507 + HTC_CREDIT_DIST_REASON Reason)
43509 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
43510 + COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
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) {
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;
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);
43532 + if (pCurEpDist->TxCredits > pCurEpDist->TxCreditsNorm) {
43533 + /* oversubscribed endpoints need to reduce back to normal */
43534 + ReduceCredits(pCredInfo, pCurEpDist, pCurEpDist->TxCreditsNorm);
43538 + pCurEpDist = pCurEpDist->pNext;
43541 + A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits);
43545 + case HTC_CREDIT_DIST_ACTIVITY_CHANGE :
43546 + RedistributeCredits(pCredInfo,pEPDistList);
43548 + case HTC_CREDIT_DIST_SEEK_CREDITS :
43549 + SeekCredits(pCredInfo,pEPDistList);
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));
43562 +/* redistribute credits based on activity change */
43563 +static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
43564 + HTC_ENDPOINT_CREDIT_DIST *pEPDistList)
43566 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist = pEPDistList;
43568 + /* walk through the list and remove credits from inactive endpoints */
43569 + while (pCurEpDist != NULL) {
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);
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 */
43582 + pCurEpDist = pCurEpDist->pNext;
43585 + A_ASSERT(pCredInfo->CurrentFreeCredits <= pCredInfo->TotalAvailableCredits);
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)
43593 + HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
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 */
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 */
43610 + if (pCredInfo->CurrentFreeCredits >= 2 * pEPDist->TxCreditsSeek) {
43611 + /* try to give more credits than it needs */
43612 + credits = 2 * pEPDist->TxCreditsSeek;
43614 + /* give what we can */
43615 + credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
43618 + if (credits >= pEPDist->TxCreditsSeek) {
43619 + /* we found some to fullfill the seek request */
43623 + /* we don't have enough in the free pool, try taking away from lower priority services
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.
43632 + /* starting at the lowest priority */
43633 + pCurEpDist = pCredInfo->pLowestPriEpDist;
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;
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,
43646 + pCurEpDist->TxCreditsAssigned - need);
43648 + if (pCredInfo->CurrentFreeCredits >= pEPDist->TxCreditsSeek) {
43649 + /* we have enough */
43654 + pCurEpDist = pCurEpDist->pPrev;
43657 + /* return what we can get */
43658 + credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
43662 + /* did we find some credits? */
43664 + /* give what we can */
43665 + GiveCredits(pCredInfo, pEPDist, credits);
43670 +/* initialize and setup credit distribution */
43671 +A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo)
43673 + HTC_SERVICE_ID servicepriority[5];
43675 + A_MEMZERO(pCredInfo,sizeof(COMMON_CREDIT_STATE_INFO));
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 */
43683 + /* set callbacks and priority list */
43684 + HTCSetCreditDistribution(HTCHandle,
43686 + ar6000_credit_distribute,
43687 + ar6000_credit_init,
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
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.
43704 + * Redistribution and use in source and binary forms, with or without
43705 + * modification, are permitted provided that the following conditions
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.
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.
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.
43730 + * $Id: //depot/sw/releases/olca2.0-GPL/host/wlan/src/wlan_node.c#1 $
43733 + * IEEE 802.11 node handling support.
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>
43745 +#include <wmi_api.h>
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);
43752 +wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size)
43756 + ni = A_MALLOC_NOWAIT(sizeof(bss_t));
43758 + if (ni != NULL) {
43759 + ni->ni_buf = A_MALLOC_NOWAIT(wh_size);
43760 + if (ni->ni_buf == NULL) {
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;
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
43779 + ni->ni_scangen = 0;
43785 +wlan_node_free(bss_t *ni)
43787 + if (ni->ni_buf != NULL) {
43788 + A_FREE(ni->ni_buf);
43794 +wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
43795 + const A_UINT8 *macaddr)
43799 + A_MEMCPY(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN);
43800 + hash = IEEE80211_NODE_HASH(macaddr);
43801 + ieee80211_node_initref(ni); /* mark referenced */
43803 + ni->ni_tstamp = A_GET_MS(WLAN_NODE_INACT_TIMEOUT_MSEC);
43804 + IEEE80211_NODE_LOCK_BH(nt);
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)
43811 + nt->nt_node_last->ni_list_next = ni;
43813 + nt->nt_node_last = ni;
43814 + if(nt->nt_node_first == NULL)
43816 + nt->nt_node_first = ni;
43819 + /* Insert into the hash list i.e. the bucket */
43820 + if((ni->ni_hash_next = nt->nt_hash[hash]) != NULL)
43822 + nt->nt_hash[hash]->ni_hash_prev = ni;
43824 + ni->ni_hash_prev = NULL;
43825 + nt->nt_hash[hash] = ni;
43827 + if (!nt->isTimerArmed) {
43828 + A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0);
43829 + nt->isTimerArmed = TRUE;
43832 + IEEE80211_NODE_UNLOCK_BH(nt);
43836 +_ieee80211_find_node(struct ieee80211_node_table *nt,
43837 + const A_UINT8 *macaddr)
43842 + IEEE80211_NODE_LOCK_ASSERT(nt);
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 */
43855 +wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr)
43859 + IEEE80211_NODE_LOCK(nt);
43860 + ni = _ieee80211_find_node(nt, macaddr);
43861 + IEEE80211_NODE_UNLOCK(nt);
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.
43871 +wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni)
43873 + IEEE80211_NODE_LOCK(nt);
43875 + if(ni->ni_list_prev == NULL)
43877 + /* First in list so fix the list head */
43878 + nt->nt_node_first = ni->ni_list_next;
43882 + ni->ni_list_prev->ni_list_next = ni->ni_list_next;
43885 + if(ni->ni_list_next == NULL)
43887 + /* Last in list so fix list tail */
43888 + nt->nt_node_last = ni->ni_list_prev;
43892 + ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
43895 + if(ni->ni_hash_prev == NULL)
43897 + /* First in list so fix the list head */
43899 + hash = IEEE80211_NODE_HASH(ni->ni_macaddr);
43900 + nt->nt_hash[hash] = ni->ni_hash_next;
43904 + ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
43907 + if(ni->ni_hash_next != NULL)
43909 + ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
43911 + wlan_node_free(ni);
43913 + IEEE80211_NODE_UNLOCK(nt);
43917 +wlan_node_dec_free(bss_t *ni)
43919 + if (ieee80211_node_dectestref(ni)) {
43920 + wlan_node_free(ni);
43925 +wlan_free_allnodes(struct ieee80211_node_table *nt)
43929 + while ((ni = nt->nt_node_first) != NULL) {
43930 + wlan_node_reclaim(nt, ni);
43935 +wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
43941 + gen = ++nt->nt_scangen;
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);
43949 + wlan_node_dec_free(ni);
43952 + IEEE80211_NODE_UNLOCK(nt);
43956 + * Node table support.
43959 +wlan_node_table_init(void *wmip, struct ieee80211_node_table *nt)
43963 + AR_DEBUG_PRINTF(ATH_DEBUG_WLAN, ("node table = 0x%x\n", (A_UINT32)nt));
43964 + IEEE80211_NODE_LOCK_INIT(nt);
43966 + nt->nt_node_first = nt->nt_node_last = NULL;
43967 + for(i = 0; i < IEEE80211_NODE_HASHSIZE; i++)
43969 + nt->nt_hash[i] = NULL;
43971 + A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt);
43972 + nt->isTimerArmed = FALSE;
43973 + nt->nt_wmip = wmip;
43977 +wlan_node_timeout(A_ATH_TIMER arg)
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;
43983 + wmi_get_current_bssid(nt->nt_wmip, myBssid);
43985 + bss = nt->nt_node_first;
43986 + while (bss != NULL)
43988 + nextBss = bss->ni_list_next;
43989 + if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
43992 + if (bss->ni_tstamp <= A_GET_MS(0))
43995 + * free up all but the current bss - if set
43997 + wlan_node_reclaim(nt, bss);
44002 + * Re-arm timer, only when we have a bss other than
44003 + * current bss AND it is not aged-out.
44005 + reArmTimer = TRUE;
44012 + A_TIMEOUT_MS(&nt->nt_inact_timer, WLAN_NODE_INACT_TIMEOUT_MSEC, 0);
44014 + nt->isTimerArmed = reArmTimer;
44018 +wlan_node_table_cleanup(struct ieee80211_node_table *nt)
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);
44027 +wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
44028 + A_UINT32 ssidLength, A_BOOL bIsWPA2)
44030 + bss_t *ni = NULL;
44031 + A_UCHAR *pIESsid = NULL;
44033 + IEEE80211_NODE_LOCK (nt);
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) {
44039 + // Step 1 : Check SSID
44040 + if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {
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);
44048 + if (FALSE == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) {
44049 + ieee80211_node_incref(ni); /* mark referenced */
44050 + IEEE80211_NODE_UNLOCK (nt);
44057 + IEEE80211_NODE_UNLOCK (nt);
44063 +wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni)
44065 + IEEE80211_NODE_LOCK (nt);
44066 + wlan_node_dec_free (ni);
44067 + IEEE80211_NODE_UNLOCK (nt);
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
44074 + * Copyright (c) 2001 Atsushi Onoe
44075 + * Copyright (c) 2002-2004 Sam Leffler, Errno Consulting
44076 + * All rights reserved.
44078 + * Redistribution and use in source and binary forms, with or without
44079 + * modification, are permitted provided that the following conditions
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.
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.
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.
44105 + * IEEE 802.11 input handling.
44108 +#include "a_config.h"
44109 +#include "athdefs.h"
44110 +#include "a_types.h"
44111 +#include "a_osapi.h"
44113 +#include <ieee80211.h>
44114 +#include <wlan_api.h>
44116 +#define IEEE80211_VERIFY_LENGTH(_len, _minlen) do { \
44117 + if ((_len) < (_minlen)) { \
44118 + return A_EINVAL; \
44122 +#define IEEE80211_VERIFY_ELEMENT(__elem, __maxlen) do { \
44123 + if ((__elem) == NULL) { \
44124 + return A_EINVAL; \
44126 + if ((__elem)[1] > (__maxlen)) { \
44127 + return A_EINVAL; \
44132 +/* unaligned little endian access */
44133 +#define LE_READ_2(p) \
44135 + ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8)))
44137 +#define LE_READ_4(p) \
44139 + ((((A_UINT8 *)(p))[0] ) | (((A_UINT8 *)(p))[1] << 8) | \
44140 + (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24)))
44143 +static int __inline
44144 +iswpaoui(const A_UINT8 *frm)
44146 + return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
44149 +static int __inline
44150 +iswmmoui(const A_UINT8 *frm)
44152 + return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
44155 +static int __inline
44156 +iswmmparam(const A_UINT8 *frm)
44158 + return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
44161 +static int __inline
44162 +iswmminfo(const A_UINT8 *frm)
44164 + return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE;
44167 +static int __inline
44168 +isatherosoui(const A_UINT8 *frm)
44170 + return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
44173 +static int __inline
44174 +iswscoui(const A_UINT8 *frm)
44176 + return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI);
44180 +wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie)
44182 + A_UINT8 *frm, *efrm;
44185 + efrm = (A_UINT8 *) (frm + framelen);
44188 + * beacon/probe response frame format
44190 + * [2] beacon interval
44191 + * [2] capability information
44193 + * [tlv] supported rates
44194 + * [tlv] country information
44195 + * [tlv] parameter set (FH/DS)
44196 + * [tlv] erp information
44197 + * [tlv] extended supported rates
44199 + * [tlv] WPA or RSN
44200 + * [tlv] Atheros Advanced Capabilities
44202 + IEEE80211_VERIFY_LENGTH(efrm - frm, 12);
44203 + A_MEMZERO(cie, sizeof(*cie));
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;
44210 + while (frm < efrm) {
44212 + case IEEE80211_ELEMID_SSID:
44213 + cie->ie_ssid = frm;
44215 + case IEEE80211_ELEMID_RATES:
44216 + cie->ie_rates = frm;
44218 + case IEEE80211_ELEMID_COUNTRY:
44219 + cie->ie_country = frm;
44221 + case IEEE80211_ELEMID_FHPARMS:
44223 + case IEEE80211_ELEMID_DSPARMS:
44224 + cie->ie_chan = frm[2];
44226 + case IEEE80211_ELEMID_TIM:
44227 + cie->ie_tim = frm;
44229 + case IEEE80211_ELEMID_IBSSPARMS:
44231 + case IEEE80211_ELEMID_XRATES:
44232 + cie->ie_xrates = frm;
44234 + case IEEE80211_ELEMID_ERP:
44235 + if (frm[1] != 1) {
44236 + //A_PRINTF("Discarding ERP Element - Bad Len\n");
44239 + cie->ie_erp = frm[2];
44241 + case IEEE80211_ELEMID_RSN:
44242 + cie->ie_rsn = frm;
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;
44258 + frm += frm[1] + 2;
44260 + IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE);
44261 + IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN);
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
44270 + * Copyright (c) 2004-2005 Atheros Communications Inc.
44271 + * All rights reserved.
44273 + * This module implements frequently used wlan utilies
44275 + * $Id: //depot/sw/releases/olca2.0-GPL/host/wlan/src/wlan_utils.c#1 $
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;
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.
44291 +#include <a_config.h>
44292 +#include <athdefs.h>
44293 +#include <a_types.h>
44294 +#include <a_osapi.h>
44297 + * converts ieee channel number to frequency
44300 +wlan_ieee2freq(int chan)
44302 + if (chan == 14) {
44305 + if (chan < 14) { /* 0-13 */
44306 + return (2407 + (chan*5));
44308 + if (chan < 27) { /* 15-26 */
44309 + return (2512 + ((chan-15)*20));
44311 + return (5000 + (chan*5));
44315 + * Converts MHz frequency to IEEE channel number.
44318 +wlan_freq2ieee(A_UINT16 freq)
44320 + if (freq == 2484)
44323 + return (freq - 2407) / 5;
44325 + return 15 + ((freq - 2512) / 20);
44326 + return (freq - 5000) / 5;
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
44333 + * Copyright (c) 2004-2007 Atheros Communications Inc.
44334 + * All rights reserved.
44336 + * This module implements the hardware independent layer of the
44337 + * Wireless Module Interface (WMI) protocol.
44339 + * $Id: //depot/sw/releases/olca2.0-GPL/host/wmi/wmi.c#3 $
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;
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.
44355 +#include <a_config.h>
44356 +#include <athdefs.h>
44357 +#include <a_types.h>
44358 +#include <a_osapi.h>
44360 +#include "htc_api.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"
44374 +static A_STATUS wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44376 +static A_STATUS wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44378 +static A_STATUS wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44380 +static A_STATUS wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44382 +static A_STATUS wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44384 +static A_STATUS wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44386 +static A_STATUS wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44388 +static A_STATUS wmi_sync_point(struct wmi_t *wmip);
44390 +static A_STATUS wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
44392 +static A_STATUS wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
44394 +static A_STATUS wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
44396 +static A_STATUS wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
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,
44402 +static A_STATUS wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap,
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,
44408 +#endif /* CONFIG_HOST_DSET_SUPPORT */
44411 +static A_STATUS wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap,
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,
44421 +static A_STATUS wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44423 +static A_STATUS wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
44426 +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len);
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 */
44434 +#ifdef CONFIG_HOST_TCMD_SUPPORT
44436 +wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44440 +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44443 +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44446 +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44449 +wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex);
44452 +wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44455 +wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44457 +static A_STATUS wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
44460 +static const A_INT32 wmi_rateTable[] = {
44475 +#define MODE_A_SUPPORT_RATE_START 4
44476 +#define MODE_A_SUPPORT_RATE_STOP 11
44478 +#define MODE_GONLY_SUPPORT_RATE_START MODE_A_SUPPORT_RATE_START
44479 +#define MODE_GONLY_SUPPORT_RATE_STOP MODE_A_SUPPORT_RATE_STOP
44481 +#define MODE_B_SUPPORT_RATE_START 0
44482 +#define MODE_B_SUPPORT_RATE_STOP 3
44484 +#define MODE_G_SUPPORT_RATE_START 0
44485 +#define MODE_G_SUPPORT_RATE_STOP 11
44487 +#define MAX_NUMBER_OF_SUPPORT_RATES (MODE_G_SUPPORT_RATE_STOP + 1)
44489 +/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
44490 +const A_UINT8 up_to_ac[]= {
44502 +wmi_init(void *devt)
44504 + struct wmi_t *wmip;
44506 + wmip = A_MALLOC(sizeof(struct wmi_t));
44507 + if (wmip == NULL) {
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;
44522 +wmi_qos_state_init(struct wmi_t *wmip)
44526 + if (wmip == NULL) {
44531 + /* Initialize QoS States */
44532 + wmip->wmi_numQoSStream = 0;
44534 + wmip->wmi_fatPipeExists = 0;
44536 + for (i=0; i < WMM_NUM_AC; i++) {
44537 + wmip->wmi_streamExistsForAC[i]=0;
44540 + /* Initialize the static Wmi stream Pri to WMM AC mappings Arrays */
44541 + WMI_INIT_WMISTREAM_AC_MAP(wmip);
44543 + UNLOCK_WMI(wmip);
44545 + A_WMI_SET_NUMDATAENDPTS(wmip->wmi_devt, 1);
44549 +wmi_shutdown(struct wmi_t *wmip)
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);
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.
44567 +wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
44570 + A_UINT16 typeorlen;
44571 + ATH_MAC_HDR macHdr;
44572 + ATH_LLC_SNAP_HDR *llcHdr;
44574 + A_ASSERT(osbuf != NULL);
44576 + if (A_NETBUF_HEADROOM(osbuf) <
44577 + (sizeof(ATH_LLC_SNAP_HDR) + sizeof(WMI_DATA_HDR)))
44579 + return A_NO_MEMORY;
44582 + datap = A_NETBUF_DATA(osbuf);
44584 + typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
44586 + if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
44588 + * packet is already in 802.3 format - return success
44590 + A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
44595 + * Save mac fields and length to be inserted later
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));
44603 + * Make room for LLC+SNAP headers
44605 + if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
44606 + return A_NO_MEMORY;
44609 + datap = A_NETBUF_DATA(osbuf);
44611 + A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
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;
44626 + * Adds a WMI data header
44627 + * Assumes there is enough room in the buffer to add header.
44630 +wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType)
44632 + WMI_DATA_HDR *dtHdr;
44634 + A_ASSERT(osbuf != NULL);
44636 + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
44637 + return A_NO_MEMORY;
44640 + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
44641 + dtHdr->info = msgType;
44647 +A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT8 dir, A_UINT8 up)
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;
44657 + A_ASSERT(osbuf != NULL);
44659 + datap = A_NETBUF_DATA(osbuf);
44661 + if (up == UNDEFINED_PRI) {
44662 + llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) +
44663 + sizeof(ATH_MAC_HDR));
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));
44671 + if (userPriority < MAX_NUM_PRI) {
44672 + trafficClass = convert_userPriority_to_trafficClass(userPriority);
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 */
44680 + streamExists = wmip->wmi_fatPipeExists;
44681 + UNLOCK_WMI(wmip);
44683 + if (!(streamExists & (1 << trafficClass))) {
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);
44694 + return trafficClass;
44698 +wmi_get_stream_id(struct wmi_t *wmip, A_UINT8 trafficClass)
44700 + return WMI_ACCESSCATEGORY_WMISTREAM(wmip, trafficClass);
44704 + * performs 802.3 to DIX encapsulation for received packets.
44705 + * Assumes the entire 802.3 header is contigous.
44708 +wmi_dot3_2_dix(struct wmi_t *wmip, void *osbuf)
44711 + ATH_MAC_HDR macHdr;
44712 + ATH_LLC_SNAP_HDR *llcHdr;
44714 + A_ASSERT(osbuf != NULL);
44715 + datap = A_NETBUF_DATA(osbuf);
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;
44721 + if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
44722 + return A_NO_MEMORY;
44725 + datap = A_NETBUF_DATA(osbuf);
44727 + A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
44733 + * Removes a WMI data header
44736 +wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
44738 + A_ASSERT(osbuf != NULL);
44740 + return (A_NETBUF_PULL(osbuf, sizeof(WMI_DATA_HDR)));
44744 +wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg)
44746 + wlan_iterate_nodes(&wmip->wmi_scan_table, f, arg);
44750 + * WMI Extended Event received from Target.
44753 +wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
44755 + WMIX_CMD_HDR *cmd;
44759 + A_STATUS status = A_OK;
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);
44768 + cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
44769 + id = cmd->commandId;
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);
44778 + datap = A_NETBUF_DATA(osbuf);
44779 + len = A_NETBUF_LEN(osbuf);
44782 + case (WMIX_DSETOPENREQ_EVENTID):
44783 + status = wmi_dset_open_req_rx(wmip, datap, len);
44785 +#ifdef CONFIG_HOST_DSET_SUPPORT
44786 + case (WMIX_DSETCLOSE_EVENTID):
44787 + status = wmi_dset_close_rx(wmip, datap, len);
44789 + case (WMIX_DSETDATAREQ_EVENTID):
44790 + status = wmi_dset_data_req_rx(wmip, datap, len);
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);
44797 + case (WMIX_GPIO_DATA_EVENTID):
44798 + wmi_gpio_data_rx(wmip, datap, len);
44800 + case (WMIX_GPIO_ACK_EVENTID):
44801 + wmi_gpio_ack_rx(wmip, datap, len);
44803 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
44804 + case (WMIX_HB_CHALLENGE_RESP_EVENTID):
44805 + wmi_hbChallengeResp_rx(wmip, datap, len);
44807 + case (WMIX_DBGLOG_EVENTID):
44808 + wmi_dbglog_event_rx(wmip, datap, len);
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;
44824 +A_UINT32 cmdRecvNum;
44827 +wmi_control_rx(struct wmi_t *wmip, void *osbuf)
44829 + WMI_CMD_HDR *cmd;
44832 + A_UINT32 len, i, loggingReq;
44833 + A_STATUS status = A_OK;
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);
44843 + cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
44844 + id = cmd->commandId;
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);
44853 + datap = A_NETBUF_DATA(osbuf);
44854 + len = A_NETBUF_LEN(osbuf);
44856 + ar6000_get_driver_cfg(wmip->wmi_devt,
44857 + AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS,
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"));
44870 + UNLOCK_WMI(wmip);
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);
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);
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);
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);
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);
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);
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);
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);
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);
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.
44923 + A_WMI_SEND_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
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);
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);
44934 + case (WMI_CMDERROR_EVENTID):
44935 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_CMDERROR_EVENTID\n", DBGARG));
44936 + status = wmi_errorEvent_rx(wmip, datap, len);
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);
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);
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);
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);
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);
44959 + case (WMI_EXTENSION_EVENTID):
44960 + A_DPRINTF(DBG_WMI, (DBGFMT "WMI_EXTENSION_EVENTID\n", DBGARG));
44961 + status = wmi_control_rx_xtnd(wmip, osbuf);
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);
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);
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);
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);
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);
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);
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);
44996 + case (WMI_APLIST_EVENTID):
44997 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Received APLIST Event\n"));
44998 + status = wmi_aplistEvent_rx(wmip, datap, len);
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);
45004 + case (WMI_GET_WOW_LIST_EVENTID):
45005 + status = wmi_get_wow_list_event_rx(wmip, datap, len);
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);
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;
45019 + A_NETBUF_FREE(osbuf);
45025 +wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45027 + WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
45029 + if (len < sizeof(WMI_READY_EVENT)) {
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);
45040 +wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45042 + WMI_CONNECT_EVENT *ev;
45044 + if (len < sizeof(WMI_CONNECT_EVENT)) {
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]));
45054 + A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
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,
45066 +wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45068 + WMI_REG_DOMAIN_EVENT *ev;
45070 + if (len < sizeof(*ev)) {
45073 + ev = (WMI_REG_DOMAIN_EVENT *)datap;
45075 + A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
45081 +wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45083 + WMI_NEIGHBOR_REPORT_EVENT *ev;
45086 + if (len < sizeof(*ev)) {
45089 + ev = (WMI_NEIGHBOR_REPORT_EVENT *)datap;
45090 + numAps = ev->numberOfAps;
45092 + if (len < (int)(sizeof(*ev) + ((numAps - 1) * sizeof(WMI_NEIGHBOR_INFO)))) {
45096 + A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
45102 +wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45104 + WMI_DISCONNECT_EVENT *ev;
45106 + if (len < sizeof(WMI_DISCONNECT_EVENT)) {
45109 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45111 + ev = (WMI_DISCONNECT_EVENT *)datap;
45113 + A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
45115 + A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
45116 + ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
45122 +wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45124 + WMI_TKIP_MICERR_EVENT *ev;
45126 + if (len < sizeof(*ev)) {
45129 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45131 + ev = (WMI_TKIP_MICERR_EVENT *)datap;
45132 + A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
45138 +wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45141 + WMI_BSS_INFO_HDR *bih;
45143 + A_UINT32 nodeCachingAllowed;
45145 + if (len <= sizeof(WMI_BSS_INFO_HDR)) {
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) {
45157 + if(!nodeCachingAllowed) {
45162 + bih = (WMI_BSS_INFO_HDR *)datap;
45163 + buf = datap + sizeof(WMI_BSS_INFO_HDR);
45164 + len -= sizeof(WMI_BSS_INFO_HDR);
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],
45172 + if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
45173 + printk("%s() A_OK 2\n", __FUNCTION__);
45177 + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
45178 + if (bss != NULL) {
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
45184 + wlan_node_reclaim(&wmip->wmi_scan_table, bss);
45187 + bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
45188 + if (bss == NULL) {
45189 + return A_NO_MEMORY;
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);
45197 + if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != A_OK) {
45198 + wlan_node_free(bss);
45203 + * Update the frequency in ie_chan, overwriting of channel number
45204 + * which is done in wlan_parse_beacon
45206 + bss->ni_cie.ie_chan = bih->channel;
45207 + wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
45213 +wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45216 + WMI_OPT_RX_INFO_HDR *bih;
45219 + if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
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);
45227 + A_DPRINTF(DBG_WMI2, (DBGFMT "opt frame event %2.2x:%2.2x\n", DBGARG,
45228 + bih->bssid[4], bih->bssid[5]));
45230 + bss = wlan_find_node(&wmip->wmi_scan_table, bih->bssid);
45231 + if (bss != NULL) {
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
45237 + wlan_node_reclaim(&wmip->wmi_scan_table, bss);
45240 + bss = wlan_node_alloc(&wmip->wmi_scan_table, len);
45241 + if (bss == NULL) {
45242 + return A_NO_MEMORY;
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);
45254 + /* This event indicates inactivity timeout of a fatpipe(pstream)
45258 +wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45260 + WMI_PSTREAM_TIMEOUT_EVENT *ev;
45262 + if (len < sizeof(WMI_PSTREAM_TIMEOUT_EVENT)) {
45266 + A_DPRINTF(DBG_WMI, (DBGFMT "wmi_pstream_timeout_event_rx\n", DBGARG));
45268 + ev = (WMI_PSTREAM_TIMEOUT_EVENT *)datap;
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.
45275 + /* Set the activeTsids for this AC to 0 */
45277 + wmip->wmi_streamExistsForAC[ev->trafficClass]=0;
45278 + wmip->wmi_fatPipeExists &= ~(1 << ev->trafficClass);
45279 + UNLOCK_WMI(wmip);
45281 + /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
45282 + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
45288 +wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45290 + WMI_BIT_RATE_CMD *reply;
45293 + if (len < sizeof(WMI_BIT_RATE_CMD)) {
45296 + reply = (WMI_BIT_RATE_CMD *)datap;
45297 + A_DPRINTF(DBG_WMI,
45298 + (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
45300 + if (reply->rateIndex == RATE_AUTO) {
45301 + rate = RATE_AUTO;
45303 + rate = wmi_rateTable[(A_UINT32) reply->rateIndex];
45306 + A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
45312 +wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45314 + WMI_FIX_RATES_CMD *reply;
45316 + if (len < sizeof(WMI_BIT_RATE_CMD)) {
45319 + reply = (WMI_FIX_RATES_CMD *)datap;
45320 + A_DPRINTF(DBG_WMI,
45321 + (DBGFMT "Enter - fixed rate mask %x\n", DBGARG, reply->fixRateMask));
45323 + A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
45329 +wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45331 + WMI_CHANNEL_LIST_REPLY *reply;
45333 + if (len < sizeof(WMI_CHANNEL_LIST_REPLY)) {
45336 + reply = (WMI_CHANNEL_LIST_REPLY *)datap;
45337 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45339 + A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
45340 + reply->channelList);
45346 +wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45348 + WMI_TX_PWR_REPLY *reply;
45350 + if (len < sizeof(*reply)) {
45353 + reply = (WMI_TX_PWR_REPLY *)datap;
45354 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45356 + A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
45361 +wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45363 + WMI_GET_KEEPALIVE_CMD *reply;
45365 + if (len < sizeof(*reply)) {
45368 + reply = (WMI_GET_KEEPALIVE_CMD *)datap;
45369 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45371 + A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
45378 +wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45380 + WMIX_DSETOPENREQ_EVENT *dsetopenreq;
45382 + if (len < sizeof(WMIX_DSETOPENREQ_EVENT)) {
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);
45397 +#ifdef CONFIG_HOST_DSET_SUPPORT
45399 +wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45401 + WMIX_DSETCLOSE_EVENT *dsetclose;
45403 + if (len < sizeof(WMIX_DSETCLOSE_EVENT)) {
45406 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45408 + dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
45409 + A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
45415 +wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45417 + WMIX_DSETDATAREQ_EVENT *dsetdatareq;
45419 + if (len < sizeof(WMIX_DSETDATAREQ_EVENT)) {
45422 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
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);
45435 +#endif /* CONFIG_HOST_DSET_SUPPORT */
45438 +wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45440 + WMI_SCAN_COMPLETE_EVENT *ev;
45442 + ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
45443 + A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, ev->status);
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.
45456 +wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45458 + WMI_CMD_ERROR_EVENT *ev;
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"));
45466 + case (ILLEGAL_STATE):
45467 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Illegal State\n"));
45469 + case (INTERNAL_ERROR):
45470 + AR_DEBUG_PRINTF(ATH_DEBUG_WMI, ("Internal Error\n"));
45479 +wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45481 + WMI_TARGET_STATS *reply;
45483 + if (len < sizeof(*reply)) {
45486 + reply = (WMI_TARGET_STATS *)datap;
45487 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45489 + A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, reply);
45495 +wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45497 + WMI_RSSI_THRESHOLD_EVENT *reply;
45499 + if (len < sizeof(*reply)) {
45502 + reply = (WMI_RSSI_THRESHOLD_EVENT *)datap;
45503 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45505 + A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, reply->range, reply->rssi);
45512 +wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45514 + WMI_TARGET_ERROR_REPORT_EVENT *reply;
45516 + if (len < sizeof(*reply)) {
45519 + reply = (WMI_TARGET_ERROR_REPORT_EVENT *)datap;
45520 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45522 + A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, reply->errorVal);
45528 +wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45530 + WMI_CAC_EVENT *reply;
45532 + if (len < sizeof(*reply)) {
45535 + reply = (WMI_CAC_EVENT *)datap;
45536 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45538 + A_WMI_CAC_EVENT(wmip->wmi_devt, reply->ac,
45539 + reply->cac_indication, reply->statusCode,
45540 + reply->tspecSuggestion);
45546 +wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45548 + WMIX_HB_CHALLENGE_RESP_EVENT *reply;
45550 + if (len < sizeof(*reply)) {
45553 + reply = (WMIX_HB_CHALLENGE_RESP_EVENT *)datap;
45554 + A_DPRINTF(DBG_WMI, (DBGFMT "wmi: challenge response event\n", DBGARG));
45556 + A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
45562 +wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45564 + WMI_TARGET_ROAM_TBL *reply;
45566 + if (len < sizeof(*reply)) {
45569 + reply = (WMI_TARGET_ROAM_TBL *)datap;
45570 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45572 + A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
45578 +wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45580 + WMI_TARGET_ROAM_DATA *reply;
45582 + if (len < sizeof(*reply)) {
45585 + reply = (WMI_TARGET_ROAM_DATA *)datap;
45586 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45588 + A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
45594 +wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45596 + WMI_TX_RETRY_ERR_EVENT *reply;
45598 + if (len < sizeof(*reply)) {
45601 + reply = (WMI_TX_RETRY_ERR_EVENT *)datap;
45602 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45604 + A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
45610 +wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45612 + WMI_SNR_THRESHOLD_EVENT *reply;
45614 + if (len < sizeof(*reply)) {
45617 + reply = (WMI_SNR_THRESHOLD_EVENT *)datap;
45618 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45620 + A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->snr);
45626 +wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45628 + WMI_LQ_THRESHOLD_EVENT *reply;
45630 + if (len < sizeof(*reply)) {
45633 + reply = (WMI_LQ_THRESHOLD_EVENT *)datap;
45634 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45636 + A_WMI_LQ_THRESHOLD_EVENT_RX(wmip->wmi_devt, reply->range, reply->lq);
45642 +wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45644 + A_UINT16 ap_info_entry_size;
45645 + WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
45646 + WMI_AP_INFO_V1 *ap_info_v1;
45649 + if (len < sizeof(WMI_APLIST_EVENT)) {
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;
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))
45668 + * AP List Ver1 Contents
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));
45683 +wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45685 + A_UINT32 dropped;
45687 + dropped = *((A_UINT32 *)datap);
45688 + datap += sizeof(dropped);
45689 + len -= sizeof(dropped);
45690 + A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, datap, len);
45694 +#ifdef CONFIG_HOST_GPIO_SUPPORT
45696 +wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45698 + WMIX_GPIO_INTR_EVENT *gpio_intr = (WMIX_GPIO_INTR_EVENT *)datap;
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));
45704 + A_WMI_GPIO_INTR_RX(gpio_intr->intr_mask, gpio_intr->input_values);
45710 +wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45712 + WMIX_GPIO_DATA_EVENT *gpio_data = (WMIX_GPIO_DATA_EVENT *)datap;
45714 + A_DPRINTF(DBG_WMI,
45715 + (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG,
45716 + gpio_data->reg_id, gpio_data->value));
45718 + A_WMI_GPIO_DATA_RX(gpio_data->reg_id, gpio_data->value);
45724 +wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
45726 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
45728 + A_WMI_GPIO_ACK_RX();
45732 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
45735 + * Called to send a wmi command. Command specific data is already built
45736 + * on osbuf and current osbuf->data points to it.
45739 +wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
45740 + WMI_SYNC_FLAG syncflag)
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;
45746 + A_ASSERT(osbuf != NULL);
45748 + if (syncflag >= END_WMIFLAG) {
45752 + if ((syncflag == SYNC_BEFORE_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
45754 + * We want to make sure all data currently queued is transmitted before
45755 + * the cmd execution. Establish a new sync point.
45757 + wmi_sync_point(wmip);
45760 + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
45761 + return A_NO_MEMORY;
45764 + cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
45765 + cHdr->commandId = cmdId;
45768 + * Send cmd, some via control pipe, others via data pipe
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;
45775 + A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID);
45777 + if ((syncflag == SYNC_AFTER_WMIFLAG) || (syncflag == SYNC_BOTH_WMIFLAG)) {
45779 + * We want to make sure all new data queued waits for the command to
45780 + * execute. Establish a new sync point.
45782 + wmi_sync_point(wmip);
45785 +#undef IS_LONG_CMD
45789 +wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
45790 + WMI_SYNC_FLAG syncflag)
45792 + WMIX_CMD_HDR *cHdr;
45794 + if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {
45795 + return A_NO_MEMORY;
45798 + cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
45799 + cHdr->commandId = cmdId;
45801 + return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
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)
45813 + WMI_CONNECT_CMD *cc;
45815 + if ((pairwiseCrypto == NONE_CRYPT) && (groupCrypto != NONE_CRYPT)) {
45818 + if ((pairwiseCrypto != NONE_CRYPT) && (groupCrypto == NONE_CRYPT)) {
45822 + osbuf = A_NETBUF_ALLOC(sizeof(WMI_CONNECT_CMD));
45823 + if (osbuf == NULL) {
45824 + return A_NO_MEMORY;
45827 + A_NETBUF_PUT(osbuf, sizeof(WMI_CONNECT_CMD));
45829 + cc = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
45830 + A_MEMZERO(cc, sizeof(*cc));
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;
45844 + if (bssid != NULL) {
45845 + A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
45847 + if (wmi_set_keepalive_cmd(wmip, wmip->wmi_keepaliveInterval) != A_OK) {
45851 + return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
45855 +wmi_reconnect_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT16 channel)
45858 + WMI_RECONNECT_CMD *cc;
45860 + osbuf = A_NETBUF_ALLOC(sizeof(WMI_RECONNECT_CMD));
45861 + if (osbuf == NULL) {
45862 + return A_NO_MEMORY;
45865 + A_NETBUF_PUT(osbuf, sizeof(WMI_RECONNECT_CMD));
45867 + cc = (WMI_RECONNECT_CMD *)(A_NETBUF_DATA(osbuf));
45868 + A_MEMZERO(cc, sizeof(*cc));
45870 + cc->channel = channel;
45872 + if (bssid != NULL) {
45873 + A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
45876 + return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
45880 +wmi_disconnect_cmd(struct wmi_t *wmip)
45885 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
45886 + if (osbuf == NULL) {
45887 + return A_NO_MEMORY;
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));
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)
45904 + WMI_START_SCAN_CMD *sc;
45906 + if ((scanType != WMI_LONG_SCAN) && (scanType != WMI_SHORT_SCAN)) {
45910 + osbuf = A_NETBUF_ALLOC(sizeof(*sc));
45911 + if (osbuf == NULL) {
45912 + return A_NO_MEMORY;
45915 + A_NETBUF_PUT(osbuf, sizeof(*sc));
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;
45924 + return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
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)
45936 + WMI_SCAN_PARAMS_CMD *sc;
45938 + osbuf = A_NETBUF_ALLOC(sizeof(*sc));
45939 + if (osbuf == NULL) {
45940 + return A_NO_MEMORY;
45943 + A_NETBUF_PUT(osbuf, sizeof(*sc));
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;
45957 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_SCAN_PARAMS_CMDID,
45958 + NO_SYNC_WMIFLAG));
45962 +wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask)
45965 + WMI_BSS_FILTER_CMD *cmd;
45967 + if (filter >= LAST_BSS_FILTER) {
45971 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
45972 + if (osbuf == NULL) {
45973 + return A_NO_MEMORY;
45976 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
45978 + cmd = (WMI_BSS_FILTER_CMD *)(A_NETBUF_DATA(osbuf));
45979 + A_MEMZERO(cmd, sizeof(*cmd));
45980 + cmd->bssFilter = filter;
45981 + cmd->ieMask = ieMask;
45983 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BSS_FILTER_CMDID,
45984 + NO_SYNC_WMIFLAG));
45988 +wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
45989 + A_UINT8 ssidLength, A_UCHAR *ssid)
45992 + WMI_PROBED_SSID_CMD *cmd;
45994 + if (index > MAX_PROBED_SSID_INDEX) {
45997 + if (ssidLength > sizeof(cmd->ssid)) {
46000 + if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssidLength > 0)) {
46003 + if ((flag & SPECIFIC_SSID_FLAG) && !ssidLength) {
46007 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46008 + if (osbuf == NULL) {
46009 + return A_NO_MEMORY;
46012 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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);
46021 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
46022 + NO_SYNC_WMIFLAG));
46026 +wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons)
46029 + WMI_LISTEN_INT_CMD *cmd;
46031 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46032 + if (osbuf == NULL) {
46033 + return A_NO_MEMORY;
46036 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46038 + cmd = (WMI_LISTEN_INT_CMD *)(A_NETBUF_DATA(osbuf));
46039 + A_MEMZERO(cmd, sizeof(*cmd));
46040 + cmd->listenInterval = listenInterval;
46041 + cmd->numBeacons = listenBeacons;
46043 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LISTEN_INT_CMDID,
46044 + NO_SYNC_WMIFLAG));
46048 +wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmissTime, A_UINT16 bmissBeacons)
46051 + WMI_BMISS_TIME_CMD *cmd;
46053 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46054 + if (osbuf == NULL) {
46055 + return A_NO_MEMORY;
46058 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46060 + cmd = (WMI_BMISS_TIME_CMD *)(A_NETBUF_DATA(osbuf));
46061 + A_MEMZERO(cmd, sizeof(*cmd));
46062 + cmd->bmissTime = bmissTime;
46063 + cmd->numBeacons = bmissBeacons;
46065 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BMISS_TIME_CMDID,
46066 + NO_SYNC_WMIFLAG));
46070 +wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
46071 + A_UINT8 ieLen, A_UINT8 *ieInfo)
46074 + WMI_SET_ASSOC_INFO_CMD *cmd;
46077 + cmdLen = sizeof(*cmd) + ieLen - 1;
46078 + osbuf = A_NETBUF_ALLOC(cmdLen);
46079 + if (osbuf == NULL) {
46080 + return A_NO_MEMORY;
46083 + A_NETBUF_PUT(osbuf, cmdLen);
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);
46091 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
46092 + NO_SYNC_WMIFLAG));
46096 +wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode)
46099 + WMI_POWER_MODE_CMD *cmd;
46101 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46102 + if (osbuf == NULL) {
46103 + return A_NO_MEMORY;
46106 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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;
46113 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_MODE_CMDID,
46114 + NO_SYNC_WMIFLAG));
46118 +wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
46119 + A_UINT16 atim_windows, A_UINT16 timeout_value)
46122 + WMI_IBSS_PM_CAPS_CMD *cmd;
46124 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46125 + if (osbuf == NULL) {
46126 + return A_NO_MEMORY;
46129 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46131 + cmd = (WMI_IBSS_PM_CAPS_CMD *)(A_NETBUF_DATA(osbuf));
46132 + A_MEMZERO(cmd, sizeof(*cmd));
46133 + cmd->power_saving = pmEnable;
46135 + cmd->atim_windows = atim_windows;
46136 + cmd->timeout_value = timeout_value;
46138 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_IBSS_PM_CAPS_CMDID,
46139 + NO_SYNC_WMIFLAG));
46143 +wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
46144 + A_UINT16 psPollNum, A_UINT16 dtimPolicy)
46147 + WMI_POWER_PARAMS_CMD *pm;
46149 + osbuf = A_NETBUF_ALLOC(sizeof(*pm));
46150 + if (osbuf == NULL) {
46151 + return A_NO_MEMORY;
46154 + A_NETBUF_PUT(osbuf, sizeof(*pm));
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;
46162 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWER_PARAMS_CMDID,
46163 + NO_SYNC_WMIFLAG));
46167 +wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout)
46170 + WMI_DISC_TIMEOUT_CMD *cmd;
46172 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46173 + if (osbuf == NULL) {
46174 + return A_NO_MEMORY;
46177 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46179 + cmd = (WMI_DISC_TIMEOUT_CMD *)(A_NETBUF_DATA(osbuf));
46180 + A_MEMZERO(cmd, sizeof(*cmd));
46181 + cmd->disconnectTimeout = timeout;
46183 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_DISC_TIMEOUT_CMDID,
46184 + NO_SYNC_WMIFLAG));
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)
46194 + WMI_ADD_CIPHER_KEY_CMD *cmd;
46196 + if ((keyIndex > WMI_MAX_KEY_INDEX) || (keyLength > WMI_MAX_KEY_LEN) ||
46197 + (keyMaterial == NULL))
46202 + if ((WEP_CRYPT != keyType) && (NULL == keyRSC)) {
46206 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46207 + if (osbuf == NULL) {
46208 + return A_NO_MEMORY;
46211 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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));
46223 + cmd->key_op_ctrl = key_op_ctrl;
46225 + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
46229 +wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk)
46232 + WMI_ADD_KRK_CMD *cmd;
46234 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46236 + if (osbuf == NULL) {
46237 + return A_NO_MEMORY;
46240 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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);
46246 + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
46250 +wmi_delete_krk_cmd(struct wmi_t *wmip)
46254 + osbuf = A_NETBUF_ALLOC(0);
46256 + if (osbuf == NULL) {
46257 + return A_NO_MEMORY;
46260 + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_KRK_CMDID, NO_SYNC_WMIFLAG));
46264 +wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex)
46267 + WMI_DELETE_CIPHER_KEY_CMD *cmd;
46269 + if (keyIndex > WMI_MAX_KEY_INDEX) {
46273 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46274 + if (osbuf == NULL) {
46275 + return A_NO_MEMORY;
46278 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46280 + cmd = (WMI_DELETE_CIPHER_KEY_CMD *)(A_NETBUF_DATA(osbuf));
46281 + A_MEMZERO(cmd, sizeof(*cmd));
46282 + cmd->keyIndex = keyIndex;
46284 + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_CIPHER_KEY_CMDID,
46285 + NO_SYNC_WMIFLAG));
46289 +wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
46293 + WMI_SET_PMKID_CMD *cmd;
46295 + if (bssid == NULL) {
46299 + if ((set == TRUE) && (pmkId == NULL)) {
46303 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46304 + if (osbuf == NULL) {
46305 + return A_NO_MEMORY;
46308 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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;
46316 + A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
46317 + cmd->enable = PMKID_DISABLE;
46320 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
46324 +wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en)
46327 + WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
46329 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46330 + if (osbuf == NULL) {
46331 + return A_NO_MEMORY;
46334 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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;
46339 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
46340 + NO_SYNC_WMIFLAG));
46344 +wmi_set_akmp_params_cmd(struct wmi_t *wmip,
46345 + WMI_SET_AKMP_PARAMS_CMD *akmpParams)
46348 + WMI_SET_AKMP_PARAMS_CMD *cmd;
46350 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46351 + if (osbuf == NULL) {
46352 + return A_NO_MEMORY;
46355 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46356 + cmd = (WMI_SET_AKMP_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
46357 + cmd->akmpInfo = akmpParams->akmpInfo;
46359 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AKMP_PARAMS_CMDID,
46360 + NO_SYNC_WMIFLAG));
46364 +wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
46365 + WMI_SET_PMKID_LIST_CMD *pmkInfo)
46368 + WMI_SET_PMKID_LIST_CMD *cmd;
46372 + cmdLen = sizeof(pmkInfo->numPMKID) +
46373 + pmkInfo->numPMKID * sizeof(WMI_PMKID);
46375 + osbuf = A_NETBUF_ALLOC(cmdLen);
46377 + if (osbuf == NULL) {
46378 + return A_NO_MEMORY;
46381 + A_NETBUF_PUT(osbuf, cmdLen);
46382 + cmd = (WMI_SET_PMKID_LIST_CMD *)(A_NETBUF_DATA(osbuf));
46383 + cmd->numPMKID = pmkInfo->numPMKID;
46385 + for (i = 0; i < cmd->numPMKID; i++) {
46386 + A_MEMCPY(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
46390 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_LIST_CMDID,
46391 + NO_SYNC_WMIFLAG));
46395 +wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
46399 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
46400 + if (osbuf == NULL) {
46401 + return A_NO_MEMORY;
46404 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_PMKID_LIST_CMDID,
46405 + NO_SYNC_WMIFLAG));
46409 +wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, WMI_PRI_STREAM_ID streamID)
46411 + WMI_DATA_HDR *dtHdr;
46413 + A_ASSERT(streamID != WMI_CONTROL_PRI);
46414 + A_ASSERT(osbuf != NULL);
46416 + if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
46417 + return A_NO_MEMORY;
46420 + dtHdr = (WMI_DATA_HDR *)A_NETBUF_DATA(osbuf);
46422 + (SYNC_MSGTYPE & WMI_DATA_HDR_MSG_TYPE_MASK) << WMI_DATA_HDR_MSG_TYPE_SHIFT;
46424 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - streamID %d\n", DBGARG, streamID));
46426 + return (A_WMI_CONTROL_TX(wmip->wmi_devt, osbuf, streamID));
46429 +typedef struct _WMI_DATA_SYNC_BUFS {
46430 + A_UINT8 trafficClass;
46432 +}WMI_DATA_SYNC_BUFS;
46435 +wmi_sync_point(struct wmi_t *wmip)
46438 + WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
46439 + A_UINT8 i,numPriStreams=0;
46442 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
46444 + memset(dataSyncBufs,0,sizeof(dataSyncBufs));
46446 + /* lock out while we walk through the priority list and assemble our local array */
46449 + for (i=0; i < WMM_NUM_AC ; i++) {
46450 + if (wmip->wmi_fatPipeExists & (1 << i)) {
46452 + dataSyncBufs[numPriStreams-1].trafficClass = i;
46456 + UNLOCK_WMI(wmip);
46458 + /* dataSyncBufs is now filled with entries (starting at index 0) containing valid streamIDs */
46462 + * We allocate all network buffers needed so we will be able to
46463 + * send all required frames.
46465 + cmd_osbuf = A_NETBUF_ALLOC(0); /* no payload */
46466 + if (cmd_osbuf == NULL) {
46467 + status = A_NO_MEMORY;
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;
46480 + * Send sync cmd followed by sync data messages on all endpoints being
46483 + status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
46484 + NO_SYNC_WMIFLAG);
46486 + if (A_FAILED(status)) {
46489 + /* cmd buffer sent, we no longer own it */
46490 + cmd_osbuf = NULL;
46492 + for(i=0; i < numPriStreams; i++) {
46493 + A_ASSERT(dataSyncBufs[i].osbuf != NULL);
46495 + status = wmi_dataSync_send(wmip, dataSyncBufs[i].osbuf,
46496 + WMI_ACCESSCATEGORY_WMISTREAM(wmip,dataSyncBufs[i].trafficClass));
46498 + if (A_FAILED(status)) {
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;
46508 + /* free up any resources left over (possibly due to an error) */
46510 + if (cmd_osbuf != NULL) {
46511 + A_NETBUF_FREE(cmd_osbuf);
46514 + for (i = 0; i < numPriStreams; i++) {
46515 + if (dataSyncBufs[i].osbuf != NULL) {
46516 + A_NETBUF_FREE(dataSyncBufs[i].osbuf);
46524 +wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
46527 + WMI_CREATE_PSTREAM_CMD *cmd;
46528 + A_UINT16 activeTsids=0;
46529 + A_UINT8 fatPipeExistsForAC=0;
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)) )
46548 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46549 + if (osbuf == NULL) {
46550 + return A_NO_MEMORY;
46553 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46555 + A_DPRINTF(DBG_WMI,
46556 + (DBGFMT "Sending create_pstream_cmd: ac=%d tsid:%d\n", DBGARG,
46557 + params->trafficClass, params->tsid));
46559 + cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
46560 + A_MEMZERO(cmd, sizeof(*cmd));
46561 + A_MEMCPY(cmd, params, sizeof(*cmd));
46563 + /* this is an implicitly created Fat pipe */
46564 + if (params->tsid == WMI_IMPLICIT_PSTREAM) {
46566 + fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
46567 + wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
46568 + UNLOCK_WMI(wmip);
46570 + /* this is an explicitly created thin stream within a fat pipe */
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
46578 + wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
46579 + UNLOCK_WMI(wmip);
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.
46586 + if (!fatPipeExistsForAC) {
46587 + A_WMI_STREAM_TX_ACTIVE(wmip->wmi_devt, params->trafficClass);
46590 + /* mike: should be SYNC_BEFORE_WMIFLAG */
46591 + return (wmi_cmd_send(wmip, osbuf, WMI_CREATE_PSTREAM_CMDID,
46592 + NO_SYNC_WMIFLAG));
46596 +wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 tsid)
46599 + WMI_DELETE_PSTREAM_CMD *cmd;
46601 + A_UINT16 activeTsids=0;
46603 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46604 + if (osbuf == NULL) {
46605 + return A_NO_MEMORY;
46608 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46610 + cmd = (WMI_DELETE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
46611 + A_MEMZERO(cmd, sizeof(*cmd));
46613 + cmd->trafficClass = trafficClass;
46614 + cmd->tsid = tsid;
46617 + activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
46618 + UNLOCK_WMI(wmip);
46620 + /* Check if the tsid was created & exists */
46621 + if (!(activeTsids & (1<<tsid))) {
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 */
46629 + A_DPRINTF(DBG_WMI,
46630 + (DBGFMT "Sending delete_pstream_cmd: trafficClass: %d tsid=%d\n", DBGARG, trafficClass, tsid));
46632 + status = (wmi_cmd_send(wmip, osbuf, WMI_DELETE_PSTREAM_CMDID,
46633 + SYNC_BEFORE_WMIFLAG));
46636 + wmip->wmi_streamExistsForAC[trafficClass] &= ~(1<<tsid);
46637 + activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
46638 + UNLOCK_WMI(wmip);
46641 + /* Indicate stream inactivity to driver layer only if all tsids
46642 + * within this AC are deleted.
46644 + if(!activeTsids) {
46645 + A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, trafficClass);
46646 + wmip->wmi_fatPipeExists &= ~(1<<trafficClass);
46653 + * used to set the bit rate. rate is in Kbps. If rate == -1
46654 + * then auto selection is used.
46657 +wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 rate)
46660 + WMI_BIT_RATE_CMD *cmd;
46663 + if (rate != -1) {
46664 + index = wmi_validate_bitrate(wmip, rate);
46665 + if(index == A_EINVAL){
46672 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46673 + if (osbuf == NULL) {
46674 + return A_NO_MEMORY;
46677 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46679 + cmd = (WMI_BIT_RATE_CMD *)(A_NETBUF_DATA(osbuf));
46680 + A_MEMZERO(cmd, sizeof(*cmd));
46682 + cmd->rateIndex = index;
46684 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
46688 +wmi_get_bitrate_cmd(struct wmi_t *wmip)
46692 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
46693 + if (osbuf == NULL) {
46694 + return A_NO_MEMORY;
46697 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
46701 + * Returns TRUE iff the given rate index is legal in the current PHY mode.
46704 +wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_UINT32 rateIndex)
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)) {
46715 + case WMI_11B_MODE:
46716 + if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
46721 + case WMI_11GONLY_MODE:
46722 + if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
46727 + case WMI_11G_MODE:
46728 + case WMI_11AG_MODE:
46729 + if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
46743 +wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate)
46750 + if (wmi_rateTable[(A_UINT32) i] == 0) {
46753 + if (wmi_rateTable[(A_UINT32) i] == rate) {
46762 + if(wmi_is_bitrate_index_valid(wmip, i) != TRUE) {
46770 +wmi_set_fixrates_cmd(struct wmi_t *wmip, A_INT16 fixRatesMask)
46773 + WMI_FIX_RATES_CMD *cmd;
46774 + A_UINT32 rateIndex;
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));
46787 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
46788 + if (osbuf == NULL) {
46789 + return A_NO_MEMORY;
46792 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
46794 + cmd = (WMI_FIX_RATES_CMD *)(A_NETBUF_DATA(osbuf));
46795 + A_MEMZERO(cmd, sizeof(*cmd));
46797 + cmd->fixRateMask = fixRatesMask;
46799 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
46803 +wmi_get_ratemask_cmd(struct wmi_t *wmip)
46807 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
46808 + if (osbuf == NULL) {
46809 + return A_NO_MEMORY;
46812 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
46816 +wmi_get_channelList_cmd(struct wmi_t *wmip)
46820 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
46821 + if (osbuf == NULL) {
46822 + return A_NO_MEMORY;
46825 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_CHANNEL_LIST_CMDID,
46826 + NO_SYNC_WMIFLAG));
46830 + * used to generate a wmi sey channel Parameters cmd.
46831 + * mode should always be specified and corresponds to the phy mode of the
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.
46840 +wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
46841 + WMI_PHY_MODE mode, A_INT8 numChan,
46842 + A_UINT16 *channelList)
46845 + WMI_CHANNEL_PARAMS_CMD *cmd;
46848 + size = sizeof (*cmd);
46851 + if (numChan > WMI_MAX_CHANNELS) {
46854 + size += sizeof(A_UINT16) * (numChan - 1);
46857 + osbuf = A_NETBUF_ALLOC(size);
46858 + if (osbuf == NULL) {
46859 + return A_NO_MEMORY;
46862 + A_NETBUF_PUT(osbuf, size);
46864 + cmd = (WMI_CHANNEL_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
46865 + A_MEMZERO(cmd, size);
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));
46873 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
46874 + NO_SYNC_WMIFLAG));
46878 +wmi_set_rssi_threshold_params(struct wmi_t *wmip,
46879 + WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
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) {
46899 + size = sizeof (*cmd);
46901 + osbuf = A_NETBUF_ALLOC(size);
46902 + if (osbuf == NULL) {
46903 + return A_NO_MEMORY;
46906 + A_NETBUF_PUT(osbuf, size);
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));
46912 + return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
46913 + NO_SYNC_WMIFLAG));
46917 +wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
46918 + WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
46922 + WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
46924 + if( hostModeCmd->awake == hostModeCmd->asleep) {
46928 + size = sizeof (*cmd);
46930 + osbuf = A_NETBUF_ALLOC(size);
46931 + if (osbuf == NULL) {
46932 + return A_NO_MEMORY;
46935 + A_NETBUF_PUT(osbuf, size);
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));
46941 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_HOST_SLEEP_MODE_CMDID,
46942 + NO_SYNC_WMIFLAG));
46946 +wmi_set_wow_mode_cmd(struct wmi_t *wmip,
46947 + WMI_SET_WOW_MODE_CMD *wowModeCmd)
46951 + WMI_SET_WOW_MODE_CMD *cmd;
46953 + size = sizeof (*cmd);
46955 + osbuf = A_NETBUF_ALLOC(size);
46956 + if (osbuf == NULL) {
46957 + return A_NO_MEMORY;
46960 + A_NETBUF_PUT(osbuf, size);
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));
46966 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
46967 + NO_SYNC_WMIFLAG));
46972 +wmi_get_wow_list_cmd(struct wmi_t *wmip,
46973 + WMI_GET_WOW_LIST_CMD *wowListCmd)
46977 + WMI_GET_WOW_LIST_CMD *cmd;
46979 + size = sizeof (*cmd);
46981 + osbuf = A_NETBUF_ALLOC(size);
46982 + if (osbuf == NULL) {
46983 + return A_NO_MEMORY;
46986 + A_NETBUF_PUT(osbuf, size);
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));
46992 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
46993 + NO_SYNC_WMIFLAG));
46998 +wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
47000 + WMI_GET_WOW_LIST_REPLY *reply;
47002 + if (len < sizeof(WMI_GET_WOW_LIST_REPLY)) {
47005 + reply = (WMI_GET_WOW_LIST_REPLY *)datap;
47007 + A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
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)
47020 + WMI_ADD_WOW_PATTERN_CMD *cmd;
47021 + A_UINT8 *filter_mask = NULL;
47023 + size = sizeof (*cmd);
47025 + size += ((2 * addWowCmd->filter_size)* sizeof(A_UINT8));
47026 + osbuf = A_NETBUF_ALLOC(size);
47027 + if (osbuf == NULL) {
47028 + return A_NO_MEMORY;
47031 + A_NETBUF_PUT(osbuf, size);
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;
47038 + A_MEMCPY(cmd->filter, pattern, addWowCmd->filter_size);
47040 + filter_mask = (A_UINT8*)(cmd->filter + cmd->filter_size);
47041 + A_MEMCPY(filter_mask, mask, addWowCmd->filter_size);
47044 + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
47045 + NO_SYNC_WMIFLAG));
47049 +wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
47050 + WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
47054 + WMI_DEL_WOW_PATTERN_CMD *cmd;
47056 + size = sizeof (*cmd);
47058 + osbuf = A_NETBUF_ALLOC(size);
47059 + if (osbuf == NULL) {
47060 + return A_NO_MEMORY;
47063 + A_NETBUF_PUT(osbuf, size);
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));
47069 + return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
47070 + NO_SYNC_WMIFLAG));
47075 +wmi_set_snr_threshold_params(struct wmi_t *wmip,
47076 + WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
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) {
47092 + size = sizeof (*cmd);
47094 + osbuf = A_NETBUF_ALLOC(size);
47095 + if (osbuf == NULL) {
47096 + return A_NO_MEMORY;
47099 + A_NETBUF_PUT(osbuf, size);
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));
47105 + return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
47106 + NO_SYNC_WMIFLAG));
47110 +wmi_clr_rssi_snr(struct wmi_t *wmip)
47114 + osbuf = A_NETBUF_ALLOC(sizeof(int));
47115 + if (osbuf == NULL) {
47116 + return A_NO_MEMORY;
47119 + return (wmi_cmd_send(wmip, osbuf, WMI_CLR_RSSI_SNR_CMDID,
47120 + NO_SYNC_WMIFLAG));
47124 +wmi_set_lq_threshold_params(struct wmi_t *wmip,
47125 + WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
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 ) {
47141 + size = sizeof (*cmd);
47143 + osbuf = A_NETBUF_ALLOC(size);
47144 + if (osbuf == NULL) {
47145 + return A_NO_MEMORY;
47148 + A_NETBUF_PUT(osbuf, size);
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));
47154 + return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
47155 + NO_SYNC_WMIFLAG));
47159 +wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 mask)
47163 + WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
47165 + size = sizeof (*cmd);
47167 + osbuf = A_NETBUF_ALLOC(size);
47168 + if (osbuf == NULL) {
47169 + return A_NO_MEMORY;
47172 + A_NETBUF_PUT(osbuf, size);
47174 + cmd = (WMI_TARGET_ERROR_REPORT_BITMASK *)(A_NETBUF_DATA(osbuf));
47175 + A_MEMZERO(cmd, size);
47177 + cmd->bitmask = mask;
47179 + return (wmi_cmd_send(wmip, osbuf, WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
47180 + NO_SYNC_WMIFLAG));
47184 +wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie, A_UINT32 source)
47187 + WMIX_HB_CHALLENGE_RESP_CMD *cmd;
47189 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47190 + if (osbuf == NULL) {
47191 + return A_NO_MEMORY;
47194 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47196 + cmd = (WMIX_HB_CHALLENGE_RESP_CMD *)(A_NETBUF_DATA(osbuf));
47197 + cmd->cookie = cookie;
47198 + cmd->source = source;
47200 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_HB_CHALLENGE_RESP_CMDID,
47201 + NO_SYNC_WMIFLAG));
47205 +wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
47206 + A_UINT16 tsr, A_BOOL rep, A_UINT16 size,
47210 + WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
47212 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47213 + if (osbuf == NULL) {
47214 + return A_NO_MEMORY;
47217 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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;
47226 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DBGLOG_CFG_MODULE_CMDID,
47227 + NO_SYNC_WMIFLAG));
47231 +wmi_get_stats_cmd(struct wmi_t *wmip)
47235 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
47236 + if (osbuf == NULL) {
47237 + return A_NO_MEMORY;
47240 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_STATISTICS_CMDID,
47241 + NO_SYNC_WMIFLAG));
47245 +wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid)
47248 + WMI_ADD_BAD_AP_CMD *cmd;
47250 + if ((bssid == NULL) || (apIndex > WMI_MAX_BAD_AP_INDEX)) {
47254 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47255 + if (osbuf == NULL) {
47256 + return A_NO_MEMORY;
47259 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47261 + cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
47262 + cmd->badApIndex = apIndex;
47263 + A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
47265 + return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, NO_SYNC_WMIFLAG));
47269 +wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex)
47272 + WMI_DELETE_BAD_AP_CMD *cmd;
47274 + if (apIndex > WMI_MAX_BAD_AP_INDEX) {
47278 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47279 + if (osbuf == NULL) {
47280 + return A_NO_MEMORY;
47283 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47285 + cmd = (WMI_DELETE_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
47286 + cmd->badApIndex = apIndex;
47288 + return (wmi_cmd_send(wmip, osbuf, WMI_DELETE_BAD_AP_CMDID,
47289 + NO_SYNC_WMIFLAG));
47293 +wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM)
47296 + WMI_SET_TX_PWR_CMD *cmd;
47298 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47299 + if (osbuf == NULL) {
47300 + return A_NO_MEMORY;
47303 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47305 + cmd = (WMI_SET_TX_PWR_CMD *)(A_NETBUF_DATA(osbuf));
47308 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
47312 +wmi_get_txPwr_cmd(struct wmi_t *wmip)
47316 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
47317 + if (osbuf == NULL) {
47318 + return A_NO_MEMORY;
47321 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
47325 +wmi_switch_radio(struct wmi_t *wmip, A_UINT8 on)
47327 + WMI_SCAN_PARAMS_CMD scParams = {0, 0, 0, 0, 0,
47328 + WMI_SHORTSCANRATIO_DEFAULT,
47329 + DEFAULT_SCAN_CTRL_FLAGS,
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) {
47346 + wmi_disconnect_cmd(wmip);
47347 + if (wmi_scanparams_cmd(wmip, 0xFFFF, 0, 0, 0,
47348 + 0, 0, 0, 0xFF, 0) != A_OK) {
47358 +wmi_get_mapped_qos_queue(struct wmi_t *wmip, A_UINT8 trafficClass)
47360 + A_UINT16 activeTsids=0;
47363 + activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
47364 + UNLOCK_WMI(wmip);
47366 + return activeTsids;
47370 +wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
47374 + osbuf = A_NETBUF_ALLOC(0); /* no payload */
47375 + if (osbuf == NULL) {
47376 + return A_NO_MEMORY;
47379 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_TBL_CMDID,
47380 + NO_SYNC_WMIFLAG));
47384 +wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType)
47387 + A_UINT32 size = sizeof(A_UINT8);
47388 + WMI_TARGET_ROAM_DATA *cmd;
47390 + osbuf = A_NETBUF_ALLOC(size); /* no payload */
47391 + if (osbuf == NULL) {
47392 + return A_NO_MEMORY;
47395 + A_NETBUF_PUT(osbuf, size);
47397 + cmd = (WMI_TARGET_ROAM_DATA *)(A_NETBUF_DATA(osbuf));
47398 + cmd->roamDataType = roamDataType;
47400 + return (wmi_cmd_send(wmip, osbuf, WMI_GET_ROAM_DATA_CMDID,
47401 + NO_SYNC_WMIFLAG));
47405 +wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
47409 + WMI_SET_ROAM_CTRL_CMD *cmd;
47411 + osbuf = A_NETBUF_ALLOC(size);
47412 + if (osbuf == NULL) {
47413 + return A_NO_MEMORY;
47416 + A_NETBUF_PUT(osbuf, size);
47418 + cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
47419 + A_MEMZERO(cmd, size);
47421 + A_MEMCPY(cmd, p, size);
47423 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
47424 + NO_SYNC_WMIFLAG));
47428 +wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
47429 + WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
47433 + WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
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))
47443 + osbuf = A_NETBUF_ALLOC(size);
47444 + if (osbuf == NULL) {
47445 + return A_NO_MEMORY;
47448 + A_NETBUF_PUT(osbuf, size);
47450 + cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
47451 + A_MEMZERO(cmd, size);
47453 + A_MEMCPY(cmd, pCmd, size);
47455 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
47456 + NO_SYNC_WMIFLAG));
47459 +#ifdef CONFIG_HOST_GPIO_SUPPORT
47460 +/* Send a command to Target to change GPIO output pins. */
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)
47469 + WMIX_GPIO_OUTPUT_SET_CMD *output_set;
47472 + size = sizeof(*output_set);
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));
47478 + osbuf = A_NETBUF_ALLOC(size);
47479 + if (osbuf == NULL) {
47480 + return A_NO_MEMORY;
47482 + A_NETBUF_PUT(osbuf, size);
47483 + output_set = (WMIX_GPIO_OUTPUT_SET_CMD *)(A_NETBUF_DATA(osbuf));
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;
47490 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_OUTPUT_SET_CMDID,
47491 + NO_SYNC_WMIFLAG));
47494 +/* Send a command to the Target requesting state of the GPIO input pins */
47496 +wmi_gpio_input_get(struct wmi_t *wmip)
47500 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
47502 + osbuf = A_NETBUF_ALLOC(0);
47503 + if (osbuf == NULL) {
47504 + return A_NO_MEMORY;
47507 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INPUT_GET_CMDID,
47508 + NO_SYNC_WMIFLAG));
47511 +/* Send a command to the Target that changes the value of a GPIO register. */
47513 +wmi_gpio_register_set(struct wmi_t *wmip,
47514 + A_UINT32 gpioreg_id,
47518 + WMIX_GPIO_REGISTER_SET_CMD *register_set;
47521 + size = sizeof(*register_set);
47523 + A_DPRINTF(DBG_WMI,
47524 + (DBGFMT "Enter - reg=%d value=0x%x\n", DBGARG, gpioreg_id, value));
47526 + osbuf = A_NETBUF_ALLOC(size);
47527 + if (osbuf == NULL) {
47528 + return A_NO_MEMORY;
47530 + A_NETBUF_PUT(osbuf, size);
47531 + register_set = (WMIX_GPIO_REGISTER_SET_CMD *)(A_NETBUF_DATA(osbuf));
47533 + register_set->gpioreg_id = gpioreg_id;
47534 + register_set->value = value;
47536 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_SET_CMDID,
47537 + NO_SYNC_WMIFLAG));
47540 +/* Send a command to the Target to fetch the value of a GPIO register. */
47542 +wmi_gpio_register_get(struct wmi_t *wmip,
47543 + A_UINT32 gpioreg_id)
47546 + WMIX_GPIO_REGISTER_GET_CMD *register_get;
47549 + size = sizeof(*register_get);
47551 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - reg=%d\n", DBGARG, gpioreg_id));
47553 + osbuf = A_NETBUF_ALLOC(size);
47554 + if (osbuf == NULL) {
47555 + return A_NO_MEMORY;
47557 + A_NETBUF_PUT(osbuf, size);
47558 + register_get = (WMIX_GPIO_REGISTER_GET_CMD *)(A_NETBUF_DATA(osbuf));
47560 + register_get->gpioreg_id = gpioreg_id;
47562 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_REGISTER_GET_CMDID,
47563 + NO_SYNC_WMIFLAG));
47566 +/* Send a command to the Target acknowledging some GPIO interrupts. */
47568 +wmi_gpio_intr_ack(struct wmi_t *wmip,
47569 + A_UINT32 ack_mask)
47572 + WMIX_GPIO_INTR_ACK_CMD *intr_ack;
47575 + size = sizeof(*intr_ack);
47577 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter ack_mask=0x%x\n", DBGARG, ack_mask));
47579 + osbuf = A_NETBUF_ALLOC(size);
47580 + if (osbuf == NULL) {
47581 + return A_NO_MEMORY;
47583 + A_NETBUF_PUT(osbuf, size);
47584 + intr_ack = (WMIX_GPIO_INTR_ACK_CMD *)(A_NETBUF_DATA(osbuf));
47586 + intr_ack->ack_mask = ack_mask;
47588 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_GPIO_INTR_ACK_CMDID,
47589 + NO_SYNC_WMIFLAG));
47591 +#endif /* CONFIG_HOST_GPIO_SUPPORT */
47594 +wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT16 txop, A_UINT8 eCWmin,
47595 + A_UINT8 eCWmax, A_UINT8 aifsn)
47598 + WMI_SET_ACCESS_PARAMS_CMD *cmd;
47600 + if ((eCWmin > WMI_MAX_CW_ACPARAM) || (eCWmax > WMI_MAX_CW_ACPARAM) ||
47601 + (aifsn > WMI_MAX_AIFSN_ACPARAM))
47606 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47607 + if (osbuf == NULL) {
47608 + return A_NO_MEMORY;
47611 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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;
47619 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_ACCESS_PARAMS_CMDID,
47620 + NO_SYNC_WMIFLAG));
47624 +wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
47625 + A_UINT8 trafficClass, A_UINT8 maxRetries,
47626 + A_UINT8 enableNotify)
47629 + WMI_SET_RETRY_LIMITS_CMD *cmd;
47631 + if ((frameType != MGMT_FRAMETYPE) && (frameType != CONTROL_FRAMETYPE) &&
47632 + (frameType != DATA_FRAMETYPE))
47637 + if (maxRetries > WMI_MAX_RETRIES) {
47641 + if (frameType != DATA_FRAMETYPE) {
47642 + trafficClass = 0;
47645 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47646 + if (osbuf == NULL) {
47647 + return A_NO_MEMORY;
47650 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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;
47658 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RETRY_LIMITS_CMDID,
47659 + NO_SYNC_WMIFLAG));
47663 +wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid)
47665 + if (bssid != NULL) {
47666 + A_MEMCPY(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
47671 +wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode)
47674 + WMI_SET_OPT_MODE_CMD *cmd;
47676 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47677 + if (osbuf == NULL) {
47678 + return A_NO_MEMORY;
47681 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47683 + cmd = (WMI_SET_OPT_MODE_CMD *)(A_NETBUF_DATA(osbuf));
47684 + A_MEMZERO(cmd, sizeof(*cmd));
47685 + cmd->optMode = optMode;
47687 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_OPT_MODE_CMDID,
47688 + SYNC_BOTH_WMIFLAG));
47692 +wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
47694 + A_UINT8 *dstMacAddr,
47696 + A_UINT16 optIEDataLen,
47697 + A_UINT8 *optIEData)
47700 + WMI_OPT_TX_FRAME_CMD *cmd;
47701 + osbuf = A_NETBUF_ALLOC(optIEDataLen + sizeof(*cmd));
47702 + if (osbuf == NULL) {
47703 + return A_NO_MEMORY;
47706 + A_NETBUF_PUT(osbuf, (optIEDataLen + sizeof(*cmd)));
47708 + cmd = (WMI_OPT_TX_FRAME_CMD *)(A_NETBUF_DATA(osbuf));
47709 + A_MEMZERO(cmd, (optIEDataLen + sizeof(*cmd)-1));
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);
47718 + return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
47719 + NO_SYNC_WMIFLAG));
47723 +wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl)
47726 + WMI_BEACON_INT_CMD *cmd;
47728 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47729 + if (osbuf == NULL) {
47730 + return A_NO_MEMORY;
47733 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47735 + cmd = (WMI_BEACON_INT_CMD *)(A_NETBUF_DATA(osbuf));
47736 + A_MEMZERO(cmd, sizeof(*cmd));
47737 + cmd->beaconInterval = intvl;
47739 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BEACON_INT_CMDID,
47740 + NO_SYNC_WMIFLAG));
47745 +wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize)
47748 + WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
47750 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47751 + if (osbuf == NULL) {
47752 + return A_NO_MEMORY;
47755 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47757 + cmd = (WMI_SET_VOICE_PKT_SIZE_CMD *)(A_NETBUF_DATA(osbuf));
47758 + A_MEMZERO(cmd, sizeof(*cmd));
47759 + cmd->voicePktSize = voicePktSize;
47761 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_VOICE_PKT_SIZE_CMDID,
47762 + NO_SYNC_WMIFLAG));
47767 +wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSPLen)
47770 + WMI_SET_MAX_SP_LEN_CMD *cmd;
47772 + /* maxSPLen is a two-bit value. If user trys to set anything
47773 + * other than this, then its invalid
47775 + if(maxSPLen & ~0x03)
47778 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47779 + if (osbuf == NULL) {
47780 + return A_NO_MEMORY;
47783 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47785 + cmd = (WMI_SET_MAX_SP_LEN_CMD *)(A_NETBUF_DATA(osbuf));
47786 + A_MEMZERO(cmd, sizeof(*cmd));
47787 + cmd->maxSPLen = maxSPLen;
47789 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_MAX_SP_LEN_CMDID,
47790 + NO_SYNC_WMIFLAG));
47794 +convert_userPriority_to_trafficClass(A_UINT8 userPriority)
47796 + return (up_to_ac[userPriority & 0x7]);
47800 +wmi_get_power_mode_cmd(struct wmi_t *wmip)
47802 + return wmip->wmi_powerMode;
47806 +wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance)
47811 +#ifdef CONFIG_HOST_TCMD_SUPPORT
47813 +wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
47816 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
47818 + A_WMI_TCMD_RX_REPORT_EVENT(wmip->wmi_devt, datap, len);
47823 +#endif /* CONFIG_HOST_TCMD_SUPPORT*/
47826 +wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
47829 + WMI_SET_AUTH_MODE_CMD *cmd;
47831 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47832 + if (osbuf == NULL) {
47833 + return A_NO_MEMORY;
47836 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47838 + cmd = (WMI_SET_AUTH_MODE_CMD *)(A_NETBUF_DATA(osbuf));
47839 + A_MEMZERO(cmd, sizeof(*cmd));
47840 + cmd->mode = mode;
47842 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_AUTH_MODE_CMDID,
47843 + NO_SYNC_WMIFLAG));
47847 +wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
47850 + WMI_SET_REASSOC_MODE_CMD *cmd;
47852 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47853 + if (osbuf == NULL) {
47854 + return A_NO_MEMORY;
47857 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47859 + cmd = (WMI_SET_REASSOC_MODE_CMD *)(A_NETBUF_DATA(osbuf));
47860 + A_MEMZERO(cmd, sizeof(*cmd));
47861 + cmd->mode = mode;
47863 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_REASSOC_MODE_CMDID,
47864 + NO_SYNC_WMIFLAG));
47868 +wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status)
47871 + WMI_SET_LPREAMBLE_CMD *cmd;
47873 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47874 + if (osbuf == NULL) {
47875 + return A_NO_MEMORY;
47878 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47880 + cmd = (WMI_SET_LPREAMBLE_CMD *)(A_NETBUF_DATA(osbuf));
47881 + A_MEMZERO(cmd, sizeof(*cmd));
47882 + cmd->status = status;
47884 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_LPREAMBLE_CMDID,
47885 + NO_SYNC_WMIFLAG));
47889 +wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold)
47892 + WMI_SET_RTS_CMD *cmd;
47894 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47895 + if (osbuf == NULL) {
47896 + return A_NO_MEMORY;
47899 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47901 + cmd = (WMI_SET_RTS_CMD*)(A_NETBUF_DATA(osbuf));
47902 + A_MEMZERO(cmd, sizeof(*cmd));
47903 + cmd->threshold = threshold;
47905 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_RTS_CMDID,
47906 + NO_SYNC_WMIFLAG));
47910 +wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
47913 + WMI_SET_WMM_CMD *cmd;
47915 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47916 + if (osbuf == NULL) {
47917 + return A_NO_MEMORY;
47920 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47922 + cmd = (WMI_SET_WMM_CMD*)(A_NETBUF_DATA(osbuf));
47923 + A_MEMZERO(cmd, sizeof(*cmd));
47924 + cmd->status = status;
47926 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_CMDID,
47927 + NO_SYNC_WMIFLAG));
47932 +wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
47935 + WMI_SET_WMM_TXOP_CMD *cmd;
47937 + if( !((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)) )
47940 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47941 + if (osbuf == NULL) {
47942 + return A_NO_MEMORY;
47945 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
47947 + cmd = (WMI_SET_WMM_TXOP_CMD *)(A_NETBUF_DATA(osbuf));
47948 + A_MEMZERO(cmd, sizeof(*cmd));
47949 + cmd->txopEnable = cfg;
47951 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WMM_TXOP_CMDID,
47952 + NO_SYNC_WMIFLAG));
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
47962 +wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32 len)
47967 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
47969 + osbuf= A_NETBUF_ALLOC(len);
47970 + if(osbuf == NULL)
47972 + return A_NO_MEMORY;
47974 + A_NETBUF_PUT(osbuf, len);
47975 + data = A_NETBUF_DATA(osbuf);
47976 + A_MEMCPY(data, buf, len);
47978 + return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
47979 + NO_SYNC_WMIFLAG));
47985 +wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status)
47988 + WMI_SET_BT_STATUS_CMD *cmd;
47990 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
47991 + if (osbuf == NULL) {
47992 + return A_NO_MEMORY;
47995 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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;
48002 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_STATUS_CMDID,
48003 + NO_SYNC_WMIFLAG));
48007 +wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
48010 + WMI_SET_BT_PARAMS_CMD* alloc_cmd;
48012 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
48013 + if (osbuf == NULL) {
48014 + return A_NO_MEMORY;
48017 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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));
48023 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
48024 + NO_SYNC_WMIFLAG));
48028 +wmi_get_keepalive_configured(struct wmi_t *wmip)
48031 + WMI_GET_KEEPALIVE_CMD *cmd;
48032 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
48033 + if (osbuf == NULL) {
48034 + return A_NO_MEMORY;
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));
48044 +wmi_get_keepalive_cmd(struct wmi_t *wmip)
48046 + return wmip->wmi_keepaliveInterval;
48050 +wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval)
48053 + WMI_SET_KEEPALIVE_CMD *cmd;
48055 + osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
48056 + if (osbuf == NULL) {
48057 + return A_NO_MEMORY;
48060 + A_NETBUF_PUT(osbuf, sizeof(*cmd));
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;
48067 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_KEEPALIVE_CMDID,
48068 + NO_SYNC_WMIFLAG));
48072 +wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType, A_UINT8 ieLen,
48076 + WMI_SET_APPIE_CMD *cmd;
48079 + if (ieLen > WMI_MAX_IE_LEN) {
48082 + cmdLen = sizeof(*cmd) + ieLen - 1;
48083 + osbuf = A_NETBUF_ALLOC(cmdLen);
48084 + if (osbuf == NULL) {
48085 + return A_NO_MEMORY;
48088 + A_NETBUF_PUT(osbuf, cmdLen);
48090 + cmd = (WMI_SET_APPIE_CMD *)(A_NETBUF_DATA(osbuf));
48091 + A_MEMZERO(cmd, cmdLen);
48093 + cmd->mgmtFrmType = mgmtFrmType;
48094 + cmd->ieLen = ieLen;
48095 + A_MEMCPY(cmd->ieInfo, ieInfo, ieLen);
48097 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
48101 +wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen)
48106 + osbuf = A_NETBUF_ALLOC(dataLen);
48107 + if (osbuf == NULL) {
48108 + return A_NO_MEMORY;
48111 + A_NETBUF_PUT(osbuf, dataLen);
48113 + data = A_NETBUF_DATA(osbuf);
48115 + A_MEMCPY(data, cmd, dataLen);
48117 + return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
48121 +wmi_get_rate(A_INT8 rateindex)
48123 + if (rateindex == RATE_AUTO) {
48126 + return(wmi_rateTable[(A_UINT32) rateindex]);
48131 +wmi_node_return (struct wmi_t *wmip, bss_t *bss)
48135 + wlan_node_return (&wmip->wmi_scan_table, bss);
48140 +wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
48141 + A_UINT32 ssidLength, A_BOOL bIsWPA2)
48143 + bss_t *node = NULL;
48144 + node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
48145 + ssidLength, bIsWPA2);
48150 +wmi_free_allnodes(struct wmi_t *wmip)
48152 + wlan_free_allnodes(&wmip->wmi_scan_table);
48156 +wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr)
48159 + ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
48164 +wmi_dset_open_reply(struct wmi_t *wmip,
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)
48174 + WMIX_DSETOPEN_REPLY_CMD *open_reply;
48176 + A_DPRINTF(DBG_WMI, (DBGFMT "Enter - wmip=0x%x\n", DBGARG, (int)wmip));
48178 + osbuf = A_NETBUF_ALLOC(sizeof(*open_reply));
48179 + if (osbuf == NULL) {
48180 + return A_NO_MEMORY;
48183 + A_NETBUF_PUT(osbuf, sizeof(*open_reply));
48184 + open_reply = (WMIX_DSETOPEN_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
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;
48194 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETOPEN_REPLY_CMDID,
48195 + NO_SYNC_WMIFLAG));
48199 +wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
48201 + WMI_PMKID_LIST_REPLY *reply;
48202 + A_UINT32 expected_len;
48204 + if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
48207 + reply = (WMI_PMKID_LIST_REPLY *)datap;
48208 + expected_len = sizeof(reply->numPMKID) + reply->numPMKID * WMI_PMKID_LEN;
48210 + if (len < expected_len) {
48214 + A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
48215 + reply->pmkidList);
48220 +#ifdef CONFIG_HOST_DSET_SUPPORT
48222 +wmi_dset_data_reply(struct wmi_t *wmip,
48224 + A_UINT8 *user_buf,
48226 + A_UINT32 targ_buf,
48227 + A_UINT32 targ_reply_fn,
48228 + A_UINT32 targ_reply_arg)
48231 + WMIX_DSETDATA_REPLY_CMD *data_reply;
48234 + size = sizeof(*data_reply) + length;
48236 + A_DPRINTF(DBG_WMI,
48237 + (DBGFMT "Enter - length=%d status=%d\n", DBGARG, length, status));
48239 + osbuf = A_NETBUF_ALLOC(size);
48240 + if (osbuf == NULL) {
48241 + return A_NO_MEMORY;
48243 + A_NETBUF_PUT(osbuf, size);
48244 + data_reply = (WMIX_DSETDATA_REPLY_CMD *)(A_NETBUF_DATA(osbuf));
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;
48252 + if (status == A_OK) {
48253 + if (a_copy_from_user(data_reply->buf, user_buf, length)) {
48258 + return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_DSETDATA_REPLY_CMDID,
48259 + NO_SYNC_WMIFLAG));
48261 +#endif /* CONFIG_HOST_DSET_SUPPORT */
48264 +wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status)
48269 + wps_enable = status;
48271 + osbuf = a_netbuf_alloc(sizeof(1));
48272 + if (osbuf == NULL) {
48273 + return A_NO_MEMORY;
48276 + a_netbuf_put(osbuf, sizeof(1));
48278 + cmd = (char *)(a_netbuf_to_data(osbuf));
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));
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
48292 + * Copyright (c) 2004-2007 Atheros Communications Inc.
48293 + * All rights reserved.
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;
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.
48311 +Wireless Module Interface (WMI) Documentaion
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.
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.
48326 +WMI Message Structure
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:
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.
48338 + Contains information on message type and user priority. Message type
48339 + differentiates between a data packet and a synchronization message.
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).
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.
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.
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.
48367 + Table B-1 describes the AR6000 WLAN connection states:
48369 + Table B-1. AR6000 Connection States
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
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.
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:
48397 +Table B-2. AR6000 Message Types
48403 + Control messages that flow from the host to the device
48406 + Control messages that flow from the device to the host.
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.
48414 +WMI Message Format
48416 + All WMI control commands, replies and events use the header format:
48418 + WMI_CMD_HDR Header Format
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.
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.
48436 +Command Restrictions
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.
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.
48448 +Command and Data Synchronization
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.
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.
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
48474 + Cause the AR6000 device to avoid a particular AP
48476 + Add or replace any of the four AR6000 encryption keys
48478 + Used to add a pattern to the WoW pattern list
48480 + Clear the current calculated RSSI and SNR value
48482 + Request that the AR6000 device establish a wireless connection
48483 + with the specified SSID
48485 + Create prioritized data endpoint between the host and device
48487 + Clear an entry in the bad AP table
48488 + DELETE_CIPHER_KEY
48489 + Delete a previously added cipher key
48491 + Delete a prioritized data endpoint
48492 + DELETE_WOW_PATTERN
48493 + Remove a pre-specified pattern from the WoW pattern list
48495 + WMI message interface command
48497 + Retrieve rate most recently used by the AR6000
48499 + Retrieve list of channels used by the AR6000
48501 + Retrieves the rate-mask set via the SET_FIXRATES command.
48502 + GET_PMKID_LIST_CMD
48503 + Retrieve the firmware list of PMKIDs
48505 + Internal use for data collection; available in special build only
48507 + Retrieve the roaming table maintained on the target
48509 + Request that the target send the statistics it maintains
48511 + Retrieve the current AR6000 device Tx power levels
48513 + Retrieve the current list of WoW patterns
48514 + LQ_THRESHOLD_PARAMS
48515 + Set the link quality thresholds
48517 + Send a special frame (special feature)
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
48524 + Determine dwell time and changes scanned channels
48525 + SET_ACCESS_PARAMS
48526 + Set access parameters for the wireless network
48528 + Set the BSSID for an ad hoc network
48530 + Set multiPMKID mode
48532 + Add application-specified IE to a management frame
48534 + Specify the IEs the device should add to association or
48535 + reassociation requests
48537 + Set 802.11 authentication mode of reconnection
48539 + Set the beacon interval for an ad hoc network
48541 + Set the AR6000 to a specific fixed bit rate
48543 + Set the beacon miss time
48545 + Inform the AR6000 of network types about which it wants to
48546 + receive information using a
\93BSSINFO
\94 event
48548 + Set the status of a Bluetooth stream (SCO or A2DP) or set
48549 + Bluetooth coexistence register parameters
48551 + Set the status of a Bluetooth stream (SCO or A2DP)
48552 + SET_CHANNEL_PARAMETERS
48553 + Configure WLAN channel parameters
48555 + Set the amount of time the AR6000 spends attempting to
48556 + reestablish a connection
48558 + Set the device to a specific fixed PHY rate (supported subset)
48560 + Internal AR6000 command to set certain hardware parameters
48561 + SET_HOST_SLEEP_MODE
48562 + Set the host mode to asleep or awake
48564 + Support a non-standard power management scheme for an
48567 + Request a listen interval
48569 + Override the short preamble capability of the AR6000 device
48571 + Set the maximum service period
48573 + Set the special mode on/off (special feature)
48575 + Set the pairwise master key ID (PMKID)
48576 + SET_PMKID_LIST_CMD
48577 + Configure the firmware list of PMKIDs
48579 + Set guidelines on trade-off between power utilization
48581 + Configure power parameters
48582 + SET_POWERSAVE_PARAMS
48583 + Set the two AR6000 power save timers
48585 + Provide list of SSIDs the device should seek
48587 + Specify whether the disassociated frame should be sent upon
48590 + Limit how many times the device tries to send a frame
48592 + Control roaming behavior
48594 + Determine when RTS should be sent
48596 + Set the AR6000 scan parameters
48597 + SET_TKIP_COUNTERMEASURES
48598 + Enable/disable reports of TKIP MIC errors
48600 + Specify the AR6000 device Tx power levels
48601 + SET_VOICE_PKT_SIZE
48602 + Set voice packet size
48604 + Override the AR6000 WMM capability
48606 + Configure TxOP bursting when sending traffic to a WMM-
48609 + Enable/disable WoW mode
48611 + Enable/disable profile check in cserv when the WPS protocol
48613 + SNR_THRESHOLD_PARAMS
48614 + Configure how the device monitors and reports SNR of BSS
48616 + Start a long or short channel scan
48618 + Force a synchronization point between command and data
48620 + TARGET_REPORT_ERROR_BITMASK
48621 + Control
\93ERROR_REPORT
\94 events from the AR6000
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.
48634 + If the AR6000 are currently connected to the AP specified in this command, they
48638 + wmiconfig eth1 --badap <bssid> <badApIndex>
48640 +Command Parameters
48641 + UINT8 badApIndex Index [0...1] that identifies which entry in the
48642 + bad AP table to use
48645 + UINT8 bssid[6] MAC address of the AP to avoid
48648 + badApIndex = 0, 1 Entry in the bad AP table to use
48651 + The bad AP table is cleared
48657 +
\93DELETE_BAD_AP
\94 on page B-13
48659 +=====================================================================
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.
48671 + wmiconfig eth1 --cipherkey <keyIndex> <keyType> <keyUsage>
48672 + <keyLength> <keyopctrl> <keyRSC> <key>
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
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
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
48709 + The four available keys are disabled.
48712 + The cipher should correspond to the encryption mode specified in the
\93CONNECT
\94
48716 +
\93DELETE_CIPHER_KEY
\94
48718 +=====================================================================
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.
48732 + wmiconfig
\96addwowpattern <list-id> <filter-size> <filter-offset>
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
48747 + None defined (default host mode is awake)
48753 +
\93DELETE_WOW_PATTERN
\94
48755 +=====================================================================
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.
48767 + wmiconfig eth1 --cleanRssiSnr
48769 +Command Parameters
48781 +=====================================================================
48787 + New connect control information (connectCtrl) is added, with 32 possible modifiers.
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
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.
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.
48812 + CONNECT_IGNORE_AAC_BEACON
48813 + Ignore the Admission Capacity information in the
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
48821 + wmiconfig --setconnectctrl <ctrl flags bitmask>
48823 +Command Parameters
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;
48839 + ctrl flags bitmask
48840 + = 0x0001 CONNECT_ASSOC_POLICY_USER
48841 + Assoc frames are sent using the policy specified by
48843 + = 0x0002 CONNECT_SEND_REASSOC
48844 + Send Reassoc frame while connecting, otherwise send
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
48853 + ... CONNECT_CMD, continued
48856 + INFRA_NETWORK = 0x01,
48857 + ADHOC_NETWORK = 0x02,
48858 + ADHOC_CREATOR = 0x04,
48862 + OPEN_AUTH = 0x01,
48863 + SHARED_AUTH = 0x02,
48864 + LEAP_AUTH = 0x04,
48865 + } DOT11_AUTH_MODE;
48867 + NONE_AUTH = 0x01,
48869 + WPA_PSK_AUTH = 0x03,
48870 + WPA2_AUTH = 0x04,
48871 + WPA2_PSK_AUTH = 0x05,
48872 + WPA_AUTH_CCKM = 0x06,
48873 + WPA2_AUTH_CCKM = 0x07,
48876 + NONE_CRYPT = 0x01,
48877 + WEP_CRYPT = 0x02,
48878 + TKIP_CRYPT = 0x03,
48879 + AES_CRYPT = 0x04,
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;
48889 + pairwiseCryptoLen and groupCryptoLen are valid when the respective
48890 + CryptoTypesis WEP_CRYPT, otherwise this value should be 0. This is the length in
48899 +=====================================================================
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.
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
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:
48936 + 802.1D user priority range (0
\967)
48938 + = 0 Tx (uplink) traffic
48939 + = 1 Rx (downlink) traffic
48940 + = 2 Bi-directional traffic
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>
48957 + <max service interval>
48958 + Inactivity interval (in ms) (0 = Infinite)
48959 + <suspension interval>
48961 + <service start time>
48962 + Service start time
48964 + TSID range (0
\9615)
48966 + Nominal MAC SDU size
48968 + Maximum MAC SDU size
48970 + Minimum data rate (in bps)
48972 + Mean data rate (in bps)
48974 + Peak data rate (in bps)
48976 + Maximum burst size (in bps)
48980 + Minimum PHY rate (in bps)
48982 + Surplus bandwidth allowance
48984 + Medium time in TU of 32-ms periods per sec
48985 + ... CREATE_PSTREAM (continued)
48987 +Command Parameters
48988 + UINT8 trafficClass TRAFFIC_CLASS value
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
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)
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
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
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
49044 + ... CREATE_PSTREAM (continued)
49047 + VI BE BK Supported, Y/N?
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)
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
49076 +
\93DELETE_PSTREAM
\94
49077 +=====================================================================
49083 + The host uses this command to clear a particular entry in the bad AP table
49086 + wmiconfig eth1 --rmAP [--num=<index>] // used to clear a badAP
49087 + entry. num is index from 0-3
49089 +Command Parameters
49090 + UINT8 badApIndex Index [0...n] that identifies the entry in the bad
49091 + AP table to delete
49094 + badApIndex = 0, 1, 2, 3
49095 + Entry in the bad AP table
49106 +=====================================================================
49110 + DELETE_CIPHER_KEY
49113 + The host uses this command to delete a key that was previously added with the
49114 +
\93ADD_CIPHER_KEY
\94 command.
49119 +Command Parameters
49120 + UINT8 keyIndex Index (0...3) of the key to be deleted
49123 + keyIndex = 0, 1,2, 3 Key to delete
49129 + The host should not delete a key that is currently in use by the AR6000.
49132 +
\93ADD_CIPHER_KEY
\94
49134 +=====================================================================
49140 + The host uses this command to delete a prioritized data endpoint created by a
49141 + previous
\93CREATE_PSTREAM
\94 command
49144 + --deleteqos <trafficClass> <tsid>, where:
49152 + The TSpec ID; use the -qosqueue option
49153 + to get the active TSpec IDs for each traffic class
49155 +Command Parameters
49156 + A_UINT8 trafficClass Indicate the traffic class of the stream
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
49173 + This command should only be issued after a
\93CREATE_PSTREAM
\94 command has
49174 + successfully created a prioritized stream
49177 +
\93CREATE_PSTREAM
\94
49179 +=====================================================================
49183 + DELETE_WOW_PATTERN
49186 + The host uses this command to remove a pre-specified pattern from the
49187 + WoW pattern list.
49190 + wmiconfig
\96delwowpattern <list-id> <pattern-id>
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
49209 +
\93ADD_WOW_PATTERN
\94
49211 +=====================================================================
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.
49227 +Command Parameters
49242 +=====================================================================
49249 + Used by the host to obtain the rate most recently used by the AR6000 device
49252 + wmiconfig eth1 --getfixrates
49254 +Command Parameters
49262 + See the
\93SET_BIT_RATE
\94 command
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
49272 +
\93SET_BIT_RATE
\94
49274 +=====================================================================
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.
49287 +Command Parameters
49291 + UINT8 reserved Reserved
49292 + UINT8 numberOfChannels Number of channels the reply contains
49293 + UINT16 channelList[numberOfChannels] Array of channel frequencies (in MHz)
49299 + The maximum number of channels that can be reported are 32
49301 +=====================================================================
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.
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.
49317 + wmiconfig eth1 --getfixrates
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
49335 +
\93SET_FIXRATES
\94
49337 +=====================================================================
49342 + GET_PMKID_LIST_CMD
49345 + Retrieves the list of PMKIDs on the firmware. The
49346 + WMI_GET_PMKID_LIST_EVENT is generated by the firmware.
49351 +Command Parameters
49360 + SET_PMKID_LIST_CMD GET_PMKID_LIST_EVENT
49362 +=====================================================================
49369 + Retrieve the roaming table maintained on the target. The response is reported
49370 + asynchronously through the ROAM_TBL_EVENT.
49373 + wmiconfig --getroamtable <roamctrl> <info>
49375 +Command Parameters
49376 + A_UINT8 roamCtrlType;
49377 + A_UINT16 roamMode
49378 + A_UINT16 numEntries
49379 + WMI_BSS_ROAM_INFO bssRoamInfo[1]
49382 + Reported asynchronously through the ROAM_TBL_EVENT
49393 +=====================================================================
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.
49406 + wmiconfig --getTargetStats --clearStats
49408 +Command Parameters
49409 + TARGET_STATS targetStats
49415 + RSSI return value (0
\96100)
49418 + All statistics are cleared (zeroed)
49421 + The --getTargetStats option must be used; the --clearStats option is also available also
49424 +=====================================================================
49430 + The host uses this command to retrieve the current Tx power level
49433 + wmiconfig -i eth1 --getpower
49435 +Command Parameters
49439 + UINT16 dbM The current Tx power level specified in dbM
49442 + The maximum permitted by the regulatory domain
49450 +=====================================================================
49457 + The host uses this command to retrieve the current list of WoW patterns.
49460 + wmiconfig
\96getwowlist <list-id>
49462 +Command Parameters
49463 + A_UINT8 filter_list_id ID of the list of WoW patterns to retrieve
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)
49481 +
\93SET_WSC_STATUS
\94
49483 +=====================================================================
49487 + LQ_THRESHOLD_PARAMS
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.
49494 + --lqThreshold <enable> <upper_threshold_1> ...
49495 + <upper_threshold_4> <lower_threshold_1> ... <lower_threshold_4>
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
49502 + <lower_threshold_x> Below thresholds (value in [0,100]), in
49506 + See command parameters
49514 +=====================================================================
49521 + Special feature, sends a special frame.
49524 + wmiconfig --sendframe <frmType> <dstaddr> <bssid> <optIEDatalen>
49527 +Command Parameters
49529 + A_UINT16 optIEDataLen;
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;
49537 + <frmtype> = 1 Probe request frame
49538 + = 2 Probe response frame
49546 + Send a special frame only when special mode is on.
49548 +=====================================================================
49555 + This command requests a reconnection to a BSS to which the AR6000 device was
49556 + formerly connected
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
49576 +
\93CONNECT_CMD
\94
49578 +=====================================================================
49582 + RSSI_THRESHOLD_PARAMS
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).
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>
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)
49610 + pollTime is 0, and sampling is disabled
49613 + Can only be issued if the AR6000 device is connected
49616 +=====================================================================
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.
49628 + wmiconfig -scan -minact=<ms> --maxact=<ms>
49630 +Command Parameters
49631 + UINT16 maxact Channel dwell time (in ms), default = 0
49632 + UINT16 minact Channel dwell time (in ms), default = 105
49635 + See channel parameters
49641 + The minact value should be greater than 0; maxact should be between 5
\9665535 ms
49642 + and greater than minact
49644 +=====================================================================
49648 + SET_ACCESS_PARAMS
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.
49655 + wmiconfig eth1 --acparams --txop <limit> --cwmin <0-15>
49656 + --cwmax <0-15> --aifsn<0-15>
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
49670 + Reasonable defaults that vary, between endpoints (prioritized streams)
49675 +=====================================================================
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).
49687 + wmiconfig eth1 --adhocbssid <bssid>
49689 +Command Parameters
49690 + A_UINT8 bssid[ATH_MAC_LEN] BSSID is specified in xx:xx:xx:xx:xx:xx format
49701 +=====================================================================
49708 + Enables or disables multi PMKID mode.
49711 + wmiconfig eth1 --setakmp --multipmkid=<on/off>
49713 +Command Parameters
49715 + A_UINT32 akmpInfo;
49716 + } WMI_SET_AKMP_PARAMS_CMD;
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.
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.
49730 + MultiPMKID mode is disabled
49735 +=====================================================================
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.
49746 + wmiconfig --setappie <frame> <IE>, where:
49749 + One of beacon, probe, respon, assoc
49752 + A hex string beginning with DD (if = 0, no
49753 + IE is sent in the management frame)
49755 +Command Parameters
49757 + A WMI_MGMT_FRAME_TYPE
49760 + Length of the IE to add to the GMT frame
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.
49772 +=====================================================================
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.
49785 + wmiconfig eth1 --setAssocIe <IE>
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
49800 + This command can only be issued in the DISCONNECTED state
49802 +=====================================================================
49809 + Sets the 802.11 authentication mode of reconnection
49812 + wmiconfig eth1 --setauthmode <mode>
49814 +Command Parameters
49818 + mode = 0x00 Proceed with authentication during reconnect
49819 + = 0x01 Do not proceed with authentication during reconnect
49827 +=====================================================================
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.
49840 + wmiconfig eth1 --ibssconintv
49842 +Command Parameters
49843 + UINT16 beaconInterval Specifies the beacon interval in TU units (1024 ms)
49849 + The default beacon interval is 100 TUs (102.4 ms)
49852 + This command can only be issued before the AR6000 device starts an ad hoc network
49855 +
\93SET_IBSS_PM_CAPS
\94
49857 +=====================================================================
49864 + The host uses this command to set the AR6000 device to a specific fixed rate.
49867 + wmiconfig eth1 --setfixrates <rate_0> ... <rate_n>
49869 +Command Parameters
49871 + A WMI_BIT_RATE value
49890 + See command parameters
49893 + The dynamic rate is determined by the AR6000 device
49896 + This command is intended for use only during development/debug; it is not
49897 +intended for use in production
49900 +
\93GET_BIT_RATE
\94
49902 +=====================================================================
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.
49915 + wmiconfig eth1 --setbmissbeacons=<val>
49916 + wmiconfig eth1 --setbmisstime=<val>
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]
49927 + bmissTime is 1500 TUs (1536 ms)
49932 +=====================================================================
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.
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.
49951 + wmiconfig eth1
\96filter = <filter> --ieMask 0x<mask>
49953 +Command Parameters
49958 + A_UINT8 bssFilter; See WMI_BSS_FILTER
49960 + } __ATTRIB_PACK WMI_BSS_FILTER_CMD;
49962 + The ieMask can take this combination of values:
49965 + BSS_ELEMID_CHANSWITCH = 0x01
49966 + BSS_ELEMID_ATHEROS = 0x02,
49973 + BssFilter = NONE_BSS_FILTER (0)
49979 +
\93CONNECT_CMD
\94
49981 +=====================================================================
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.
49993 + wmiconfig
\96setBTparams <paramType> <params>
49995 +Command Parameters
49998 + BT_PARAMS_SCO scoParams;
49999 + BT_PARAMS_A2DP a2dpParams;
50000 + BT_PARAMS_MISC miscParams;
50001 + BT_COEX_REGS regs;
50003 + A_UINT8 paramType;
50005 + A_UINT8 noSCOPkts; Number of SCO packets between consecutive PS-POLLs
50006 + A_UINT8 pspollTimeout;
50010 + A2DP BT stream parameters
50012 + A_UINT32 dutycycle;
50014 + } BT_PARAMS_A2DP;
50017 + WLAN_PROTECT_POLICY_TYPE protectParams;
50018 + A_UINT16 wlanCtrlFlags;
50020 + A_UINT8 paramType;
50021 + } BT_PARAMS_MISC;
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
50041 +=====================================================================
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.
50052 + wmiconfig
\96setBTstatus <streamType> <status>
50054 +Command Parameters
50056 + A_UINT8 streamType; Stream type
50057 + A_UINT8 status; Stream status
50058 + }WMI_SET_BT_STATUS_CMD;
50062 + BT_STREAM_UNDEF = 0
50068 + } BT_STREAM_TYPE;
50071 + BT_STATUS_UNDEF = 0
50075 + BT_STATUS_SUSPEND
50077 + } BT_STREAM_STATUS;
50085 +=====================================================================
50089 + SET_CHANNEL_PARAMETERS
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.
50099 + wmiconfig eth1 --wmode <mode> <list>
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.
50128 + 802.11a/g modules
50132 + Defaults to all channels permitted by the
50133 + current regulatory domain.
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.
50139 +=====================================================================
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.
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.
50159 + wmiconfig eth1 --disc=<timeout in seconds>
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
50171 + disconnectTimeout is 10 seconds
50174 + This command can only be issued while in a DISCONNECTED state
50176 +=====================================================================
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.
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.
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.
50215 +
\93GET_FIXRATES
\94
50217 +=====================================================================
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.
50230 +Command Parameters
50231 + ATH_HAL_SETCABTO_CMDID
50232 + Sets the timeout waiting for the multicast
50233 + traffic after a DTIM beacon (in TUs).
50242 + This command should be executed before issuing a connect command.
50244 +=====================================================================
50248 + SET_HOST_SLEEP_MODE
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.
50258 + wmiconfig
\96sethostmode=<asleep/awake>
50260 +Command Parameters
50261 + A_BOOL awake Set the host mode to awake
50262 + A_BOOL asleep Set the host mode to asleep
50265 + 1 = awake, 0 = asleep
50268 + None defined (default host mode is awake)
50274 +=====================================================================
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.
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>
50291 +Command Parameters
50292 + UINT8 power_saving
50294 + The non-standard power saving scheme is
50295 + disabled and maximum throughput (with no
50296 + power saving) is obtained.
50299 + Ad hoc power saving scheme is enabled (but
50300 + throughput may be decreased)
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.
50308 + The duration is communicated between wireless
50309 + STAs through an IE in beacons and probe responses.
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.
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
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.
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
50346 + By default, power_saving is enabled with atim_window = 20 ms
50349 + Can only be issued before the AR6000 starts an ad hoc network
50352 +
\93SET_BEACON_INT
\94
50354 +=====================================================================
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.
50370 + wmiconfig eth1 --listen=<#of TUs, can range from 15 to 3000>
50372 + --listenbeacons=<#of beacons, can range from 1 to 50>
50374 +Command Parameters
50375 + UINT16 listenInterval
50376 + Specifies the listen interval in Kms
50377 + (1024 ms), ranging from 100 to 1000
50379 + UINT16 listenbeacons
50380 + Specifies the listen interval in beacons,
50381 + ranging from 1 to 50
50387 + The device sets the listen interval equal to the beacon interval of the AP it associates
50393 +=====================================================================
50400 + Overrides the short preamble capability of the AR6000 device
50405 +Command Parameters
50406 + WMI_LPREAMBLE_DISABLED
50407 + The device is short-preamble capable
50409 + WMI_LPREAMBLE_ENABLED
50410 + The device supports only the long-
50423 +=====================================================================
50429 + Set the maximum service period; indicates the number of packets the AR6001 can
50430 + receive from the AP when triggered
50433 + wmiconfig eth1 --setMaxSPLength <maxSPLen>
50435 +Command Parameters
50437 + An APSD_SP_LEN_TYPE value
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
50449 + maxSPLen is DELIVER_ALL_PKT
50454 +=====================================================================
50461 + Special feature, sets the special mode on/off
50464 + wmiconfig eth1 --mode <mode>
50465 + Set the optional mode, where mode is special or off
50467 +Command Parameters
50481 +=====================================================================
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.
50494 + wmiconfig eth1 --setbsspmkid --bssid=<aabbccddeeff>
50495 + --bsspmkid=<pmkid>
50497 +Command Parameters
50499 + The MAC address of the AP that the
50500 + PMKID corresponds to (6 bytes in hex
50504 + Either PMKID_DISABLE (0) to disable
50505 + the PMKID or PMKID_ENABLE (1) to
50506 + enable it (16 bytes in hex format)
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
50516 + = 0 (disable), 1 (enable)
50517 + PKMID enabled/disabled
50523 + Only supported in infrastructure networks
50525 +=====================================================================
50529 + SET_PMKID_LIST_CMD
50532 + Configures the list of PMKIDs on the firmware.
50535 + wmiconfig --setpmkidlist --numpmkid=<n> --pmkid=<pmkid_1>
50536 + ... --pmkid=<pmkid_n>
50538 + Where n is the number of pmkids (maximum = 8) and pmkid_i is the ith pmkid (16
50539 + bytes in hex format)
50541 +Command Parameters
50543 + A_UINT8 pmkid[WMI_PMKID_LEN];
50544 + } __ATTRIB_PACK WMI_PMKID;
50547 + A_UINT32 numPMKID;
50548 + WMI_PMKID pmkidList[WMI_MAX_PMKID_CACHE];
50549 + } __ATTRIB_PACK WMI_SET_PMKID_LIST_CMD;
50558 + Supported only in infrastructure modes
50560 +=====================================================================
50567 + The host uses this command to provide the AR6000 device with guidelines on the
50568 + desired trade-off between power utilization and performance.
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.
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
50581 +Command Parameters
50583 + WMI_POWER_MODE value
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
50592 + All other values are reserved
50596 + See command parameters
50599 + powerMode is REC_POWER
50602 + This command should only be issued in the DISCONNECTED state for the
50603 + infrastructure network.
50605 + For a PM-disabled ad hoc network, the power mode should remain in
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.
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.
50615 +=====================================================================
50622 + The host uses this command to configure power parameters
50625 + wmiconfig eth1 --pmparams --it=<ms> --np=<number of PS POLL>
50626 + --dp=<DTIM policy: ignore/normal/stick>
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
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
50639 + UINT16 dtim_policy
50640 + A WMI_POWER_PARAMS_CMD value
50644 + The device does not listen to any content after
50645 + beacon (CAB) traffic
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)
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
50656 +Command Parameters
50657 + See command parameters
50672 +=====================================================================
50676 + SET_POWERSAVE_PARAMS
50679 + Set the two AR6000 power save timers (PS-POLL timer and APSD trigger timer) and
50680 + the two ASPD TIM policies
50683 + wmiconfig eth1--psparams --psPollTimer=<psPollTimeout in ms>
50684 + --triggerTimer=<triggerTimeout in ms> --apsdTimPolicy=<ignore/
50685 + adhere> --simulatedAPSDTimPolicy=<ignore/adhere>
50687 +Command Parameters
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
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
50699 + APSD_TIM_POLICY apsdTimPolicy;
50700 + TIM behavior with queue APSD enabled
50702 + APSD_TIM_POLICY simulatedAPSD
50705 + TIM behavior with simulated APSD
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;
50719 + psPollTimeout is 50 ms; triggerTimeout is 10 ms;
50720 + apsdTimPolicy = IGNORE_TIM_ALL_QUEUES_APSD;
50721 + simulatedAPSDTimPolicy = POWERSAVE_TIMERS_POLICY
50724 + When this command is used, all parameters must be set; this command does not
50725 + allow setting only one parameter.
50727 +=====================================================================
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.
50741 + wmiconfig eth1 --ssid=<ssid> [--num=<index>]
50743 +Command Parameters
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)
50753 + WMI_PROBED_SSID_INFO probedSSID[1]
50754 + } WMI_PROBED_SSID_CMD
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
50765 + SSID string actively probed for when
50766 + permitted by the regulatory domain
50767 + } WMI_PROBED_SSID_INFO
50772 + DISABLE_SSID_FLAG = 0
50774 + SPECIFIC_SSID_FLAG = 1
50775 + Probes specified SSID
50776 + ANY_SSID_FLAG = 2
50777 + Probes for any SSID
50781 + The entries are unused.
50786 +=====================================================================
50793 + Specify whether the disassociated frame should be sent or not upon reassociation.
50796 + wmiconfig eth1 --setreassocmode <mode>
50798 +Command Parameters
50804 + Send disassoc to a previously connected AP
50805 + upon reassociation
50807 + Do not send disassoc to previously connected
50808 + AP upon reassociation
50817 +=====================================================================
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.
50827 + wmiconfig --setretrylimits <frameType> <trafficClass> <maxRetries>
50830 +Command Parameters
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.
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
50852 + A_UINT8 numEntries
50853 + WMI_RETRY_LIMIT_INFO retryLimitInfo[1]
50854 + } WMI_SET_RETRY_LIMITS_CMD
50858 + MGMT_FRAMETYPE = 0 Management frame
50859 + CONTROL_FRAMETYPE = 1 Control frame
50860 + DATA_FRAMETYPE = 2 Data frame
50864 + Retries are set to 15
50869 +=====================================================================
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.
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.
50888 + wmiconfig --roam <roamctrl> <info>, where info is <scan period>
50889 + <scan threshold> <roam threshold> <roam rssi floor>
50891 +Command Parameters
50892 + A_UINT8 roamCtrlType;
50895 + WMI_FORCE_ROAM = 1
50896 + Roam to the specified BSSID
50898 + WMI_SET_ROAM_MODE = 2
50899 + Default, progd bias, no roam
50901 + WMI_SET_HOST_BIAS = 3
50902 + Set the host bias
50904 + WMI_SET_LOWRSSI_SCAN_PARAMS = 4
50907 + A_UINT8 bssid[ATH_MAC_LEN];
50910 + A_UINT8 roamMode;
50911 + WMI_SET_ROAM_MODE
50913 + A_UINT8 bssBiasInfo;
50914 + WMI_SET_HOST_BIAS
50916 + A_UINT16 lowrssi_scan_period;
50917 + WMI_SET_LOWRSSI_SCAN_PARAMS
50920 + lowrssi_scan_threshold;
50921 + WMI_SET_LOWRSSI_SCAN_PARAMS
50923 + A_INT16 lowrssi_roam_threshold;
50924 + WMI_SET_LOWRSSI_SCAN_PARAMS
50926 + A_UINT8 roam_rssi_floor;
50927 + WMI_SET_LOWRSSI_SCAN_PARAMS
50930 + None defined (default lowrssi scan is disabled. Enabled only when scan period is set.)
50935 +=====================================================================
50942 + Decides when RTS should be sent.
50945 + wmiconfig eth1 --setRTS <pkt length threshold>
50947 +Command Parameters
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.
50964 +=====================================================================
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.
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.
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.
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>
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
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.
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.
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.
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.
51031 + UINT8 shortScanRatio
51032 + Number of short scans to perform for each
51035 + UINT8 scanCtrlFlasgs
51037 + UINT16 minactChDwellTime
51040 + UINT32 maxDFSchActTime
51041 + The maximum time a DFS channel can stay
51042 + active before being marked passive, specified in
51049 + ForegroundScanStart
51053 + ForegroundScanEndPeriod
51056 + BackgroundScanPeriod
51059 + ActiveChannelDwellTime
51062 +=====================================================================
51066 + SET_TKIP_COUNTERMEASURES
51069 + The host issues this command to tell the target whether to enable or disable TKIP
51075 +Command Parameters
51076 + UINT8 WMI_TKIP_CM_ENABLE
51077 + Enables the countermeasures
51080 + UINT8 TKIP_CM_DISABLE
51081 + Disables the countermeasures
51087 + By default, TKIP MIC reporting is disabled
51092 +=====================================================================
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.
51104 + wmiconfig --power <dbM>
51106 +Command Parameters
51108 + The desired Tx power specified in dbM.
51109 + If = 0, the device chooses the maximum
51110 + permitted by the regulatory domain.
51116 + The maximum permitted by the regulatory domain
51125 +=====================================================================
51128 + SET_VOICE_PKT_SIZE
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.
51136 + wmiconfig eth1 --setVoicePktSize <size-in-bytes>
51138 +Command Parameters
51139 + UINT16 voicePktSize
51140 + Packet size in octets
51146 + voicePktSize default is 400 bytes
51149 + No effect if WMM is unavailable
51152 +=====================================================================
51158 + Overrides the AR6000 device WMM capability
51161 + wmiconfig eth1 --setwmm <enable>
51163 +Command Parameters
51168 + Disables WMM support
51181 +=====================================================================
51187 + Configures TxOP Bursting when sending traffic to a WMM capable AP
51190 + wmiconfig eth1 --txopbursting <burstEnable>
51194 + Disallow TxOp bursting
51197 + Allow TxOp bursting
51199 +Command Parameters
51201 + = WMI_TXOP_DISABLED
51204 + = WMI_TXOP_ENABLED
51214 + Bursting is off by default
51219 +=====================================================================
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.
51233 + wmiconfig
\96setwowmode <enable/disable>
51235 +Command Parameters
51236 + A_BOOL enable_wow
51237 + Enable or disable WoW:
51247 + None defined (default WoW mode is disabled).
51253 +
\93GET_WOW_LIST
\94
51256 +=====================================================================
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
51270 +Command Parameters
51272 + = 1 WSC registration in progress
51273 + = 0 WSC protocol not running
51279 + None defined (default = 0)
51285 +=====================================================================
51288 + SNR_THRESHOLD_PARAMS
51291 + Configures how the AR6000 device monitors and reports SNR of the connected BSS,
51292 + used as a link quality metric.
51295 + --snrThreshold <weight> <upper_threshold_1> ...
51296 + <upper_threshold_4> <lower_threshold_1> ... <lower_threshold_4>
51299 +Command Parameters
51301 + Share with rssiThreshold. Range in [1, 16], used
51302 + in the formula to calculate average RSSI
51304 + <upper_threshold_x>
51305 + Above thresholds expressed in db, in ascending
51308 + <lower_threshold_x>
51309 + Below thresholds expressed in db, in ascending
51313 + The signal strength sampling frequency in
51314 + seconds. If polltime = 0, signal strength
51315 + sampling is disabled
51326 +=====================================================================
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
51342 + wmiconfig eth1 --startscan <scan type> <forcefgscan> 0
51343 + <homeDwellTime> <forceScanInterval>
51345 +Command Parameters
51351 + WMI_LONG_SCAN =0x0
51352 + Requests a full scan
51353 + WMI_SHORT_SCAN =0x1
51354 + Requests a short scan
51357 + A_BOOL forceFgScan
51360 + Disable the foreground scan
51364 + Forces a foreground scan
51366 + A_UINT32 homeDwellTime
51367 + Maximum duration in the home
51370 + A_UINT32 forceScanInterval
51371 + Time interval between scans (in ms)
51373 + A_UINT32 scanType
51377 + Disable forcing foreground scan
51380 + isLegacy field will no longer be supported (pass as 0 for now)
51383 +=====================================================================
51389 + The host uses this command to force a synchronization point between the command
51395 +Command Parameters
51414 +=====================================================================
51417 + TARGET_ERROR_REPORT_BITMASK
51420 + Allows the host to control
\93ERROR_REPORT
\94 events from the AR6000 device.
51422 + If error reporting is disabled for an error type, a count of errors of that type is
51423 + maintained by the device.
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.
51428 + Error counts for each error type are available through the
\93GET_TARGET_STATS
\94
51432 + wmiconfig eth1 --setErrorReportingBitmask
51434 +Command Parameters
51436 + Represents the set of
51437 + WMI_TARGET_ERROR_VAL error types
51438 + enabled for reporting
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
51447 + Host changes the PS setting when
51448 + STA is off home channel
51450 + WMI_TARGET_KEY_NOT_FOUND = 0x00000002
51452 + WMI_TARGET_DECRYPTION_ERR = 0x00000004
51454 + WMI_TARGET_BMISS = 0x00000008
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
51463 + } WMI_TARGET_ERROR_VAL
51466 + Bitmask is 0, and all error reporting is disabled
51472 +=====================================================================
51481 + Contains information describing BSSs collected during a scan
51484 + Indicates signalling events in admission control
51487 + The AR6000 device encounters an error while attempting to process
51491 + The device has connected to a wireless network
51494 + The device lost connectivity with a wireless network
51497 + An error has occurred for which the host previously requested
51498 + notification with the command
51499 +
\93TARGET_ERROR_REPORT_BITMASK
\94
51502 + WMI extension event
51504 +GET_PMKID_LIST_EVENT
51505 + Created in response to a
\93GET_PMKID_LIST_CMD
\94 command
51507 +GET_WOW_LIST_EVENT
51508 + Response to the wmiconfig
\93GET_WOW_LIST
\94 command to
51509 + retrieve the configured WoW patterns
51512 + Neighbor APs that match the current profile were detected
51514 +OPT_RX_FRAME_EVENT
51515 + (Special feature) informs the host of the reception of a special frame
51518 + A prioritized stream has been idle for a specified interval
51521 + The AR6000 device is ready to accept commands
51524 + The regulatory domain has changed
51526 +REPORT_ROAM_DATA_EVENT
51527 + Reports the roam time calculations made by the device
51528 + (generated with a special build)
51532 + Reply to a
\93GET_TARGET_STATS
\94 command
51535 + Reports the roam table
51538 + Signal strength from the connected AP has crossed the threshold
51539 + defined in the
\93RSSI_THRESHOLD_PARAMS
\94 command
51541 +SCAN_COMPLETE_EVENT
51542 + A scan has completed (added status SCAN_ABORTED in release 2.0)
51545 + Event generated by the TCMD
51548 + TKIP MIC errors were detected
51550 +=====================================================================
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.
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.
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.
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
51589 + Indicates signal strength
51590 + A_UINT8 bssid[ATH_MAC_LEN];
51592 + } _ATTRIB_PACK_WMI_BSS_INFO_HDR;
51594 + Beacon or Probe Response Frame
51598 + BEACON_FTYPE = 0x1
51599 + Indicates a beacon frame
51601 + Indicates a probe response frame
51602 + ACTION_MGMT_FTYPE
51605 +=====================================================================
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.
51622 + Access class pertaining to the
51625 + UINT8 cac_indication
51626 + Type of indication; indications are
51627 + listed in WMI_CAC_INDICATION
51630 + AP response status code for a
51633 + UINT8 tspecSuggestion[63]
51634 + Suggested TSPEC from AP
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
51645 +=====================================================================
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.
51660 + Corresponds to the command which generated
51663 + A WMI_ERROR_CODE value
51667 + INVALID_PARAM = 1
51668 + Invalid parameter
51669 + ILLEGAL_STATE = 2
51671 + INTERNAL_ERROR = 3
51673 + All other values reserved
51677 +=====================================================================
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.
51693 + Channel frequency (in MHz) of the network the
51694 + AR6000 are connected to
51697 + MAC address of the AP the AR6000 are
51698 + connected to or the BSSID of the ad hoc
51701 + UINT16 listenInterval
51702 + Listen interval (in Kms) that the AR6000 are
51705 + UINT 8 beaconIeLen
51706 + Length (in bytes) of the beacon IEs
51709 + Pointer to an array containing beacon IEs,
51710 + followed first by association request IEs then by
51711 + association response IEs
51713 + UINT8 assocReqLen
51714 + Length (in bytes) of the assocReqIEs array
51716 + UINT8 assocRespLen
51717 + Length (in bytes) of the assocRespIEs array
51722 +=====================================================================
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.
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.
51743 + A WMI_DISCONNECT_REASON value
51746 + Indicates which BSS the device was connected to
51748 + UINT8 assocRespLen
51749 + Length of the 802.11 association response frame
51750 + that triggered this event, or 0 if not applicable
51752 + UINT8 assocInfo[assocRespLen]
51753 + Copy of the 802.11 association response frame
51757 + NO_NETWORK_AVAIL =0x01
51758 + Indicates that the device was unable to
51759 + establish or find the desired network
51761 + Indicates the devices is no longer receiving
51762 + beacons from the BSS it was previously
51765 + DISCONNECT_CMD =0x03
51766 + Indicates a
\93DISCONNECT
\94 command was
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
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
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
51790 + INVALID_PROFILE =0x0A
51791 + Indicates that an attempt was made to
51792 + reconnect to a BSS that no longer matches the
51794 + All other values are reserved
51795 + } WMI_DISCONNECT_REASON
51798 +=====================================================================
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.
51813 + WMI_TARGET_ERROR_VAL value. See
51814 +
\93TARGET_ERROR_REPORT_BITMASK
\94.
51831 + A non-power save disabled node has joined
51832 + the PS-enabled network
51835 +=====================================================================
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
51853 +=====================================================================
51857 + GET_PMKID_LIST_EVENT
51860 + Generated by firmware in response to a
\93GET_PMKID_LIST_CMD
\94 command.
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;
51873 +=====================================================================
51877 + GET_WOW_LIST_EVENT
51880 + Response to the wmiconfig
\96getwowlist command to retrieve the configured Wake on
51881 + Wireless patterns
51889 + A_UINT8 num_filters
51890 + Total number of patterns in the list
51891 + A_UINT8 this_filter_num
51892 + The filter number
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;
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
51920 +=====================================================================
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.
51932 + A total of numberOfAps pairs of bssid/bssFlags exist, one pair for each AP.
51938 + UINT8 numberOfAps
51939 + The number of APs reported about in
51943 + MAC address of a neighbor AP
51945 + A WMI_BSS_FLAGS value
51951 + WMI_DEFAULT_BSS_FLAGS = 0
51952 + Logical OR of 1 or more
51954 + WMI_PREAUTH_CAPABLE_BSS
51956 + Indicates that this AP is capable of
51957 + preauthentication
51958 + WMI_PMKID_VALID_BSS
51960 + Indicates that the AR6000 have a
51961 + valid pairwise master key for this AP
51965 +=====================================================================
51970 + OPT_RX_FRAME_EVENT
51973 + Special feature, informs host of the reception of a special frame.
51980 + A_UINT16 channel;
51981 + A_UINT8 frameType;
51983 + A_UINT8 srcAddr[ATH_MAC_LEN];
51984 + A_UINT8 bssid[ATH_MAC_LEN];
51985 + }WMI_OPT_RX_INFO_HDR
51990 +=====================================================================
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.
52011 + Indicated the traffic class of priority
52012 + stream that timed out
52027 +=====================================================================
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.
52041 + Device MAC address
52042 + UINT8 phyCapability
52043 + A WMI_PHY_CAPABILITY value. Indicates the
52044 + capabilities of the device wireless module
\92s radio
52048 + WMI_11A_CAPABILITY = 1
52049 + WMI_11G_CAPABILITY = 2
52050 + WMI_11AG_CAPABILITY = 3
52051 + } WMI_PHY_CAPABILITY
52054 +=====================================================================
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.
52073 + The range of 0x0000
\96 0x00FF
52074 + corresponds to an ISO country code.
52076 + Other regCodes are reserved for world
52077 + mode settings and specific regulatory
52084 +=====================================================================
52089 + REPORT_STATISTICS
52092 + A reply to a
\93GET_TARGET_STATS
\94 command.
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.
52101 + UINT32 tx_packets
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
52114 + Number of packets which failed Tx, due
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
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
52134 + Number of Rx errors due to all failures
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
52140 + UINT32 rx_decrypt_err
52141 + Number of Rx errors due to decryption
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
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
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.
52187 +=====================================================================
52193 + Reports the roam table, which contains the current roam mode and this information
52200 + A_UINT8 bssid[ATH_MAC_LEN];
52206 + A_UINT8 last_rssi
52207 + Last recorded RSSI
52208 + A_UINT8 roam_util
52209 + Utility value used in roaming decision
52211 + Base utility with the BSS
52213 + Host configured for this BSS
52217 + Current roam mode
52223 + Host bias-based roam
52226 + Lock to the current BSS
52229 + Autonomous roaming disabled
52232 +=====================================================================
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
52247 + A WMI_RSSI_THRESHOLD_VAL
52248 + value, which indicates the range of
52249 + the average signal strength
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
52261 +=====================================================================
52264 + SCAN_COMPLETE_EVENT
52267 + Indicates the scan status. if the Scan was not completed, this event is generated with
52268 + the status A_ECANCELED.
52274 + A_UINT8 scanStatus
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;
52285 +=====================================================================
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.
52306 +=====================================================================
52314 + Indicates that TKIP MIC errors were detected.
52321 + Indicates the TKIP key ID
52328 + See event parameters
52330 +=====================================================================
52332 +WMI Extension Commands
52334 +The WMI EXTENSION command is used to multiplex a collection of
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
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.
52348 +All extensions (subcommandIds) are listed in the header file include/wmix.h.
52349 +See also
\93WMI Extension Events
\94 on page B-58.
52352 +WMI Extension Commands
52356 + Read GPIO pins configured for input
52359 + Acknowledge and re-arm GPIO interrupts reported earlier
52362 + Manage output on GPIO pins configured for output
52365 + Read an arbitrary GPIO register
52368 + Dynamically change GPIO configuration
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
52376 +=====================================================================
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.
52385 +NOTE: Support for GPIO is optional.
52390 +Command Parameters
52407 +=====================================================================
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).
52420 +NOTE: Support for GPIO is optional.
52425 +Command Parameters
52427 + A mask of interrupting GPIO pins (e.g., ack_mask
52428 + bit [3] acknowledges an interrupt from the pin GPIO3).
52437 + The host should acknowledge only interrupts about which it was notified.
52440 +=====================================================================
52446 + Manages output on GPIO pins configured for output.
52448 + Conflicts between set_mask and clear_mask or enable_mask and disable_mask result
52449 + in undefined behavior.
52451 +NOTE: Support for GPIO is optional.
52456 +Command Parameters
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
52479 +=====================================================================
52483 + GPIO_REGISTER_GET
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.
52489 +NOTE: Support for GPIO is optional.
52494 +Command Parameters
52497 + Specifies a GPIO register identifier, as defined
52498 +in include/AR6000/AR6000_gpio.h
52510 +=====================================================================
52513 + GPIO_REGISTER_SET
52516 + Allows the host to dynamically change GPIO configuration (usually handled
52517 + statically through the GPIO configuration DataSet).
52519 +NOTE: Support for GPIO is optional.
52524 +Command Parameters
52525 + UINT32 gpioreg_id
52526 + Specifies a GPIO register identifier, as defined in
52527 + include/AR6000/AR6000_gpio.h
52529 + Specifies a value to write to the specified
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.
52545 +=====================================================================
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.
52556 + wmiconfig eth1 --lqThreshold <enable> <upper_threshold_1>...
52557 + <upper_threshold_4> <lower_threshold_1>... <lower_threshold_4>
52559 +Command Parameters
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;
52573 + Disable link quality sampling
52576 + Enable link quality sampling
52579 + thresholdAbove_Val
52581 + Above thresholds (value in [0,100]), in ascending
52584 + Below_Val [1...4] = below thresholds (value
52585 + in [0,100]), in ascending order
52593 +=====================================================================
52594 +WMI Extension Events
52596 +The WMI EXTENSION event is used for a collection of events that:
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
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
52610 +All extensions (subcommandIds) are listed in the header file include/wmix.h.
52611 +See also
\93WMI Extension Commands
\94 on page B-55.
52614 +WMI Extension Events
52618 + Acknowledges a host set command has been processed by the device
52621 + Response to a host
\92s request for data
52624 + Signals that GPIO interrupts are pending
52627 +=====================================================================
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.
52636 +NOTE: Support for GPIO is optional.
52648 +=====================================================================
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).
52658 +NOTE: Support for GPIO is optional.
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).
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)
52677 +=====================================================================
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.
52691 +NOTE: Support for GPIO is optional.
52698 + Indicates which GPIO interrupts are currently pending
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
52709 +=====================================================================
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
52715 +#ifndef _WMI_HOST_H_
52716 +#define _WMI_HOST_H_
52718 + * Copyright (c) 2004-2006 Atheros Communications Inc.
52719 + * All rights reserved.
52721 + * This file contains local definitios for the wmi host module.
52723 + * $Id: //depot/sw/releases/olca2.0-GPL/host/wmi/wmi_host.h#1 $
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;
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.
52739 +#ifdef __cplusplus
52743 +struct wmi_stats {
52744 + A_UINT32 cmd_len_err;
52745 + A_UINT32 cmd_id_err;
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;
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;
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; }
52775 +#define WMI_WMISTREAM_ACCESSCATEGORY(w,s) (w)->wmi_wmiStream2AcMapping[s]
52776 +#define WMI_ACCESSCATEGORY_WMISTREAM(w,ac) (w)->wmi_ac2WmiStreamMapping[ac]
52778 +#define LOCK_WMI(w) A_MUTEX_LOCK(&(w)->wmi_lock);
52779 +#define UNLOCK_WMI(w) A_MUTEX_UNLOCK(&(w)->wmi_lock);
52781 +#ifdef __cplusplus
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 @@
52791 EXPORT_SYMBOL_GPL(bus_remove_file);
52793 +int bus_create_device_link(struct bus_type *bus, struct kobject *target,
52794 + const char *name)
52797 + if (bus_get(bus)) {
52798 + error = sysfs_create_link(&bus->p->devices_kset->kobj, target,
52805 +EXPORT_SYMBOL_GPL(bus_create_device_link);
52807 +void bus_remove_device_link(struct bus_type *bus, const char *name)
52809 + if (bus_get(bus)) {
52810 + sysfs_remove_link(&bus->p->devices_kset->kobj, name);
52814 +EXPORT_SYMBOL_GPL(bus_remove_device_link);
52816 static struct kobj_type bus_ktype = {
52817 .sysfs_ops = &bus_sysfs_ops,
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
52824 const char *dev_driver_string(const struct device *dev)
52827 + printk(KERN_ERR"Null dev to dev_driver_string\n");
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
52839 void device_pm_add(struct device *dev)
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);
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
52856 +config NR_TTY_DEVICES
52857 + int "Maximum tty device number"
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.
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
52875 #include <linux/err.h>
52876 #include <linux/debugfs.h>
52877 #include <linux/seq_file.h>
52878 -#include <linux/gpio.h>
52880 +#include <mach/gpio.h>
52882 /* Optional implementation infrastructure for GPIO interfaces.
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
52888 #include <linux/platform_device.h>
52889 #include <linux/clk.h>
52890 #include <linux/cpufreq.h>
52891 +#include <linux/io.h>
52893 #include <asm/irq.h>
52894 -#include <asm/io.h>
52896 #include <plat/regs-iic.h>
52897 #include <plat/iic.h>
52898 @@ -135,6 +135,14 @@
52901 tmp = readl(i2c->regs + S3C2410_IICCON);
52903 +/* S3c2442 datasheet
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.
52910 writel(tmp & ~S3C2410_IICCON_IRQEN, i2c->regs + S3C2410_IICCON);
52913 @@ -480,6 +488,15 @@
52914 if (i2c->suspended)
52917 + if (i2c->suspended) {
52918 + dev_err(i2c->dev,
52919 + "Hey I am still asleep (suspended: %d), retry later\n",
52926 ret = s3c24xx_i2c_set_master(i2c);
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 @@
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
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.
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
52952 This driver can also be built as a module. If so, the module
52953 will be called ds1682.
52956 + tristate "EEPROMs from most vendors"
52957 + depends on SYSFS && EXPERIMENTAL
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:
52964 + 24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
52965 + 24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
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.
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).
52978 + This driver can also be built as a module. If so, the module
52979 + will be called at24.
52981 +config SENSORS_EEPROM
52982 + tristate "EEPROM reader"
52983 + depends on EXPERIMENTAL
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.
52989 + This driver can also be built as a module. If so, the module
52990 + will be called eeprom.
52992 +config SENSORS_PCF50606
52993 + tristate "Philips/NXP PCF50606"
52996 + If you say yes here you get support for Philips/NXP PCF50606
52997 + PMU (Power Management Unit) chips.
52999 + This driver can also be built as a module. If so, the module
53000 + will be called pcf50606.
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.
53010 + tristate "Philips/NXP PCA9632 low power LED driver"
53013 + If you say yes here you get support for the Philips/NXP PCA9632
53016 + This driver can also be built as a module. If so, the module
53017 + will be called pca9632.
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
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
53041 + * Philips/NXP PCA9632 low power LED driver.
53042 + * Copyright (C) 2008 Matt Hsu <matt_hsu@openmoko.org>
53044 + * low_level implementation are based on pcf50606 driver
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.
53051 + * - attach ledclass??
53052 + * - add platform data
53056 +#include <linux/module.h>
53057 +#include <linux/init.h>
53058 +#include <linux/i2c.h>
53059 +#include <linux/platform_device.h>
53061 +#include "pca9632.h"
53063 +/* Addresses to scan */
53064 +static unsigned short normal_i2c[] = { 0x62, I2C_CLIENT_END };
53066 +/* Insmod parameters */
53067 +I2C_CLIENT_INSMOD_1(pca9632);
53069 +enum pca9632_pwr_state {
53074 +enum pca9632_led_output {
53077 + PCA9632_CTRL_BY_PWM,
53078 + PCA9632_CTRL_BY_PWM_GRPPWM,
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",
53088 +struct pca9632_data {
53089 + struct i2c_client client;
53090 + struct mutex lock;
53093 +static struct i2c_driver pca9632_driver;
53094 +static struct platform_device *pca9632_pdev;
53096 +static int pca9632_attach_adapter(struct i2c_adapter *adapter);
53097 +static int pca9632_detach_client(struct i2c_client *client);
53099 +static int __reg_write(struct pca9632_data *pca, u_int8_t reg, u_int8_t val)
53101 + return i2c_smbus_write_byte_data(&pca->client, reg, val);
53104 +static int reg_write(struct pca9632_data *pca, u_int8_t reg, u_int8_t val)
53108 + mutex_lock(&pca->lock);
53109 + ret = __reg_write(pca, reg, val);
53110 + mutex_unlock(&pca->lock);
53115 +static int32_t __reg_read(struct pca9632_data *pca, u_int8_t reg)
53119 + ret = i2c_smbus_read_byte_data(&pca->client, reg);
53124 +static u_int8_t reg_read(struct pca9632_data *pca, u_int8_t reg)
53128 + mutex_lock(&pca->lock);
53129 + ret = __reg_read(pca, reg);
53130 + mutex_unlock(&pca->lock);
53132 + return ret & 0xff;
53135 +static int reg_set_bit_mask(struct pca9632_data *pca,
53136 + u_int8_t reg, u_int8_t mask, u_int8_t val)
53143 + mutex_lock(&pca->lock);
53145 + tmp = __reg_read(pca, reg);
53148 + ret = __reg_write(pca, reg, tmp);
53150 + mutex_unlock(&pca->lock);
53155 +static inline int calc_dc(uint8_t idc)
53157 + return (idc * 100) / 256;
53163 +static int software_rst(struct i2c_adapter *adapter)
53165 + u8 buf[] = { 0xa5, 0x5a };
53167 + struct i2c_msg msg[] = {
53172 + .len = sizeof(buf)
53176 + return i2c_transfer(adapter, msg, 1);
53180 + * Group dmblnk control
53182 +static void config_group_dmblnk(struct pca9632_data *pca, int group_dmblnk_mode)
53184 + reg_set_bit_mask(pca, PCA9632_REG_MODE2, 0x20,
53185 + group_dmblnk_mode << PCA9632_DMBLNK_SHIFT);
53188 +static int get_group_dmblnk(struct pca9632_data *pca)
53190 + return reg_read(pca, PCA9632_REG_MODE2) >> PCA9632_DMBLNK_SHIFT;
53193 +static ssize_t show_group_dmblnk(struct device *dev, struct device_attribute
53194 + *attr, char *buf)
53196 + struct i2c_client *client = to_i2c_client(dev);
53197 + struct pca9632_data *pca = i2c_get_clientdata(client);
53199 + if (get_group_dmblnk(pca))
53200 + return sprintf(buf, "blinking\n");
53202 + return sprintf(buf, "dimming\n");
53205 +static ssize_t set_group_dmblnk(struct device *dev, struct device_attribute
53206 + *attr, const char *buf, size_t count)
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);
53213 + dev_info(&pca->client.dev, "blinking\n");
53215 + dev_info(&pca->client.dev, "dimming\n");
53217 + config_group_dmblnk(pca, mode);
53222 +static DEVICE_ATTR(group_dmblnk, S_IRUGO | S_IWUSR, show_group_dmblnk,
53223 + set_group_dmblnk);
53225 +static int reg_id_by_name(const char *name)
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;
53241 +static int get_led_output(struct pca9632_data *pca, int ldrx)
53243 + u_int8_t led_state;
53246 + led_state = reg_read(pca, PCA9632_REG_LEDOUT);
53247 + led_state = (led_state >> (2 * ldrx)) & 0x03;
53249 + return led_state;
53252 +static void config_led_output(struct pca9632_data *pca, int ldrx,
53253 + enum pca9632_led_output led_output)
53259 + mask = 0x03 << (2 * ldrx);
53260 + tmp = reg_set_bit_mask(pca, PCA9632_REG_LEDOUT,
53261 + mask, led_output << (2 * ldrx));
53265 + * Individual brightness control
53267 +static ssize_t show_brightness(struct device *dev, struct device_attribute
53268 + *attr, char *buf)
53270 + struct i2c_client *client = to_i2c_client(dev);
53271 + struct pca9632_data *pca = i2c_get_clientdata(client);
53274 + ldrx = reg_id_by_name(attr->attr.name);
53276 + switch (get_led_output(pca, ldrx)) {
53278 + case PCA9632_OFF:
53280 + return sprintf(buf, "%s",
53281 + led_output_name[get_led_output(pca, ldrx)]);
53283 + case PCA9632_CTRL_BY_PWM:
53284 + return sprintf(buf, "%d%% \n", calc_dc(reg_read(pca, ldrx)));
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)));
53297 + return sprintf(buf, "invalid argument\n");
53300 +static ssize_t set_brightness(struct device *dev, struct device_attribute *attr,
53301 + const char *buf, size_t count)
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);
53308 + ldrx = reg_id_by_name(attr->attr.name);
53309 + reg_set_bit_mask(pca, ldrx, 0xff, pwm);
53315 +DEVICE_ATTR(led0_pwm, S_IRUGO | S_IWUSR, show_brightness, set_brightness);
53317 +DEVICE_ATTR(led1_pwm, S_IRUGO | S_IWUSR, show_brightness, set_brightness);
53319 +DEVICE_ATTR(led2_pwm, S_IRUGO | S_IWUSR, show_brightness, set_brightness);
53321 +DEVICE_ATTR(led3_pwm, S_IRUGO | S_IWUSR, show_brightness, set_brightness);
53324 + * Group frequency control
53326 +static ssize_t show_group_freq(struct device *dev, struct device_attribute
53327 + *attr, char *buf)
53330 + struct i2c_client *client = to_i2c_client(dev);
53331 + struct pca9632_data *pca = i2c_get_clientdata(client);
53333 + period = ((reg_read(pca, PCA9632_REG_GRPFREQ) + 1) * 1000) / 24;
53335 + return sprintf(buf, "%d ms\n", period);
53338 +static ssize_t set_group_freq(struct device *dev, struct device_attribute *attr,
53339 + const char *buf, size_t count)
53341 + struct i2c_client *client = to_i2c_client(dev);
53342 + struct pca9632_data *pca = i2c_get_clientdata(client);
53344 + unsigned int freq = simple_strtoul(buf, NULL, 10);
53345 + reg_write(pca, PCA9632_REG_GRPFREQ, freq);
53350 +DEVICE_ATTR(group_freq, S_IRUGO | S_IWUSR, show_group_freq, set_group_freq);
53353 + * Group duty cycle tonrol*
53355 +static ssize_t show_group_dc(struct device *dev, struct device_attribute *attr,
53358 + struct i2c_client *client = to_i2c_client(dev);
53359 + struct pca9632_data *pca = i2c_get_clientdata(client);
53361 + if (get_group_dmblnk(pca)) {
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));
53367 + return sprintf(buf, "%d%% \n", calc_dc(reg_read(pca,
53368 + PCA9632_REG_GRPPWM)));
53371 + return sprintf(buf, "%d%% \n", calc_dc(reg_read(pca,
53372 + PCA9632_REG_GRPPWM) & 0xf0));
53375 +static ssize_t set_group_dc(struct device *dev, struct device_attribute *attr,
53376 + const char *buf, size_t count)
53378 + struct i2c_client *client = to_i2c_client(dev);
53379 + struct pca9632_data *pca = i2c_get_clientdata(client);
53381 + unsigned int dc = simple_strtoul(buf, NULL, 10);
53383 + reg_set_bit_mask(pca, PCA9632_REG_GRPPWM, 0xff, dc);
53388 +static DEVICE_ATTR(group_dc, S_IRUGO | S_IWUSR, show_group_dc, set_group_dc);
53391 + * LED driver output
53393 +static ssize_t show_led_output(struct device *dev, struct device_attribute
53394 + *attr, char *buf)
53396 + struct i2c_client *client = to_i2c_client(dev);
53397 + struct pca9632_data *pca = i2c_get_clientdata(client);
53400 + ldrx = reg_id_by_name(attr->attr.name);
53402 + return sprintf(buf, "%s \n",
53403 + led_output_name[get_led_output(pca, ldrx)]);
53406 +static ssize_t set_led_output(struct device *dev, struct device_attribute *attr,
53407 + const char *buf, size_t count)
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;
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);
53422 +DEVICE_ATTR(led0_output, S_IRUGO | S_IWUSR, show_led_output, set_led_output);
53424 +DEVICE_ATTR(led1_output, S_IRUGO | S_IWUSR, show_led_output, set_led_output);
53426 +DEVICE_ATTR(led2_output, S_IRUGO | S_IWUSR, show_led_output, set_led_output);
53428 +DEVICE_ATTR(led3_output, S_IRUGO | S_IWUSR, show_led_output, set_led_output);
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,
53445 +static struct attribute_group pca_attr_group = {
53446 + .name = NULL, /* put in device directory */
53447 + .attrs = pca_sysfs_entries,
53451 +static int pca9632_suspend(struct device *dev, pm_message_t state)
53453 + /* FIXME: Not implemented */
53457 +static int pca9632_resume(struct device *dev)
53459 + /* FIXME: Not implemented */
53463 +#define pca9632_suspend NULL
53464 +#define pca9632_resume NULL
53467 +static struct i2c_driver pca9632_driver = {
53469 + .name = "pca9632",
53470 + .suspend = pca9632_suspend,
53471 + .resume = pca9632_resume,
53473 + .id = I2C_DRIVERID_PCA9632,
53474 + .attach_adapter = pca9632_attach_adapter,
53475 + .detach_client = pca9632_detach_client,
53478 +static int pca9632_detect(struct i2c_adapter *adapter, int address, int kind)
53480 + struct i2c_client *new_client;
53481 + struct pca9632_data *pca;
53484 + pca = kzalloc(sizeof(struct pca9632_data), GFP_KERNEL);
53488 + mutex_init(&pca->lock);
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;
53497 + strlcpy(new_client->name, "pca9632", I2C_NAME_SIZE);
53499 + /* register with i2c core */
53500 + err = i2c_attach_client(new_client);
53504 + err = sysfs_create_group(&new_client->dev.kobj, &pca_attr_group);
53506 + goto exit_detach;
53508 + /* software reset */
53509 + if (!software_rst(adapter))
53510 + dev_info(&pca->client.dev, "pca9632 sw-rst done\n");
53512 + /* enter normal mode */
53513 + reg_set_bit_mask(pca, PCA9632_REG_MODE1, 0x10, PCA9632_NORMAL);
53518 + i2c_detach_client(new_client);
53525 +static int pca9632_attach_adapter(struct i2c_adapter *adapter)
53527 + return i2c_probe(adapter, &addr_data, pca9632_detect);
53530 +static int pca9632_detach_client(struct i2c_client *client)
53534 + sysfs_remove_group(&client->dev.kobj, &pca_attr_group);
53535 + err = i2c_detach_client(client);
53540 + kfree(i2c_get_clientdata(client));
53545 +static int __init pca9632_plat_probe(struct platform_device *pdev)
53547 + /* FIXME: platform data should be attached here */
53548 + pca9632_pdev = pdev;
53553 +static int pca9632_plat_remove(struct platform_device *pdev)
53558 +static struct platform_driver pca9632_plat_driver = {
53559 + .probe = pca9632_plat_probe,
53560 + .remove = pca9632_plat_remove,
53562 + .owner = THIS_MODULE,
53563 + .name = "pca9632",
53567 +static int __init pca9632_init(void)
53571 + rc = platform_driver_register(&pca9632_plat_driver);
53573 + i2c_add_driver(&pca9632_driver);
53578 +static void __exit pca9632_exit(void)
53580 + i2c_del_driver(&pca9632_driver);
53582 + platform_driver_unregister(&pca9632_plat_driver);
53585 +MODULE_AUTHOR("Matt Hsu <matt_hsu@openmoko.org>");
53586 +MODULE_DESCRIPTION("NXP PCA9632 driver");
53587 +MODULE_LICENSE("GPL");
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
53595 +#ifndef _PCA9632_H
53596 +#define _PCA9632_H
53599 +enum pca9632_regs{
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,
53616 +#define PCA9632_DMBLNK_SHIFT 5
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
53623 +/* Philips/NXP PCF50606 Power Management Unit (PMU) driver
53625 + * (C) 2006-2007 by Openmoko, Inc.
53626 + * Authors: Harald Welte <laforge@openmoko.org>,
53627 + * Matt Hsu <matt@openmoko.org>
53628 + * All rights reserved.
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.
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.
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
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
53650 + * - adc driver (hw_sensors like)
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>
53676 +#include <asm/mach-types.h>
53677 +#include <mach/gta01.h>
53679 +#include "pcf50606.h"
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() */
53685 +#define DEBUGPC(x, args ...) printk(x, ## args)
53687 +#define DEBUGPC(x, args ...)
53690 +/***********************************************************************
53691 + * Static data / structures
53692 + ***********************************************************************/
53694 +static unsigned short normal_i2c[] = { 0x08, I2C_CLIENT_END };
53696 +I2C_CLIENT_INSMOD_1(pcf50606);
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 */
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
53713 +#define PCF50606_F_PWR_PRESSED 0x00000100
53714 +#define PCF50606_F_RTC_SECOND 0x00000200
53716 +enum close_state {
53718 + CLOSE_STATE_ALLOW = 0x2342,
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,
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;
53742 + int onkey_seconds;
53744 + int coldplug_done;
53745 + int suppress_onkey_events;
53746 + enum pcf50606_suspend_states suspend_state;
53749 + u_int8_t dcdc1, dcdc2;
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;
53759 + u_int8_t int1m, int2m, int3m;
53764 +static struct i2c_driver pcf50606_driver;
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);
53772 +static struct platform_device *pcf50606_pdev;
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[] = {
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,
53790 +/***********************************************************************
53791 + * Low-Level routines
53792 + ***********************************************************************/
53794 +static inline int __reg_write(struct pcf50606_data *pcf, u_int8_t reg,
53797 + if (pcf->suspend_state == PCF50606_SS_COMPLETED_SUSPEND) {
53798 + dev_err(&pcf->client.dev, "__reg_write while suspended.\n");
53801 + return i2c_smbus_write_byte_data(&pcf->client, reg, val);
53804 +static int reg_write(struct pcf50606_data *pcf, u_int8_t reg, u_int8_t val)
53808 + mutex_lock(&pcf->lock);
53809 + ret = __reg_write(pcf, reg, val);
53810 + mutex_unlock(&pcf->lock);
53815 +static inline int32_t __reg_read(struct pcf50606_data *pcf, u_int8_t reg)
53819 + if (pcf->suspend_state == PCF50606_SS_COMPLETED_SUSPEND) {
53820 + dev_err(&pcf->client.dev, "__reg_read while suspended.\n");
53823 + ret = i2c_smbus_read_byte_data(&pcf->client, reg);
53828 +static u_int8_t reg_read(struct pcf50606_data *pcf, u_int8_t reg)
53832 + mutex_lock(&pcf->lock);
53833 + ret = __reg_read(pcf, reg);
53834 + mutex_unlock(&pcf->lock);
53836 + return ret & 0xff;
53839 +static int reg_set_bit_mask(struct pcf50606_data *pcf,
53840 + u_int8_t reg, u_int8_t mask, u_int8_t val)
53847 + mutex_lock(&pcf->lock);
53849 + tmp = __reg_read(pcf, reg);
53852 + ret = __reg_write(pcf, reg, tmp);
53854 + mutex_unlock(&pcf->lock);
53859 +static int reg_clear_bits(struct pcf50606_data *pcf, u_int8_t reg, u_int8_t val)
53864 + mutex_lock(&pcf->lock);
53866 + tmp = __reg_read(pcf, reg);
53868 + ret = __reg_write(pcf, reg, tmp);
53870 + mutex_unlock(&pcf->lock);
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)
53879 + u_int8_t adcs2, adcs1;
53882 + dev_dbg(&pcf->client.dev, "entering (pcf=%p, channel=%u, data2=%p)\n",
53883 + pcf, channel, data2);
53885 + channel &= PCF50606_ADCC2_ADCMUX_MASK;
53887 + mutex_lock(&pcf->lock);
53889 + /* start ADC conversion of selected channel */
53890 + __reg_write(pcf, PCF50606_REG_ADCC2, channel |
53891 + PCF50606_ADCC2_ADCSTART | PCF50606_ADCC2_RES_10BIT);
53894 + adcs2 = __reg_read(pcf, PCF50606_REG_ADCS2);
53895 + } while (!(adcs2 & PCF50606_ADCS2_ADCRDY));
53897 + adcs1 = __reg_read(pcf, PCF50606_REG_ADCS1);
53898 + ret = (adcs1 << 2) | (adcs2 & 0x03);
53901 + adcs1 = __reg_read(pcf, PCF50606_REG_ADCS3);
53902 + *data2 = (adcs1 << 2) | ((adcs2 & 0x0c) >> 2);
53905 + mutex_unlock(&pcf->lock);
53907 + dev_dbg(&pcf->client.dev, "returning %u %u\n", ret,
53908 + data2 ? *data2 : 0);
53913 +/***********************************************************************
53915 + ***********************************************************************/
53917 +static u_int8_t dcudc_voltage(unsigned int millivolts)
53919 + if (millivolts < 900)
53921 + if (millivolts > 5500)
53923 + if (millivolts <= 3300) {
53924 + millivolts -= 900;
53925 + return millivolts/300;
53927 + if (millivolts < 4000)
53930 + millivolts -= 4000;
53931 + return millivolts/100;
53935 +static unsigned int dcudc_2voltage(u_int8_t bits)
53939 + return 900 + bits * 300;
53940 + else if (bits < 0x10)
53943 + return 4000 + bits * 100;
53946 +static u_int8_t dcdec_voltage(unsigned int millivolts)
53948 + if (millivolts < 900)
53950 + else if (millivolts > 3300)
53953 + millivolts -= 900;
53954 + return millivolts/300;
53957 +static unsigned int dcdec_2voltage(u_int8_t bits)
53960 + return 900 + bits*300;
53963 +static u_int8_t dcdc_voltage(unsigned int millivolts)
53965 + if (millivolts < 900)
53967 + else if (millivolts > 3600)
53970 + if (millivolts < 1500) {
53971 + millivolts -= 900;
53972 + return millivolts/25;
53974 + millivolts -= 1500;
53975 + return 0x18 + millivolts/300;
53979 +static unsigned int dcdc_2voltage(u_int8_t bits)
53982 + if ((bits & 0x18) == 0x18)
53983 + return 1500 + ((bits & 0x7) * 300);
53985 + return 900 + (bits * 25);
53988 +static u_int8_t dx_voltage(unsigned int millivolts)
53990 + if (millivolts < 900)
53992 + else if (millivolts > 3300)
53995 + millivolts -= 900;
53996 + return millivolts/100;
53999 +static unsigned int dx_2voltage(u_int8_t bits)
54002 + return 900 + (bits * 100);
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,
54016 +int pcf50606_onoff_set(struct pcf50606_data *pcf,
54017 + enum pcf50606_regulator_id reg, int on)
54021 + if (reg >= __NUM_PCF50606_REGULATORS)
54024 + /* IOREG cannot be powered off since it powers the PMU I2C */
54025 + if (reg == PCF50606_REGULATOR_IOREG)
54028 + addr = regulator_registers[reg];
54031 + reg_set_bit_mask(pcf, addr, 0xe0, 0x00);
54033 + reg_set_bit_mask(pcf, addr, 0xe0, 0xe0);
54037 +EXPORT_SYMBOL_GPL(pcf50606_onoff_set);
54039 +int pcf50606_onoff_get(struct pcf50606_data *pcf,
54040 + enum pcf50606_regulator_id reg)
54042 + u_int8_t val, addr;
54044 + if (reg >= __NUM_PCF50606_REGULATORS)
54047 + addr = regulator_registers[reg];
54048 + val = (reg_read(pcf, addr) & 0xe0) >> 5;
54050 + /* PWREN1 = 1, PWREN2 = 1, see table 16 of datasheet */
54059 +EXPORT_SYMBOL_GPL(pcf50606_onoff_get);
54061 +int pcf50606_voltage_set(struct pcf50606_data *pcf,
54062 + enum pcf50606_regulator_id reg,
54063 + unsigned int millivolts)
54065 + u_int8_t volt_bits;
54069 + dev_dbg(&pcf->client.dev, "pcf=%p, reg=%d, mvolts=%d\n", pcf, reg,
54072 + if (reg >= __NUM_PCF50606_REGULATORS)
54075 + if (millivolts > pcf->pdata->rails[reg].voltage.max)
54079 + case PCF50606_REGULATOR_DCD:
54080 + volt_bits = dcdc_voltage(millivolts);
54081 + rc = reg_set_bit_mask(pcf, PCF50606_REG_DCDC1, 0x1f,
54084 + case PCF50606_REGULATOR_DCDE:
54085 + volt_bits = dcdec_voltage(millivolts);
54086 + rc = reg_set_bit_mask(pcf, PCF50606_REG_DCDEC1, 0x0f,
54089 + case PCF50606_REGULATOR_DCUD:
54090 + volt_bits = dcudc_voltage(millivolts);
54091 + rc = reg_set_bit_mask(pcf, PCF50606_REG_DCUDC1, 0x1f,
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);
54101 + case PCF50606_REGULATOR_LPREG:
54102 + volt_bits = dx_voltage(millivolts);
54103 + rc = reg_set_bit_mask(pcf, PCF50606_REG_LPREGC1, 0x1f,
54106 + case PCF50606_REGULATOR_IOREG:
54107 + if (millivolts < 1800)
54109 + volt_bits = dx_voltage(millivolts);
54110 + rc = reg_set_bit_mask(pcf, PCF50606_REG_IOREGC, 0x1f,
54119 +EXPORT_SYMBOL_GPL(pcf50606_voltage_set);
54121 +unsigned int pcf50606_voltage_get(struct pcf50606_data *pcf,
54122 + enum pcf50606_regulator_id reg)
54124 + u_int8_t volt_bits;
54126 + unsigned int rc = 0;
54128 + if (reg >= __NUM_PCF50606_REGULATORS)
54132 + case PCF50606_REGULATOR_DCD:
54133 + volt_bits = reg_read(pcf, PCF50606_REG_DCDC1) & 0x1f;
54134 + rc = dcdc_2voltage(volt_bits);
54136 + case PCF50606_REGULATOR_DCDE:
54137 + volt_bits = reg_read(pcf, PCF50606_REG_DCDEC1) & 0x0f;
54138 + rc = dcdec_2voltage(volt_bits);
54140 + case PCF50606_REGULATOR_DCUD:
54141 + volt_bits = reg_read(pcf, PCF50606_REG_DCUDC1) & 0x1f;
54142 + rc = dcudc_2voltage(volt_bits);
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);
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);
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);
54171 +EXPORT_SYMBOL_GPL(pcf50606_voltage_get);
54173 +/* go into 'STANDBY' mode, i.e. power off the main CPU and peripherals */
54174 +void pcf50606_go_standby(void)
54176 + reg_write(pcf50606_global, PCF50606_REG_OOCC1,
54177 + PCF50606_OOCC1_GOSTDBY);
54179 +EXPORT_SYMBOL_GPL(pcf50606_go_standby);
54181 +void pcf50606_gpo0_set(struct pcf50606_data *pcf, int on)
54190 + reg_set_bit_mask(pcf, PCF50606_REG_GPOC1, 0x0f, val);
54192 +EXPORT_SYMBOL_GPL(pcf50606_gpo0_set);
54194 +int pcf50606_gpo0_get(struct pcf50606_data *pcf)
54196 + u_int8_t reg = reg_read(pcf, PCF50606_REG_GPOC1) & 0x0f;
54198 + if (reg == 0x07 || reg == 0x08)
54203 +EXPORT_SYMBOL_GPL(pcf50606_gpo0_get);
54205 +static void pcf50606_work(struct work_struct *work)
54207 + struct pcf50606_data *pcf =
54208 + container_of(work, struct pcf50606_data, work);
54209 + u_int8_t pcfirq[3];
54212 + mutex_lock(&pcf->working_lock);
54213 + pcf->working = 1;
54216 + if (!&pcf->client.dev)
54220 + * if we are presently suspending, we are not in a position to deal
54221 + * with pcf50606 interrupts at all.
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.
54230 + if ((pcf->suspend_state == PCF50606_SS_STARTING_SUSPEND) ||
54231 + (pcf->suspend_state == PCF50606_SS_COMPLETED_SUSPEND))
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
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
54248 + if (pcf->suspend_state &&
54249 + (pcf->suspend_state != PCF50606_SS_COMPLETED_RESUME))
54252 + /* this is the case early in resume! Sanity check! */
54253 + if (i2c_get_clientdata(&pcf->client) == NULL)
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
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);
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.
54277 + /* hey did we just resume? (because we don't get here unless we are
54278 + * running normally or the first call after resumption)
54280 + * pcf50606 resume is really really over now then.
54282 + if (pcf->suspend_state != PCF50606_SS_RUNNING) {
54283 + pcf->suspend_state = PCF50606_SS_RUNNING;
54285 + /* peek at the IRQ reason, if power button then set a flag
54286 + * so that we do not signal the event to userspace
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");
54293 + pcf->suppress_onkey_events = 0;
54297 + if (!pcf->coldplug_done) {
54298 + DEBUGPC("PMU Coldplug init\n");
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);
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,
54318 + pcf->coldplug_done = 1;
54322 + dev_dbg(&pcf->client.dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x:",
54323 + pcfirq[0], pcfirq[1], pcfirq[2]);
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);
54332 + DEBUGPC("ONKEYF(unreported) ");
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);
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);
54354 + DEBUGPC("ONKEYR(suppressed) ");
54355 + /* don't suppress any more power button events */
54356 + pcf->suppress_onkey_events = 0;
54358 + /* disable SECOND interrupt in case RTC didn't
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);
54365 + if (pcfirq[0] & PCF50606_INT1_EXTONR) {
54366 + DEBUGPC("EXTONR ");
54367 + input_report_key(pcf->input_dev, KEY_POWER2, 1);
54369 + if (pcfirq[0] & PCF50606_INT1_EXTONF) {
54370 + DEBUGPC("EXTONF ");
54371 + input_report_key(pcf->input_dev, KEY_POWER2, 0);
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);
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' */
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
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) ");
54403 + /* FIXME: what to do if userspace doesn't
54404 + * shut down? Do we want to force it? */
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);
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 */
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 */
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 */
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 */
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 */
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 */
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);
54470 + if (pcfirq[1] & PCF50606_INT2_CHGWDEXP) {
54471 + /* Charger watchdog expires */
54472 + DEBUGPC("CHGWDEXP ");
54473 + /* FIXME: how to signal this to userspace */
54476 + if (pcfirq[2] & PCF50606_INT3_ADCRDY) {
54477 + /* ADC result ready */
54478 + DEBUGPC("ADCRDY ");
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);
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);
54494 + /* FIXME: TSCPRES */
54495 + if (pcfirq[2] & PCF50606_INT3_LOWBAT) {
54496 + if (__reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON) {
54498 + * hey no need to freak out, we have some kind of
54499 + * valid charger power
54501 + DEBUGPC("(NO)BAT ");
54503 + /* Really low battery voltage, we have 8 seconds left */
54504 + DEBUGPC("LOWBAT ");
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
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);
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
54526 + apm_queue_event(APM_CRITICAL_SUSPEND);
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);
54533 + if (pcfirq[2] & PCF50606_INT3_HIGHTMP) {
54534 + /* High temperature */
54535 + DEBUGPC("HIGHTMP ");
54536 + apm_queue_event(APM_CRITICAL_SUSPEND);
54542 + pcf->working = 0;
54543 + input_sync(pcf->input_dev);
54544 + put_device(&pcf->client.dev);
54545 + mutex_unlock(&pcf->working_lock);
54551 + if ((pcf->suspend_state != PCF50606_SS_STARTING_SUSPEND) &&
54552 + (pcf->suspend_state != PCF50606_SS_COMPLETED_SUSPEND)) {
54554 + dev_info(&pcf->client.dev, "rescheduling interrupt service\n");
54556 + if (!schedule_work(&pcf->work))
54557 + dev_err(&pcf->client.dev, "int service reschedule failed\n");
54559 + /* we don't put the device here, hold it for next time */
54560 + mutex_unlock(&pcf->working_lock);
54563 +static irqreturn_t pcf50606_irq(int irq, void *_pcf)
54565 + struct pcf50606_data *pcf = _pcf;
54567 + dev_dbg(&pcf->client.dev, "entering(irq=%u, pcf=%p): scheduling work\n",
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");
54573 + return IRQ_HANDLED;
54576 +static u_int16_t adc_to_batt_millivolts(u_int16_t adc)
54578 + u_int16_t mvolts;
54580 + mvolts = (adc * 6000) / 1024;
54585 +#define BATTVOLT_SCALE_START 2800
54586 +#define BATTVOLT_SCALE_END 4200
54587 +#define BATTVOLT_SCALE_DIVIDER ((BATTVOLT_SCALE_END - BATTVOLT_SCALE_START)/100)
54589 +static u_int8_t battvolt_scale(u_int16_t battvolt)
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;
54598 +u_int16_t pcf50606_battvolt(struct pcf50606_data *pcf)
54601 + adc = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_RES, NULL);
54603 + return adc_to_batt_millivolts(adc);
54605 +EXPORT_SYMBOL_GPL(pcf50606_battvolt);
54607 +static ssize_t show_battvolt(struct device *dev, struct device_attribute *attr,
54610 + struct i2c_client *client = to_i2c_client(dev);
54611 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54613 + return sprintf(buf, "%u\n", pcf50606_battvolt(pcf));
54615 +static DEVICE_ATTR(battvolt, S_IRUGO | S_IWUSR, show_battvolt, NULL);
54617 +static int reg_id_by_name(const char *name)
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;
54643 +static ssize_t show_vreg(struct device *dev, struct device_attribute *attr,
54646 + struct i2c_client *client = to_i2c_client(dev);
54647 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54648 + unsigned int reg_id;
54650 + reg_id = reg_id_by_name(attr->attr.name);
54654 + if (pcf50606_onoff_get(pcf, reg_id) > 0)
54655 + return sprintf(buf, "%u\n", pcf50606_voltage_get(pcf, reg_id));
54657 + return strlcpy(buf, "0\n", PAGE_SIZE);
54660 +static ssize_t set_vreg(struct device *dev, struct device_attribute *attr,
54661 + const char *buf, size_t count)
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;
54668 + reg_id = reg_id_by_name(attr->attr.name);
54672 + dev_dbg(dev, "attempting to set %s(%d) to %lu mvolts\n",
54673 + attr->attr.name, reg_id, mvolts);
54675 + if (mvolts == 0) {
54676 + pcf50606_onoff_set(pcf, reg_id, 0);
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);
54684 + pcf50606_onoff_set(pcf, reg_id, 1);
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);
54699 +/***********************************************************************
54700 + * Charger Control
54701 + ***********************************************************************/
54703 +/* Enable/disable fast charging (500mA in the GTA01) */
54704 +void pcf50606_charge_fast(struct pcf50606_data *pcf, int on)
54706 + if (!(pcf->pdata->used_features & PCF50606_FEAT_MBC))
54710 + /* We can allow PCF to automatically charge
54712 + pcf->flags |= PCF50606_F_CHG_FAST;
54713 + reg_set_bit_mask(pcf, PCF50606_REG_MBCC1,
54714 + PCF50606_MBCC1_AUTOFST,
54715 + PCF50606_MBCC1_AUTOFST);
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
54723 + reg_set_bit_mask(pcf, PCF50606_REG_MBCC1,
54724 + PCF50606_MBCC1_CHGMOD_MASK,
54725 + PCF50606_MBCC1_CHGMOD_IDLE);
54728 +EXPORT_SYMBOL_GPL(pcf50606_charge_fast);
54730 +static inline u_int16_t adc_to_rntc(struct pcf50606_data *pcf, u_int16_t adc)
54732 + u_int32_t r_ntc = (adc * (u_int32_t)pcf->pdata->r_fix_batt)
54738 +static inline int16_t rntc_to_temp(u_int16_t rntc)
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 */
54746 + return -99; /* Below our range */
54749 +static ssize_t show_battemp(struct device *dev, struct device_attribute *attr,
54752 + struct i2c_client *client = to_i2c_client(dev);
54753 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54756 + adc = adc_read(pcf, PCF50606_ADCMUX_BATTEMP, NULL);
54758 + return sprintf(buf, "%d\n", rntc_to_temp(adc_to_rntc(pcf, adc)));
54760 +static DEVICE_ATTR(battemp, S_IRUGO | S_IWUSR, show_battemp, NULL);
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)
54766 + int32_t res = (adc_adcin1 - adc_batvolt) * 2400;
54767 + return (res * 1000) / (pcf->pdata->r_sense_milli * 1024);
54770 +static ssize_t show_chgcur(struct device *dev, struct device_attribute *attr,
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;
54778 + adc_batvolt = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_ADCIN1,
54780 + ma = adc_to_chg_milliamps(pcf, adc_adcin1, adc_batvolt);
54782 + return sprintf(buf, "%d\n", ma);
54784 +static DEVICE_ATTR(chgcur, S_IRUGO | S_IWUSR, show_chgcur, NULL);
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",
54797 +static ssize_t show_chgmode(struct device *dev, struct device_attribute *attr,
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);
54805 + return sprintf(buf, "%s\n", chgmode_names[chgmod]);
54808 +static ssize_t set_chgmode(struct device *dev, struct device_attribute *attr,
54809 + const char *buf, size_t count)
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);
54815 + mbcc1 &= ~PCF50606_MBCC1_CHGMOD_MASK;
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;
54831 + reg_write(pcf, PCF50606_REG_MBCC1, mbcc1);
54836 +static DEVICE_ATTR(chgmode, S_IRUGO | S_IWUSR, show_chgmode, set_chgmode);
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",
54847 +static ssize_t show_chgstate(struct device *dev, struct device_attribute *attr,
54850 + struct i2c_client *client = to_i2c_client(dev);
54851 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
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]);
54860 + b += sprintf(b, "\n");
54864 +static DEVICE_ATTR(chgstate, S_IRUGO | S_IWUSR, show_chgstate, NULL);
54866 +/***********************************************************************
54868 + ***********************************************************************/
54870 +static void pcf50606_get_power_status(struct apm_power_info *info)
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);
54877 + if (reg_read(pcf, PCF50606_REG_OOCS) & PCF50606_OOCS_EXTON)
54878 + info->ac_line_status = APM_AC_ONLINE;
54880 + info->ac_line_status = APM_AC_OFFLINE;
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);
54889 + info->battery_status = APM_BATTERY_STATUS_CHARGING;
54890 + info->battery_flag = APM_BATTERY_FLAG_CHARGING;
54895 +/***********************************************************************
54897 + ***********************************************************************/
54899 +struct pcf50606_time {
54909 +static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50606_time *pcf)
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;
54920 +static void rtc2pcf_time(struct pcf50606_time *pcf, struct rtc_time *rtc)
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);
54931 +static int pcf50606_rtc_ioctl(struct device *dev, unsigned int cmd,
54932 + unsigned long arg)
54934 + struct i2c_client *client = to_i2c_client(dev);
54935 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
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);
54944 + /* enable the alarm interrupt */
54945 + reg_clear_bits(pcf, PCF50606_REG_INT1M, PCF50606_INT1_ALARM);
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);
54954 + /* ensable periodic interrupt (hz tick) */
54955 + pcf->flags |= PCF50606_F_RTC_SECOND;
54956 + reg_clear_bits(pcf, PCF50606_REG_INT1M, PCF50606_INT1_SECOND);
54959 + return -ENOIOCTLCMD;
54962 +static int pcf50606_rtc_read_time(struct device *dev, struct rtc_time *tm)
54964 + struct i2c_client *client = to_i2c_client(dev);
54965 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54966 + struct pcf50606_time pcf_tm;
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);
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);
54982 + pcf2rtc_time(tm, &pcf_tm);
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);
54991 +static int pcf50606_rtc_set_time(struct device *dev, struct rtc_time *tm)
54993 + struct i2c_client *client = to_i2c_client(dev);
54994 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
54995 + struct pcf50606_time pcf_tm;
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);
55006 + mutex_lock(&pcf->lock);
55008 + /* disable SECOND interrupt */
55009 + int1m = __reg_read(pcf, PCF50606_REG_INT1M);
55010 + __reg_write(pcf, PCF50606_REG_INT1M, int1m | PCF50606_INT1_SECOND);
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);
55020 + /* restore INT1M, potentially re-enable SECOND interrupt */
55021 + __reg_write(pcf, PCF50606_REG_INT1M, int1m);
55023 + mutex_unlock(&pcf->lock);
55028 +static int pcf50606_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
55030 + struct i2c_client *client = to_i2c_client(dev);
55031 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55032 + struct pcf50606_time pcf_tm;
55034 + mutex_lock(&pcf->lock);
55036 + __reg_read(pcf, PCF50606_REG_INT1M) & PCF50606_INT1_ALARM
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);
55047 + pcf2rtc_time(&alrm->time, &pcf_tm);
55052 +static int pcf50606_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
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;
55059 + rtc2pcf_time(&pcf_tm, &alrm->time);
55061 + mutex_lock(&pcf->lock);
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);
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);
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);
55083 + mutex_unlock(&pcf->lock);
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,
55097 +/***********************************************************************
55099 + ***********************************************************************/
55101 +static void pcf50606_wdt_start(struct pcf50606_data *pcf)
55103 + reg_set_bit_mask(pcf, PCF50606_REG_OOCC1, PCF50606_OOCC1_WDTRST,
55104 + PCF50606_OOCC1_WDTRST);
55107 +static void pcf50606_wdt_stop(struct pcf50606_data *pcf)
55109 + reg_clear_bits(pcf, PCF50606_REG_OOCS, PCF50606_OOCS_WDTEXP);
55112 +static void pcf50606_wdt_keepalive(struct pcf50606_data *pcf)
55114 + pcf50606_wdt_start(pcf);
55117 +static int pcf50606_wdt_open(struct inode *inode, struct file *file)
55119 + struct pcf50606_data *pcf = pcf50606_global;
55121 + file->private_data = pcf;
55123 + /* start the timer */
55124 + pcf50606_wdt_start(pcf);
55126 + return nonseekable_open(inode, file);
55129 +static int pcf50606_wdt_release(struct inode *inode, struct file *file)
55131 + struct pcf50606_data *pcf = file->private_data;
55133 + if (pcf->allow_close == CLOSE_STATE_ALLOW)
55134 + pcf50606_wdt_stop(pcf);
55136 + printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
55137 + pcf50606_wdt_keepalive(pcf);
55140 + pcf->allow_close = CLOSE_STATE_NOT;
55145 +static ssize_t pcf50606_wdt_write(struct file *file, const char __user *data,
55146 + size_t len, loff_t *ppos)
55148 + struct pcf50606_data *pcf = file->private_data;
55152 + for (i = 0; i != len; i++) {
55154 + if (get_user(c, data + i))
55157 + pcf->allow_close = CLOSE_STATE_ALLOW;
55159 + pcf50606_wdt_keepalive(pcf);
55165 +static struct watchdog_info pcf50606_wdt_ident = {
55166 + .options = WDIOF_MAGICCLOSE,
55167 + .firmware_version = 0,
55168 + .identity = "PCF50606 Watchdog",
55171 +static int pcf50606_wdt_ioctl(struct inode *inode, struct file *file,
55172 + unsigned int cmd, unsigned long arg)
55174 + struct pcf50606_data *pcf = file->private_data;
55175 + void __user *argp = (void __user *)arg;
55176 + int __user *p = argp;
55179 + case WDIOC_GETSUPPORT:
55180 + return copy_to_user(argp, &pcf50606_wdt_ident,
55181 + sizeof(pcf50606_wdt_ident)) ? -EFAULT : 0;
55183 + case WDIOC_GETSTATUS:
55184 + case WDIOC_GETBOOTSTATUS:
55185 + return put_user(0, p);
55186 + case WDIOC_KEEPALIVE:
55187 + pcf50606_wdt_keepalive(pcf);
55189 + case WDIOC_GETTIMEOUT:
55190 + return put_user(8, p);
55192 + return -ENOIOCTLCMD;
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,
55205 +static struct miscdevice pcf50606_wdt_miscdev = {
55206 + .minor = WATCHDOG_MINOR,
55207 + .name = "watchdog",
55208 + .fops = &pcf50606_wdt_fops,
55211 +/***********************************************************************
55213 + ***********************************************************************/
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",
55222 +static ssize_t show_pwm_dc(struct device *dev, struct device_attribute *attr,
55225 + struct i2c_client *client = to_i2c_client(dev);
55226 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55229 + val = reg_read(pcf, PCF50606_REG_PWMC1) >> PCF50606_PWMC1_DC_SHIFT;
55232 + return sprintf(buf, "%s\n", pwm_dc_table[val]);
55235 +static ssize_t set_pwm_dc(struct device *dev, struct device_attribute *attr,
55236 + const char *buf, size_t count)
55238 + struct i2c_client *client = to_i2c_client(dev);
55239 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
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));
55252 +static DEVICE_ATTR(pwm_dc, S_IRUGO | S_IWUSR, show_pwm_dc, set_pwm_dc);
55254 +static const char *pwm_clk_table[] = {
55255 + "512", "256", "128", "64",
55256 + "56300", "28100", "14100", "7000",
55259 +static ssize_t show_pwm_clk(struct device *dev, struct device_attribute *attr,
55262 + struct i2c_client *client = to_i2c_client(dev);
55263 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55266 + val = reg_read(pcf, PCF50606_REG_PWMC1) >> PCF50606_PWMC1_CLK_SHIFT;
55269 + return sprintf(buf, "%s\n", pwm_clk_table[val]);
55272 +static ssize_t set_pwm_clk(struct device *dev, struct device_attribute *attr,
55273 + const char *buf, size_t count)
55275 + struct i2c_client *client = to_i2c_client(dev);
55276 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
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));
55290 +static DEVICE_ATTR(pwm_clk, S_IRUGO | S_IWUSR, show_pwm_clk, set_pwm_clk);
55292 +static int pcf50606bl_get_intensity(struct backlight_device *bd)
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);
55298 + return intensity & 0xf;
55301 +static int pcf50606bl_set_intensity(struct backlight_device *bd)
55303 + struct pcf50606_data *pcf = bl_get_data(bd);
55304 + int intensity = bd->props.brightness;
55306 + if (bd->props.power != FB_BLANK_UNBLANK)
55308 + if (bd->props.fb_blank != FB_BLANK_UNBLANK)
55311 + return reg_set_bit_mask(pcf, PCF50606_REG_PWMC1, 0x1e,
55312 + (intensity << PCF50606_PWMC1_DC_SHIFT));
55315 +static struct backlight_ops pcf50606bl_ops = {
55316 + .get_brightness = pcf50606bl_get_intensity,
55317 + .update_status = pcf50606bl_set_intensity,
55320 +/***********************************************************************
55321 + * Driver initialization
55322 + ***********************************************************************/
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",
55331 +static struct platform_device gta01_pm_bt_dev = {
55332 + .name = "neo1973-pm-bt",
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,
55348 +static struct attribute_group pcf_attr_group = {
55349 + .name = NULL, /* put in device directory */
55350 + .attrs = pcf_sysfs_entries,
55353 +static void populate_sysfs_group(struct pcf50606_data *pcf)
55356 + struct attribute **attr;
55358 + for (attr = pcf_sysfs_entries; *attr; attr++)
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;
55366 + if (pcf->pdata->used_features & PCF50606_FEAT_CHGCUR)
55367 + pcf_sysfs_entries[i++] = &dev_attr_chgcur.attr;
55369 + if (pcf->pdata->used_features & PCF50606_FEAT_BATVOLT)
55370 + pcf_sysfs_entries[i++] = &dev_attr_battvolt.attr;
55372 + if (pcf->pdata->used_features & PCF50606_FEAT_BATTEMP)
55373 + pcf_sysfs_entries[i++] = &dev_attr_battemp.attr;
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;
55381 +static int pcf50606_detect(struct i2c_adapter *adapter, int address, int kind)
55383 + struct i2c_client *new_client;
55384 + struct pcf50606_data *data;
55388 + if (!pcf50606_pdev) {
55389 + printk(KERN_ERR "pcf50606: driver needs a platform_device!\n");
55393 + irq = platform_get_irq(pcf50606_pdev, 0);
55395 + dev_err(&pcf50606_pdev->dev, "no irq in platform resources!\n");
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");
55406 + data = kzalloc(sizeof(*data), GFP_KERNEL);
55410 + mutex_init(&data->lock);
55411 + mutex_init(&data->working_lock);
55412 + INIT_WORK(&data->work, pcf50606_work);
55414 + data->working = 0;
55415 + data->suppress_onkey_events = 0;
55416 + data->onkey_seconds = -1;
55417 + data->pdata = pcf50606_pdev->dev.platform_data;
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);
55427 + /* now we try to detect the chip */
55429 + /* register with i2c core */
55430 + err = i2c_attach_client(new_client);
55432 + dev_err(&new_client->dev,
55433 + "error during i2c_attach_client()\n");
55437 + populate_sysfs_group(data);
55439 + err = sysfs_create_group(&new_client->dev.kobj, &pcf_attr_group);
55441 + dev_err(&new_client->dev, "error creating sysfs group\n");
55442 + goto exit_detach;
55445 + /* create virtual charger 'device' */
55447 + /* input device registration */
55448 + data->input_dev = input_allocate_device();
55449 + if (!data->input_dev)
55452 + data->input_dev->name = "FIC Neo1973 PMU events";
55453 + data->input_dev->phys = "I2C";
55454 + data->input_dev->id.bustype = BUS_I2C;
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);
55461 + err = input_register_device(data->input_dev);
55465 + /* register power off handler with core power management */
55466 + pm_power_off = &pcf50606_go_standby;
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);
55474 + err = request_irq(irq, pcf50606_irq, IRQF_TRIGGER_FALLING,
55475 + "pcf50606", data);
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);
55483 + pcf50606_global = data;
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);
55494 + if (data->pdata->used_features & PCF50606_FEAT_WDT) {
55495 + err = misc_register(&pcf50606_wdt_miscdev);
55497 + dev_err(&new_client->dev, "cannot register miscdev on "
55498 + "minor=%d (%d)\n", WATCHDOG_MINOR, err);
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);
55510 + if (data->pdata->used_features & PCF50606_FEAT_PWM_BL) {
55511 + data->backlight = backlight_device_register("pcf50606-bl",
55512 + &new_client->dev,
55514 + &pcf50606bl_ops);
55515 + if (!data->backlight)
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);
55524 + apm_get_power_status = pcf50606_get_power_status;
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(>a01_pm_bt_dev);
55537 + platform_device_register(>a01_pm_gps_dev);
55538 + /* a link for gllin compatibility */
55539 + err = bus_create_device_link(&platform_bus_type,
55540 + >a01_pm_gps_dev.dev.kobj, "gta01-pm-gps.0");
55543 + "sysfs_create_link (gta01-pm-gps.0): %d\n", err);
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);
55551 + reg_clear_bits(data, PCF50606_REG_ACDC1,
55552 + PCF50606_ACDC1_ACDAPE);
55557 + if (data->pdata->used_features & PCF50606_FEAT_WDT)
55558 + misc_deregister(&pcf50606_wdt_miscdev);
55560 + if (data->pdata->used_features & PCF50606_FEAT_RTC)
55561 + rtc_device_unregister(pcf50606_global->rtc);
55563 + free_irq(pcf50606_global->irq, pcf50606_global);
55564 + pcf50606_global = NULL;
55566 + pm_power_off = NULL;
55567 + input_unregister_device(data->input_dev);
55569 + sysfs_remove_group(&new_client->dev.kobj, &pcf_attr_group);
55571 + i2c_detach_client(new_client);
55577 +static int pcf50606_attach_adapter(struct i2c_adapter *adapter)
55579 + return i2c_probe(adapter, &addr_data, &pcf50606_detect);
55582 +static int pcf50606_detach_client(struct i2c_client *client)
55584 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55586 + apm_get_power_status = NULL;
55587 + input_unregister_device(pcf->input_dev);
55589 + if (pcf->pdata->used_features & PCF50606_FEAT_PWM_BL)
55590 + backlight_device_unregister(pcf->backlight);
55592 + if (pcf->pdata->used_features & PCF50606_FEAT_WDT)
55593 + misc_deregister(&pcf50606_wdt_miscdev);
55595 + if (pcf->pdata->used_features & PCF50606_FEAT_RTC)
55596 + rtc_device_unregister(pcf->rtc);
55598 + free_irq(pcf->irq, pcf);
55600 + sysfs_remove_group(&client->dev.kobj, &pcf_attr_group);
55602 + pm_power_off = NULL;
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)
55621 + struct i2c_client *client = to_i2c_client(dev);
55622 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55625 + /* we suspend once (!) as late as possible in the suspend sequencing */
55627 + if ((state.event != PM_EVENT_SUSPEND) ||
55628 + (pcf->suspend_state != PCF50606_SS_RUNNING))
55631 + /* The general idea is to power down all unused power supplies,
55632 + * and then mask all PCF50606 interrup sources but EXTONR, ONKEYF
55635 + mutex_lock(&pcf->lock);
55637 + pcf->suspend_state = PCF50606_SS_STARTING_SUSPEND;
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.
55644 + disable_irq(pcf->irq);
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);
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)) {
55665 + /* IOREG powers the I@C interface so we cannot switch
55667 + if (i == PCF50606_REGULATOR_IOREG)
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]);
55675 + __reg_write(pcf, regulator_registers[i], tmp);
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);
55686 + pcf->suspend_state = PCF50606_SS_COMPLETED_SUSPEND;
55688 + mutex_unlock(&pcf->lock);
55693 +static int pcf50606_resume(struct device *dev)
55695 + struct i2c_client *client = to_i2c_client(dev);
55696 + struct pcf50606_data *pcf = i2c_get_clientdata(client);
55698 + mutex_lock(&pcf->lock);
55700 + pcf->suspend_state = PCF50606_SS_STARTING_RESUME;
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);
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);
55720 + pcf->suspend_state = PCF50606_SS_COMPLETED_RESUME;
55722 + enable_irq(pcf->irq);
55724 + mutex_unlock(&pcf->lock);
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.
55729 + get_device(&pcf->client.dev);
55730 + pcf50606_work(&pcf->work);
55735 +#define pcf50606_suspend NULL
55736 +#define pcf50606_resume NULL
55739 +static struct i2c_driver pcf50606_driver = {
55741 + .name = "pcf50606",
55742 + .suspend = pcf50606_suspend,
55743 + .resume = pcf50606_resume,
55745 + .id = I2C_DRIVERID_PCF50606,
55746 + .attach_adapter = pcf50606_attach_adapter,
55747 + .detach_client = pcf50606_detach_client,
55750 +/* platform driver, since i2c devices don't have platform_data */
55751 +static int __init pcf50606_plat_probe(struct platform_device *pdev)
55753 + struct pcf50606_platform_data *pdata = pdev->dev.platform_data;
55758 + pcf50606_pdev = pdev;
55763 +static int pcf50606_plat_remove(struct platform_device *pdev)
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.
55773 +static int pcf50606_plat_resume(struct platform_device *pdev)
55775 + /* i2c_get_clientdata(to_i2c_client(&pdev->dev)) returns NULL at this
55776 + * early resume time so we have to use pcf50606_global
55778 + pcf50606_global->suspend_state = PCF50606_SS_RESUMING_BUT_NOT_US_YET;
55783 +static struct platform_driver pcf50606_plat_driver = {
55784 + .probe = pcf50606_plat_probe,
55785 + .remove = pcf50606_plat_remove,
55786 + .resume_early = pcf50606_plat_resume,
55788 + .owner = THIS_MODULE,
55789 + .name = "pcf50606",
55793 +static int __init pcf50606_init(void)
55797 + rc = platform_driver_register(&pcf50606_plat_driver);
55799 + rc = i2c_add_driver(&pcf50606_driver);
55804 +static void pcf50606_exit(void)
55806 + i2c_del_driver(&pcf50606_driver);
55807 + platform_driver_unregister(&pcf50606_plat_driver);
55810 +MODULE_DESCRIPTION("I2C chip driver for NXP PCF50606 power management unit");
55811 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
55812 +MODULE_LICENSE("GPL");
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
55820 +#ifndef _PCF50606_H
55821 +#define _PCF50606_H
55823 +/* Philips PCF50606 Power Managemnt Unit (PMU) driver
55824 + * (C) 2006-2007 by Openmoko, Inc.
55825 + * Author: Harald Welte <laforge@openmoko.org>
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
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,
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,
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,
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 */
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 */
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 */
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 */
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,
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,
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,
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,
56008 + PCF50606_ADCC1_TSCINT = 0x80,
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,
56022 +#define PCF50606_ADCC2_ADCMUX_MASK (0xf << 1)
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,
56043 +enum pcf50606_adcs2 {
56044 + PCF50606_ADCS2_ADCRDY = 0x80,
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,
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,
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,
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,
56117 +#define PCF50606_PWMC1_CLK_SHIFT 5
56118 +#define PCF50606_PWMC1_DC_SHIFT 1
56120 +#endif /* _PCF50606_H */
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
56126 +#ifndef _PCF50633_H
56127 +#define _PCF50633_H
56129 +/* Philips PCF50633 Power Managemnt Unit (PMU) driver
56130 + * (C) 2006-2007 by Openmoko, Inc.
56131 + * Author: Harald Welte <laforge@openmoko.org>
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,
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,
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,
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 */
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,
56249 + PCF50633_REG_DCDCPFM = 0x84,
56250 + __NUM_PCF50633_REGS
56254 +enum pcf50633_reg_oocshdwn {
56255 + PCF50633_OOCSHDWN_GOSTDBY = 0x01,
56256 + PCF50633_OOCSHDWN_TOTRST = 0x04,
56257 + PCF50633_OOCSHDWN_COLDBOOT = 0x08,
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,
56267 + PCF50633_OOCWAKE_USB = 0x40,
56268 + PCF50633_OOCWAKE_ADP = 0x80,
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,
56283 +#define PCF50633_MBCC1_WDTIME_MASK 0xc0
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) */
56294 +#define PCF50633_MBCC2_VBATCOND_MASK 0x03
56295 +#define PCF50633_MBCC2_VMAX_MASK 0x3c
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,
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,
56312 +#define PCF50633_ADCC1_AVERAGE_MASK 0x0c
56313 +#define PCF50633_ADCC1_ADCMUX_MASK 0xf0
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,
56322 +#define PCF50633_ADCC2_RATIO_MASK 0x03
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,
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,
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
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,
56350 +#define PCF50633_REGULATOR_ON_MASK 0x0f
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,
56358 +#define PCF50633_REGULATOR_ACTPH_MASK 0x30
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,
56371 +#define PCF50633_GPOCFG_GPOSEL_MASK 0x07
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,
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,
56394 +#define PCF50633_MBCC2_VMAX_MASK 0x3c
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,
56408 +#define PCF56033_MBCC7_USB_MASK 0x03
56410 +enum pcf50633_reg_mbcc8 {
56411 + PCF50633_MBCC8_USBENASUS = 0x10,
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,
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,
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,
56448 +#define PCF50633_MBCS2_RESSTAT_AUTO 0x40
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) */
56461 +/* this is to be provided by the board implementation */
56462 +extern const u_int8_t pcf50633_initial_regs[__NUM_PCF50633_REGS];
56464 +void pcf50633_reg_write(u_int8_t reg, u_int8_t val);
56466 +u_int8_t pcf50633_reg_read(u_int8_t reg);
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);
56471 +void pcf50633_charge_autofast(int on);
56473 +#endif /* _PCF50606_H */
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
56479 -/* i2c-core.c - a device driver for the iic-bus interface */
56480 /* ------------------------------------------------------------------------- */
56481 /* Copyright (C) 1995-99 Simon G. Vogl
56483 @@ -158,10 +157,16 @@
56488 driver = to_i2c_driver(dev->driver);
56489 if (!driver->suspend)
56491 return driver->suspend(to_i2c_client(dev), mesg);
56493 + if (!dev->driver->suspend)
56495 + return dev->driver->suspend(dev, mesg);
56499 static int i2c_device_resume(struct device * dev)
56500 @@ -170,10 +175,16 @@
56505 driver = to_i2c_driver(dev->driver);
56506 if (!driver->resume)
56508 return driver->resume(to_i2c_client(dev));
56510 + if (!dev->driver->resume)
56512 + return dev->driver->resume(dev);
56516 static void i2c_client_release(struct device *dev)
56517 @@ -1129,11 +1140,11 @@
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",
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
56535 #include <linux/input.h>
56536 #include <linux/gpio_keys.h>
56538 -#include <asm/gpio.h>
56539 +#include <mach/gpio.h>
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 @@
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
56555 + Say Y here to enable the buttons on the FIC Neo1973
56558 + To compile this driver as a module, choose M here: the
56559 + module will be called neo1973kbd.
56561 +config KEYBOARD_QT2410
56562 + tristate "QT2410 buttons"
56563 + depends on MACH_QT2410
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
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
56585 + * Keyboard driver for FIC Neo1973 GSM phone
56587 + * (C) 2006-2007 by Openmoko, Inc.
56588 + * Author: Harald Welte <laforge@openmoko.org>
56589 + * All rights reserved.
56591 + * inspired by corkgbd.c by Richard Purdie
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.
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>
56609 +#include <mach/gpio.h>
56610 +#include <asm/mach-types.h>
56613 +extern int global_inside_suspend;
56615 +#define global_inside_suspend 0
56618 +struct neo1973kbd {
56619 + struct platform_device *pdev;
56620 + struct input_dev *input;
56621 + struct device *cdev;
56622 + struct work_struct work;
56624 + int work_in_progress;
56625 + int hp_irq_count_in_work;
56626 + int hp_irq_count;
56630 +static struct class *neo1973kbd_switch_class;
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 */
56640 +struct neo1973kbd_key {
56641 + const char * name;
56642 + irqreturn_t (*isr)(int irq, void *dev_id);
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);
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,
56658 + [NEO1973_KEY_HOLD] = {
56659 + .name = "Neo1973 HOLD button",
56660 + .isr = neo1973kbd_default_key_irq,
56661 + .input_key = KEY_PAUSE,
56663 + [NEO1973_KEY_JACK] = {
56664 + .name = "Neo1973 Headphone jack",
56665 + .isr = neo1973kbd_headphone_irq,
56667 + [NEO1973_KEY_PLUS] = {
56668 + .name = "GTA03 PLUS button",
56669 + .isr = neo1973kbd_default_key_irq,
56670 + .input_key = KEY_KPPLUS,
56672 + [NEO1973_KEY_MINUS] = {
56673 + .name = "GTA03 MINUS button",
56674 + .isr = neo1973kbd_default_key_irq,
56675 + .input_key = KEY_KPMINUS,
56679 +/* This timer section filters AUX button IRQ bouncing */
56681 +static void aux_key_timer_f(unsigned long data);
56683 +static struct timer_list aux_key_timer =
56684 + TIMER_INITIALIZER(aux_key_timer_f, 0, 0);
56686 +#define AUX_TIMER_TIMEOUT (HZ >> 7)
56687 +#define AUX_TIMER_ALLOWED_NOOP 2
56688 +#define AUX_TIMER_CONSECUTIVE_EVENTS 5
56690 +struct neo1973kbd *timer_kbd;
56692 +static void aux_key_timer_f(unsigned long data)
56694 + static int noop_counter;
56695 + static int last_key = -1;
56696 + static int last_count;
56700 + !gpio_get_value(timer_kbd->pdev->resource[NEO1973_KEY_AUX].start);
56701 + if (machine_is_neo1973_gta02())
56702 + key_pressed = !key_pressed;
56704 + if (likely(key_pressed == last_key))
56708 + last_key = key_pressed;
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);
56716 + timer_kbd->aux_state = last_key;
56717 + noop_counter = 0;
56720 + if (unlikely(++noop_counter > AUX_TIMER_ALLOWED_NOOP)) {
56721 + noop_counter = 0;
56726 + mod_timer(&aux_key_timer, jiffies + AUX_TIMER_TIMEOUT);
56729 +static irqreturn_t neo1973kbd_aux_irq(int irq, void *dev)
56731 + mod_timer(&aux_key_timer, jiffies + AUX_TIMER_TIMEOUT);
56733 + return IRQ_HANDLED;
56736 +static irqreturn_t neo1973kbd_default_key_irq(int irq, void *dev_id)
56738 + struct neo1973kbd *kbd = dev_id;
56741 + for (n = 0; n < ARRAY_SIZE(keys); n++) {
56743 + if (irq != keys[n].irq)
56746 + input_report_key(kbd->input, keys[n].input_key,
56747 + gpio_get_value(kbd->pdev->resource[n].start));
56748 + input_sync(kbd->input);
56751 + return IRQ_HANDLED;
56755 +static const char *event_array_jack[2][4] = {
56757 + "SWITCH_NAME=headset",
56758 + "SWITCH_STATE=0",
56763 + "SWITCH_NAME=headset",
56764 + "SWITCH_STATE=1",
56770 +static void neo1973kbd_jack_event(struct device *dev, int num)
56772 + kobject_uevent_env(&dev->kobj, KOBJ_CHANGE, (char **)event_array_jack[!!num]);
56776 +static void neo1973kbd_debounce_jack(struct work_struct *work)
56778 + struct neo1973kbd *kbd = container_of(work, struct neo1973kbd, work);
56779 + unsigned long flags;
56785 + * we wait out any multiple interrupt
56786 + * stuttering in 100ms lumps
56789 + kbd->hp_irq_count_in_work = kbd->hp_irq_count;
56791 + } while (kbd->hp_irq_count != kbd->hp_irq_count_in_work);
56793 + * no new interrupts on jack for 100ms...
56794 + * ok we will report it
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);
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
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);
56809 + kbd->work_in_progress = 0;
56810 + local_irq_restore(flags);
56812 + * interrupt that comes here will either queue a new work action
56813 + * since work_in_progress is cleared now, or be dealt with
56820 +static irqreturn_t neo1973kbd_headphone_irq(int irq, void *dev_id)
56822 + struct neo1973kbd *neo1973kbd_data = dev_id;
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
56833 + neo1973kbd_data->hp_irq_count++;
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
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))
56846 + "Unable to schedule headphone debounce\n");
56848 + neo1973kbd_data->work_in_progress = 1;
56851 + return IRQ_HANDLED;
56855 +static int neo1973kbd_suspend(struct platform_device *dev, pm_message_t state)
56857 + if (machine_is_neo1973_gta02()) {
56858 + disable_irq(keys[NEO1973_KEY_AUX].irq);
56859 + del_timer_sync(&aux_key_timer);
56864 +static int neo1973kbd_resume(struct platform_device *dev)
56866 + if (machine_is_neo1973_gta02())
56867 + enable_irq(keys[NEO1973_KEY_AUX].irq);
56872 +#define neo1973kbd_suspend NULL
56873 +#define neo1973kbd_resume NULL
56876 +static ssize_t neo1973kbd_switch_name_show(struct device *dev,
56877 + struct device_attribute *attr, char *buf)
56879 + return sprintf(buf, "%s\n", "neo1973 Headset Jack");
56882 +static ssize_t neo1973kbd_switch_state_show(struct device *dev,
56883 + struct device_attribute *attr, char *buf)
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));
56890 +static DEVICE_ATTR(name, S_IRUGO , neo1973kbd_switch_name_show, NULL);
56891 +static DEVICE_ATTR(state, S_IRUGO , neo1973kbd_switch_state_show, NULL);
56893 +static int neo1973kbd_probe(struct platform_device *pdev)
56895 + struct neo1973kbd *neo1973kbd;
56896 + struct input_dev *input_dev;
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);
56909 + neo1973kbd->pdev = pdev;
56910 + timer_kbd = neo1973kbd;
56912 + if (pdev->resource[0].flags != 0)
56915 + platform_set_drvdata(pdev, neo1973kbd);
56917 + neo1973kbd->input = input_dev;
56919 + INIT_WORK(&neo1973kbd->work, neo1973kbd_debounce_jack);
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;
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);
56934 + rc = input_register_device(neo1973kbd->input);
56936 + goto out_register;
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;
56945 + rc = device_create_file(neo1973kbd->cdev, &dev_attr_name);
56947 + goto out_device_create_file;
56949 + rc = device_create_file(neo1973kbd->cdev, &dev_attr_state);
56951 + goto out_device_create_file;
56953 + /* register GPIO IRQs */
56954 + for(n = 0; n < min(pdev->num_resources, ARRAY_SIZE(keys)); n++) {
56956 + if (!pdev->resource[0].start)
56959 + irq = gpio_to_irq(pdev->resource[n].start);
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);
56968 + /* unwind any irq registrations and fail */
56972 + free_irq(gpio_to_irq(pdev->resource[n].start),
56975 + goto out_device_create_file;
56978 + keys[n].irq = irq;
56982 + * GTA01 revisions before Bv4 can't be resumed by the PMU, so we use
56985 + if (machine_is_neo1973_gta01())
56986 + enable_irq_wake(keys[NEO1973_KEY_AUX].irq);
56988 + enable_irq_wake(keys[NEO1973_KEY_JACK].irq);
56992 +out_device_create_file:
56993 + device_unregister(neo1973kbd->cdev);
56994 +out_device_create:
56995 + input_unregister_device(neo1973kbd->input);
56997 + input_free_device(neo1973kbd->input);
56998 + platform_set_drvdata(pdev, NULL);
56999 + kfree(neo1973kbd);
57004 +static int neo1973kbd_remove(struct platform_device *pdev)
57006 + struct neo1973kbd *neo1973kbd = platform_get_drvdata(pdev);
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);
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);
57021 +static struct platform_driver neo1973kbd_driver = {
57022 + .probe = neo1973kbd_probe,
57023 + .remove = neo1973kbd_remove,
57024 + .suspend = neo1973kbd_suspend,
57025 + .resume = neo1973kbd_resume,
57027 + .name = "neo1973-button",
57031 +static int __devinit neo1973kbd_init(void)
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);
57039 +static void __exit neo1973kbd_exit(void)
57041 + platform_driver_unregister(&neo1973kbd_driver);
57042 + class_destroy(neo1973kbd_switch_class);
57045 +module_init(neo1973kbd_init);
57046 +module_exit(neo1973kbd_exit);
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
57056 + * Keyboard driver for Armzone QT2410
57058 + * (C) 2006 by Openmoko, Inc.
57059 + * Author: Harald Welte <laforge@openmoko.org>
57060 + * All rights reserved.
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.
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>
57077 +#include <mach/hardware.h>
57078 +#include <mach/gta01.h>
57081 + struct input_dev *input;
57082 + unsigned int suspended;
57083 + unsigned long suspend_jiffies;
57086 +static irqreturn_t gta01kbd_interrupt(int irq, void *dev_id)
57088 + struct gta01kbd *gta01kbd_data = dev_id;
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);
57094 + input_report_key(gta01kbd_data->input, KEY_PHONE, 0);
57096 + input_sync(gta01kbd_data->input);
57098 + return IRQ_HANDLED;
57103 +static int gta01kbd_suspend(struct platform_device *dev, pm_message_t state)
57105 + struct gta01kbd *gta01kbd = platform_get_drvdata(dev);
57107 + gta01kbd->suspended = 1;
57112 +static int gta01kbd_resume(struct platform_device *dev)
57114 + struct gta01kbd *gta01kbd = platform_get_drvdata(dev);
57116 + gta01kbd->suspended = 0;
57121 +#define gta01kbd_suspend NULL
57122 +#define gta01kbd_resume NULL
57125 +static int gta01kbd_probe(struct platform_device *pdev)
57127 + struct gta01kbd *gta01kbd;
57128 + struct input_dev *input_dev;
57132 + gta01kbd = kzalloc(sizeof(struct gta01kbd), GFP_KERNEL);
57137 + input_dev = input_allocate_device();
57138 + if (!gta01kbd || !input_dev) {
57143 + if (pdev->resource[0].flags != 0) {\
57145 + goto bail_free_dev;
57148 + irq_911 = s3c2410_gpio_getirq(pdev->resource[0].start);
57149 + if (irq_911 < 0) {
57151 + goto bail_free_dev;
57154 + platform_set_drvdata(pdev, gta01kbd);
57156 + gta01kbd->input = input_dev;
57159 + spin_lock_init(>a01kbd->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;
57165 + /* Init Hinge Timer */
57166 + init_timer(&corgikbd->htimer);
57167 + corgikbd->htimer.function = corgikbd_hinge_timer;
57168 + corgikbd->htimer.data = (unsigned long) corgikbd;
57170 + corgikbd->suspend_jiffies=jiffies;
57172 + memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode));
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;
57182 + input_dev->evbit[0] = BIT(EV_KEY);
57184 + input_dev->keycode = gta01kbd->keycode;
57185 + input_dev->keycodesize = sizeof(unsigned char);
57186 + input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode);
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);
57196 + rc = input_register_device(gta01kbd->input);
57198 + goto bail_free_dev;
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);
57207 + /* FIXME: headphone insert */
57210 + mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL));
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);
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);
57225 + /* Setup the headphone jack as an input */
57226 + pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN);
57232 + input_free_device(input_dev);
57239 +static int gta01kbd_remove(struct platform_device *pdev)
57241 + struct gta01kbd *gta01kbd = platform_get_drvdata(pdev);
57243 + free_irq(s3c2410_gpio_getirq(pdev->resource[0].start), gta01kbd);
57247 + for (i = 0; i < CORGI_KEY_SENSE_NUM; i++)
57248 + free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd);
57250 + del_timer_sync(&corgikbd->htimer);
57251 + del_timer_sync(&corgikbd->timer);
57253 + input_unregister_device(gta01kbd->input);
57260 +static struct platform_driver gta01kbd_driver = {
57261 + .probe = gta01kbd_probe,
57262 + .remove = gta01kbd_remove,
57263 + .suspend = gta01kbd_suspend,
57264 + .resume = gta01kbd_resume,
57266 + .name = "qt2410-button",
57270 +static int __devinit gta01kbd_init(void)
57272 + return platform_driver_register(>a01kbd_driver);
57275 +static void __exit gta01kbd_exit(void)
57277 + platform_driver_unregister(>a01kbd_driver);
57280 +module_init(gta01kbd_init);
57281 +module_exit(gta01kbd_exit);
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.
57293 +config INPUT_LIS302DL
57294 + tristate "STmicro LIS302DL 3-axis accelerometer"
57295 + depends on SPI_MASTER
57297 + SPI driver for the STmicro LIS302DL 3-axis accelerometer.
57299 + The userspece interface is a 3-axis (X/Y/Z) relative movement
57300 + Linux input device, reporting REL_[XYZ] events.
57302 config INPUT_PCF50633_PMU
57303 tristate "PCF50633 PMU events"
57304 depends on MFD_PCF50633
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.
57310 +config INPUT_PCF50606_PMU
57311 + tristate "PCF50606 PMU events"
57312 + depends on MFD_PCF50606
57314 + Say Y to include support for input events on NXP PCF50606.
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
57322 +/* Linux kernel driver for the ST LIS302D 3-axis accelerometer
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.
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.
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.
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
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
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>
57366 +#include <linux/lis302dl.h>
57368 +/* Utility functions */
57369 +static u8 __reg_read(struct lis302dl_info *lis, u8 reg)
57371 + struct spi_message msg;
57372 + struct spi_transfer t;
57373 + u8 data[2] = {0xc0 | reg};
57376 + spi_message_init(&msg);
57377 + memset(&t, 0, sizeof t);
57379 + spi_message_add_tail(&t, &msg);
57380 + t.tx_buf = &data[0];
57381 + t.rx_buf = &data[0];
57383 + /* Should complete without blocking */
57384 + rc = spi_non_blocking_transfer(lis->spi, &msg);
57386 + dev_err(lis->dev, "Error reading register\n");
57393 +static void __reg_write(struct lis302dl_info *lis, u8 reg, u8 val)
57395 + struct spi_message msg;
57396 + struct spi_transfer t;
57397 + u8 data[2] = {reg, val};
57399 + spi_message_init(&msg);
57400 + memset(&t, 0, sizeof t);
57402 + spi_message_add_tail(&t, &msg);
57403 + t.tx_buf = &data[0];
57404 + t.rx_buf = &data[0];
57406 + /* Completes without blocking */
57407 + if (spi_non_blocking_transfer(lis->spi, &msg) < 0)
57408 + dev_err(lis->dev, "Error writing register\n");
57411 +static void __reg_set_bit_mask(struct lis302dl_info *lis, u8 reg, u8 mask,
57418 + tmp = __reg_read(lis, reg);
57421 + __reg_write(lis, reg, tmp);
57424 +static int __ms_to_duration(struct lis302dl_info *lis, int ms)
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);
57431 + return min(ms / 10, 2550);
57434 +static int __duration_to_ms(struct lis302dl_info *lis, int duration)
57436 + if (lis->flags & LIS302DL_F_DR)
57437 + return (duration * 25) / 10;
57439 + return duration * 10;
57442 +static u8 __mg_to_threshold(struct lis302dl_info *lis, int mg)
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);
57449 + return min(mg / 18, 127);
57452 +static int __threshold_to_mg(struct lis302dl_info *lis, u8 threshold)
57454 + if (lis->flags & LIS302DL_F_FS)
57455 + return threshold * 71;
57457 + return threshold * 18;
57460 +/* interrupt handling related */
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,
57471 +static void __lis302dl_int_mode(struct device *dev, int int_pin,
57472 + enum lis302dl_intmode mode)
57474 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57476 + switch (int_pin) {
57478 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x07, mode);
57481 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL3, 0x38, mode << 3);
57488 +static void __enable_wakeup(struct lis302dl_info *lis)
57490 + __reg_write(lis, LIS302DL_REG_CTRL1, 0);
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));
57501 + /* Route the interrupt for wakeup */
57502 + __lis302dl_int_mode(lis->dev, 1,
57503 + LIS302DL_INTMODE_FF_WU_1);
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);
57515 +static void __enable_data_collection(struct lis302dl_info *lis)
57517 + u_int8_t ctrl1 = LIS302DL_CTRL1_PD | LIS302DL_CTRL1_Xen |
57518 + LIS302DL_CTRL1_Yen | LIS302DL_CTRL1_Zen;
57520 + /* make sure we're powered up and generate data ready */
57521 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, ctrl1, ctrl1);
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);
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));
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);
57548 +static void _report_btn_single(struct input_dev *inp, int btn)
57550 + input_report_key(inp, btn, 1);
57552 + input_report_key(inp, btn, 0);
57555 +static void _report_btn_double(struct input_dev *inp, int btn)
57557 + input_report_key(inp, btn, 1);
57559 + input_report_key(inp, btn, 0);
57561 + input_report_key(inp, btn, 1);
57563 + input_report_key(inp, btn, 0);
57568 +static void lis302dl_bitbang_read_sample(struct lis302dl_info *lis)
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;
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];
57584 + /* grab the set of register containing status and XYZ data */
57586 + local_irq_save(flags);
57588 + /* Should complete without blocking */
57589 + if (spi_non_blocking_transfer(lis->spi, &msg) < 0)
57590 + dev_err(lis->dev, "Error reading registers\n");
57592 + local_irq_restore(flags);
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.
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))
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]);
57616 + input_sync(lis->input_dev);
57619 + if (lis->threshold)
57620 + /* acknowledge the wakeup source */
57621 + __reg_read(lis, LIS302DL_REG_FF_WU_SRC_1);
57624 +static irqreturn_t lis302dl_interrupt(int irq, void *_lis)
57626 + struct lis302dl_info *lis = _lis;
57628 + lis302dl_bitbang_read_sample(lis);
57629 + return IRQ_HANDLED;
57634 +static ssize_t show_overruns(struct device *dev, struct device_attribute *attr,
57637 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57639 + return sprintf(buf, "%u\n", lis->overruns);
57642 +static DEVICE_ATTR(overruns, S_IRUGO, show_overruns, NULL);
57644 +static ssize_t show_rate(struct device *dev, struct device_attribute *attr,
57647 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57649 + unsigned long flags;
57651 + local_irq_save(flags);
57652 + ctrl1 = __reg_read(lis, LIS302DL_REG_CTRL1);
57653 + local_irq_restore(flags);
57655 + return sprintf(buf, "%d\n", ctrl1 & LIS302DL_CTRL1_DR ? 400 : 100);
57658 +static ssize_t set_rate(struct device *dev, struct device_attribute *attr,
57659 + const char *buf, size_t count)
57661 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57662 + unsigned long flags;
57664 + local_irq_save(flags);
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;
57671 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_DR,
57673 + lis->flags &= ~LIS302DL_F_DR;
57675 + local_irq_restore(flags);
57680 +static DEVICE_ATTR(sample_rate, S_IRUGO | S_IWUSR, show_rate, set_rate);
57682 +static ssize_t show_scale(struct device *dev, struct device_attribute *attr,
57685 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57687 + unsigned long flags;
57689 + local_irq_save(flags);
57690 + ctrl1 = __reg_read(lis, LIS302DL_REG_CTRL1);
57691 + local_irq_restore(flags);
57693 + return sprintf(buf, "%s\n", ctrl1 & LIS302DL_CTRL1_FS ? "9.2" : "2.3");
57696 +static ssize_t set_scale(struct device *dev, struct device_attribute *attr,
57697 + const char *buf, size_t count)
57699 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57700 + unsigned long flags;
57702 + local_irq_save(flags);
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;
57709 + __reg_set_bit_mask(lis, LIS302DL_REG_CTRL1, LIS302DL_CTRL1_FS,
57711 + lis->flags &= ~LIS302DL_F_FS;
57714 + if (lis->flags & LIS302DL_F_INPUT_OPEN)
57715 + __enable_data_collection(lis);
57717 + local_irq_restore(flags);
57722 +static DEVICE_ATTR(full_scale, S_IRUGO | S_IWUSR, show_scale, set_scale);
57724 +static ssize_t show_threshold(struct device *dev, struct device_attribute *attr,
57727 + struct lis302dl_info *lis = dev_get_drvdata(dev);
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)));
57734 +static ssize_t set_threshold(struct device *dev, struct device_attribute *attr,
57735 + const char *buf, size_t count)
57737 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57738 + unsigned int val;
57740 + if (sscanf(buf, "%u\n", &val) != 1)
57742 + /* 8g is the maximum if FS is 1 */
57746 + /* Set the threshold and write it out if the device is used */
57747 + lis->threshold = val;
57749 + if (lis->flags & LIS302DL_F_INPUT_OPEN) {
57750 + unsigned long flags;
57752 + local_irq_save(flags);
57753 + __enable_data_collection(lis);
57754 + local_irq_restore(flags);
57760 +static DEVICE_ATTR(threshold, S_IRUGO | S_IWUSR, show_threshold, set_threshold);
57762 +static ssize_t show_duration(struct device *dev, struct device_attribute *attr,
57765 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57767 + return sprintf(buf, "%d\n", __duration_to_ms(lis,
57768 + __ms_to_duration(lis, lis->duration)));
57771 +static ssize_t set_duration(struct device *dev, struct device_attribute *attr,
57772 + const char *buf, size_t count)
57774 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57775 + unsigned int val;
57777 + if (sscanf(buf, "%u\n", &val) != 1)
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));
57790 +static DEVICE_ATTR(duration, S_IRUGO | S_IWUSR, show_duration, set_duration);
57792 +static ssize_t lis302dl_dump(struct device *dev, struct device_attribute *attr,
57795 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57799 + unsigned long flags;
57801 + local_irq_save(flags);
57803 + for (n = 0; n < sizeof(reg); n++)
57804 + reg[n] = __reg_read(lis, n);
57806 + local_irq_restore(flags);
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);
57815 + return end - buf;
57817 +static DEVICE_ATTR(dump, S_IRUGO, lis302dl_dump, NULL);
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)
57823 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57824 + unsigned int threshold;
57826 + if (sscanf(buf, "%u\n", &threshold) != 1)
57829 + if (threshold > 8000)
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;
57842 + lis->wakeup.threshold = threshold;
57844 + if (!(lis->flags & LIS302DL_F_IRQ_WAKE)) {
57845 + enable_irq_wake(lis->pdata->interrupt);
57846 + lis->flags |= LIS302DL_F_IRQ_WAKE;
57852 +static ssize_t show_wakeup_threshold(struct device *dev,
57853 + struct device_attribute *attr, char *buf)
57855 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57857 + /* All events off? */
57858 + if (lis->wakeup.threshold == 0)
57859 + return sprintf(buf, "off\n");
57861 + return sprintf(buf, "%u\n", lis->wakeup.threshold);
57864 +static DEVICE_ATTR(wakeup_threshold, S_IRUGO | S_IWUSR, show_wakeup_threshold,
57865 + set_wakeup_threshold);
57867 +static ssize_t set_wakeup_duration(struct device *dev,
57868 + struct device_attribute *attr, const char *buf, size_t count)
57870 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57871 + unsigned int duration;
57873 + if (sscanf(buf, "%u\n", &duration) != 1)
57876 + if (duration > 2550)
57879 + lis->wakeup.duration = duration;
57884 +static ssize_t show_wakeup_duration(struct device *dev,
57885 + struct device_attribute *attr, char *buf)
57887 + struct lis302dl_info *lis = dev_get_drvdata(dev);
57889 + return sprintf(buf, "%u\n", lis->wakeup.duration);
57892 +static DEVICE_ATTR(wakeup_duration, S_IRUGO | S_IWUSR, show_wakeup_duration,
57893 + set_wakeup_duration);
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,
57907 +static struct attribute_group lis302dl_attr_group = {
57909 + .attrs = lis302dl_sysfs_entries,
57912 +/* input device handling and driver core interaction */
57914 +static int lis302dl_input_open(struct input_dev *inp)
57916 + struct lis302dl_info *lis = input_get_drvdata(inp);
57917 + unsigned long flags;
57919 + local_irq_save(flags);
57921 + __enable_data_collection(lis);
57922 + lis->flags |= LIS302DL_F_INPUT_OPEN;
57924 + local_irq_restore(flags);
57929 +static void lis302dl_input_close(struct input_dev *inp)
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;
57936 + local_irq_save(flags);
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;
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,
57950 + local_irq_restore(flags);
57953 +/* get the device to reload its coefficients from EEPROM and wait for it
57957 +static int __lis302dl_reset_device(struct lis302dl_info *lis)
57959 + int timeout = 10;
57961 + __reg_write(lis, LIS302DL_REG_CTRL2,
57962 + LIS302DL_CTRL2_BOOT | LIS302DL_CTRL2_FDS);
57964 + while ((__reg_read(lis, LIS302DL_REG_CTRL2)
57965 + & LIS302DL_CTRL2_BOOT) && (timeout--))
57968 + return !!(timeout < 0);
57971 +static int __devinit lis302dl_probe(struct spi_device *spi)
57974 + struct lis302dl_info *lis;
57976 + unsigned long flags;
57977 + struct lis302dl_platform_data *pdata = spi->dev.platform_data;
57979 + spi->mode = SPI_MODE_3;
57980 + rc = spi_setup(spi);
57982 + dev_err(&spi->dev, "spi_setup failed\n");
57986 + lis = kzalloc(sizeof(*lis), GFP_KERNEL);
57990 + lis->dev = &spi->dev;
57993 + dev_set_drvdata(lis->dev, lis);
57995 + lis->pdata = pdata;
57997 + rc = sysfs_create_group(&lis->dev->kobj, &lis302dl_attr_group);
57999 + dev_err(lis->dev, "error creating sysfs group\n");
58000 + goto bail_free_lis;
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");
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;
58017 + rc = input_register_device(lis->input_dev);
58019 + dev_err(lis->dev, "error %d registering input device\n", rc);
58020 + goto bail_inp_dev;
58023 + local_irq_save(flags);
58024 + /* Configure our IO */
58025 + (lis->pdata->lis302dl_suspend_io)(lis, 1);
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);
58032 + local_irq_restore(flags);
58033 + goto bail_inp_reg;
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);
58042 + lis->threshold = 0;
58043 + lis->duration = 0;
58044 + memset(&lis->wakeup, 0, sizeof(lis->wakeup));
58046 + if (__lis302dl_reset_device(lis))
58047 + dev_err(lis->dev, "device BOOT reload failed\n");
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);
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);
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);
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);
58072 + /* push-pull, active-low */
58073 + __reg_write(lis, LIS302DL_REG_CTRL3, LIS302DL_CTRL3_IHL);
58075 + __lis302dl_int_mode(lis->dev, 1, LIS302DL_INTMODE_GND);
58076 + __lis302dl_int_mode(lis->dev, 2, LIS302DL_INTMODE_GND);
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);
58084 + dev_info(lis->dev, "Found %s\n", pdata->name);
58086 + lis->pdata = pdata;
58088 + set_irq_handler(lis->pdata->interrupt, handle_level_irq);
58090 + rc = request_irq(lis->pdata->interrupt, lis302dl_interrupt,
58091 + IRQF_TRIGGER_LOW, "lis302dl", lis);
58094 + dev_err(lis->dev, "error requesting IRQ %d\n",
58095 + lis->pdata->interrupt);
58096 + goto bail_inp_reg;
58101 + input_unregister_device(lis->input_dev);
58103 + input_free_device(lis->input_dev);
58105 + sysfs_remove_group(&lis->dev->kobj, &lis302dl_attr_group);
58111 +static int __devexit lis302dl_remove(struct spi_device *spi)
58113 + struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
58114 + unsigned long flags;
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);
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);
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);
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,
58160 +static int lis302dl_suspend(struct spi_device *spi, pm_message_t state)
58162 + struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
58163 + unsigned long flags;
58167 + /* determine if we want to wake up from the accel. */
58168 + if (lis->flags & LIS302DL_F_WUP_CLICK)
58171 + disable_irq(lis->pdata->interrupt);
58172 + local_irq_save(flags);
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.
58181 + (lis->pdata->lis302dl_suspend_io)(lis, 1);
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]);
58188 + /* power down or enable wakeup */
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);
58195 + __enable_wakeup(lis);
58197 + /* place our IO to the device in sleep-compatible states */
58198 + (lis->pdata->lis302dl_suspend_io)(lis, 0);
58200 + local_irq_restore(flags);
58205 +static int lis302dl_resume(struct spi_device *spi)
58207 + struct lis302dl_info *lis = dev_get_drvdata(&spi->dev);
58208 + unsigned long flags;
58211 + if (lis->flags & LIS302DL_F_WUP_CLICK)
58214 + local_irq_save(flags);
58216 + /* get our IO to the device back in operational states */
58217 + (lis->pdata->lis302dl_suspend_io)(lis, 1);
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);
58227 + if (__lis302dl_reset_device(lis))
58228 + dev_err(&spi->dev, "device BOOT reload failed\n");
58230 + lis->regs[LIS302DL_REG_CTRL1] |= LIS302DL_CTRL1_PD |
58231 + LIS302DL_CTRL1_Xen |
58232 + LIS302DL_CTRL1_Yen |
58233 + LIS302DL_CTRL1_Zen;
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]]);
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);
58243 + local_irq_restore(flags);
58244 + enable_irq(lis->pdata->interrupt);
58249 +#define lis302dl_suspend NULL
58250 +#define lis302dl_resume NULL
58253 +static struct spi_driver lis302dl_spi_driver = {
58255 + .name = "lis302dl",
58256 + .owner = THIS_MODULE,
58259 + .probe = lis302dl_probe,
58260 + .remove = __devexit_p(lis302dl_remove),
58261 + .suspend = lis302dl_suspend,
58262 + .resume = lis302dl_resume,
58265 +static int __devinit lis302dl_init(void)
58267 + return spi_register_driver(&lis302dl_spi_driver);
58270 +static void __exit lis302dl_exit(void)
58272 + spi_unregister_driver(&lis302dl_spi_driver);
58275 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
58276 +MODULE_LICENSE("GPL");
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
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
58295 +/* Philips PCF50606 Input Driver
58297 + * (C) 2006-2008 by Openmoko, Inc.
58298 + * Author: Balaji Rao <balajirrao@openmoko.org>
58299 + * All rights reserved.
58301 + * Broken down from monstrous PCF50606 driver mainly by
58302 + * Harald Welte, Matt Hsu, Andy Green and Werner Almesberger
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.
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>
58318 +#include <linux/mfd/pcf50606/core.h>
58320 +#define PCF50606_OOCS_ONKEY 0x01
58321 +#define PCF50606_OOCS_EXTON 0x02
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
58332 +#define PCF50606_REG_OOCS 0x01
58334 +struct pcf50606_input {
58335 + struct pcf50606 *pcf;
58336 + struct input_dev *input_dev;
58340 +pcf50606_input_irq(int irq, void *data)
58342 + struct pcf50606_input *input;
58343 + int onkey_released;
58346 + onkey_released = pcf50606_reg_read(input->pcf, PCF50606_REG_OOCS) &
58347 + PCF50606_OOCS_ONKEY;
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);
58354 + input_sync(input->input_dev);
58357 +static int __devinit pcf50606_input_probe(struct platform_device *pdev)
58359 + struct pcf50606_input *input;
58360 + struct pcf50606_subdev_pdata *pdata = pdev->dev.platform_data;
58361 + struct input_dev *input_dev;
58365 + input = kzalloc(sizeof(*input), GFP_KERNEL);
58369 + input_dev = input_allocate_device();
58370 + if (!input_dev) {
58375 + platform_set_drvdata(pdev, input);
58376 + input->pcf = pdata->pcf;
58377 + input->input_dev = input_dev;
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);
58384 + ret = input_register_device(input_dev);
58386 + input_free_device(input_dev);
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);
58398 +static int __devexit pcf50606_input_remove(struct platform_device *pdev)
58400 + struct pcf50606_input *input = platform_get_drvdata(pdev);
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);
58411 +static struct platform_driver pcf50606_input_driver = {
58413 + .name = "pcf50606-input",
58415 + .probe = pcf50606_input_probe,
58416 + .remove = __devexit_p(pcf50606_input_remove),
58419 +static int __init pcf50606_input_init(void)
58421 + return platform_driver_register(&pcf50606_input_driver);
58423 +module_init(pcf50606_input_init);
58425 +static void __exit pcf50606_input_exit(void)
58427 + platform_driver_unregister(&pcf50606_input_driver);
58429 +module_exit(pcf50606_input_exit);
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 */
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 */
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
58459 if INPUT_TOUCHSCREEN
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
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.
58473 +if TOUCHSCREEN_FILTER
58475 +config TOUCHSCREEN_FILTER_GROUP
58476 + bool "Group Touchscreen Filter"
58477 + depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
58480 + Say Y here if you want to use the Group touchscreen filter, it
58481 + avoids using atypical samples.
58483 +config TOUCHSCREEN_FILTER_MEDIAN
58484 + bool "Median Average Touchscreen Filter"
58485 + depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
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.
58491 +config TOUCHSCREEN_FILTER_MEAN
58492 + bool "Mean Average Touchscreen Filter"
58493 + depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
58496 + Say Y here if you want to use the Mean touchscreen filter, it
58497 + can further improve decent quality data by removing jitter
58499 +config TOUCHSCREEN_FILTER_LINEAR
58500 + bool "Linear Touchscreen Filter"
58501 + depends on INPUT_TOUCHSCREEN && TOUCHSCREEN_FILTER
58504 + Say Y here if you want to use the Linear touchscreen filter, it
58505 + enables the use of calibration data for the touchscreen.
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.
58516 +config TOUCHSCREEN_S3C2410
58517 + tristate "Samsung S3C2410 touchscreen input driver"
58518 + depends on ARCH_S3C2410 && INPUT && INPUT_TOUCHSCREEN
58521 + Say Y here if you have the s3c2410 touchscreen.
58523 + If unsure, say N.
58525 + To compile this driver as a module, choose M here: the
58526 + module will be called s3c2410_ts.
58528 +config TOUCHSCREEN_S3C2410_DEBUG
58529 + boolean "Samsung S3C2410 touchscreen debug messages"
58530 + depends on TOUCHSCREEN_S3C2410
58532 + Select this if you want debug messages
58534 config TOUCHSCREEN_GUNZE
58535 tristate "Gunze AHL-51S touchscreen"
58537 @@ -408,4 +474,15 @@
58538 To compile this driver as a module, choose M here: the
58539 module will be called tsc2007.
58541 +config TOUCHSCREEN_PCAP7200
58542 + tristate "EETI Projected capacitive touchscreen controller"
58544 + Say Y here if you have the EETI PCAP7200 touchscreen
58545 + controller chip in your system.
58547 + If unsure, say N.
58549 + To compile this driver as a module, choose M here: the
58550 + module will be called pcap7200.
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
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
58571 + /* Projected capacitive touchscreen controller driver.
58573 + * Copyright(c) 2008 Openmoko Inc.
58575 + * Author: Matt Hsu <matt_hsu@openmoko.org>
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.
58583 + * - apply ts_filter
58584 + * - add support for gesture event
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>
58599 +#include <linux/pcap7200.h>
58600 +#include <../drivers/input/touchscreen/ts_filter.h>
58602 +#include <mach/om-3d7k.h>
58604 +#define PCAP7200_OP_MODE_REG 0x07
58605 +#define RPT_PKT_SIZE 5
58606 +#define EVENT_UP 0x80
58607 +#define EVENT_DOWN 0x81
58610 +#define coord_interpret(msb_byte, lsb_byte) \
58611 + (msb_byte << 7 | lsb_byte)
58613 +struct pcap7200_data{
58614 + struct i2c_client *client;
58615 + struct input_dev *dev;
58616 + struct ts_filter **tsf;
58617 + struct mutex lock;
58619 + struct work_struct work;
58622 +static void pcap7200_work(struct work_struct *work)
58624 + struct pcap7200_data *pcap =
58625 + container_of(work, struct pcap7200_data, work);
58626 + uint8_t rpt_pkt[RPT_PKT_SIZE], event;
58630 + mutex_lock(&pcap->lock);
58632 + memset(rpt_pkt, 0, sizeof(rpt_pkt));
58634 + BUG_ON(pcap == NULL);
58636 + ret = i2c_master_recv(pcap->client, rpt_pkt, RPT_PKT_SIZE);
58638 + event = rpt_pkt[0];
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.
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);
58650 + coords[0] = coord_interpret(rpt_pkt[1], rpt_pkt[2]);
58651 + coords[1] = coord_interpret(rpt_pkt[3], rpt_pkt[4]);
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);
58662 + /* FIMXE: gesture events should be reported here. */
58665 + input_sync(pcap->dev);
58668 + mutex_unlock(&pcap->lock);
58669 + enable_irq(pcap->irq);
58672 +static const char *op_mode_name[] = {
58673 + [SLEEP] = "sleep",
58674 + [WAKEUP] = "wakeup",
58675 + [SINGLE_TOUCH] = "single_touch",
58676 + [MULTI_TOUCH] = "multi_touch",
58679 +static struct i2c_driver pcap7200_driver;
58681 +static int __set_op_mode(struct pcap7200_data *pcap, u_int8_t val)
58683 + u8 buf[] = { PCAP7200_OP_MODE_REG, val};
58686 + mutex_lock(&pcap->lock);
58688 + val = val & 0x03;
58690 + /* this chip has an issue.
58691 + * you need to give wakeup call for 3 times if it's
58694 + if (val == WAKEUP) {
58695 + for (i = 0; i < 3; i++)
58696 + ret = i2c_master_send(pcap->client, buf, sizeof(buf));
58698 + ret = i2c_master_send(pcap->client, buf, sizeof(buf));
58700 + mutex_unlock(&pcap->lock);
58704 +static ssize_t set_op_mode(struct device *dev, struct device_attribute *attr,
58705 + const char *buf, size_t count)
58707 + struct i2c_client *client = to_i2c_client(dev);
58708 + struct pcap7200_data *pcap = i2c_get_clientdata(client);
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);
58719 +static DEVICE_ATTR(op_mode, S_IRUGO | S_IWUSR, NULL, set_op_mode);
58721 +static irqreturn_t pcap7200_irq(int irq, void *_pcap)
58723 + struct pcap7200_data *pcap = _pcap;
58725 + disable_irq(pcap->irq);
58726 + schedule_work(&pcap->work);
58728 + return IRQ_HANDLED;
58732 +pcap7200_probe(struct i2c_client *client, const struct i2c_device_id *ids)
58734 + struct pcap7200_data *pcap;
58735 + struct input_dev *input_dev;
58737 + struct pcap7200_platform_data *pdata = client->dev.platform_data;
58739 + /* allocate pcap7200 data */
58740 + pcap = kzalloc(sizeof(struct pcap7200_data), GFP_KERNEL);
58744 + i2c_set_clientdata(client, pcap);
58745 + pcap->client = client;
58747 + mutex_init(&pcap->lock);
58750 + if (pdata->reset) {
58752 + dev_dbg(&client->dev, "hard reset\n");
58755 + /* operating mode */
58756 + __set_op_mode(pcap, pdata->mode);
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");
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);
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);
58776 + input_dev->name = client->name;
58777 + input_dev->id.bustype = BUS_I2C;
58778 + input_dev->dev.parent = &client->dev;
58780 + err = input_register_device(input_dev);
58785 + INIT_WORK(&pcap->work, pcap7200_work);
58787 + err = sysfs_create_file(&client->dev.kobj, &dev_attr_op_mode.attr);
58790 + dev_err(&client->dev, "Failed to create sysfs\n");
58795 + if (client->irq < 0) {
58796 + dev_err(&client->dev,
58797 + "No irq allocated in client resources!\n");
58798 + goto exit_rmsysfs;
58801 + pcap->irq = client->irq;
58802 + err = request_irq(pcap->irq, pcap7200_irq, IRQF_TRIGGER_LOW, "pcap7200", pcap);
58805 + goto exit_rmsysfs;
58810 + sysfs_remove_file(&client->dev.kobj, &dev_attr_op_mode.attr);
58812 + input_unregister_device(input_dev);
58818 +static int pcap7200_remove(struct i2c_client *client)
58820 + struct pcap7200_data *pcap = i2c_get_clientdata(client);
58822 + free_irq(pcap->irq, pcap);
58823 + input_unregister_device(pcap->dev);
58829 +static int pcap7200_suspend(struct device *dev, pm_message_t state)
58831 + struct i2c_client *client = to_i2c_client(dev);
58832 + struct pcap7200_data *pcap = i2c_get_clientdata(client);
58834 + __set_op_mode(pcap, SLEEP);
58838 +static int pcap7200_resume(struct device *dev)
58840 + struct i2c_client *client = to_i2c_client(dev);
58841 + struct pcap7200_data *pcap = i2c_get_clientdata(client);
58843 + __set_op_mode(pcap, WAKEUP);
58847 +#define pcap7200_suspend NULL
58848 +#define pcap7200_resume NULL
58851 +static struct i2c_device_id pcap7200_id_table[] = {
58852 + {"pcap7200", 0x0a},
58855 +static struct i2c_driver pcap7200_driver = {
58857 + .name = "pcap7200",
58858 + .suspend = pcap7200_suspend,
58859 + .resume = pcap7200_resume,
58861 + .id_table = pcap7200_id_table,
58862 + .probe = pcap7200_probe,
58863 + .remove = pcap7200_remove,
58866 +static int __init pcap7200_init(void)
58868 + return i2c_add_driver(&pcap7200_driver);
58871 +static void pcap7200_exit(void)
58873 + i2c_del_driver(&pcap7200_driver);
58875 +module_init(pcap7200_init);
58876 +module_exit(pcap7200_exit);
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
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.
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.
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
58899 + * Copyright (c) 2004 Arnaud Patard <arnaud.patard@rtp-net.org>
58900 + * iPAQ H1940 touchscreen support
58904 + * 2004-09-05: Herbert Pötzl <herbert@13thfloor.at>
58905 + * - added clock (de-)allocation code
58907 + * 2005-03-06: Arnaud Patard <arnaud.patard@rtp-net.org>
58908 + * - h1940_ -> s3c2410 (this driver is now also used on the n30
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
58916 + * 2005-03-23: Arnaud Patard <arnaud.patard@rtp-net.org>
58917 + * - Make use of some undocumented features of the touchscreen
58920 + * 2007-05-23: Harald Welte <laforge@openmoko.org>
58921 + * - Add proper support for S32440
58923 + * 2008-06-23: Andy Green <andy@openmoko.com>
58924 + * - removed averaging system
58925 + * - added generic Touchscreen filter stuff
58927 + * 2008-11-27: Nelson Castillo <arhuaco@freaks-unidos.net>
58928 + * - improve interrupt handling
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>
58946 +#include <mach/regs-gpio.h>
58947 +#include <mach/ts.h>
58948 +#include <mach/hardware.h>
58949 +#include <plat/regs-adc.h>
58951 +#include "ts_filter_chain.h"
58953 +/* For ts.dev.id.version */
58954 +#define S3C2410TSVERSION 0x0101
58956 +#define TSC_SLEEP (S3C2410_ADCTSC_PULL_UP_DISABLE | S3C2410_ADCTSC_XY_PST(0))
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))
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))
58970 +#define DEBUG_LVL KERN_DEBUG
58972 +MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
58973 +MODULE_DESCRIPTION("s3c2410 touchscreen driver");
58974 +MODULE_LICENSE("GPL");
58977 + * Definitions & global arrays.
58980 +static char *s3c2410ts_name = "s3c2410 TouchScreen";
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 */
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
58991 + * Per-touchscreen data.
58994 +struct s3c2410ts {
58995 + struct input_dev *dev;
58996 + struct ts_filter_chain *chain;
58999 + struct kfifo *event_fifo;
59002 +static struct s3c2410ts ts;
59004 +static void __iomem *base_addr;
59007 + * A few low level functions.
59010 +static inline void s3c2410_ts_connect(void)
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);
59018 +static void s3c2410_ts_start_adc_conversion(void)
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);
59027 + * Just send the input events.
59030 +enum ts_input_event {IE_DOWN = 0, IE_UP};
59032 +static void ts_input_report(int event, int coords[])
59034 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
59035 + static char *s[] = {"down", "up"};
59036 + struct timeval tv;
59038 + do_gettimeofday(&tv);
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);
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]);
59052 + input_report_key(ts.dev, BTN_TOUCH, 0);
59053 + input_report_abs(ts.dev, ABS_PRESSURE, 0);
59055 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
59056 + printk(DEBUG_LVL "T:%06d %6s\n",
59057 + (int)tv.tv_usec, s[event]);
59061 + input_sync(ts.dev);
59065 + * Manage the state of the touchscreen.
59068 +static void event_send_timer_f(unsigned long data);
59070 +static struct timer_list event_send_timer =
59071 + TIMER_INITIALIZER(event_send_timer_f, 0, 0);
59073 +static void event_send_timer_f(unsigned long data)
59075 + static int noop_counter;
59078 + while (__kfifo_get(ts.event_fifo, (unsigned char *)&event_type,
59082 + switch (event_type) {
59084 + if (ts.state == TS_STATE_RELEASE_PENDING)
59085 + /* Ignore short UP event */
59086 + ts.state = TS_STATE_PRESSED;
59090 + ts.state = TS_STATE_RELEASE_PENDING;
59094 + if (ts.is_down) /* stylus_action needs a conversion */
59095 + s3c2410_ts_start_adc_conversion();
59097 + if (unlikely(__kfifo_get(ts.event_fifo,
59098 + (unsigned char *)buf,
59100 + != sizeof(int) * 2))
59101 + goto ts_exit_error;
59103 + ts_input_report(IE_DOWN, buf);
59104 + ts.state = TS_STATE_PRESSED;
59108 + goto ts_exit_error;
59111 + noop_counter = 0;
59114 + if (noop_counter++ >= 1) {
59115 + noop_counter = 0;
59116 + if (ts.state == TS_STATE_RELEASE_PENDING) {
59118 + * We delay the UP event for a while to avoid jitter.
59119 + * If we get a DOWN event we do not send it.
59121 + ts_input_report(IE_UP, NULL);
59122 + ts.state = TS_STATE_STANDBY;
59124 + ts_filter_chain_clear(ts.chain);
59127 + mod_timer(&event_send_timer, jiffies + TS_RELEASE_TIMEOUT);
59132 +ts_exit_error: /* should not happen unless we have a bug */
59133 + printk(KERN_ERR __FILE__ ": event_send_timer_f failed\n");
59137 + * Manage interrupts.
59140 +static irqreturn_t stylus_updown(int irq, void *dev_id)
59142 + unsigned long data0;
59143 + unsigned long data1;
59146 + data0 = readl(base_addr+S3C2410_ADCDAT0);
59147 + data1 = readl(base_addr+S3C2410_ADCDAT1);
59149 + ts.is_down = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) &&
59150 + (!(data1 & S3C2410_ADCDAT0_UPDOWN));
59152 + event_type = ts.is_down ? 'D' : 'U';
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");
59159 + s3c2410_ts_start_adc_conversion();
59161 + writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
59163 + mod_timer(&event_send_timer, jiffies + 1);
59165 + return IRQ_HANDLED;
59168 +static irqreturn_t stylus_action(int irq, void *dev_id)
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;
59178 + switch (ts_filter_chain_feed(ts.chain, &buf[1])) {
59180 + /* The filter wants more points. */
59181 + s3c2410_ts_start_adc_conversion();
59182 + return IRQ_HANDLED;
59184 + /* We have a point from the filters or no filtering enabled. */
59188 + printk(KERN_ERR __FILE__
59189 + ":%d Invalid ts_filter_chain_feed return value.\n",
59192 + /* Error. Ignore the event. */
59193 + ts_filter_chain_clear(ts.chain);
59194 + writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
59195 + return IRQ_HANDLED;
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");
59202 + writel(WAIT4INT(1), base_addr + S3C2410_ADCTSC);
59203 + mod_timer(&event_send_timer, jiffies + 1);
59205 + return IRQ_HANDLED;
59208 +static struct clk *adc_clock;
59211 + * The functions for inserting/removing us as a module.
59214 +static int __init s3c2410ts_probe(struct platform_device *pdev)
59217 + struct s3c2410_ts_mach_info *info;
59218 + struct input_dev *input_dev;
59221 + dev_info(&pdev->dev, "Starting\n");
59223 + info = (struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
59227 + dev_err(&pdev->dev, "Hm... too bad: no platform data for ts\n");
59231 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
59232 + printk(DEBUG_LVL "Entering s3c2410ts_init\n");
59235 + adc_clock = clk_get(NULL, "adc");
59236 + if (!adc_clock) {
59237 + dev_err(&pdev->dev, "failed to get adc clock source\n");
59240 + clk_enable(adc_clock);
59242 +#ifdef CONFIG_TOUCHSCREEN_S3C2410_DEBUG
59243 + printk(DEBUG_LVL "got and enabled clock\n");
59246 + base_addr = ioremap(S3C2410_PA_ADC,0x20);
59247 + if (base_addr == NULL) {
59248 + dev_err(&pdev->dev, "Failed to remap register block\n");
59254 + /* If we acutally are a S3C2410: Configure GPIOs */
59255 + if (!strcmp(pdev->name, "s3c2410-ts"))
59256 + s3c2410_ts_connect();
59258 + if ((info->presc & 0xff) > 0)
59259 + writel(S3C2410_ADCCON_PRSCEN |
59260 + S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
59261 + base_addr + S3C2410_ADCCON);
59263 + writel(0, base_addr+S3C2410_ADCCON);
59265 + /* Initialise registers */
59266 + if ((info->delay & 0xffff) > 0)
59267 + writel(info->delay & 0xffff, base_addr + S3C2410_ADCDLY);
59269 + writel(WAIT4INT(0), base_addr + S3C2410_ADCTSC);
59271 + /* Initialise input stuff */
59272 + memset(&ts, 0, sizeof(struct s3c2410ts));
59273 + input_dev = input_allocate_device();
59275 + if (!input_dev) {
59276 + dev_err(&pdev->dev, "Unable to allocate the input device\n");
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);
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)) {
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);
59304 + if (IS_ERR(ts.chain))
59307 + ts_filter_chain_clear(ts.chain);
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);
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);
59326 + dev_info(&pdev->dev, "Successfully loaded\n");
59328 + /* All went ok, so register to the input system */
59329 + rc = input_register_device(ts.dev);
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);
59344 + disable_irq(IRQ_ADC);
59346 + ts_filter_chain_destroy(ts.chain);
59347 + kfifo_free(ts.event_fifo);
59349 + input_unregister_device(ts.dev);
59351 + iounmap(base_addr);
59357 +static int s3c2410ts_remove(struct platform_device *pdev)
59359 + disable_irq(IRQ_ADC);
59360 + disable_irq(IRQ_TC);
59361 + free_irq(IRQ_TC,ts.dev);
59362 + free_irq(IRQ_ADC,ts.dev);
59365 + clk_disable(adc_clock);
59366 + clk_put(adc_clock);
59367 + adc_clock = NULL;
59370 + input_unregister_device(ts.dev);
59371 + iounmap(base_addr);
59373 + ts_filter_chain_destroy(ts.chain);
59375 + kfifo_free(ts.event_fifo);
59381 +static int s3c2410ts_suspend(struct platform_device *pdev, pm_message_t state)
59383 + writel(TSC_SLEEP, base_addr+S3C2410_ADCTSC);
59384 + writel(readl(base_addr+S3C2410_ADCCON) | S3C2410_ADCCON_STDBM,
59385 + base_addr+S3C2410_ADCCON);
59387 + disable_irq(IRQ_ADC);
59388 + disable_irq(IRQ_TC);
59390 + clk_disable(adc_clock);
59395 +static int s3c2410ts_resume(struct platform_device *pdev)
59397 + struct s3c2410_ts_mach_info *info =
59398 + ( struct s3c2410_ts_mach_info *)pdev->dev.platform_data;
59400 + clk_enable(adc_clock);
59403 + ts_filter_chain_clear(ts.chain);
59405 + enable_irq(IRQ_ADC);
59406 + enable_irq(IRQ_TC);
59408 + if ((info->presc&0xff) > 0)
59409 + writel(S3C2410_ADCCON_PRSCEN |
59410 + S3C2410_ADCCON_PRSCVL(info->presc&0xFF),
59411 + base_addr+S3C2410_ADCCON);
59413 + writel(0,base_addr+S3C2410_ADCCON);
59415 + /* Initialise registers */
59416 + if ((info->delay & 0xffff) > 0)
59417 + writel(info->delay & 0xffff, base_addr+S3C2410_ADCDLY);
59419 + writel(WAIT4INT(0), base_addr+S3C2410_ADCTSC);
59425 +#define s3c2410ts_suspend NULL
59426 +#define s3c2410ts_resume NULL
59429 +static struct platform_driver s3c2410ts_driver = {
59431 + .name = "s3c2410-ts",
59432 + .owner = THIS_MODULE,
59434 + .probe = s3c2410ts_probe,
59435 + .remove = s3c2410ts_remove,
59436 + .suspend = s3c2410ts_suspend,
59437 + .resume = s3c2410ts_resume,
59441 +static struct platform_driver s3c2440ts_driver = {
59443 + .name = "s3c2440-ts",
59444 + .owner = THIS_MODULE,
59446 + .probe = s3c2410ts_probe,
59447 + .remove = s3c2410ts_remove,
59448 + .suspend = s3c2410ts_suspend,
59449 + .resume = s3c2410ts_resume,
59453 +static int __init s3c2410ts_init(void)
59457 + rc = platform_driver_register(&s3c2410ts_driver);
59461 + rc = platform_driver_register(&s3c2440ts_driver);
59463 + platform_driver_unregister(&s3c2410ts_driver);
59468 +static void __exit s3c2410ts_exit(void)
59470 + platform_driver_unregister(&s3c2440ts_driver);
59471 + platform_driver_unregister(&s3c2410ts_driver);
59474 +module_init(s3c2410ts_init);
59475 +module_exit(s3c2410ts_exit);
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
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.
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.
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
59496 + * Copyright (c) 2008,2009 Andy Green <andy@openmoko.com>
59499 +#include <linux/kernel.h>
59500 +#include <linux/device.h>
59502 +#include "ts_filter_chain.h"
59503 +#include "ts_filter.h"
59506 + * Tux, would you like the following function in /lib?
59507 + * It helps us avoid silly code.
59511 + * sptrlen - Count how many non-null pointers are in a pointer array
59512 + * @arr: The array of pointers
59514 +static int sptrlen(const void *arr)
59516 + /* All pointers have the same size. */
59517 + const int **p = (const int **)arr;
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. */
59534 + /* FIXME: Add a spinlock and use it. */
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)
59542 + struct ts_filter_chain *c;
59546 + BUG_ON((count_coords < 1));
59547 + BUG_ON(count_coords > MAX_TS_FILTER_COORDS);
59549 + c = kzalloc(sizeof(struct ts_filter_chain), GFP_KERNEL);
59551 + goto create_err_1;
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);
59557 + goto create_err_1;
59558 + c->pchain = c->arr + len;
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);
59565 + dev_info(&pdev->dev, "Filter %d creation failed\n",
59567 + goto create_err_2;
59570 + f->api = conf->api;
59571 + c->arr[count++] = f;
59573 + if (f->api->haspoint && f->api->getpoint && f->api->process)
59574 + c->pchain[c->pchain_len++] = f;
59579 + dev_info(&pdev->dev, "%d filter(s) initialized\n", count);
59584 + ts_filter_chain_destroy(c); /* Also frees c. */
59586 + dev_info(&pdev->dev, "Error in filter chain initialization\n");
59588 + * FIXME: Individual filters have to return errors this way.
59589 + * We only have to forward the errors we find.
59591 + return ERR_PTR(-ENOMEM);
59593 +EXPORT_SYMBOL_GPL(ts_filter_chain_create);
59595 +void ts_filter_chain_destroy(struct ts_filter_chain *c)
59598 + struct ts_filter **a = c->arr;
59600 + ((*a)->api->destroy)(*a);
59607 +EXPORT_SYMBOL_GPL(ts_filter_chain_destroy);
59609 +void ts_filter_chain_clear(struct ts_filter_chain *c)
59611 + struct ts_filter **a = c->arr;
59614 + if ((*a)->api->clear)
59615 + ((*a)->api->clear)(*a);
59619 +EXPORT_SYMBOL_GPL(ts_filter_chain_clear);
59621 +static void ts_filter_chain_scale(struct ts_filter_chain *c, int *coords)
59623 + struct ts_filter **a = c->arr;
59625 + if ((*a)->api->scale)
59626 + ((*a)->api->scale)(*a, coords);
59631 +int ts_filter_chain_feed(struct ts_filter_chain *c, int *coords)
59633 + int len = c->pchain_len;
59636 + if (!c->pchain[0])
59637 + return 1; /* Nothing to do. */
59639 + BUG_ON(c->pchain[0]->api->haspoint(c->pchain[0]));
59641 + if (c->pchain[0]->api->process(c->pchain[0], coords))
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);
59648 + c->pchain[i]->api->process(c->pchain[i], coords))
59649 + return -1; /* Error. */
59655 + if (i >= 0) { /* Same as i == len. */
59656 + ts_filter_chain_scale(c, coords);
59662 +EXPORT_SYMBOL_GPL(ts_filter_chain_feed);
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
59668 +#ifndef __TS_FILTER_CHAIN_H__
59669 +#define __TS_FILTER_CHAIN_H__
59672 + * Touchscreen filter chains.
59674 + * (c) 2008,2009 Andy Green <andy@openmoko.com>
59677 +#include "ts_filter.h"
59679 +#include <linux/err.h>
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;
59688 +struct ts_filter_chain;
59690 +#ifdef CONFIG_TOUCHSCREEN_FILTER
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.
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);
59702 +/* Destroy the chain. */
59703 +extern void ts_filter_chain_destroy(struct ts_filter_chain *c);
59705 +/* Clear the filter chain. */
59706 +extern void ts_filter_chain_clear(struct ts_filter_chain *c);
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
59716 +int ts_filter_chain_feed(struct ts_filter_chain *c, int *coords);
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)
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
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.
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.
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
59745 + * Copyright (C) 2008,2009 by Openmoko, Inc.
59746 + * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
59747 + * All rights reserved.
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.
59753 + * 1) We collect S samples.
59755 + * 2) For each dimension:
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.
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.
59770 +#include <linux/kernel.h>
59771 +#include <linux/slab.h>
59772 +#include <linux/sort.h>
59773 +#include "ts_filter_group.h"
59775 +struct ts_filter_group {
59776 + /* Private filter configuration. */
59777 + struct ts_filter_group_configuration *config;
59778 + /* Filter API. */
59779 + struct ts_filter tsf;
59781 + int N; /* How many samples we have. */
59782 + int *samples[MAX_TS_FILTER_COORDS]; /* The samples: our input. */
59784 + int *group_size; /* Used for temporal computations. */
59785 + int *sorted_samples; /* Used for temporal computations. */
59787 + int range_max[MAX_TS_FILTER_COORDS]; /* Max. computed ranges. */
59788 + int range_min[MAX_TS_FILTER_COORDS]; /* Min. computed ranges. */
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. */
59795 +#define ts_filter_to_filter_group(f) \
59796 + container_of(f, struct ts_filter_group, tsf)
59799 +static void ts_filter_group_clear_internal(struct ts_filter_group *tsfg,
59803 + tsfg->tries_left = attempts;
59805 + tsfg->result = 0;
59808 +static void ts_filter_group_clear(struct ts_filter *tsf)
59810 + struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf);
59812 + ts_filter_group_clear_internal(tsfg, tsfg->config->attempts);
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)
59820 + struct ts_filter_group *tsfg;
59823 + tsfg = kzalloc(sizeof(struct ts_filter_group), GFP_KERNEL);
59827 + tsfg->config = container_of(conf,
59828 + struct ts_filter_group_configuration,
59830 + tsfg->tsf.count_coords = count_coords;
59832 + BUG_ON(tsfg->config->attempts <= 0);
59834 + tsfg->samples[0] = kmalloc((2 + count_coords) * sizeof(int) *
59835 + tsfg->config->length, GFP_KERNEL);
59836 + if (!tsfg->samples[0]) {
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;
59847 + ts_filter_group_clear_internal(tsfg, tsfg->config->attempts);
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);
59853 + return &tsfg->tsf;
59856 +static void ts_filter_group_destroy(struct ts_filter *tsf)
59858 + struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf);
59860 + kfree(tsfg->samples[0]); /* first guy has pointer from kmalloc */
59864 +static int int_cmp(const void *_a, const void *_b)
59866 + const int *a = _a;
59867 + const int *b = _b;
59876 +static void ts_filter_group_prepare_next(struct ts_filter *tsf);
59878 +static int ts_filter_group_process(struct ts_filter *tsf, int *coords)
59880 + struct ts_filter_group *tsfg = ts_filter_to_filter_group(tsf);
59884 + BUG_ON(tsfg->N >= tsfg->config->length);
59885 + BUG_ON(tsfg->ready);
59887 + for (n = 0; n < tsf->count_coords; n++)
59888 + tsfg->samples[n][tsfg->N] = coords[n];
59890 + if (++tsfg->N < tsfg->config->length)
59891 + return 0; /* We need more samples. */
59893 + for (n = 0; n < tsfg->tsf.count_coords; n++) {
59894 + int *v = tsfg->sorted_samples;
59897 + int best_idx = 0;
59900 + memcpy(v, tsfg->samples[n], tsfg->N * sizeof(int));
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
59909 + sort(v, tsfg->N, sizeof(int), int_cmp, NULL);
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]++;
59916 + tsfg->group_size[++ngroups] = 1;
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];
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. */
59937 + return 1; /* We give up: error. */
59940 + tsfg->range_min[n] = v[best_idx];
59941 + tsfg->range_max[n] = v[best_idx + best_size - 1];
59944 + ts_filter_group_prepare_next(tsf);
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.
59954 +static void ts_filter_group_prepare_next(struct ts_filter *tsf)
59956 + struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
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])
59967 + if (n == priv->tsf.count_coords) /* Sample is OK. */
59973 + if (unlikely(priv->result >= priv->N)) { /* No sample to deliver. */
59974 + ts_filter_group_clear_internal(priv, priv->config->attempts);
59981 +static int ts_filter_group_haspoint(struct ts_filter *tsf)
59983 + struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
59985 + return priv->ready;
59988 +static void ts_filter_group_getpoint(struct ts_filter *tsf, int *point)
59990 + struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
59993 + BUG_ON(!priv->ready);
59995 + for (n = 0; n < priv->tsf.count_coords; n++)
59996 + point[n] = priv->samples[n][priv->result];
60000 + /* This call will update priv->ready. */
60001 + ts_filter_group_prepare_next(tsf);
60005 + * Get ready to process the next batch of points, forget
60006 + * points we could have delivered.
60008 +static void ts_filter_group_scale(struct ts_filter *tsf, int *coords)
60010 + struct ts_filter_group *priv = ts_filter_to_filter_group(tsf);
60012 + ts_filter_group_clear_internal(priv, priv->config->attempts);
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,
60024 +EXPORT_SYMBOL_GPL(ts_filter_group_api);
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
60030 +#ifndef __TS_FILTER_GROUP_H__
60031 +#define __TS_FILTER_GROUP_H__
60033 +#include "ts_filter.h"
60036 + * Touchscreen group filter.
60038 + * Copyright (C) 2008,2009 by Openmoko, Inc.
60039 + * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
60043 +struct ts_filter_group_configuration {
60044 + /* Size of the filter. */
60047 + * If two points are separated by this distance or less they
60048 + * are considered to be members of the same group.
60050 + int close_enough;
60051 + /* Minimum allowed size for the biggest group in the sample set. */
60054 + * Number of times we try to get a group of points with at least
60055 + * threshold points.
60059 + /* Generic filter configuration. */
60060 + struct ts_filter_configuration config;
60063 +extern const struct ts_filter_api ts_filter_group_api;
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
60070 +#ifndef __TS_FILTER_H__
60071 +#define __TS_FILTER_H__
60074 + * Touchscreen filter.
60076 + * (c) 2008,2009 Andy Green <andy@openmoko.com>
60079 +#include <linux/platform_device.h>
60081 +#define MAX_TS_FILTER_COORDS 3 /* X, Y and Z (pressure). */
60084 +struct ts_filter_configuration;
60086 +/* Operations that a filter can perform. */
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);
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.
60107 + * Process the filter.
60108 + * It returns non-zero if the filter reaches an error.
60110 + int (*process)(struct ts_filter *filter, int *coords);
60112 + * Is the filter ready to return a point?
60113 + * Please do not code side effects in this function.
60115 + int (*haspoint)(struct ts_filter *filter);
60118 + * Do not call unless the filter actually has a point to deliver.
60120 + void (*getpoint)(struct ts_filter *filter, int *coords);
60123 + * Scale the points - optional.
60124 + * A filter could only scale coordinates.
60126 + void (*scale)(struct ts_filter *filter, int *coords);
60130 + * Generic filter configuration. Actual configurations have this structure
60133 +struct ts_filter_configuration {
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;
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
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.
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.
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
60163 + * Copyright (C) 2008,2009 by Openmoko, Inc.
60164 + * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
60165 + * All rights reserved.
60167 + * Linearly scale touchscreen values.
60169 + * Expose the TS_FILTER_LINEAR_NCONSTANTS for the linear transformation
60174 +#include <linux/kernel.h>
60175 +#include <linux/slab.h>
60176 +#include <linux/string.h>
60178 +#include "ts_filter_linear.h"
60180 +struct ts_filter_linear;
60184 +struct const_obj {
60185 + /* The actual private object. */
60186 + struct ts_filter_linear *tsfl;
60187 + /* Our kobject. */
60188 + struct kobject kobj;
60191 +#define to_const_obj(x) container_of(x, struct const_obj, kobj)
60193 +struct const_attribute {
60194 + struct attribute attr;
60195 + ssize_t (*show)(struct const_obj *const, struct const_attribute *attr,
60197 + ssize_t (*store)(struct const_obj *const, struct const_attribute *attr,
60198 + const char *buf, size_t count);
60201 +#define to_const_attr(x) container_of(x, struct const_attribute, attr)
60204 +/* Private linear filter structure. */
60206 +struct ts_filter_linear {
60207 + /* Private configuration for this filter. */
60208 + struct ts_filter_linear_configuration *config;
60210 + /* Generic filter API. */
60211 + struct ts_filter tsf;
60213 + /* Linear constants for the transformation. */
60214 + int constants[TS_FILTER_LINEAR_NCONSTANTS];
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];
60230 +#define ts_filter_to_filter_linear(f) \
60231 + container_of(f, struct ts_filter_linear, tsf)
60233 +/* Sysfs functions. */
60235 +static ssize_t const_attr_show(struct kobject *kobj,
60236 + struct attribute *attr,
60239 + struct const_attribute *a = to_const_attr(attr);
60241 + return a->show(to_const_obj(kobj), a, buf);
60244 +static ssize_t const_attr_store(struct kobject *kobj,
60245 + struct attribute *attr,
60246 + const char *buf, size_t len)
60248 + struct const_attribute *a = to_const_attr(attr);
60250 + return a->store(to_const_obj(kobj), a, buf, len);
60253 +static struct sysfs_ops const_sysfs_ops = {
60254 + .show = const_attr_show,
60255 + .store = const_attr_store,
60258 +static void const_release(struct kobject *kobj)
60260 + kfree(to_const_obj(kobj)->tsfl);
60263 +static ssize_t const_show(struct const_obj *obj, struct const_attribute *attr,
60268 + sscanf(attr->attr.name, "%d", &who);
60269 + return sprintf(buf, "%d\n", obj->tsfl->constants[who]);
60272 +static ssize_t const_store(struct const_obj *obj, struct const_attribute *attr,
60273 + const char *buf, size_t count)
60277 + sscanf(attr->attr.name, "%d", &who);
60278 + sscanf(buf, "%d", &obj->tsfl->constants[who]);
60282 +/* Filter functions. */
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)
60289 + struct ts_filter_linear *tsfl;
60293 + tsfl = kzalloc(sizeof(struct ts_filter_linear), GFP_KERNEL);
60297 + tsfl->config = container_of(conf,
60298 + struct ts_filter_linear_configuration,
60301 + tsfl->tsf.count_coords = count_coords;
60303 + for (i = 0; i < TS_FILTER_LINEAR_NCONSTANTS; ++i) {
60304 + tsfl->constants[i] = tsfl->config->constants[i];
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;
60314 + tsfl->attrs[i] = NULL;
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 */
60321 + ret = kobject_init_and_add(&tsfl->c_obj.kobj, &tsfl->const_ktype,
60322 + &pdev->dev.kobj, "calibration");
60324 + kobject_put(&tsfl->c_obj.kobj);
60328 + dev_info(&pdev->dev, "Created Linear filter coords:%d\n", count_coords);
60330 + return &tsfl->tsf;
60333 +static void ts_filter_linear_destroy(struct ts_filter *tsf)
60335 + struct ts_filter_linear *tsfl = ts_filter_to_filter_linear(tsf);
60337 + /* Kernel frees tsfl in const_release. */
60338 + kobject_put(&tsfl->c_obj.kobj);
60341 +static void ts_filter_linear_scale(struct ts_filter *tsf, int *coords)
60343 + struct ts_filter_linear *tsfl = ts_filter_to_filter_linear(tsf);
60345 + int *k = tsfl->constants;
60346 + int c0 = coords[tsfl->config->coord0];
60347 + int c1 = coords[tsfl->config->coord1];
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];
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,
60358 +EXPORT_SYMBOL_GPL(ts_filter_linear_api);
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
60364 +#ifndef __TS_FILTER_LINEAR_H__
60365 +#define __TS_FILTER_LINEAR_H__
60367 +#include "ts_filter.h"
60368 +#include <linux/kobject.h>
60371 + * Touchscreen linear filter.
60373 + * Copyright (C) 2008,2009 by Openmoko, Inc.
60374 + * Author: Nelson Castillo <arhuaco@freaks-unidos.net>
60378 +#define TS_FILTER_LINEAR_NCONSTANTS 7
60380 +struct ts_filter_linear_configuration {
60381 + /* Calibration constants. */
60382 + int constants[TS_FILTER_LINEAR_NCONSTANTS];
60383 + /* First coordinate. */
60385 + /* Second coordinate. */
60388 + /* Generic filter configuration. */
60389 + struct ts_filter_configuration config;
60392 +extern const struct ts_filter_api ts_filter_linear_api;
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
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.
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.
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
60414 + * Copyright (c) 2008,2009
60415 + * Andy Green <andy@openmoko.com>
60416 + * Nelson Castillo <arhuaco@freaks-unidos.net>
60418 + * Simple mean filter.
60422 +#include <linux/errno.h>
60423 +#include <linux/kernel.h>
60424 +#include <linux/slab.h>
60426 +#include "ts_filter_mean.h"
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;
60434 + /* Index on a circular buffer. */
60436 + /* Useful to tell if the circular buffer is full(read:ready). */
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. */
60446 +#define ts_filter_to_filter_mean(f) container_of(f, struct ts_filter_mean, tsf)
60449 +static void ts_filter_mean_clear(struct ts_filter *tsf);
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)
60456 + struct ts_filter_mean *priv;
60460 + priv = kzalloc(sizeof(struct ts_filter_mean), GFP_KERNEL);
60464 + priv->tsf.count_coords = count_coords;
60465 + priv->config = container_of(conf,
60466 + struct ts_filter_mean_configuration,
60469 + BUG_ON(priv->config->length <= 0);
60471 + v = kmalloc(priv->config->length * sizeof(int) * count_coords,
60476 + for (n = 0; n < count_coords; n++) {
60477 + priv->fifo[n] = v;
60478 + v += priv->config->length;
60481 + ts_filter_mean_clear(&priv->tsf);
60483 + dev_info(&pdev->dev, "Created Mean filter len:%d coords:%d\n",
60484 + priv->config->length, count_coords);
60486 + return &priv->tsf;
60489 +static void ts_filter_mean_destroy(struct ts_filter *tsf)
60491 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60493 + kfree(priv->fifo[0]); /* first guy has pointer from kmalloc */
60497 +static void ts_filter_mean_clear(struct ts_filter *tsf)
60499 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60504 + memset(priv->sum, 0, tsf->count_coords * sizeof(int));
60507 +static int ts_filter_mean_process(struct ts_filter *tsf, int *coords)
60509 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60512 + BUG_ON(priv->ready);
60514 + for (n = 0; n < tsf->count_coords; n++) {
60515 + priv->sum[n] += coords[n];
60516 + priv->fifo[n][priv->curr] = coords[n];
60519 + if (priv->count + 1 == priv->config->length)
60524 + priv->curr = (priv->curr + 1) % priv->config->length;
60526 + return 0; /* No error. */
60529 +static int ts_filter_mean_haspoint(struct ts_filter *tsf)
60531 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60533 + return priv->ready;
60536 +static void ts_filter_mean_getpoint(struct ts_filter *tsf, int *point)
60538 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60541 + BUG_ON(!priv->ready);
60543 + for (n = 0; n < tsf->count_coords; n++) {
60544 + point[n] = priv->sum[n];
60545 + priv->sum[n] -= priv->fifo[n][priv->curr];
60551 +static void ts_filter_mean_scale(struct ts_filter *tsf, int *coords)
60554 + struct ts_filter_mean *priv = ts_filter_to_filter_mean(tsf);
60556 + for (n = 0; n < tsf->count_coords; n++) {
60557 + coords[n] += priv->config->length >> 1; /* Rounding. */
60558 + coords[n] /= priv->config->length;
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,
60571 +EXPORT_SYMBOL_GPL(ts_filter_mean_api);
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
60577 +#ifndef __TS_FILTER_MEAN_H__
60578 +#define __TS_FILTER_MEAN_H__
60580 +#include "ts_filter.h"
60583 + * Touchscreen filter.
60588 + * Andy Green <andy@openmoko.com>
60589 + * Nelson Castillo <arhuaco@freaks-unidos.net>
60592 +/* Configuration for this filter. */
60593 +struct ts_filter_mean_configuration {
60594 + /* Number of points for the mean. */
60597 + /* Generic filter configuration. */
60598 + struct ts_filter_configuration config;
60601 +/* API functions for the mean filter */
60602 +extern const struct ts_filter_api ts_filter_mean_api;
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
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.
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.
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
60624 + * Copyright (c) 2008 Andy Green <andy@openmoko.com>
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.
60633 + * This strongly rejects brief excursions away from a central point that is
60634 + * sticky in time compared to the excursion duration.
60636 + * Thanks to Dale Schumacher (who wrote some example code) and Carl-Daniel
60637 + * Halifinger who pointed out this would be a good method.
60640 +#include <linux/errno.h>
60641 +#include <linux/kernel.h>
60642 +#include <linux/slab.h>
60643 +#include "ts_filter_median.h"
60645 +struct ts_filter_median {
60646 + /* Private configuration. */
60647 + struct ts_filter_median_configuration *config;
60648 + /* Generic Filter API. */
60649 + struct ts_filter tsf;
60651 + /* Count raw samples we get. */
60652 + int samples_count;
60654 + * Remember the last coordinates we got in order to know if
60655 + * we are moving slow or fast.
60657 + int last_issued[MAX_TS_FILTER_COORDS];
60658 + /* How many samples in the sort buffer are 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. */
60666 + /* Do we have a sample to deliver? */
60670 +#define ts_filter_to_filter_median(f) \
60671 + container_of(f, struct ts_filter_median, tsf)
60674 +static void ts_filter_median_insert(int *p, int sample, int count)
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. */
60688 + p[count] = sample; /* Nobody was bigger than us, add us on the end. */
60691 +static void ts_filter_median_del(int *p, int value, int count)
60695 + for (index = 0; index < count; index++)
60696 + if (p[index] == value) {
60697 + for (; index < count; index++)
60698 + p[index] = p[index + 1];
60704 +static void ts_filter_median_clear(struct ts_filter *tsf)
60706 + struct ts_filter_median *tsfm = ts_filter_to_filter_median(tsf);
60711 + memset(&tsfm->last_issued[0], 1, tsf->count_coords * sizeof(int));
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)
60721 + struct ts_filter_median *tsfm = kzalloc(sizeof(struct ts_filter_median),
60727 + tsfm->config = container_of(conf,
60728 + struct ts_filter_median_configuration,
60731 + tsfm->tsf.count_coords = count_coords;
60733 + tsfm->config->midpoint = (tsfm->config->extent >> 1) + 1;
60735 + p = kmalloc(2 * count_coords * sizeof(int) * (tsfm->config->extent + 1),
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;
60749 + ts_filter_median_clear(&tsfm->tsf);
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);
60756 + return &tsfm->tsf;
60759 +static void ts_filter_median_destroy(struct ts_filter *tsf)
60761 + struct ts_filter_median *tsfm = ts_filter_to_filter_median(tsf);
60763 + kfree(tsfm->sort[0]); /* First guy has pointer from kmalloc. */
60767 +static void ts_filter_median_scale(struct ts_filter *tsf, int *coords)
60771 + for (n = 0; n < tsf->count_coords; n++)
60772 + coords[n] = (coords[n] + 2) / 3;
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.
60781 +static int ts_filter_median_process(struct ts_filter *tsf, int *coords)
60783 + struct ts_filter_median *tsfm = ts_filter_to_filter_median(tsf);
60785 + int movement = 1;
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);
60793 + /* Move us on in the fifo. */
60794 + if (++tsfm->pos == (tsfm->config->extent + 1))
60797 + /* Have we finished a median sampling? */
60798 + if (++tsfm->valid < tsfm->config->extent)
60799 + goto process_exit; /* No valid sample to use. */
60801 + BUG_ON(tsfm->valid != tsfm->config->extent);
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.
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],
60815 + tsfm->samples_count--;
60816 + if (tsfm->samples_count >= 0)
60817 + goto process_exit;
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];
60825 + movement += abs(tsfm->last_issued[n] - coords[n]);
60828 + if (movement > tsfm->config->decimation_threshold) /* Moving fast. */
60829 + tsfm->samples_count = tsfm->config->decimation_above;
60831 + tsfm->samples_count = tsfm->config->decimation_below;
60833 + memcpy(&tsfm->last_issued[0], coords, tsf->count_coords * sizeof(int));
60841 +static int ts_filter_median_haspoint(struct ts_filter *tsf)
60843 + struct ts_filter_median *priv = ts_filter_to_filter_median(tsf);
60845 + return priv->ready;
60848 +static void ts_filter_median_getpoint(struct ts_filter *tsf, int *point)
60850 + struct ts_filter_median *priv = ts_filter_to_filter_median(tsf);
60852 + BUG_ON(!priv->ready);
60854 + memcpy(point, &priv->last_issued[0], tsf->count_coords * sizeof(int));
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,
60868 +EXPORT_SYMBOL_GPL(ts_filter_median_api);
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
60874 +#ifndef __TS_FILTER_MEDIAN_H__
60875 +#define __TS_FILTER_MEDIAN_H__
60877 +#include "ts_filter.h"
60880 + * Touchscreen filter.
60884 + * (c) 2008 Andy Green <andy@openmoko.com>
60887 +struct ts_filter_median_configuration {
60888 + /* Size of the filter. */
60890 + /* Precomputed 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;
60899 + /* Generic configuration. */
60900 + struct ts_filter_configuration config;
60903 +extern const struct ts_filter_api ts_filter_median_api;
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"
60912 source "drivers/platform/Kconfig"
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
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
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.
60931 +config LEDS_NEO1973_VIBRATOR
60932 + tristate "Vibrator Support for the FIC Neo1973 GSM phone"
60933 + depends on LEDS_CLASS && MACH_NEO1973
60935 + This option enables support for the vibrator on the FIC Neo1973.
60937 +config LEDS_NEO1973_GTA02
60938 + tristate "LED Support for the FIC Neo1973 (GTA02)"
60939 + depends on LEDS_CLASS && MACH_NEO1973_GTA02
60941 + This option enables support for the LEDs on the FIC Neo1973.
60943 +config LEDS_LP5521
60944 + tristate "LED Support for LP5521 LED I2C chip"
60945 + depends on LEDS_CLASS && I2C
60947 + If you say yes here you get support for the National Semiconductor
60948 + LP5521 LED driver.
60950 comment "LED Triggers"
60952 config LEDS_TRIGGERS
60953 @@ -234,4 +253,11 @@
60954 This allows LEDs to be controlled by network device activity.
60957 +config LEDS_TRIGGER_NETDEV
60958 + tristate "LED Network Device Trigger"
60959 + depends on LEDS_TRIGGERS
60961 + This allows LEDs to be controlled by Network Device activity.
60962 + If unsure, say Y.
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
60969 if (count == size) {
60972 +#if 0 /* This is really bad. Don't do it!!!! */
60973 if (state == LED_OFF)
60974 led_trigger_remove(led_cdev);
60976 led_set_brightness(led_cdev, state);
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
60983 +/* NS LP5521 Programmable LED driver.
60985 + * (C) 2009 by Openmoko, Inc.
60986 + * Author: Matt Hsu <matt_hsu@openmoko.org>
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.
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.
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
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>
61011 +#include <linux/lp5521.h>
61013 +#define LP5521_DRIVER_NAME "lp5521"
61015 +static int __lp5521_reg_write(struct lp5521 *lp, u8 reg, u8 value)
61017 + return i2c_smbus_write_byte_data(lp->client, reg, value);
61020 +static int reg_write(struct lp5521 *lp, u_int8_t reg, u_int8_t val)
61024 + mutex_lock(&lp->lock);
61025 + ret = __lp5521_reg_write(lp, reg, val);
61026 + mutex_unlock(&lp->lock);
61031 +static int __lp5521_reg_read(struct lp5521 *lp, u8 reg)
61035 + ret = i2c_smbus_read_byte_data(lp->client, reg);
61040 +static u_int8_t reg_read(struct lp5521 *lp, u_int8_t reg)
61044 + mutex_lock(&lp->lock);
61045 + ret = __lp5521_reg_read(lp, reg);
61046 + mutex_unlock(&lp->lock);
61048 + return ret & 0xff;
61051 +static int reg_set_bit_mask(struct lp5521 *lp,
61052 + u_int8_t reg, u_int8_t mask, u_int8_t val)
61059 + mutex_lock(&lp->lock);
61061 + tmp = __lp5521_reg_read(lp, reg);
61064 + ret = __lp5521_reg_write(lp, reg, tmp);
61066 + mutex_unlock(&lp->lock);
61071 +static const char *lp5521_ch_name[] = {
61072 + "blue", "green", "red",
61075 +static inline int channel_id_by_name(const char *name)
61077 + int channel_id = -1;
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;
61089 + return channel_id;
61092 +static const char *lp5521_ch_mode[] = {
61093 + "disable", "load", "run",
61098 + * Individual mode control
61100 +static ssize_t show_mode(struct device *dev, struct device_attribute
61101 + *attr, char *buf)
61103 + struct i2c_client *client = to_i2c_client(dev);
61104 + struct lp5521 *lp = i2c_get_clientdata(client);
61108 + id = channel_id_by_name(attr->attr.name);
61109 + val = reg_read(lp, LP5521_REG_OP_MODE);
61111 + val = val >> (id * 2);
61114 + return sprintf(buf, "%s\n", lp5521_ch_mode[val]);
61117 +static ssize_t set_mode(struct device *dev, struct device_attribute *attr,
61118 + const char *buf, size_t count)
61120 + struct i2c_client *client = to_i2c_client(dev);
61121 + struct lp5521 *lp = i2c_get_clientdata(client);
61125 + id = channel_id_by_name(attr->attr.name);
61127 + mask = (0x3 << (id * 2));
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)));
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);
61144 + * Individual pwm control
61146 +static ssize_t show_pwm(struct device *dev, struct device_attribute
61147 + *attr, char *buf)
61149 + struct i2c_client *client = to_i2c_client(dev);
61150 + struct lp5521 *lp = i2c_get_clientdata(client);
61154 + id = channel_id_by_name(attr->attr.name);
61155 + val = reg_read(lp, LP5521_REG_B_PWM-id);
61157 + return sprintf(buf, "%d\n", val);
61160 +static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
61161 + const char *buf, size_t count)
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);
61168 + id = channel_id_by_name(attr->attr.name);
61169 + reg_write(lp, LP5521_REG_B_PWM-id, pwm);
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);
61179 + * Individual current control
61181 +static ssize_t show_cur(struct device *dev, struct device_attribute
61182 + *attr, char *buf)
61184 + struct i2c_client *client = to_i2c_client(dev);
61185 + struct lp5521 *lp = i2c_get_clientdata(client);
61189 + id = channel_id_by_name(attr->attr.name);
61190 + val = reg_read(lp, LP5521_REG_B_CUR-id);
61192 + return sprintf(buf, "%d (100uA)\n", val);
61195 +static ssize_t set_cur(struct device *dev, struct device_attribute *attr,
61196 + const char *buf, size_t count)
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);
61203 + id = channel_id_by_name(attr->attr.name);
61204 + reg_write(lp, LP5521_REG_B_CUR-id, cur);
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);
61213 +static struct attribute *lp_sysfs_entries[16];
61215 +static struct attribute_group lp_attr_group = {
61217 + .attrs = lp_sysfs_entries,
61220 +static void populate_sysfs_group(struct lp5521 *lp)
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;
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;
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;
61243 +static struct i2c_driver lp5521_driver;
61246 +static int lp5521_suspend(struct device *dev, pm_message_t state)
61248 + /* FIXME: Not implemented
61249 + * Here we could upload firmware to perform
61250 + * any scenarios we want and save registers.
61255 +static int lp5521_resume(struct device *dev)
61257 + /* FIXME: Not implemented */
61261 +#define lp5521_suspend NULL
61262 +#define lp5521_resume NULL
61265 +static irqreturn_t lp5521_irq(int irq, void *_lp)
61267 + struct lp5521 *lp = _lp;
61268 + dev_info(lp->dev, "lp5521 interrupt\n");
61270 + return IRQ_HANDLED;
61273 +static int __devinit
61274 +lp5521_probe(struct i2c_client *client, const struct i2c_device_id *id)
61276 + struct lp5521 *lp;
61278 + struct lp5521_platform_data *pdata = client->dev.platform_data;
61280 + lp = kzalloc(sizeof(*lp), GFP_KERNEL);
61284 + lp->client = client;
61285 + lp->irq = client->irq;
61286 + lp->dev = &client->dev;
61287 + i2c_set_clientdata(client, lp);
61289 + lp->pdata = pdata;
61290 + mutex_init(&lp->lock);
61292 + /* enter start-up mode */
61293 + if (pdata->ext_enable)
61294 + (pdata->ext_enable)(1);
61296 + reg_write(lp, LP5521_REG_ENABLE, 0x40);
61298 + /* charge pump mode and clk src selection */
61299 + reg_write(lp, LP5521_REG_CONFIG, 0x11);
61301 + /* allocate IRQ resource */
61303 + ret = request_irq(client->irq, lp5521_irq,
61304 + IRQF_TRIGGER_LOW, LP5521_DRIVER_NAME, lp);
61306 + dev_err(lp->dev, "request IRQ failed\n");
61310 + dev_err(lp->dev, "No IRQ allocated \n");
61313 + populate_sysfs_group(lp);
61315 + ret = sysfs_create_group(&client->dev.kobj, &lp_attr_group);
61318 + dev_err(lp->dev, "error creating sysfs group\n");
61329 +static int __devexit lp5521_remove(struct i2c_client *client)
61331 + struct lp5521 *lp = i2c_get_clientdata(client);
61338 +static struct i2c_device_id lp5521_id[] = {
61339 + {LP5521_DRIVER_NAME, },
61342 +static struct i2c_driver lp5521_driver = {
61344 + .name = LP5521_DRIVER_NAME,
61345 + .suspend = lp5521_suspend,
61346 + .resume = lp5521_resume,
61348 + .id_table = lp5521_id,
61349 + .probe = lp5521_probe,
61350 + .remove = __exit_p(lp5521_remove),
61353 +static int __init lp5521_init(void)
61355 + return i2c_add_driver(&lp5521_driver);
61358 +static void __exit lp5521_exit(void)
61360 + i2c_del_driver(&lp5521_driver);
61363 +MODULE_AUTHOR("Matt Hsu <matt_hsu@openmoko.org>");
61364 +MODULE_DESCRIPTION("NS lp5521 LED driver");
61365 +MODULE_LICENSE("GPLv2");
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
61374 + * LED driver for the Openmoko GTA02 GSM phone
61376 + * (C) 2006-2008 by Openmoko, Inc.
61377 + * Author: Harald Welte <laforge@openmoko.org>
61378 + * All rights reserved.
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.
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>
61396 +#define MAX_LEDS 3
61397 +#define COUNTER 256
61399 +struct gta02_led_priv
61402 + struct led_classdev cdev;
61403 + unsigned int gpio;
61406 +struct gta02_led_bundle
61409 + struct gta02_led_priv led[MAX_LEDS];
61412 +static inline struct gta02_led_priv *to_priv(struct led_classdev *led_cdev)
61414 + return container_of(led_cdev, struct gta02_led_priv, cdev);
61417 +static inline struct gta02_led_bundle *to_bundle(struct led_classdev *led_cdev)
61419 + return dev_get_drvdata(led_cdev->dev->parent);
61422 +static void gta02led_set(struct led_classdev *led_cdev,
61423 + enum led_brightness value)
61425 + unsigned long flags;
61426 + struct gta02_led_priv *lp = to_priv(led_cdev);
61428 + spin_lock_irqsave(&lp->lock, flags);
61429 + neo1973_gpb_setpin(lp->gpio, value ? 1 : 0);
61430 + spin_unlock_irqrestore(&lp->lock, flags);
61434 +static int gta02led_suspend(struct platform_device *pdev, pm_message_t state)
61436 + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev);
61439 + for (i = 0; i < bundle->num_leds; i++)
61440 + led_classdev_suspend(&bundle->led[i].cdev);
61445 +static int gta02led_resume(struct platform_device *pdev)
61447 + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev);
61450 + for (i = 0; i < bundle->num_leds; i++)
61451 + led_classdev_resume(&bundle->led[i].cdev);
61457 +static int __init gta02led_probe(struct platform_device *pdev)
61460 + struct gta02_led_bundle *bundle;
61462 + if (!machine_is_neo1973_gta02())
61465 + bundle = kzalloc(sizeof(struct gta02_led_bundle), GFP_KERNEL);
61468 + platform_set_drvdata(pdev, bundle);
61470 + for (i = 0; i < pdev->num_resources; i++) {
61471 + struct gta02_led_priv *lp;
61472 + struct resource *r;
61474 + if (i >= MAX_LEDS)
61477 + r = platform_get_resource(pdev, 0, i);
61478 + if (!r || !r->start || !r->name)
61481 + lp = &bundle->led[i];
61483 + lp->gpio = r->start;
61484 + lp->cdev.name = r->name;
61485 + lp->cdev.brightness_set = gta02led_set;
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);
61498 + spin_lock_init(&lp->lock);
61499 + rc = led_classdev_register(&pdev->dev, &lp->cdev);
61502 + bundle->num_leds = i;
61507 +static int gta02led_remove(struct platform_device *pdev)
61509 + struct gta02_led_bundle *bundle = platform_get_drvdata(pdev);
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);
61518 + platform_set_drvdata(pdev, NULL);
61524 +static struct platform_driver gta02led_driver = {
61525 + .probe = gta02led_probe,
61526 + .remove = gta02led_remove,
61528 + .suspend = gta02led_suspend,
61529 + .resume = gta02led_resume,
61532 + .name = "gta02-led",
61536 +static int __init gta02led_init(void)
61538 + return platform_driver_register(>a02led_driver);
61541 +static void __exit gta02led_exit(void)
61543 + platform_driver_unregister(>a02led_driver);
61546 +module_init(gta02led_init);
61547 +module_exit(gta02led_exit);
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
61557 + * LED driver for the vibrator of the Openmoko GTA01/GTA02 GSM Phones
61559 + * (C) 2006-2008 by Openmoko, Inc.
61560 + * Author: Harald Welte <laforge@openmoko.org>
61561 + * All rights reserved.
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.
61567 + * Javi Roman <javiroman@kernel-labs.org>:
61568 + * Implement PWM support for GTA01Bv4 and later
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>
61582 +#include <asm/plat-s3c24xx/neo1973.h>
61584 +#define COUNTER 64
61586 +static struct neo1973_vib_priv {
61587 + struct led_classdev cdev;
61588 + unsigned int gpio;
61590 + unsigned int has_pwm;
61591 + struct s3c2410_pwm pwm;
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;
61598 + struct neo1973_vib_platform_data *pdata;
61599 +} neo1973_vib_priv;
61601 +int neo1973_vibrator_fiq_handler(void)
61603 + neo1973_vib_priv.fiq_count++;
61605 + if (!neo1973_vib_priv.vib_pwm_latched && !neo1973_vib_priv.vib_pwm)
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);
61612 + if ((u8)neo1973_vib_priv.fiq_count)
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);
61622 +static void neo1973_vib_vib_set(struct led_classdev *led_cdev,
61623 + enum led_brightness value)
61625 + unsigned long flags;
61626 + struct neo1973_vib_priv *vp = container_of(led_cdev,
61627 + struct neo1973_vib_priv,
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 */
61638 + * value == 255 -> 99% duty cycle (full power)
61639 + * value == 128 -> 50% duty cycle (medium power)
61640 + * value == 0 -> 0% duty cycle (zero power)
61642 + spin_lock_irqsave(&vp->lock, flags);
61645 + s3c2410_pwm_duty_cycle(value / 4, &vp->pwm);
61647 + neo1973_gpb_setpin(vp->gpio, value ? 1 : 0);
61649 + spin_unlock_irqrestore(&vp->lock, flags);
61652 +static struct neo1973_vib_priv neo1973_vib_led = {
61654 + .name = "neo1973:vibrator",
61655 + .brightness_set = neo1973_vib_vib_set,
61659 +static int neo1973_vib_init_hw(struct neo1973_vib_priv *vp)
61663 + rc = s3c2410_pwm_init(&vp->pwm);
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;
61674 + rc = s3c2410_pwm_enable(&vp->pwm);
61678 + s3c2410_pwm_start(&vp->pwm);
61684 +static int neo1973_vib_suspend(struct platform_device *dev, pm_message_t state)
61686 + led_classdev_suspend(&neo1973_vib_led.cdev);
61687 + if (neo1973_vib_priv.pdata)
61688 + neo1973_vib_priv.pdata->disable_fiq();
61692 +static int neo1973_vib_resume(struct platform_device *dev)
61694 + struct neo1973_vib_priv *vp = platform_get_drvdata(dev);
61697 + neo1973_vib_init_hw(vp);
61699 + led_classdev_resume(&neo1973_vib_led.cdev);
61700 + if (neo1973_vib_priv.pdata)
61701 + neo1973_vib_priv.pdata->enable_fiq();
61705 +#endif /* CONFIG_PM */
61707 +static int __init neo1973_vib_probe(struct platform_device *pdev)
61709 + struct resource *r;
61712 + if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
61715 + r = platform_get_resource(pdev, 0, 0);
61716 + if (!r || !r->start)
61719 + neo1973_vib_led.gpio = r->start;
61721 + neo1973_vib_priv.pdata = pdev->dev.platform_data;
61722 + platform_set_drvdata(pdev, &neo1973_vib_led);
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 */
61736 + if (neo1973_vib_led.gpio == S3C2410_GPB3) {
61737 + rc = neo1973_vib_init_hw(&neo1973_vib_led);
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;
61745 +#ifdef CONFIG_MACH_NEO1973_GTA02
61748 + spin_lock_init(&neo1973_vib_led.lock);
61750 + return led_classdev_register(&pdev->dev, &neo1973_vib_led.cdev);
61753 +static int neo1973_vib_remove(struct platform_device *pdev)
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 */
61761 + if (neo1973_vib_led.has_pwm)
61762 + s3c2410_pwm_disable(&neo1973_vib_led.pwm);
61764 + led_classdev_unregister(&neo1973_vib_led.cdev);
61769 +static struct platform_driver neo1973_vib_driver = {
61770 + .probe = neo1973_vib_probe,
61771 + .remove = neo1973_vib_remove,
61773 + .suspend = neo1973_vib_suspend,
61774 + .resume = neo1973_vib_resume,
61777 + .name = "neo1973-vibrator",
61781 +static int __init neo1973_vib_init(void)
61783 + return platform_driver_register(&neo1973_vib_driver);
61786 +static void __exit neo1973_vib_exit(void)
61788 + platform_driver_unregister(&neo1973_vib_driver);
61791 +module_init(neo1973_vib_init);
61792 +module_exit(neo1973_vib_exit);
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
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
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.
61834 +config VIDEO_SAMSUNG
61835 + bool "S3C SMDK CAMERA support"
61836 + depends on VIDEO_V4L2
61843 +depends on VIDEO_SAMSUNG
61844 +prompt "Select CIS module type"
61845 +default VIDEO_SAMSUNG_S5K3BA
61847 +config VIDEO_SAMSUNG_S5K4BA
61848 + bool "S5K4BA (2.0M CIS module, 1600x1200)"
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/
61863 +obj-$(CONFIG_VIDEO_SAMSUNG) += s3c_camera_driver.o s3c_camif.o samsung/
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
61872 +/* drivers/media/video/s3c_camera_driver.c
61874 + * Copyright (c) 2008 Samsung Electronics
61876 + * Samsung S3C Camera driver
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.
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.
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
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"
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>
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);
61939 +/*************************************************************************
61941 + ************************************************************************/
61942 +camif_cfg_t *s3c_camif_get_fimc_object(int nr)
61944 + camif_cfg_t *ret = NULL;
61947 + case CODEC_MINOR:
61948 + ret = &s3c_fimc[FIMC_CODEC_INDEX];
61951 + case PREVIEW_MINOR:
61952 + ret = &s3c_fimc[FIMC_PREVIEW_INDEX];
61956 + printk(KERN_ERR "Unknown minor number\n");
61957 + ret = &s3c_fimc[FIMC_PREVIEW_INDEX];
61963 +#if defined(FSM_ON_PREVIEW)
61964 +static int s3c_camif_check_global_status(camif_cfg_t *cfg)
61968 + if (down_interruptible(&cfg->cis->lock))
61969 + return -ERESTARTSYS;
61971 + if (cfg->cis->status & CWANT2START) {
61972 + cfg->cis->status &= ~CWANT2START;
61973 + cfg->auto_restart = 1;
61976 + ret = 0; /* There is no codec */
61977 + cfg->auto_restart = 0; /* Duplicated ..Dummy */
61980 + up(&cfg->cis->lock);
61986 +static int s3c_camif_convert_format(int pixfmt, int *fmtptr)
61988 + int fmt = CAMIF_YCBCR420;
61991 + switch (pixfmt) {
61992 + case V4L2_PIX_FMT_RGB565:
61993 + case V4L2_PIX_FMT_RGB565X:
61994 + fmt = CAMIF_RGB16;
61998 + case V4L2_PIX_FMT_BGR24: /* Not tested */
61999 + case V4L2_PIX_FMT_RGB24:
62000 + fmt = CAMIF_RGB24;
62004 + case V4L2_PIX_FMT_BGR32:
62005 + case V4L2_PIX_FMT_RGB32:
62006 + fmt = CAMIF_RGB24;
62010 + case V4L2_PIX_FMT_GREY: /* Not tested */
62011 + fmt = CAMIF_YCBCR420;
62015 + case V4L2_PIX_FMT_YUYV:
62016 + case V4L2_PIX_FMT_UYVY:
62017 + fmt = CAMIF_YCBCR422I;
62021 + case V4L2_PIX_FMT_YUV422P:
62022 + fmt = CAMIF_YCBCR422;
62026 + case V4L2_PIX_FMT_YUV420:
62027 + fmt = CAMIF_YCBCR420;
62038 +static int s3c_camif_set_fb_info(camif_cfg_t *cfg, int depth, int fourcc)
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;
62052 +static int s3c_camif_convert_type(camif_cfg_t *cfg, int f)
62056 + cfg->target_x = cfg->v2.frmbuf.fmt.width;
62057 + cfg->target_y = cfg->v2.frmbuf.fmt.height;
62059 + s3c_camif_convert_format(cfg->v2.frmbuf.fmt.pixelformat, &pixfmt);
62061 + cfg->dst_fmt = pixfmt;
62066 +/*************************************************************************
62068 + ************************************************************************/
62069 +static int s3c_camif_start_capture(camif_cfg_t * cfg)
62073 + cfg->capture_enable = CAMIF_DMA_ON;
62075 + s3c_camif_start_dma(cfg);
62077 + cfg->status = CAMIF_STARTED;
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;
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);
62092 +ssize_t s3c_camif_start_preview(camif_cfg_t *cfg)
62094 + cfg->capture_enable = CAMIF_DMA_ON;
62096 + s3c_camif_start_dma(cfg);
62098 + cfg->status = CAMIF_STARTED;
62099 + cfg->fsm = CAMIF_1st_INT;
62100 + cfg->perf.frames = 0;
62105 +ssize_t s3c_camif_stop_preview(camif_cfg_t *cfg)
62107 + cfg->capture_enable = CAMIF_DMA_OFF;
62108 + cfg->status = CAMIF_STOPPED;
62110 + s3c_camif_stop_dma(cfg);
62112 + cfg->perf.frames = 0;
62117 +ssize_t s3c_camif_stop_capture(camif_cfg_t *cfg)
62119 + cfg->capture_enable = CAMIF_DMA_OFF;
62120 + cfg->status = CAMIF_STOPPED;
62122 + s3c_camif_stop_dma(cfg);
62124 + cfg->perf.frames = 0;
62129 +ssize_t s3c_camif_stop_fimc(camif_cfg_t *cfg)
62131 + cfg->capture_enable = CAMIF_BOTH_DMA_OFF;
62132 + cfg->fsm = CAMIF_DUMMY_INT;
62133 + cfg->perf.frames = 0;
62135 + s3c_camif_stop_dma(cfg);
62140 +#if defined(FSM_ON_PREVIEW)
62141 +static void s3c_camif_start_preview_with_codec(camif_cfg_t *cfg)
62143 + camif_cfg_t *other = cfg->other;
62145 + /* Preview Stop */
62146 + cfg->capture_enable = CAMIF_DMA_OFF;
62147 + s3c_camif_stop_dma(cfg);
62149 + /* Start Preview and CODEC */
62150 + cfg->capture_enable =CAMIF_BOTH_DMA_ON;
62152 + s3c_camif_start_dma(cfg);
62153 + cfg->fsm = CAMIF_1st_INT; /* For Preview */
62156 + panic("Unexpected error: other is null\n");
62158 + switch (other->pp_num) {
62160 + other->fsm = CAMIF_1st_INT; /* For CODEC */
62164 + other->fsm = CAMIF_Yth_INT;
62168 + panic("Invalid pingpong number");
62173 +static void s3c_camif_auto_restart(camif_cfg_t *cfg)
62175 + if (cfg->auto_restart)
62176 + s3c_camif_start_preview_with_codec(cfg);
62180 +static void s3c_camif_change_mode(camif_cfg_t *cfg, int mode)
62182 + camif_cis_t *cis = cfg->cis;
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;
62191 +/* 4BA max is UXGA, but we don't have UXGA control values */
62192 +#elif defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
62193 + res = SENSOR_SVGA;
62195 + } else if (mode == SENSOR_DEFAULT) {
62196 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
62197 + res = SENSOR_SVGA;
62199 + res = SENSOR_VGA;
62204 + s3c_camif_stop_fimc(cfg);
62207 + case SENSOR_SXGA:
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;
62215 + case SENSOR_UXGA:
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;
62223 + case SENSOR_SVGA:
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;
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;
62240 + cis->win_hor_ofst = cis->win_hor_ofst2 = 0;
62241 + cis->win_ver_ofst = cis->win_ver_ofst2 = 0;
62243 + s3c_camif_set_source_format(cis);
62246 +static int s3c_camif_check_zoom_range(camif_cfg_t *cfg, int 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) >
62254 + printk(KERN_INFO "Invalid Zoom-in: this zoom-in on "
62255 + "preview scaler already comes to the maximum\n");
62259 + cfg->sc.zoom_in_cnt++;
62262 + case V4L2_CID_ZOOMOUT:
62263 + if (cfg->sc.zoom_in_cnt > 0) {
62264 + cfg->sc.zoom_in_cnt--;
62266 + printk(KERN_INFO "Invalid Zoom-out: this zoom-out on "
62267 + "preview scaler already comes to the minimum\n");
62280 +static int s3c_camif_restart_preview(camif_cfg_t *cfg)
62284 + s3c_camif_stop_preview(cfg);
62286 + if (s3c_camif_control_fimc(cfg)) {
62287 + printk(KERN_ERR "S3C fimc control failed\n");
62291 + s3c_camif_start_preview(cfg);
62296 +static int s3c_camif_send_sensor_command(camif_cfg_t *cfg, unsigned int cmd,
62299 + cfg->cis->sensor->driver->command(cfg->cis->sensor, cmd, (void *) arg);
62304 +/*************************************************************************
62306 + ************************************************************************/
62307 +static int s3c_camif_v4l2_querycap(camif_cfg_t *cfg, void *arg)
62309 + struct v4l2_capability *cap = arg;
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");
62315 + cap->version = 0;
62316 + cap->capabilities = V4L2_CAP_VIDEO_OVERLAY | V4L2_CAP_VIDEO_CAPTURE |
62317 + V4L2_CAP_STREAMING;
62322 +static int s3c_camif_v4l2_g_fbuf(camif_cfg_t *cfg, void *arg)
62324 + struct v4l2_framebuffer *fb = arg;
62326 + *fb = cfg->v2.frmbuf;
62328 + fb->base = cfg->v2.frmbuf.base;
62329 + fb->capability = V4L2_FBUF_CAP_LIST_CLIPPING;
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;
62339 +static int s3c_camif_v4l2_s_fbuf(camif_cfg_t *cfg, void *arg)
62341 + struct v4l2_framebuffer *fb = arg;
62344 + for (i = 0; i < NUMBER_OF_PREVIEW_FORMATS; i++)
62345 + if (fimc_preview_formats[i].pixelformat == fb->fmt.pixelformat)
62348 + if (i == NUMBER_OF_PREVIEW_FORMATS)
62351 + cfg->v2.frmbuf.base = fb->base;
62352 + cfg->v2.frmbuf.flags = fb->flags;
62353 + cfg->v2.frmbuf.capability = fb->capability;
62355 + cfg->target_x = fb->fmt.width;
62356 + cfg->target_y = fb->fmt.height;
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);
62362 + return s3c_camif_control_fimc(cfg);
62365 +static int s3c_camif_v4l2_g_fmt(camif_cfg_t *cfg, void *arg)
62367 + struct v4l2_format *f = arg;
62368 + int size = sizeof(struct v4l2_pix_format);
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);
62385 +static int s3c_camif_v4l2_s_fmt(camif_cfg_t *cfg, void *arg)
62387 + struct v4l2_format *f = arg;
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 ? */
62396 + s3c_camif_convert_type(cfg, 1);
62397 + s3c_camif_control_fimc(cfg);
62408 +static int s3c_camif_v4l2_enum_fmt(camif_cfg_t *cfg, void *arg)
62410 + struct v4l2_fmtdesc *f = arg;
62411 + int index = f->index;
62413 + if (index >= NUMBER_OF_CODEC_FORMATS)
62416 + switch (f->type) {
62417 + case V4L2_BUF_TYPE_VIDEO_CAPTURE:
62420 + case V4L2_BUF_TYPE_VIDEO_OVERLAY:
62425 + memset(f, 0, sizeof(*f));
62426 + memcpy(f, cfg->v2.fmtdesc + index, sizeof(*f));
62431 +static int s3c_camif_v4l2_overlay(camif_cfg_t *cfg, void *arg)
62433 + int on = *(int *) arg;
62436 + return s3c_camif_start_preview(cfg);
62438 + return s3c_camif_stop_preview(cfg);
62441 +static int s3c_camif_v4l2_g_ctrl(camif_cfg_t *cfg, void *arg)
62446 +static int s3c_camif_v4l2_s_ctrl(camif_cfg_t *cfg, void *arg)
62448 + struct v4l2_control *ctrl = arg;
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);
62461 + case V4L2_CID_HFLIP:
62462 + cfg->flip = CAMIF_FLIP_X;
62463 + s3c_camif_change_flip(cfg);
62466 + case V4L2_CID_VFLIP:
62467 + cfg->flip = CAMIF_FLIP_Y;
62468 + s3c_camif_change_flip(cfg);
62471 + case V4L2_CID_ROTATE_180:
62472 + cfg->flip = CAMIF_FLIP_MIRROR;
62473 + s3c_camif_change_flip(cfg);
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);
62482 + case V4L2_CID_ROTATE_270:
62483 + cfg->flip = CAMIF_FLIP_ROTATE_270;
62484 + s3c_camif_change_flip(cfg);
62488 + case V4L2_CID_ROTATE_BYPASS:
62489 + cfg->flip = CAMIF_FLIP;
62490 + s3c_camif_change_flip(cfg);
62493 + case V4L2_CID_ZOOMIN:
62494 + if (!s3c_camif_check_zoom_range(cfg, ctrl->id))
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;
62501 + s3c_camif_restart_preview(cfg);
62505 + case V4L2_CID_ZOOMOUT:
62506 + if (!s3c_camif_check_zoom_range(cfg, ctrl->id))
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;
62513 + s3c_camif_restart_preview(cfg);
62517 + case V4L2_CID_CONTRAST:
62518 + case V4L2_CID_AUTO_WHITE_BALANCE:
62519 + s3c_camif_send_sensor_command(cfg, SENSOR_WB,
62524 + printk(KERN_ERR "Invalid control id: %d\n", ctrl->id);
62531 +static int s3c_camif_v4l2_streamon(camif_cfg_t *cfg, void *arg)
62533 + return s3c_camif_start_capture(cfg);
62536 +static int s3c_camif_v4l2_streamoff(camif_cfg_t *cfg, void *arg)
62538 + cfg->cis->status &= ~C_WORKING;
62540 + s3c_camif_stop_capture(cfg);
62545 +static int s3c_camif_v4l2_g_input(camif_cfg_t *cfg, void *arg)
62547 + unsigned int *index = arg;
62549 + *index = cfg->v2.input->index;
62554 +static int s3c_camif_v4l2_s_input(camif_cfg_t *cfg, unsigned int index)
62558 + if (index >= NUMBER_OF_INPUTS)
62561 + cfg->v2.input = &fimc_inputs[index];
62563 + if (cfg->v2.input->type == V4L2_INPUT_TYPE_MSDMA) {
62564 + if (cfg->dma_type & CAMIF_PREVIEW) {
62565 + cfg->input_channel = MSDMA_FROM_PREVIEW;
62567 + } else if (cfg->dma_type & CAMIF_CODEC) {
62568 + cfg->input_channel = MSDMA_FROM_CODEC;
62572 + cfg->input_channel = CAMERA_INPUT;
62580 +static int s3c_camif_v4l2_g_output(camif_cfg_t *cfg, void *arg)
62582 + unsigned int *index = arg;
62584 + *index = cfg->v2.output->index;
62589 +static int s3c_camif_v4l2_s_output(camif_cfg_t *cfg, unsigned int index)
62591 + if (index >= NUMBER_OF_OUTPUTS)
62594 + cfg->v2.output = (struct v4l2_output *) &fimc_outputs[index];
62599 +static int s3c_camif_v4l2_enum_input(camif_cfg_t *cfg, void *arg)
62601 + struct v4l2_input *i = arg;
62603 + if (i->index >= NUMBER_OF_INPUTS)
62606 + memcpy(i, &fimc_inputs[i->index], sizeof(struct v4l2_input));
62611 +static int s3c_camif_v4l2_enum_output(camif_cfg_t *cfg, void *arg)
62613 + struct v4l2_output *i = arg;
62615 + if (i->index >= NUMBER_OF_OUTPUTS)
62618 + memcpy(i, &fimc_outputs[i->index], sizeof(struct v4l2_output));
62623 +static int s3c_camif_v4l2_reqbufs(camif_cfg_t *cfg, void *arg)
62625 + struct v4l2_requestbuffers *req = arg;
62627 + if (req->memory != V4L2_MEMORY_MMAP) {
62628 + printk(KERN_ERR "Only V4L2_MEMORY_MMAP capture is supported\n");
62632 + /* control user input */
62633 + if (req->count > 2)
62635 + else if (req->count > 1)
62643 +static int s3c_camif_v4l2_querybuf(camif_cfg_t *cfg, void *arg)
62645 + struct v4l2_buffer *buf = arg;
62647 + if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
62648 + buf->memory != V4L2_MEMORY_MMAP)
62651 + buf->length = cfg->buffer_size;
62652 + buf->m.offset = buf->length * buf->index;
62657 +static int s3c_camif_v4l2_qbuf(camif_cfg_t *cfg, void *arg)
62662 +static int s3c_camif_v4l2_dqbuf(camif_cfg_t *cfg, void *arg)
62664 + struct v4l2_buffer *buf = arg;
62666 + buf->index = cfg->cur_frame_num % cfg->pp_num;
62674 +static int s3c_camif_v4l2_s_msdma(camif_cfg_t *cfg, void *arg)
62676 + struct v4l2_msdma_format *f = arg;
62679 + switch(f->input_path) {
62680 + case V4L2_MSDMA_PREVIEW:
62681 + cfg->cis->user--;
62682 + /* CIS will be replaced with a CIS for MSDMA */
62684 + cfg->cis = &msdma_input;
62685 + cfg->cis->user++;
62686 + cfg->input_channel = MSDMA_FROM_PREVIEW;
62689 + case V4L2_MSDMA_CODEC:
62690 + cfg->cis->user--;
62691 + /* CIS will be replaced with a CIS for MSDMA */
62693 + cfg->cis = &msdma_input;
62694 + cfg->cis->user++;
62695 + cfg->input_channel = MSDMA_FROM_CODEC;
62699 + cfg->input_channel = CAMERA_INPUT;
62703 + cfg->cis->source_x = f->width;
62704 + cfg->cis->source_y = f->height;
62706 + s3c_camif_convert_format(f->pixelformat, (int *) &cfg->src_fmt);
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;
62713 + ret = s3c_camif_control_fimc(cfg);
62715 + switch(f->input_path) {
62716 + case V4L2_MSDMA_PREVIEW:
62717 + ret = s3c_camif_start_preview(cfg);
62720 + case V4L2_MSDMA_CODEC:
62721 + ret = s3c_camif_start_capture(cfg);
62732 +static int s3c_camif_v4l2_msdma_start(camif_cfg_t *cfg, void *arg)
62734 + if (cfg->input_channel == MSDMA_FROM_PREVIEW) {
62735 + cfg->msdma_status = 1;
62736 + s3c_camif_start_preview_msdma(cfg);
62742 +static int s3c_camif_v4l2_msdma_stop(camif_cfg_t *cfg, void *arg)
62744 + struct v4l2_msdma_format *f = arg;
62747 + cfg->cis->status &= ~C_WORKING;
62748 + cfg->msdma_status = 0;
62750 + switch(f->input_path) {
62751 + case V4L2_MSDMA_PREVIEW:
62752 + ret = s3c_camif_stop_preview(cfg);
62755 + case V4L2_MSDMA_CODEC:
62756 + ret = s3c_camif_stop_capture(cfg);
62766 +static int s3c_camif_v4l2_camera_start(camif_cfg_t *cfg, void *arg)
62771 +static int s3c_camif_v4l2_camera_stop(camif_cfg_t *cfg, void *arg)
62776 +static int s3c_camif_v4l2_cropcap(camif_cfg_t *cfg, void *arg)
62778 + struct v4l2_cropcap *cap = arg;
62780 + if (cap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
62781 + cap->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
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;
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;
62798 + cap->bounds = cfg->v2.crop_bounds;
62799 + cap->defrect = cfg->v2.crop_defrect;
62804 +static int s3c_camif_v4l2_g_crop(camif_cfg_t *cfg, void *arg)
62806 + struct v4l2_crop *crop = arg;
62808 + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
62809 + crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
62812 + crop->c = cfg->v2.crop_current;
62817 +static int s3c_camif_v4l2_s_crop(camif_cfg_t *cfg, void *arg)
62819 + struct v4l2_crop *crop = arg;
62821 + if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
62822 + crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
62825 + if (crop->c.height < 0)
62828 + if (crop->c.width < 0)
62831 + if ((crop->c.left + crop->c.width > cfg->cis->source_x) ||
62832 + (crop->c.top + crop->c.height > cfg->cis->source_y))
62835 + cfg->v2.crop_current = crop->c;
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;
62840 + cfg->cis->win_hor_ofst2 = cfg->cis->win_hor_ofst;
62841 + cfg->cis->win_ver_ofst2 = cfg->cis->win_ver_ofst;
62843 + s3c_camif_restart_preview(cfg);
62848 +static int s3c_camif_v4l2_s_parm(camif_cfg_t *cfg, void *arg)
62850 + struct v4l2_streamparm *sp = arg;
62852 + if (sp->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
62855 + if (sp->parm.capture.capturemode == V4L2_MODE_HIGHQUALITY) {
62856 + s3c_camif_change_mode(cfg, SENSOR_MAX);
62857 + s3c_camif_control_fimc(cfg);
62859 + s3c_camif_change_mode(cfg, SENSOR_DEFAULT);
62860 + s3c_camif_control_fimc(cfg);
62866 +/*************************************************************************
62868 + ************************************************************************/
62869 +#if defined(FSM_ON_CODEC) && !defined(USE_LAST_IRQ)
62870 +int s3c_camif_do_fsm_codec(camif_cfg_t *cfg)
62872 + cfg->perf.frames++;
62874 + if (cfg->fsm == CAMIF_DUMMY_INT &&
62875 + cfg->perf.frames > CAMIF_CAPTURE_SKIP_FRAMES)
62876 + cfg->fsm = CAMIF_NORMAL_INT;
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;
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;
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;
62899 + printk(KERN_INFO "Unexpect INT: %d\n", cfg->fsm);
62900 + return INSTANT_SKIP;
62905 +#if defined(FSM_ON_CODEC) && defined(USE_LAST_IRQ)
62906 +int s3c_camif_do_fsm_codec_lastirq(camif_cfg_t *cfg)
62908 + cfg->perf.frames++;
62910 + if (cfg->fsm == CAMIF_DUMMY_INT &&
62911 + cfg->perf.frames > CAMIF_CAPTURE_SKIP_FRAMES - 2)
62912 + cfg->fsm = CAMIF_SET_LAST_INT;
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;
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);
62925 +/* in 64xx, lastirq is not auto cleared. */
62926 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
62927 + s3c_camif_disable_lastirq(cfg);
62929 + cfg->status = CAMIF_INT_HAPPEN;
62930 + cfg->fsm = CAMIF_STOP_CAPTURE;
62931 + return INSTANT_SKIP;
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;
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;
62947 + printk(KERN_INFO "Unexpect INT: %d\n", cfg->fsm);
62948 + return = INSTANT_SKIP;
62953 +#if defined(FSM_ON_PREVIEW)
62954 +static int s3c_camif_do_lastirq_preview(camif_cfg_t *cfg)
62956 + cfg->perf.frames++;
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;
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;
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;
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;
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;
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;
62998 + case CAMIF_DUMMY_INT:
62999 + DPRINTK(KERN_INFO "CAMIF_DUMMY_INT\n");
63000 + cfg->status = CAMIF_STOPPED;
63001 + return INSTANT_SKIP;
63004 + printk(KERN_INFO "Unexpected INT %d\n", cfg->fsm);
63005 + return INSTANT_SKIP;
63010 +static irqreturn_t s3c_camif_do_irq_codec(int irq, void *dev_id)
63012 + camif_cfg_t *cfg = (camif_cfg_t *) dev_id;
63014 +/* @@@ SMKD ? - WA */
63015 +#if 0 && (defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410))
63016 + s3c_gpio_setpin(S3C_GPN15, 1);
63018 + s3c_camif_clear_irq(irq);
63019 + s3c_camif_get_fifo_status(cfg);
63020 + s3c_camif_get_frame_num(cfg);
63022 +#if defined(FSM_ON_CODEC) && !defined(USE_LAST_IRQ)
63023 + if (s3c_camif_do_fsm_codec(cfg) == INSTANT_SKIP)
63024 + return IRQ_HANDLED;
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;
63031 + wake_up_interruptible(&cfg->waitq);
63033 + return IRQ_HANDLED;
63036 +static irqreturn_t s3c_camif_do_irq_preview(int irq, void *dev_id)
63038 + camif_cfg_t *cfg = (camif_cfg_t *) dev_id;
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);
63045 +#if defined(FSM_ON_PREVIEW)
63046 + if (s3c_camif_do_lastirq_preview(cfg) == INSTANT_SKIP)
63047 + return IRQ_HANDLED;
63049 + wake_up_interruptible(&cfg->waitq);
63051 + cfg->status = CAMIF_INT_HAPPEN;
63053 + return IRQ_HANDLED;
63056 +static void s3c_camif_release_irq(camif_cfg_t * cfg)
63058 + disable_irq(cfg->irq);
63059 + free_irq(cfg->irq, cfg);
63062 +static int s3c_camif_request_irq(camif_cfg_t * cfg)
63066 + if (cfg->dma_type & CAMIF_CODEC) {
63067 + ret = request_irq(cfg->irq, s3c_camif_do_irq_codec,
63068 + IRQF_SHARED, cfg->shortname, cfg);
63070 + printk(KERN_ERR "Request irq (CAM_C) failed\n");
63072 + printk(KERN_INFO "Request irq %d for codec\n",
63076 + if (cfg->dma_type & CAMIF_PREVIEW) {
63077 + ret = request_irq(cfg->irq, s3c_camif_do_irq_preview,
63078 + IRQF_SHARED, cfg->shortname, cfg);
63080 + printk("Request_irq (CAM_P) failed\n");
63082 + printk(KERN_INFO "Request irq %d for preview\n",
63089 +/*************************************************************************
63090 + * Standard file operations part
63091 + ************************************************************************/
63092 +long s3c_camif_ioctl(struct file *file, unsigned int cmd, unsigned long _arg)
63094 + camif_cfg_t *cfg = file->private_data;
63095 + void *arg = (void *) _arg; /* @@@ - WA */
63098 + case VIDIOC_QUERYCAP:
63099 + return s3c_camif_v4l2_querycap(cfg, arg);
63101 + case VIDIOC_G_FBUF:
63102 + return s3c_camif_v4l2_g_fbuf(cfg, arg);
63104 + case VIDIOC_S_FBUF:
63105 + return s3c_camif_v4l2_s_fbuf(cfg, arg);
63107 + case VIDIOC_G_FMT:
63108 + return s3c_camif_v4l2_g_fmt(cfg, arg);
63110 + case VIDIOC_S_FMT:
63111 + return s3c_camif_v4l2_s_fmt(cfg, arg);
63113 + case VIDIOC_ENUM_FMT:
63114 + return s3c_camif_v4l2_enum_fmt(cfg, arg);
63116 + case VIDIOC_OVERLAY:
63117 + return s3c_camif_v4l2_overlay(cfg, arg);
63119 + case VIDIOC_S_CTRL:
63120 + return s3c_camif_v4l2_s_ctrl(cfg, arg);
63122 + case VIDIOC_G_CTRL:
63123 + return s3c_camif_v4l2_g_ctrl(cfg, arg);
63125 + case VIDIOC_STREAMON:
63126 + return s3c_camif_v4l2_streamon(cfg, arg);
63128 + case VIDIOC_STREAMOFF:
63129 + return s3c_camif_v4l2_streamoff(cfg, arg);
63131 + case VIDIOC_G_INPUT:
63132 + return s3c_camif_v4l2_g_input(cfg, arg);
63134 + case VIDIOC_S_INPUT:
63135 + return s3c_camif_v4l2_s_input(cfg, *((int *) arg));
63137 + case VIDIOC_G_OUTPUT:
63138 + return s3c_camif_v4l2_g_output(cfg, arg);
63140 + case VIDIOC_S_OUTPUT:
63141 + return s3c_camif_v4l2_s_output(cfg, *((int *) arg));
63143 + case VIDIOC_ENUMINPUT:
63144 + return s3c_camif_v4l2_enum_input(cfg, arg);
63146 + case VIDIOC_ENUMOUTPUT:
63147 + return s3c_camif_v4l2_enum_output(cfg, arg);
63149 + case VIDIOC_REQBUFS:
63150 + return s3c_camif_v4l2_reqbufs(cfg, arg);
63152 + case VIDIOC_QUERYBUF:
63153 + return s3c_camif_v4l2_querybuf(cfg, arg);
63155 + case VIDIOC_QBUF:
63156 + return s3c_camif_v4l2_qbuf(cfg, arg);
63158 + case VIDIOC_DQBUF:
63159 + return s3c_camif_v4l2_dqbuf(cfg, arg);
63161 + case VIDIOC_S_MSDMA:
63162 + return s3c_camif_v4l2_s_msdma(cfg, arg);
63164 + case VIDIOC_MSDMA_START:
63165 + return s3c_camif_v4l2_msdma_start(cfg, arg);
63167 + case VIDIOC_MSDMA_STOP:
63168 + return s3c_camif_v4l2_msdma_stop(cfg, arg);
63170 + case VIDIOC_S_CAMERA_START:
63171 + return s3c_camif_v4l2_camera_start(cfg, arg);
63173 + case VIDIOC_S_CAMERA_STOP:
63174 + return s3c_camif_v4l2_camera_stop(cfg, arg);
63176 + case VIDIOC_CROPCAP:
63177 + return s3c_camif_v4l2_cropcap(cfg, arg);
63179 + case VIDIOC_G_CROP:
63180 + return s3c_camif_v4l2_g_crop(cfg, arg);
63182 + case VIDIOC_S_CROP:
63183 + return s3c_camif_v4l2_s_crop(cfg, arg);
63185 + case VIDIOC_S_PARM:
63186 + return s3c_camif_v4l2_s_parm(cfg, arg);
63188 + default: /* For v4l compatability */
63190 + v4l_compat_translate_ioctl(file, cmd, arg, s3c_camif_ioctl);
63195 +void om_3d7k_camera_on(void)
63197 + extern struct pcf50633 *om_3d7k_pcf;
63200 + gpio_direction_output(S3C64XX_GPF(3), 0);
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++) {
63206 + printk(KERN_ERR "can't bring up LDO2\n");
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++) {
63216 + printk(KERN_ERR "can't bring up HCLDO\n");
63222 + msleep(100); /* > 0 ms */
63225 + clk_enable(cam_clock);
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 */
63233 + __raw_writel(__raw_readl(S3C64XX_NORMAL_CFG) |
63234 + S3C64XX_NORMALCFG_DOMAIN_I_ON, S3C64XX_NORMAL_CFG);
63237 +void om_3d7k_camera_off(void)
63239 + extern struct pcf50633 *om_3d7k_pcf;
63241 + gpio_direction_output(S3C64XX_GPF(3), 0);
63243 + msleep(1); /* > 20 cycles */
63246 + clk_disable(cam_clock);
63247 + msleep(1); /* > 0 ms */
63249 + /* @@@ hack - WA */
63250 + pcf50633_reg_write(om_3d7k_pcf, 0x3a, 0x20); /* 2V8, ... */
63251 + pcf50633_reg_write(om_3d7k_pcf, 0x30, 0x20); /* ... then 1V5 */
63254 + __raw_writel(__raw_readl(S3C64XX_NORMAL_CFG) &
63255 + ~S3C64XX_NORMALCFG_DOMAIN_I_ON, S3C64XX_NORMAL_CFG);
63261 +#define s3c_camif_exclusive_open(inode, file) 0
63262 +#define s3c_camif_exclusive_release(inode, file)
63264 +int s3c_camif_open(struct file *file)
63267 + camif_cfg_t *cfg =
63268 + s3c_camif_get_fimc_object(MINOR(file->f_dentry->d_inode->i_rdev));
63271 + printk(KERN_ERR "An object for a CIS is missing\n");
63273 + "Using msdma_input as a default CIS data structure\n");
63274 + cfg->cis = &msdma_input;
63276 + /* global lock for both Codec and Preview */
63277 + sema_init(&cfg->cis->lock, 1);
63278 + cfg->cis->status |= P_NOT_WORKING;
63281 + if (cfg->dma_type & CAMIF_PREVIEW) {
63282 + if (cfg->dma_type & CAMIF_PREVIEW)
63283 + cfg->cis->status &= ~P_NOT_WORKING;
63285 + up(&cfg->cis->lock);
63288 + om_3d7k_camera_on();
63290 + err = s3c_camif_exclusive_open(inode, file);
63291 + cfg->cis->user++;
63292 + cfg->status = CAMIF_STOPPED;
63297 + if (file->f_flags & O_NONCAP) {
63298 + printk(KERN_ERR "Don't support non-capturing open\n");
63302 + file->private_data = cfg;
63304 + s3c_camif_init_sensor(cfg);
63309 +int s3c_camif_release(struct file *file)
63311 + camif_cfg_t *cfg =
63312 + s3c_camif_get_fimc_object(MINOR(file->f_dentry->d_inode->i_rdev));
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);
63320 + cfg->cis->status &= ~CWANT2START;
63321 + s3c_camif_stop_capture(cfg);
63324 + s3c_camif_exclusive_release(inode, file);
63326 + if (cfg->cis->sensor == NULL)
63327 + DPRINTK("A CIS sensor for MSDMA has been used\n");
63329 + cfg->cis->sensor->driver->command(cfg->cis->sensor, USER_EXIT,
63332 + cfg->cis->user--;
63333 + cfg->status = CAMIF_STOPPED;
63335 + om_3d7k_camera_off();
63336 + cfg->cis->init_sensor = 0;
63341 +ssize_t s3c_camif_read(struct file * file, char *buf, size_t count,
63344 + camif_cfg_t *cfg = NULL;
63347 + cfg = s3c_camif_get_fimc_object(MINOR(file->f_dentry->d_inode->i_rdev));
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;
63355 + cfg->status = CAMIF_STOPPED;
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;
63365 + cfg->status = CAMIF_STOPPED;
63368 + end = min_t(size_t, cfg->pp_totalsize / cfg->pp_num, count);
63370 + if (copy_to_user(buf, s3c_camif_get_frame(cfg), end))
63376 +ssize_t s3c_camif_write(struct file * f, const char *b, size_t c,
63379 + camif_cfg_t *cfg;
63382 + cfg = s3c_camif_get_fimc_object(MINOR(f->f_dentry->d_inode->i_rdev));
63386 + if (cfg->dma_type & CAMIF_PREVIEW)
63387 + s3c_camif_start_preview(cfg);
63389 + ret = s3c_camif_start_capture(cfg);
63398 + if (cfg->dma_type & CAMIF_PREVIEW) {
63399 + s3c_camif_stop_preview(cfg);
63400 + cfg->cis->status |= P_NOT_WORKING;
63402 + cfg->cis->status &= ~C_WORKING;
63403 + s3c_camif_stop_capture(cfg);
63408 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
63410 + if (cfg->dma_type & CAMIF_PREVIEW) {
63411 + s3c_camif_start_preview(cfg);
63412 + s3c_camif_do_postprocess(cfg);
63418 + panic("s3c_camera_driver.c: s3c_camif_write() - "
63419 + "Unexpected Parameter\n");
63425 +int s3c_camif_mmap(struct file* filp, struct vm_area_struct *vma)
63427 + camif_cfg_t *cfg = filp->private_data;
63429 + unsigned long pageFrameNo;
63430 + unsigned long size = vma->vm_end - vma->vm_start;
63431 + unsigned long total_size;
63433 + if (cfg->dma_type == CAMIF_PREVIEW)
63434 + total_size = RGB_MEM;
63436 + total_size = YUV_MEM;
63439 + * page frame number of the address for a source RGB frame to be stored
63442 + pageFrameNo = __phys_to_pfn(cfg->pp_phys_buf);
63444 + if (size > total_size) {
63445 + printk(KERN_ERR "The size of RGB_MEM mapping is too big\n");
63449 + if ((vma->vm_flags & VM_WRITE) && !(vma->vm_flags & VM_SHARED)) {
63450 + printk(KERN_ERR "Writable RGB_MEM mapping must be shared\n");
63454 + if (remap_pfn_range(vma, vma->vm_start, pageFrameNo + vma->vm_pgoff,
63455 + size, vma->vm_page_prot))
63461 +static unsigned int s3c_camif_poll(struct file *file, poll_table *wait)
63463 + unsigned int mask = 0;
63464 + camif_cfg_t *cfg = file->private_data;
63466 + poll_wait(file, &cfg->waitq, wait);
63468 + if (cfg->status == CAMIF_INT_HAPPEN)
63469 + mask = POLLIN | POLLRDNORM;
63471 + cfg->status = CAMIF_STOPPED;
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,
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,
63498 +/*************************************************************************
63499 + * Templates for V4L2
63500 + ************************************************************************/
63501 +void camif_vdev_release (struct video_device *vdev) {
63505 +struct video_device codec_template = {
63506 + .name = CODEC_DEV_NAME,
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,
63512 + .fops = &camif_c_fops,
63513 + .release = camif_vdev_release,
63514 + .minor = CODEC_MINOR,
63517 +struct video_device preview_template = {
63518 + .name = PREVIEW_DEV_NAME,
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,
63524 + .fops = &camif_p_fops,
63525 + .release = camif_vdev_release,
63526 + .minor = PREVIEW_MINOR,
63529 +/*************************************************************************
63530 + * Initialize part
63531 + ************************************************************************/
63532 +void s3c_camif_init_sensor(camif_cfg_t *cfg)
63534 + camif_cis_t *cis = cfg->cis;
63535 + camif_cis_t *initialized_cis;
63537 + if (!cis->sensor) {
63538 + initialized_cis = (camif_cis_t *) get_initialized_cis();
63540 + if (initialized_cis == NULL) {
63541 + printk(KERN_ERR "An I2C client for CIS sensor isn't registered\n");
63545 + cis = cfg->cis = initialized_cis;
63546 + cfg->input_channel = 0;
63547 + cfg->cis->user++;
63550 + if (!cis->init_sensor) {
63551 + cis->sensor->driver->command(cis->sensor, SENSOR_INIT, NULL);
63552 + cis->init_sensor = 1;
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;
63565 + cis->sensor->driver->command(cis->sensor, USER_ADD, NULL);
63568 +static int s3c_camif_init_preview(camif_cfg_t * cfg)
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;
63582 + //init_MUTEX((struct semaphore *) &cfg->v->lock);
63583 + init_waitqueue_head(&cfg->waitq);
63585 + cfg->status = CAMIF_STOPPED;
63587 + /* To get the handle of CODEC */
63588 + cfg->other = s3c_camif_get_fimc_object(CODEC_MINOR);
63590 + return cfg->status;
63593 +static int s3c_camif_init_codec(camif_cfg_t * cfg)
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;
63607 + //init_MUTEX((struct semaphore *) &cfg->v->lock);
63609 + init_waitqueue_head(&cfg->waitq);
63611 + cfg->status = CAMIF_STOPPED;
63613 + /* To get the handle of PREVIEW */
63614 + cfg->other = s3c_camif_get_fimc_object(PREVIEW_MINOR);
63616 + return cfg->status;
63619 +static int s3c_camif_probe(struct platform_device *pdev)
63621 + struct resource *res;
63622 + camif_cfg_t *codec, *preview;
63623 + struct clk *camif_clock;
63625 + /* Initialize fimc objects */
63626 + codec = s3c_camif_get_fimc_object(CODEC_MINOR);
63627 + preview = s3c_camif_get_fimc_object(PREVIEW_MINOR);
63629 + memset(codec, 0, sizeof(camif_cfg_t));
63630 + memset(preview, 0, sizeof(camif_cfg_t));
63632 + /* Set the fimc name */
63633 + strcpy(codec->shortname, CODEC_DEV_NAME);
63634 + strcpy(preview->shortname, PREVIEW_DEV_NAME);
63636 + /* get resource for io memory */
63637 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
63640 + printk("Failed to get io memory region resouce.\n");
63644 + /* request mem region */
63645 + res = request_mem_region(res->start, res->end - res->start + 1,
63649 + printk("Failed to request io memory region.\n");
63653 + /* ioremap for register block */
63654 + codec->regs = preview->regs =
63655 + ioremap(res->start, res->end - res->start + 1);
63657 + if (codec->regs == NULL) {
63658 + printk(KERN_ERR "Failed to remap register block\n");
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);
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);
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);
63676 + clk_enable(camif_clock);
63678 + /* Device init */
63679 + s3c_camif_init();
63680 + s3c_camif_init_codec(codec);
63681 + s3c_camif_init_preview(preview);
63684 + codec->irq = platform_get_irq(pdev, FIMC_CODEC_INDEX);
63685 + preview->irq = platform_get_irq(pdev, FIMC_PREVIEW_INDEX);
63687 + s3c_camif_request_irq(codec);
63688 + s3c_camif_request_irq(preview);
63690 + /* Register to video device */
63691 + if (video_register_device(codec->v, VFL_TYPE_GRABBER, CODEC_MINOR) !=
63693 + printk(KERN_ERR "Couldn't register this codec driver\n");
63697 + if (video_register_device(preview->v, VFL_TYPE_GRABBER, PREVIEW_MINOR)
63699 + printk(KERN_ERR "Couldn't register this preview driver\n");
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");
63708 +#error cam_clock should be defined
63711 + if (IS_ERR(cam_clock)) {
63712 + printk("Failed to find camera clock source\n");
63713 + return PTR_ERR(cam_clock);
63716 + /* Print banner */
63717 + printk(KERN_INFO "S3C FIMC v%s\n", FIMC_VER);
63722 +static int s3c_camif_remove(struct platform_device *pdev)
63724 + camif_cfg_t *codec, *preview;
63726 + codec = s3c_camif_get_fimc_object(CODEC_MINOR);
63727 + preview = s3c_camif_get_fimc_object(PREVIEW_MINOR);
63729 + s3c_camif_release_irq(codec);
63730 + s3c_camif_release_irq(preview);
63732 + iounmap(codec->pp_virt_buf);
63733 + codec->pp_virt_buf = 0;
63735 + iounmap(preview->pp_virt_buf);
63736 + preview->pp_virt_buf = 0;
63738 + video_unregister_device(codec->v);
63739 + video_unregister_device(preview->v);
63741 + s3c_camif_set_priority(0);
63742 + clk_disable(cam_clock);
63744 + memset(codec, 0, sizeof(camif_cfg_t));
63745 + memset(preview, 0, sizeof(camif_cfg_t));
63750 +static struct platform_driver s3c_camif_driver =
63752 + .probe = s3c_camif_probe,
63753 + .remove = s3c_camif_remove,
63755 + .name = "s3c-camif",
63756 + .owner = THIS_MODULE,
63760 +static int s3c_camif_register(void)
63762 + platform_driver_register(&s3c_camif_driver);
63767 +static void s3c_camif_unregister(void)
63769 + platform_driver_unregister(&s3c_camif_driver);
63772 +void s3c_camif_open_sensor(camif_cis_t *cis)
63774 + clk_set_rate(cam_clock, cis->camclk);
63775 + s3c_camif_reset(cis->reset_type, cis->reset_udelay);
63778 +void s3c_camif_register_sensor(struct i2c_client *ptr)
63780 + camif_cfg_t *codec, *preview;
63781 + camif_cis_t *cis = i2c_get_clientdata(ptr);
63783 + codec = s3c_camif_get_fimc_object(CODEC_MINOR);
63784 + preview = s3c_camif_get_fimc_object(PREVIEW_MINOR);
63786 + codec->cis = preview->cis = cis;
63788 + sema_init(&codec->cis->lock, 1);
63789 + sema_init(&preview->cis->lock, 1);
63791 + preview->cis->status |= P_NOT_WORKING; /* Default Value */
63793 + s3c_camif_set_polarity(preview);
63794 + s3c_camif_set_source_format(cis);
63795 + s3c_camif_set_priority(1);
63798 +void s3c_camif_unregister_sensor(struct i2c_client *ptr)
63800 + camif_cis_t *cis;
63802 + cis = i2c_get_clientdata(ptr);
63803 + cis->init_sensor = 0;
63806 +module_init(s3c_camif_register);
63807 +module_exit(s3c_camif_unregister);
63809 +EXPORT_SYMBOL(s3c_camif_register_sensor);
63810 +EXPORT_SYMBOL(s3c_camif_unregister_sensor);
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
63819 +/* drivers/media/video/s3c_camif.c
63821 + * Copyright (c) 2008 Samsung Electronics
63823 + * Samsung S3C Camera driver
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.
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.
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
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>
63861 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
63862 +#include <asm/arch/regs-irq.h>
63865 +#include "s3c_camif.h"
63867 +#define S3C_VIDW00ADD0B0 (S3C24XX_VA_LCD+0xa0)
63868 +#define S3C_VIDW01ADD0B0 (S3C24XX_VA_LCD+0xa8)
63870 +static unsigned int irq_old_priority;
63872 +/*************************************************************************
63874 + ************************************************************************/
63875 +int s3c_camif_get_frame_num(camif_cfg_t *cfg)
63879 + if (cfg->dma_type & CAMIF_CODEC)
63880 + index = (readl(cfg->regs + S3C_CICOSTATUS) >> 26) & 0x3;
63882 + assert(cfg->dma_type & CAMIF_PREVIEW);
63883 + index = (readl(cfg->regs + S3C_CIPRSTATUS) >> 26) & 0x3;
63886 + cfg->cur_frame_num = (index + 2) % 4; /* When 4 PingPong */
63891 +unsigned char* s3c_camif_get_frame(camif_cfg_t *cfg)
63893 + unsigned char *ret = NULL;
63894 + int cnt = cfg->cur_frame_num;
63896 + if (cfg->dma_type & CAMIF_PREVIEW)
63897 + ret = cfg->img_buf[cnt].virt_rgb;
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;
63904 + ret = cfg->img_buf[cnt].virt_y;
63910 +int s3c_camif_get_fifo_status(camif_cfg_t *cfg)
63912 + unsigned int reg, val, flag;
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);
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);
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);
63932 + return 1; /* Error */
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);
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);
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);
63951 + return 1; /* Error */
63958 +void s3c_camif_set_polarity(camif_cfg_t *cfg)
63960 + camif_cis_t *cis = cfg->cis;
63961 + unsigned int val;
63962 + unsigned int cmd;
63964 + cmd = readl(cfg->regs + S3C_CIGCTRL);
63965 + cmd &= ~(0x7 << 24);
63967 + if (cis->polarity_pclk)
63968 + cmd |= S3C_CIGCTRL_INVPOLPCLK;
63970 + if (cis->polarity_vsync)
63971 + cmd |= S3C_CIGCTRL_INVPOLVSYNC;
63973 + if (cis->polarity_href)
63974 + cmd |= S3C_CIGCTRL_INVPOLHREF;
63976 + val = readl(cfg->regs + S3C_CIGCTRL);
63978 + writel(val, cfg->regs + S3C_CIGCTRL);
63981 +/*************************************************************************
63983 + ************************************************************************/
63984 +static int s3c_camif_request_memory(camif_cfg_t *cfg)
63986 + unsigned int t_size = 0, i = 0;
63987 + unsigned int area = 0;
63989 + area = cfg->target_x * cfg->target_y;
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 */
64002 + printk(KERN_INFO "Invalid target format\n");
64003 + } else if (cfg->dma_type & CAMIF_PREVIEW) {
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 */
64010 + printk(KERN_ERR "Invalid target format\n");
64016 + if (t_size % PAGE_SIZE != 0) {
64017 + i = t_size / PAGE_SIZE;
64018 + t_size = (i + 1) * PAGE_SIZE;
64021 + t_size = t_size * cfg->pp_num;
64022 + cfg->pp_totalsize = t_size;
64024 + printk(KERN_INFO "%s memory required: 0x%08X bytes\n",
64025 + cfg->dma_type & CAMIF_CODEC ? "Codec" : "Preview", t_size);
64030 +static void s3c_camif_calc_burst_length_yuv422i(unsigned int hsize,
64031 + unsigned int *mburst, unsigned int *rburst)
64033 + unsigned int tmp, wanted;
64035 + tmp = (hsize / 2) & 0xf;
64055 + *mburst = wanted / 2;
64056 + *rburst = wanted / 2;
64059 +static void s3c_camif_calc_burst_length(unsigned int hsize,
64060 + unsigned int *mburst, unsigned int *rburst)
64062 + unsigned int tmp;
64064 + tmp = (hsize / 4) & 0xf;
64083 + tmp = (hsize / 4) % 8;
64088 + } else if (tmp == 4) {
64092 + tmp = (hsize / 4) % 4;
64094 + *rburst = tmp ? tmp : 4;
64101 +int s3c_camif_setup_dma(camif_cfg_t *cfg)
64103 + int width = cfg->target_x;
64104 + unsigned int val, yburst_m, yburst_r, cburst_m, cburst_r;
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;
64113 + s3c_camif_calc_burst_length(width * 4,
64114 + &yburst_m, &yburst_r);
64116 + if ((width / 2) % 2 != 0)
64117 + return BURST_ERR;
64119 + s3c_camif_calc_burst_length(width * 2,
64120 + &yburst_m, &yburst_r);
64123 + val = readl(cfg->regs + S3C_CICOCTRL);
64124 + val &= ~(0xfffff << 4);
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);
64131 + val = S3C_CICOCTRL_YBURST1_CO(yburst_m / 2) |
64132 + S3C_CICOCTRL_YBURST2_CO(yburst_r / 2) |
64133 + (4 << 9) | (2 << 4);
64136 + writel(val, cfg->regs + S3C_CICOCTRL);
64138 + /* CODEC DMA WIDHT is multiple of 16 */
64139 + if (width % 16 != 0)
64140 + return BURST_ERR;
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;
64148 + s3c_camif_calc_burst_length(width, &yburst_m,
64150 + s3c_camif_calc_burst_length(width / 2,
64151 + &cburst_m, &cburst_r);
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);
64162 + } else if (cfg->dma_type & CAMIF_PREVIEW) {
64163 + if (cfg->dst_fmt == CAMIF_RGB24) {
64164 + if (width % 2 != 0)
64165 + return BURST_ERR;
64167 + s3c_camif_calc_burst_length(width * 4, &yburst_m,
64170 + if ((width / 2) % 2 != 0)
64171 + return BURST_ERR;
64173 + s3c_camif_calc_burst_length(width * 2, &yburst_m,
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);
64187 +/*************************************************************************
64188 + * Input path part
64189 + ************************************************************************/
64191 + * 2443 MSDMA (Preview Only)
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)
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;
64201 + val = readl(cfg->regs + S3C_CIMSCTRL);
64202 + val &= ~(1 << 2);
64203 + writel(val, cfg->regs + S3C_CIMSCTRL);
64205 + val = readl(cfg->regs + S3C_CIMSCTRL);
64207 + writel(val, cfg->regs + S3C_CIMSCTRL);
64209 + switch(cfg->src_fmt) {
64210 + case CAMIF_YCBCR420:
64212 + val = readl(cfg->regs + S3C_CIMSCTRL);
64214 + writel(val, cfg->regs + S3C_CIMSCTRL);
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);
64231 + area = cfg->cis->source_x * cfg->cis->source_y;
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;
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;
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);
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);
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);
64255 + /* MSDMA for codec source image width */
64256 + val_width = cfg->cis->source_x; /* MSCOWIDTH */
64257 + writel(val_width, cfg->regs + S3C_CIMSWIDTH);
64262 +static int s3c_camif_input_msdma(camif_cfg_t *cfg)
64264 + if (cfg->input_channel == MSDMA_FROM_PREVIEW)
64265 + s3c_camif_input_msdma_preview(cfg);
64271 + * 6400 MSDMA (Preview & Codec)
64273 +#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
64274 +int s3c_camif_input_msdma_codec(camif_cfg_t * cfg)
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;
64281 + /* Codec path input data selection */
64282 + val = readl(cfg->regs + S3C_MSCOCTRL);
64283 + val &= ~(1 << 3);
64284 + writel(val, cfg->regs + S3C_MSCOCTRL);
64286 + val = readl(cfg->regs + S3C_MSCOCTRL);
64288 + writel(val, cfg->regs + S3C_MSCOCTRL);
64290 + switch(cfg->src_fmt) {
64291 + case CAMIF_YCBCR420:
64293 + val = readl(cfg->regs + S3C_MSCOCTRL);
64294 + val &= ~(0x3 << 1);
64295 + writel(val, cfg->regs + S3C_MSCOCTRL);
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);
64310 + area = cfg->cis->source_x * cfg->cis->source_y;
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;
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;
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);
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);
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);
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);
64345 +int s3c_camif_input_msdma_preview(camif_cfg_t * cfg)
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;
64353 + val = readl(cfg->regs + S3C_CIMSCTRL);
64354 + val &= ~(0x1 << 3);
64355 + writel(val, cfg->regs + S3C_CIMSCTRL);
64357 + val = readl(cfg->regs + S3C_CIMSCTRL);
64359 + writel(val, cfg->regs + S3C_CIMSCTRL);
64361 + switch(cfg->src_fmt) {
64362 + case CAMIF_YCBCR420:
64364 + val = readl(cfg->regs + S3C_CIMSCTRL);
64365 + val &= ~(0x3 << 1);
64366 + writel(val, cfg->regs + S3C_CIMSCTRL);
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);
64382 + area = cfg->cis->source_x * cfg->cis->source_y;
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;
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;
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);
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);
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);
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);
64417 +static int s3c_camif_input_msdma(camif_cfg_t *cfg)
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);
64428 +static int s3c_camif_input_camera(camif_cfg_t *cfg)
64430 + unsigned int val;
64432 + s3c_camif_set_offset(cfg->cis);
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);
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);
64451 + printk(KERN_ERR "Invalid DMA type\n");
64456 +static int s3c_camif_setup_input_path(camif_cfg_t *cfg)
64458 + if (cfg->input_channel == CAMERA_INPUT)
64459 + s3c_camif_input_camera(cfg);
64461 + s3c_camif_input_msdma(cfg);
64466 +/*************************************************************************
64467 + * Output path part
64468 + ************************************************************************/
64469 +static int s3c_camif_output_pp_codec_rgb(camif_cfg_t *cfg)
64472 + unsigned int val;
64473 + unsigned int area = cfg->target_x * cfg->target_y;
64475 + if (cfg->dst_fmt & CAMIF_RGB24)
64478 + assert (cfg->dst_fmt & CAMIF_RGB16);
64482 + if ((area % PAGE_SIZE) != 0) {
64483 + i = area / PAGE_SIZE;
64484 + area = (i + 1) * PAGE_SIZE;
64487 + cfg->buffer_size = area;
64489 + if (cfg->input_channel == MSDMA_FROM_CODEC) {
64491 +void __iomem *S3C24XX_VA_LCD = ioremap(S3C64XX_PA_FB, 1024*1024);
64492 + val = readl(S3C_VIDW00ADD0B0);
64495 + for (i = 0; i < 4; i++)
64496 + writel(val, cfg->regs + S3C_CICOYSA(i));
64498 + switch ( cfg->pp_num ) {
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));
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;
64514 + cfg->img_buf[i].virt_rgb += area;
64515 + cfg->img_buf[i].phys_rgb += area;
64517 + writel(cfg->img_buf[i].phys_rgb,
64518 + cfg->regs + S3C_CICOYSA(i));
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));
64536 + printk(KERN_ERR "Invalid pingpong number %d\n",
64538 + panic("s3c camif halt\n");
64545 +static int s3c_camif_output_pp_codec(camif_cfg_t *cfg)
64547 + unsigned int i, cbcr_size = 0;
64548 + unsigned int area = cfg->target_x * cfg->target_y;
64549 + unsigned int one_p_size;
64551 + area = cfg->target_x * cfg->target_y;
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);
64562 + printk(KERN_ERR "Invalid target format %d\n", cfg->dst_fmt);
64564 + one_p_size = area + 2 * cbcr_size;
64566 + if ((one_p_size % PAGE_SIZE) != 0) {
64567 + i = one_p_size / PAGE_SIZE;
64568 + one_p_size = (i + 1) * PAGE_SIZE;
64571 + cfg->buffer_size = one_p_size;
64573 + switch (cfg->pp_num) {
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));
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;
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;
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));
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));
64644 + printk(KERN_ERR "Invalid pingpong number %d\n", cfg->pp_num);
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)
64653 + unsigned int cbcr_size = 0;
64654 + unsigned int area = cfg->cis->source_x * cfg->cis->source_y;
64655 + unsigned int val;
64658 + val = readl(S3C_VIDW01ADD0);
64660 + if (!((cfg->dst_fmt & CAMIF_RGB16) || (cfg->dst_fmt & CAMIF_RGB24)))
64661 + printk(KERN_ERR "Invalid target format\n");
64663 + for (i = 0; i < 4; i++)
64664 + writel(val, cfg->regs + S3C_CIPRYSA(i));
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) {
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;
64680 + cfg->img_buf[0].virt_y = cfg->pp_virt_buf;
64681 + cfg->img_buf[0].phys_y = cfg->pp_phys_buf;
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);
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);
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);
64692 + writel(cfg->cis->source_x, cfg->regs + S3C_CIMSWIDTH);
64696 +#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
64697 +static int s3c_camif_io_duplex_preview(camif_cfg_t *cfg)
64699 + unsigned int cbcr_size = 0;
64700 + unsigned int area = cfg->cis->source_x * cfg->cis->source_y;
64701 + unsigned int val;
64705 +void __iomem *S3C24XX_VA_LCD = ioremap(S3C64XX_PA_FB, 1024*1024);
64706 + val = readl(S3C_VIDW01ADD0B0);
64709 + if (!((cfg->dst_fmt & CAMIF_RGB16) || (cfg->dst_fmt & CAMIF_RGB24)))
64710 + printk(KERN_ERR "Invalid target format\n");
64712 + for (i = 0; i < 4; i++)
64713 + writel(val, cfg->regs + S3C_CIPRYSA(i));
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) {
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;
64730 + cfg->img_buf[0].virt_y = cfg->pp_virt_buf;
64731 + cfg->img_buf[0].phys_y = cfg->pp_phys_buf;
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);
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);
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);
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);
64752 +static int s3c_camif_output_pp_preview(camif_cfg_t *cfg)
64755 + unsigned int cbcr_size = 0;
64756 + unsigned int area = cfg->target_x * cfg->target_y;
64758 + if (cfg->input_channel) {
64759 + s3c_camif_io_duplex_preview(cfg);
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)
64770 + else if (cfg->dst_fmt & CAMIF_RGB16)
64773 + printk(KERN_ERR "Invalid target format %d\n", cfg->dst_fmt);
64775 + if ((area % PAGE_SIZE) != 0) {
64776 + i = area / PAGE_SIZE;
64777 + area = (i + 1) * PAGE_SIZE;
64780 + cfg->buffer_size = area;
64782 + switch (cfg->pp_num) {
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));
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;
64798 + cfg->img_buf[i].virt_rgb += area;
64799 + cfg->img_buf[i].phys_rgb += area;
64802 + writel(cfg->img_buf[i].phys_rgb,
64803 + cfg->regs + S3C_CIPRYSA(i));
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));
64819 + printk(KERN_ERR "Invalid pingpong number %d\n", cfg->pp_num);
64825 +static int s3c_camif_output_pp(camif_cfg_t *cfg)
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);
64835 +static int s3c_camif_output_lcd(camif_cfg_t *cfg)
64837 + /* To Be Implemented */
64841 +static int s3c_camif_setup_output_path(camif_cfg_t *cfg)
64843 + if (cfg->output_channel == CAMIF_OUT_FIFO)
64844 + s3c_camif_output_lcd(cfg);
64846 + s3c_camif_output_pp(cfg);
64851 +/*************************************************************************
64853 + ************************************************************************/
64854 +static int s3c_camif_set_target_area(camif_cfg_t *cfg)
64856 + unsigned int rect = cfg->target_x * cfg->target_y;
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);
64866 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
64867 +static inline int s3c_camif_set_ratio(camif_cfg_t *cfg)
64869 + unsigned int cmd =
64870 + S3C_CICOSCCTRL_CSCR2Y_WIDE | S3C_CICOSCCTRL_CSCY2R_WIDE;
64872 + if (cfg->dma_type & CAMIF_CODEC) {
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);
64879 + writel(S3C_CICOSCPREDST_PREDSTWIDTH_CO(cfg->sc.predst_x) |
64880 + S3C_CICOSCPREDST_PREDSTHEIGHT_CO(cfg->sc.predst_y),
64881 + cfg->regs + S3C_CICOSCPREDST);
64883 + /* Differ from Preview */
64884 + if (cfg->sc.scalerbypass)
64885 + cmd |= S3C_CICOSCCTRL_SCALERBYPASS_CO;
64887 + /* Differ from Codec */
64888 + if (cfg->dst_fmt & CAMIF_RGB24)
64889 + cmd |= S3C_CICOSCCTRL_OUTRGB_FMT_RGB888;
64891 + cmd |= S3C_CICOSCCTRL_OUTRGB_FMT_RGB565;
64893 + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)
64895 + S3C_CICOSCCTRL_SCALEUP_H | S3C_CICOSCCTRL_SCALEUP_V;
64898 + S3C_CICOSCCTRL_MAINHORRATIO_CO(cfg->sc.mainhratio) |
64899 + S3C_CICOSCCTRL_MAINVERRATIO_CO(cfg->sc.mainvratio),
64900 + cfg->regs + S3C_CICOSCCTRL);
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);
64908 + writel(S3C_CIPRSCPREDST_PREDSTWIDTH_PR(cfg->sc.predst_x) |
64909 + S3C_CIPRSCPREDST_PREDSTHEIGHT_PR(cfg->sc.predst_y),
64910 + cfg->regs + S3C_CIPRSCPREDST);
64912 + if (cfg->dst_fmt & CAMIF_RGB24)
64913 + cmd |= S3C_CIPRSCCTRL_OUTRGB_FMT_PR_RGB888;
64915 + cmd |= S3C_CIPRSCCTRL_OUTRGB_FMT_PR_RGB565;
64917 + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)
64918 + cmd |= (1 << 30) | (1 << 29);
64921 + S3C_CIPRSCCTRL_MAINHORRATIO_PR(cfg->sc.mainhratio) |
64922 + S3C_CIPRSCCTRL_MAINVERRATIO_PR(cfg->sc.mainvratio),
64923 + cfg->regs + S3C_CIPRSCCTRL);
64926 + printk(KERN_ERR "Invalid DMA type\n");
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)
64935 + if (cfg->dma_type & CAMIF_CODEC) {
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);
64942 + writel(S3C_CICOSCPREDST_PREDSTWIDTH_CO(cfg->sc.predst_x) |
64943 + S3C_CICOSCPREDST_PREDSTHEIGHT_CO(cfg->sc.predst_y),
64944 + cfg->regs + S3C_CICOSCPREDST);
64946 + if (cfg->sc.scalerbypass)
64947 + cmd |= S3C_CICOSCCTRL_SCALERBYPASS_CO;
64949 + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)
64951 + S3C_CICOSCCTRL_SCALEUP_H | S3C_CICOSCCTRL_SCALEUP_V;
64954 + S3C_CICOSCCTRL_MAINHORRATIO_CO(cfg->sc.mainhratio) |
64955 + S3C_CICOSCCTRL_MAINVERRATIO_CO(cfg->sc.mainvratio),
64956 + cfg->regs + S3C_CICOSCCTRL);
64958 + } else if (cfg->dma_type & CAMIF_PREVIEW) {
64960 + cmd |= S3C_CIPRSCCTRL_SAMPLE_PR;
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);
64967 + writel(S3C_CIPRSCPREDST_PREDSTWIDTH_PR(cfg->sc.predst_x) |
64968 + S3C_CIPRSCPREDST_PREDSTHEIGHT_PR(cfg->sc.predst_y),
64969 + cfg->regs + S3C_CIPRSCPREDST);
64971 + if (cfg->dst_fmt & CAMIF_RGB24)
64972 + cmd |= S3C_CIPRSCCTRL_RGBFORMAT_24;
64974 + if (cfg->sc.scaleup_h & cfg->sc.scaleup_v)
64975 + cmd |= (1 << 29) | (1 << 28);
64978 + S3C_CIPRSCCTRL_MAINHORRATIO_PR(cfg->sc.mainhratio) |
64979 + S3C_CIPRSCCTRL_MAINVERRATIO_PR(cfg->sc.mainvratio),
64980 + cfg->regs + S3C_CIPRSCCTRL);
64983 + printk(KERN_ERR "Invalid DMA type\n");
64989 +static int s3c_camif_calc_ratio(unsigned int src_width, unsigned int dst_width,
64990 + unsigned int *ratio, unsigned int *shift)
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);
64998 + if (src_width >= 32 * dst_width) {
65000 + } else if (src_width >= 16 * dst_width) {
65002 + } else if (src_width >= 8 * dst_width) {
65004 + } else if (src_width >= 4 * dst_width) {
65006 + } else if (src_width >= 2 * dst_width) {
65012 + *ratio = 1 << *shift;
65017 +static int s3c_camif_setup_scaler(camif_cfg_t *cfg)
65019 + int tx = cfg->target_x, ty = cfg->target_y;
65022 + if (tx <= 0 || ty <= 0) {
65023 + printk(KERN_ERR "Invalid target size\n");
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);
65032 + if (sx <= 0 || sy <= 0) {
65033 + printk(KERN_ERR "Invalid source size\n");
65037 + cfg->sc.modified_src_x = sx;
65038 + cfg->sc.modified_src_y = sy;
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);
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");
65053 + cfg->sc.shfactor = 10 - (cfg->sc.hfactor + cfg->sc.vfactor);
65055 + /* Pre-scaler control register 2 */
65056 + cfg->sc.predst_x = sx / cfg->sc.prehratio;
65057 + cfg->sc.predst_y = sy / cfg->sc.prevratio;
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);
65063 + cfg->sc.scaleup_h = sx <= tx;
65064 + cfg->sc.scaleup_v = sy <= ty;
65066 + s3c_camif_set_ratio(cfg);
65067 + s3c_camif_set_target_area(cfg);
65072 +/*************************************************************************
65074 + ************************************************************************/
65075 +int s3c_camif_set_source_format(camif_cis_t *cis)
65077 + camif_cfg_t *cfg = s3c_camif_get_fimc_object(CODEC_MINOR);
65078 + unsigned int cmd = 0;
65080 + /* Configure CISRCFMT --Source Format */
65081 + if (cis->itu_fmt & CAMIF_ITU601)
65082 + cmd = CAMIF_ITU601;
65084 + assert(cis->itu_fmt & CAMIF_ITU656);
65085 + cmd = CAMIF_ITU656;
65088 + cmd |= S3C_CISRCFMT_SOURCEHSIZE(cis->source_x) |
65089 + S3C_CISRCFMT_SOURCEVSIZE(cis->source_y);
65092 + cmd |= cis->order422;
65093 + writel(cmd, cfg->regs + S3C_CISRCFMT);
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);
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)
65107 + unsigned int cmd = 0;
65109 + if (cfg->dma_type & CAMIF_CODEC) {
65110 + cmd |= S3C_CICOTRGFMT_TARGETHSIZE_CO(cfg->target_x) |
65111 + S3C_CICOTRGFMT_TARGETVSIZE_CO(cfg->target_y);
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);
65124 + printk(KERN_ERR "Invalid target format\n");
65125 + writel(cmd, cfg->regs + S3C_CICOTRGFMT);
65127 + assert(cfg->dma_type & CAMIF_PREVIEW);
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);
65135 + writel(cmd | (2 << 30), cfg->regs + S3C_CIPRTRGFMT);
65140 +#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65141 +static int s3c_camif_set_target_format(camif_cfg_t *cfg)
65143 + unsigned int cmd = 0;
65145 + if (cfg->dma_type & CAMIF_CODEC) {
65146 + cmd |= S3C_CICOTRGFMT_TARGETHSIZE_CO(cfg->target_x) |
65147 + S3C_CICOTRGFMT_TARGETVSIZE_CO(cfg->target_y);
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;
65159 + printk(KERN_ERR "Invalid target format\n");
65160 + writel(cmd, cfg->regs + S3C_CICOTRGFMT);
65162 + assert(cfg->dma_type & CAMIF_PREVIEW);
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);
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;
65180 + printk(KERN_ERR "Invalid target format\n");
65182 + writel(cmd, cfg->regs + S3C_CIPRTRGFMT);
65189 +/*************************************************************************
65191 + ************************************************************************/
65192 +int s3c_camif_control_fimc(camif_cfg_t *cfg)
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");
65200 + s3c_camif_setup_input_path(cfg);
65202 + if (s3c_camif_setup_scaler(cfg)) {
65203 + printk(KERN_ERR "Preview scaler fault: "
65204 + "change WinHorOfset or target size\n");
65208 + s3c_camif_set_target_format(cfg);
65210 + if (s3c_camif_setup_dma(cfg)) {
65211 + printk(KERN_ERR "DMA burst length error\n");
65215 + s3c_camif_setup_output_path(cfg);
65220 +int s3c_camif_start_dma(camif_cfg_t *cfg)
65222 + unsigned int n_cmd = readl(cfg->regs + S3C_CIIMGCPT);
65223 + unsigned int val;
65225 + switch(cfg->capture_enable) {
65226 + case CAMIF_BOTH_DMA_ON:
65227 + s3c_camif_reset(CAMIF_RESET, 0); /* Flush Camera Core Buffer */
65230 + val = readl(cfg->regs + S3C_CICOSCCTRL);
65231 + val |= S3C_CICOSCCTRL_COSCALERSTART;
65232 + writel(val, cfg->regs + S3C_CICOSCCTRL);
65234 + /* For Preview */
65235 + val = readl(cfg->regs + S3C_CIPRSCCTRL);
65236 + val |= S3C_CIPRSCCTRL_START;
65237 + writel(val, cfg->regs + S3C_CIPRSCCTRL);
65240 + S3C_CIIMGCPT_IMGCPTEN_COSC | S3C_CIIMGCPT_IMGCPTEN_PRSC;
65243 + case CAMIF_DMA_ON:
65244 + s3c_camif_reset(CAMIF_RESET, 0); /* Flush Camera Core Buffer */
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);
65251 + n_cmd |= S3C_CIIMGCPT_IMGCPTEN_COSC;
65253 +#if defined(CONFIG_CPU_S3C2443) || defined(CONFIG_CPU_S3C2450) || defined(CONFIG_CPU_S3C2416)
65254 + n_cmd |= (1 << 24);
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;
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));
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;
65286 + val = readl(cfg->regs + S3C_CIIMGCPT);
65287 + val &= ~(0x7 << 29);
65288 + writel(val | n_cmd | S3C_CIIMGCPT_IMGCPTEN, cfg->regs + S3C_CIIMGCPT);
65293 +int s3c_camif_stop_dma(camif_cfg_t *cfg)
65295 + unsigned int n_cmd = readl(cfg->regs + S3C_CIIMGCPT);
65296 + unsigned int val;
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);
65304 + val = readl(cfg->regs + S3C_CIPRSCCTRL);
65305 + val &= ~S3C_CIPRSCCTRL_START;
65306 + writel(val, cfg->regs + S3C_CIPRSCCTRL);
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;
65319 + if (!(n_cmd & S3C_CIIMGCPT_IMGCPTEN_PRSC))
65322 + val = readl(cfg->regs + S3C_CIPRSCCTRL);
65323 + val &= ~S3C_CIPRSCCTRL_START;
65324 + writel(val, cfg->regs + S3C_CIPRSCCTRL);
65326 + n_cmd &= ~S3C_CIIMGCPT_IMGCPTEN_PRSC;
65328 + if (!(n_cmd & S3C_CIIMGCPT_IMGCPTEN_COSC))
65335 + printk(KERN_ERR "Unexpected DMA control\n");
65338 + writel(n_cmd, cfg->regs + S3C_CIIMGCPT);
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);
65346 + val = readl(cfg->regs + S3C_CIPRCTRL);
65347 + val |= S3C_CIPRCTRL_LASTIRQEN_ENABLE;
65348 + writel(val, cfg->regs + S3C_CIPRCTRL);
65355 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65356 +int s3c_camif_start_codec_msdma(camif_cfg_t *cfg)
65361 + val = readl(cfg->regs + S3C_MSCOCTRL);
65362 + val &= ~(1 << 0);
65363 + writel(val, cfg->regs + S3C_MSCOCTRL);
65365 + val = readl(cfg->regs + S3C_MSCOCTRL);
65367 + writel(val, cfg->regs + S3C_MSCOCTRL);
65373 +int s3c_camif_start_preview_msdma(camif_cfg_t * cfg)
65375 + unsigned int val;
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);
65383 + val = readl(cfg->regs + S3C_CIMSCTRL);
65385 + writel(val, cfg->regs + S3C_CIMSCTRL);
65387 + while(!readl(cfg->regs + S3C_CIMSCTRL) & (1 << 6));
65392 +void s3c_camif_change_flip(camif_cfg_t *cfg)
65394 + unsigned int cmd = 0;
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);
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);
65412 + cmd = readl(cfg->regs + S3C_CIPRTRGFMT);
65413 + cmd &= ~(0x7 << 13);
65414 + cmd |= cfg->flip;
65415 + writel(cmd, cfg->regs + S3C_CIPRTRGFMT);
65419 +void s3c_camif_change_effect(camif_cfg_t *cfg)
65421 + unsigned int val = readl(cfg->regs + S3C_CIIMGEFF);
65423 + val &= ~((1 << 28) | (1 << 27) | (1 << 26));
65425 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65426 + val |= ((1 << 31) | (1 << 30));
65429 + switch(cfg->effect) {
65430 + case CAMIF_SILHOUETTE:
65431 + val |= S3C_CIIMGEFF_FIN_SILHOUETTE;
65434 + case CAMIF_EMBOSSING:
65435 + val |= S3C_CIIMGEFF_FIN_EMBOSSING;
65438 + case CAMIF_ART_FREEZE:
65439 + val |= S3C_CIIMGEFF_FIN_ARTFREEZE;
65442 + case CAMIF_NEGATIVE:
65443 + val |= S3C_CIIMGEFF_FIN_NEGATIVE;
65446 + case CAMIF_ARBITRARY_CB_CR:
65447 + val |= S3C_CIIMGEFF_FIN_ARBITRARY;
65450 + case CAMIF_BYPASS:
65455 + writel(val, cfg->regs + S3C_CIIMGEFF);
65458 +int s3c_camif_do_postprocess(camif_cfg_t *cfg)
65460 + unsigned int val = readl(cfg->regs + S3C_CIMSCTRL);
65462 + if (cfg->dst_fmt & CAMIF_YCBCR420)
65465 + val &= ~(1 << 1);
65467 + val &= ~(1 << 0);
65468 + writel(val, cfg->regs + S3C_CIMSCTRL);
65471 + writel(val, cfg->regs + S3C_CIMSCTRL);
65473 + printk(KERN_INFO "Postprocessing started\n");
65475 + while(!readl(cfg->regs + S3C_CIMSCTRL) & (1 << 6));
65477 + printk(KERN_INFO "Postprocessing finished\n");
65482 +int s3c_camif_set_offset(camif_cis_t *cis)
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 */
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);
65495 + writel(0, cfg->regs + S3C_CIWDOFST);
65498 + writel(0, cfg->regs + S3C_CIWDOFST);
65499 + writel(0, cfg->regs + S3C_CIDOWSFT2);
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);
65513 +void s3c_camif_set_priority(int flag)
65515 + unsigned int val;
65518 + irq_old_priority = readl(S3C64XX_PRIORITY);
65519 + val = irq_old_priority;
65520 + val &= ~(3 << 7);
65521 + writel(val, S3C64XX_PRIORITY);
65523 + /* Arbiter 1, REQ2 first */
65525 + writel(val, S3C64XX_PRIORITY);
65527 + /* Disable Priority Rotate */
65528 + val &= ~(1 << 1);
65529 + writel(val, S3C64XX_PRIORITY);
65531 + writel(irq_old_priority, S3C64XX_PRIORITY);
65534 +/*************************************************************************
65536 + ************************************************************************/
65537 +void s3c_camif_enable_lastirq(camif_cfg_t *cfg)
65539 + unsigned int val;
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);
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);
65556 +void s3c_camif_disable_lastirq(camif_cfg_t *cfg)
65558 + unsigned int val;
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);
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);
65575 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65576 +void s3c_camif_clear_irq(int irq)
65578 + camif_cfg_t *cfg = s3c_camif_get_fimc_object(CODEC_MINOR);
65579 + unsigned int val = 0;
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);
65589 + writel(val, cfg->regs + S3C_CIGCTRL);
65592 +void s3c_camif_clear_irq(int irq)
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)
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);
65617 + writel(0x1fff, S3C2443_GPJDN);
65621 +#elif defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65622 +static int s3c_camif_set_gpio(void)
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);
65638 + writel(0, S3C64XX_GPFPUD);
65644 +void s3c_camif_reset(int is, int delay)
65646 + camif_cfg_t *cfg = s3c_camif_get_fimc_object(CODEC_MINOR);
65647 + unsigned int val;
65648 + unsigned int tmp;
65651 + case CAMIF_RESET:
65652 + tmp = readl(cfg->regs + S3C_CISRCFMT);
65654 + if (tmp &= (1 << 31)) {
65655 + /* ITU-R BT 601 */
65656 + val = readl(cfg->regs + S3C_CIGCTRL);
65657 + val |= S3C_CIGCTRL_SWRST;
65659 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65660 + val |= S3C_CIGCTRL_IRQ_LEVEL;
65662 + writel(val, cfg->regs + S3C_CIGCTRL);
65665 + val = readl(cfg->regs + S3C_CIGCTRL);
65666 + val &= ~S3C_CIGCTRL_SWRST;
65667 + writel(val, cfg->regs + S3C_CIGCTRL);
65669 + /* ITU-R BT 656 */
65670 + tmp = readl(cfg->regs + S3C_CISRCFMT);
65671 + tmp |= (1 << 31);
65672 + writel(tmp, cfg->regs + S3C_CISRCFMT);
65674 + val = readl(cfg->regs + S3C_CIGCTRL);
65675 + val |= S3C_CIGCTRL_SWRST;
65677 +#if defined(CONFIG_CPU_S3C6400) || defined(CONFIG_CPU_S3C6410)
65678 + val |= S3C_CIGCTRL_IRQ_LEVEL;
65680 + writel(val, cfg->regs + S3C_CIGCTRL);
65683 + val = readl(cfg->regs + S3C_CIGCTRL);
65684 + val &= ~S3C_CIGCTRL_SWRST;
65685 + writel(val, cfg->regs + S3C_CIGCTRL);
65687 + tmp = readl(cfg->regs + S3C_CISRCFMT);
65688 + tmp &= ~(1 << 31);
65689 + writel(tmp, cfg->regs + S3C_CISRCFMT);
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);
65700 + val = readl(cfg->regs + S3C_CIGCTRL);
65701 + val &= ~S3C_CIGCTRL_CAMRST;
65702 + writel(val, cfg->regs + S3C_CIGCTRL);
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);
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);
65719 + val = readl(cfg->regs + S3C_CIGCTRL);
65720 + val |= S3C_CIGCTRL_CAMRST;
65721 + writel(val, cfg->regs + S3C_CIGCTRL);
65730 +void s3c_camif_init(void)
65732 + s3c_camif_reset(CAMIF_RESET, 0);
65733 + s3c_camif_set_gpio();
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
65739 +/* drivers/media/video/s3c_camif.h
65741 + * Copyright (c) 2008 Samsung Electronics
65743 + * Samsung S3C Camera driver
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.
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.
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
65760 +#ifndef __S3C_CAMIF_H_
65761 +#define __S3C_CAMIF_H_
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__ */
65771 +#if !defined(O_NONCAP)
65772 +#define O_NONCAP O_TRUNC
65775 +#if defined(CAMIF_DEBUG)
65776 +#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __FUNCTION__ , ## args)
65778 +#define DPRINTK(fmt, args...)
65781 +#if defined(CAMIF_DEBUG)
65782 +#define assert(expr) \
65784 + printk( "Assertion failed! %s,%s,%s,line=%d\n", \
65785 + #expr,__FILE__,__FUNCTION__,__LINE__); \
65788 +#define assert(expr)
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"
65798 +#define MEM_SIZE 0x04000000
65799 +#define FIMC_VER "2.x"
65802 +#undef FSM_ON_PREVIEW
65803 +#define FSM_ON_CODEC
65805 +#undef USE_LAST_IRQ /* turn on if pp count is 1 */
65807 +#define CODEC_DEV_NAME "CAMIF_CODEC"
65808 +#define PREVIEW_DEV_NAME "CAMIF_PREVIEW"
65810 +#define CAMIF_DEV_NUM 2
65811 +#define FIMC_CODEC_INDEX 0
65812 +#define FIMC_PREVIEW_INDEX 1
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)
65819 +#define CODEC_DEFAULT_WIDTH 640
65820 +#define CODEC_DEFAULT_HEIGHT 480
65821 +#define PREVIEW_DEFAULT_WIDTH 640
65822 +#define PREVIEW_DEFAULT_HEIGHT 480
65824 +#define CROP_DEFAULT_WIDTH 352
65825 +#define CROP_DEFAULT_HEIGHT 272
65827 +#define CODEC_DEFAULT_PPNUM 4
65828 +#define PREVIEW_DEFAULT_PPNUM 4
65830 +#define CODEC_MINOR 12
65831 +#define PREVIEW_MINOR 13
65833 +#define CHECK_FREQ 5
65834 +#define INSTANT_SKIP 0
65835 +#define INSTANT_GO 1
65837 +#define VID_HARDWARE_SAMSUNG_FIMC3X 236
65839 +#define ZOOM_AT_A_TIME_IN_PIXELS 32
65840 +#define ZOOM_IN_MAX 640
65842 +/* Codec or Preview Status */
65843 +#define CAMIF_STARTED (1 << 1)
65844 +#define CAMIF_STOPPED (1 << 2)
65845 +#define CAMIF_INT_HAPPEN (1 << 3)
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
65860 +#define CAMIF_CAPTURE_SKIP_FRAMES 5
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 */
65867 +#define USER_EXIT (1 << 2)
65868 +#define USER_ADD (1 << 1)
65869 +#define SENSOR_INIT (1 << 0)
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
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)
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)
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
65900 +enum camif_itu_fmt {
65901 + CAMIF_ITU601 = (1 << 31),
65902 + CAMIF_ITU656 = 0,
65905 +/* It is possbie to use two device simultaneously */
65906 +enum camif_dma_type {
65907 + CAMIF_PREVIEW = (1 << 0),
65908 + CAMIF_CODEC = (1 << 1),
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),
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),
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),
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),
65944 +enum image_effect {
65946 + CAMIF_ARBITRARY_CB_CR,
65948 + CAMIF_ART_FREEZE,
65949 + CAMIF_EMBOSSING ,
65950 + CAMIF_SILHOUETTE,
65953 +enum input_channel{
65955 + MSDMA_FROM_CODEC,
65956 + MSDMA_FROM_PREVIEW,
65959 +enum output_channel{
65964 +typedef struct camif_performance
65967 + int framesdropped;
65970 + __u32 reserved[4];
65974 + dma_addr_t phys_y;
65975 + dma_addr_t phys_cb;
65976 + dma_addr_t phys_cr;
65980 + dma_addr_t phys_rgb;
65984 +/* this structure convers the CIWDOFFST, prescaler, mainscaler */
65986 + u32 modified_src_x; /* After windows applyed to source_x */
65987 + u32 modified_src_y;
65990 + u32 shfactor; /* SHfactor = 10 - ( hfactor + vfactor ) */
65999 + u32 scalerbypass; /* only codec */
66003 +enum v4l2_status {
66004 + CAMIF_V4L2_INIT = (1 << 0),
66005 + CAMIF_v4L2_DIRTY = (1 << 1),
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 */
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 */
66026 + u32 init_sensor; /* initializing sensor */
66027 + u32 reset_type; /* External Sensor Reset Type */
66028 + u32 reset_udelay;
66032 +/* when App want to change v4l2 parameter,
66033 + * we instantly store it into v4l2_t v2
66034 + * and then reflect it to hardware
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;
66044 + struct v4l2_rect crop_bounds;
66045 + struct v4l2_rect crop_defrect;
66046 + struct v4l2_rect crop_current;
66051 +typedef struct camif_c_t {
66052 + struct video_device *v;
66054 + /* V4L2 param only for v4l2 driver */
66056 + camif_cis_t *cis; /* Common between Codec and Preview */
66058 + /* logical parameter */
66059 + wait_queue_head_t waitq;
66060 + u32 status; /* Start/Stop */
66061 + u32 fsm; /* Start/Stop */
66062 + u32 open_count; /* duplicated */
66064 + char shortname[16];
66068 + enum flip_mode flip;
66069 + enum image_effect effect;
66070 + enum camif_dma_type dma_type;
66072 + /* 4 pingpong Frame memory */
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;
66087 + void *other; /* other camif_cfg_t */
66088 + u32 msdma_status; /* 0 : stop, 1 : start */
66089 + void __iomem *regs;
66092 +/* Test Application Usage */
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;
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);
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
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)
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.
66158 + * Driver for FIMC2.x Camera Decoder
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>
66173 +//#define CAMIF_DEBUG
66175 +#include "../s3c_camif.h"
66176 +#include "4xa_sensor.h"
66180 + * Samsung's original code:
66181 + * .camclk = 44000000, / * for 20 fps: 44MHz, for 12 fps (more
66182 + * stable): 26MHz * /
66184 + * Experimenting with the controls yielded the following:
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.
66189 + * Div8_r = 0: 1/4, 1: 1/2 (default)
66190 + * Half_PCLK_Enable = 0: 1/1 (default), 1: 1/2
66192 + * Thus our 26.6 MHz MCLK becomes an 87.78 MHz PLL_CLK and eventually a PCLK
66196 +#define CAMCLK 26600000 /* 26.6 MHz */
66199 +static struct i2c_driver sensor_driver;
66201 +/* This is an abstract CIS sensor for MSDMA input. */
66203 +camif_cis_t msdma_input = {
66204 + .itu_fmt = CAMIF_ITU601,
66205 + .order422 = CAMIF_CBYCRY, /* another case: YCRYCB */
66206 + .camclk = CAMCLK,
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,
66220 +camif_cis_t interlace_input = {
66221 + .itu_fmt = CAMIF_ITU601,
66222 + .order422 = CAMIF_CBYCRY, /* another case: YCRYCB */
66223 + .camclk = CAMCLK,
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,
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,
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,
66255 +s5k4xa_t s5k4ba_regs_mirror[S5K4BA_REGS];
66257 +#error No samsung CIS moudule here !
66260 +camif_cis_t* get_initialized_cis(void)
66262 + if (data.init_sensor == 0)
66268 +#define CAM_ID 0x5a
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 };
66274 +static struct i2c_client_address_data addr_data = {
66275 + .normal_i2c = normal_addr,
66277 + .ignore = ignore,
66278 + .forces = forces,
66282 +static unsigned char sensor_read(struct i2c_client *client,
66283 + unsigned char subaddr)
66285 + unsigned char buf = subaddr;
66286 + struct i2c_msg msg = {
66287 + .addr = client->addr,
66293 + if (i2c_transfer(client->adapter, &msg, 1) != 1) {
66294 + printk(" I2C write Error\n");
66298 + msg.flags = I2C_M_RD;
66299 + if (i2c_transfer(client->adapter, &msg, 1) != 1) {
66300 + printk(" I2C read Error\n");
66308 +sensor_write(struct i2c_client *client,
66309 + unsigned char subaddr, unsigned char val)
66311 + unsigned char buf[2];
66312 + struct i2c_msg msg = {
66313 + .addr = client->addr,
66319 + buf[0] = subaddr;
66322 + return i2c_transfer(client->adapter, &msg, 1) == 1 ? 0 : -EIO;
66325 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
66326 +void inline sensor_init(struct i2c_client *sam_client)
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);
66336 +#error No samsung CIS moudule !
66340 +s5k4xa_attach(struct i2c_adapter *adap, int addr, int kind)
66342 + struct i2c_client *c;
66344 + c = kmalloc(sizeof(*c), GFP_KERNEL);
66348 + memset(c, 0, sizeof(struct i2c_client));
66350 + strcpy(c->name, "S5K4XA");
66352 + c->adapter = adap;
66353 + c->driver = &sensor_driver;
66354 + i2c_set_clientdata(c, &data);
66357 + s3c_camif_register_sensor(c);
66359 + return i2c_attach_client(c);
66362 +static int sensor_attach_adapter(struct i2c_adapter *adap)
66364 + extern void om_3d7k_camera_on(void);
66365 + extern void om_3d7k_camera_off(void);
66368 + s3c_camif_open_sensor(&data);
66370 + om_3d7k_camera_on();
66371 + ret = i2c_probe(adap, &addr_data, s5k4xa_attach);
66372 + om_3d7k_camera_off();
66376 +static int sensor_detach(struct i2c_client *client)
66378 + i2c_detach_client(client);
66379 + s3c_camif_unregister_sensor(client);
66385 + * This function only for SVGA Camera : 4BA
66388 +static int change_sensor_size(struct i2c_client *client, int 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);
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);
66406 +#error No samsung CIS moudule !
66409 + panic("4xa_sensor.c: unexpect value\n");
66415 +static int change_sensor_wb(struct i2c_client *client, int type)
66417 + printk("[ *** Page 0, 4XA Sensor White Balance Mode ***]\n");
66419 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
66420 + sensor_write(client, 0xFC, 0x0);
66421 + sensor_write(client, 0x30, type);
66427 + printk(" -> AWB auto mode ]\n");
66430 + printk(" -> Indoor 3100 mode ]\n");
66433 + printk(" -> Outdoor 5100 mode ]\n");
66436 + printk(" -> Indoor 2000 mode ]\n");
66439 + printk(" -> AE/AWB halt ]\n");
66442 + printk(" -> Cloudy(6000) mode ]\n");
66445 + printk(" -> Sunny(8000) mode ]\n");
66453 +sensor_command(struct i2c_client *client, unsigned int cmd, void *arg)
66456 + case SENSOR_INIT:
66457 + sensor_init(client);
66458 + printk(KERN_INFO "External Camera initialized\n");
66467 + case SENSOR_QSVGA:
66468 + change_sensor_size(client, SENSOR_QSVGA);
66472 + change_sensor_size(client, SENSOR_VGA);
66475 + case SENSOR_SVGA:
66476 + change_sensor_size(client, SENSOR_SVGA);
66479 + case SENSOR_SXGA:
66480 + change_sensor_size(client, SENSOR_SXGA);
66483 + case SENSOR_UXGA:
66484 + change_sensor_size(client, SENSOR_UXGA);
66487 + case SENSOR_BRIGHTNESS:
66488 + change_sensor_setting();
66492 + printk("[ *** 4XA Sensor White Balance , No mode ***]\n");
66493 + change_sensor_wb(client, (int) arg);
66497 + panic("4xa_sensor.c: Unexpected Sensor Command\n");
66504 +static struct i2c_driver sensor_driver = {
66506 + .name = "s5k4xa",
66508 + .id = I2C_DRIVERID_S5K_4XA,
66509 + .attach_adapter = sensor_attach_adapter,
66510 + .detach_client = sensor_detach,
66511 + .command = sensor_command
66514 +static __init int camif_sensor_init(void)
66516 + return i2c_add_driver(&sensor_driver);
66520 +static __init void camif_sensor_exit(void)
66522 + i2c_del_driver(&sensor_driver);
66525 +module_init(camif_sensor_init)
66526 +module_exit(camif_sensor_exit)
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
66535 +#ifndef _SAMSUNG_SXGA_H_
66536 +#define _SAMSUNG_SXGA_H_
66538 +/******************************************************************************
66539 + * Display resolution standards
66541 + * QCIF: 176 x 144
66543 + * QVGA: 320 x 240
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 + *****************************************************************************/
66557 +//#include "../bits.h"
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
66567 +#define CHIP_DELAY 0xFF
66569 +typedef struct samsung_t{
66570 + unsigned char subaddr;
66571 + unsigned char value;
66572 + unsigned char page;
66575 +#ifdef CONFIG_CPU_S3C24A0A
66576 +#define TRY_HIGH_CLOCK 1
66579 +/***************************************************
66580 + * name: S5K3AAEX EVT2 setfile
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,
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
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
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 + ****************************************************/
66613 +#if defined(CONFIG_VIDEO_SAMSUNG_S5K4BA)
66615 +/* For SVGA (800 x 600) */
66616 +#if 1 /* from han */
66617 +s5k4xa_t s5k4ba_reg[] =
66620 + {0x66,0x01}, /* Watch Dog Time On */
66622 + {0x00,0xAA}, /* For EDS Check */
66623 + {0x21,0x03}, /* peter */
66625 + {0x04,0x01}, /* ARM Clock Divider */
66628 + {0x30,0x90}, /* Analog offset */
66629 + {0x37,0x0d}, /* Global Gain */
66630 + {0x2d,0x48}, /* Double Shutter */
66631 + {0x60,0x00}, /* Blank_Adrs */
66633 + {0x45,0x1e}, /* 0e - CDS Timing for Average Sub_Sampling */
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 */
66641 + {0x59,0x00}, /* LineADLC offset */
66642 + {0x5b,0x08}, /* R_Ref_Ctrl */
66643 + {0x44,0x63}, /* CLP_EN */
66644 + {0x4A,0x10}, /* Clamp Control */
66649 + * Table Set for Sub-Sampling
66653 + {0x2c,0x00}, /* crcb_sel for Sub-Sampling Table */
66654 + {0x05,0x46}, /* Output Image Size Set for Capture */
66664 + {0xc5,0x26}, /* Output Image Size Set for Preview */
66669 + {0xec,0x06}, /* CrCb sel = YCBYCR(0x06) by jsgood */
66690 + /* Jeongyun added still shot cbcr_sel */
66704 + {0x73,0x21}, /* Frame AE Enable peter */
66705 + {0x20,0x02}, /* Change AWB Mode */
66708 + {0x6c,0xb0}, /* AE target */
66712 + {0x16,0x5a}, /* for Prevating AE Hunting */
66715 + {0x78,0x6a}, /* AGC Max */
66717 + {0x16,0x60}, /* Frame AE Start */
66720 + {0x57,0x18}, /* Stable_Frame_AE */
66721 + {0x2C,0x30}, /* For Forbidden Area */
66722 + {0x2E,0x00}, /* For Forbidden Area */
66724 + {0x01,0x00}, /* Stepless_Off */
66727 + {0x11,0x02}, /* AWB G Gain offset */
66730 + {0x3e,0x0a}, /* AWB Cut R max */
66733 + {0xc8,0xd0}, /* AWB Y Max */
66735 + {0x3e,0x20}, /* 30 - AWB Y_min */
66736 + {0x3d,0x10}, /* AWB Y_min Low */
66738 + {0x8c,0x04}, /* AWB Min Y Weight AWB */
66739 + {0x8d,0x16}, /* AWB Max Y Weight */
66742 + {0x32,0x04}, /* AWB moving average 8 frame */
66743 + {0x81,0x10}, /* AWB G gain suppress Disable */
66746 + {0x29,0x04}, /* Y level H */
66747 + {0x2a,0x00}, /* Y level L */
66748 + {0x2b,0x03}, /* color level H */
66749 + {0x2c,0xc8}, /* color level L */
66752 + {0x37,0x00}, /* Flicker Add for 32 MHz */
66754 + {0x72,0xa0}, /* Flicker for 32 MHz */
66755 + {0x74,0x08}, /* flicker 60 Hz Fix */
66758 + {0x02,0x02}, /* Flicker Dgain Mode */
66761 + //{0x23,0x40}, /* Mirror Option */
66762 + {0x62,0x0a}, /* Mirror Option */
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 */
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 */
66780 + {0xfc,0x01}, /* color matrix */
66803 + * EDGE ENHANCEMENT
66807 + {0x89,0x03}, /* Edge Suppress On */
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 */
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 */
66827 + {0x49,0x31}, /* CSSEL EGSEL CS_DLY */
66829 + {0x40,0x41}, /* Y delay */
66837 + {0x6F,0x0A}, /* R */
66866 + {0x87,0x08}, /* G */
66895 + {0x9F,0x05}, /* B */
66929 + {0x48,0x34}, /* 2000K */
66938 + {0x50,0x34}, /* 3000K */
66947 + {0x58,0x34}, /* 5100K */
66957 + * UPPRE0x0x FUNCTION
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 */
66994 + * GR/GB CORRECTION
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 */
67014 + {0x4C,0x01}, /* NR Enable */
67015 + {0x49,0x15}, /* Sig_Th Mult */
67016 + {0x4B,0x0A}, /* Pre_Th Mult */
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 */
67034 + * 1D-Y/C-SIGMA-LPF
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 */
67066 + {0x08,0x58}, /* Color suppress AGC MIN */
67067 + {0x09,0x03}, /* Color suppress MIN H */
67068 + {0x0a,0x80}, /* Color suppress MIN L */
67075 + //Shading file for 3BAFX
67076 + //s90000// shading off
67077 + // DSP9_SH_WIDTH_H
67080 + // DSP9_SH_HEIGHT_H
67098 + // DSP9_SH_Del_eH_R
67107 + // DSP9_SH_Del_eH_G
67116 + // DSP9_SH_Del_eH_B
67125 + // DSP9_SH_VAL_R0H
67142 + // DSP9_SH_VAL_G0H
67159 + // DSP9_SH_VAL_B0H
67176 + // DSP9_SH_M_R2_R1H
67198 + // DSP9_SH_M_R2_G1H
67220 + // DSP9_SH_M_R2_B1H
67242 + // DSP9_SH_SUB_RR0H
67257 + // DSP9_SH_SUB_RG0H
67272 + // DSP9_SH_SUB_RB0H
67288 + {0x00,0x02}, // Shading on
67290 + //==========================================================
67292 + //==========================================================
67374 + // x-shading temp. correlation factor
67376 + {0xda,0x00}, // t0(3100K)
67378 + {0xdc,0x01}, // tc(5100K)
67379 + {0xdd,0x30}, // default eeh
67382 + {0x81,0x10}, // xshading tem
67385 + {0x80,0x01}, // X-Shading On
67387 + //==========================================================
67388 + // AE WINDOW WEIGHT
67389 + //==========================================================
67391 + {0x03,0x4b}, // AE Suppress On
67394 + {0x01,0x35}, // UXGA AE Window
67398 + {0x31,0x2a}, // Subsampling AE Window
67404 + {0x3D,0x10}, // 1c
67433 + //==========================================================
67435 + //==========================================================
67436 + //=================================
67438 + //=================================
67439 + {0xfc,0x22}, // White Point (For Hue Control & MWB)
67440 + {0x01,0xD0}, // D65
67442 + {0x05,0xC0}, // 5000K
67444 + {0x09,0xA7}, // CWF
67446 + {0x0d,0x98}, // 3000K
67448 + {0x11,0x85}, // A
67451 + {0x15,0x80}, // 2000K
67455 + //=================================
67457 + //=================================
67497 + //=================================
67498 + // Pixel Filter Setting
67499 + //=================================
67530 + //=================================
67531 + // Polygon AWB Region Tune
67532 + //=================================
67534 + {0x18,0x00}, // 1
67537 + {0x1b,0x00}, // 2
67540 + {0x1e,0x00}, // 3
67543 + {0x21,0x00}, // 4
67546 + {0x24,0x00}, // 5
67549 + {0x27,0x00}, // 6
67552 + {0x2A,0x00}, // 7
67555 + {0x2D,0x00}, // 8
67558 + {0x30,0x00}, // 9
67561 + {0x33,0x00}, // 10
67564 + {0x36,0x00}, // 11
67567 + {0x39,0x00}, // 12
67570 + {0x3C,0x00}, // 13
67573 + {0x3F,0x00}, // 14
67577 + //=================================
67578 + // Moving Equation Weight
67579 + //=================================
67583 + //=================================
67585 + //=================================
67587 + {0xb1,0x00}, // {0xunny
67592 + {0xb5,0x00}, // Cloudy
67597 + {0xd7,0x00}, // Shade
67602 + //=================================
67604 + //=================================
67607 + {0x7A,0x02}, // Global AWB gain off{0xet
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
67623 + {0xde,0x00}, // LARGE OBJECT BUG FIX
67624 + {0xf0,0x6a}, // RB Ratio
67625 + //=================================
67626 + // Green Stablity Enhance
67627 + //=================================
67638 + //==========================================================
67639 + // Special Effect
67640 + //==========================================================
67641 + {0xfc,0x07}, // Special Effect
67650 + {0x73,0x21}, // Frame AE Enable, peter
67655 + {0xFF,0xFF} // REGISTER END
67658 +s5k4xa_t s5k4ba_reg[] =
67660 +//==========================================================
67661 +// CAMERA INITIAL (Analog & Clock Setting)
67662 +//==========================================================
67664 + {0x66, 0x01},// WDT
67666 + {0x00, 0xaa},// For EDS Check
67667 + {0x21, 0x03},// peter0223 added
67670 + {0x04, 0x01},// ARM Clock Divider
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)
67678 + {0x57, 0x80},// // LineADLC Roffset
67679 + {0x58, 0x80},//89 //90 // LineADLC Goffset
67680 + {0x59, 0x80},//90 // LineADLC offset don't care
67682 + {0x44, 0x64},//clamp en[6]=1 on
67683 + {0x4a, 0x30},//clamp level 0011h [7]~[4]
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
67690 + {0x66, 0x41},// 1st comp current 2uA
67691 + {0x43, 0xef},// ec_comp
67692 + {0x62, 0x60},// LD control , CFPN_EN off
67694 +//==========================================================
67695 +// Table Set for Sub-Sampling
67696 +//==========================================================
67700 + {0x2e, 0x03},//DHL
67701 + {0x05, 0x46},// Output Image Size Set for Capture
67707 + {0xc5, 0x26},// Output Image Size Set for Preview
67711 + //{0xee, 0x00},//DHL
67714 + {0xc1, 0x60},//frame_H
67716 + {0xc3, 0x8d},//frame_V
67731 +//==========================================================
67733 +//==========================================================
67738 + {0x73, 0x11},//21 Frmae AE Enable, peter0223
67739 + {0x20, 0x02},// Change AWB Mode
67742 + {0x78, 0x6a},// AGC Max
67745 + {0x6c, 0xa0},// AE target
67749 + {0x16, 0x5a},// AGC frame AE start _for Prevating AE Hunting
67750 + {0x57, 0x18},// Stable_Frame_AE
67753 + {0x83, 0x06},//low condition shutter off // Double shutter off
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
67760 + {0x25, 0x00},// CINTR Min
67761 + {0x2a, 0x01},// forbidden
67762 + {0x2b, 0x02},// For Forbidden Area
67764 + {0x2d, 0x00},// For Forbidden Area
67766 + {0x2f, 0x05},// forbidden
67767 + {0x14, 0x78},//70
67768 + {0x01, 0x00},// Stepless_Off
67771 + {0x29, 0x04},// Y level
67773 + {0x2b, 0x03},// C level
67774 + {0x2c, 0x80},//60
67777 + {0x37, 0x00},// Flicker
67780 + {0x72, 0xa0},// Flicker for 32MHz
67781 + {0x74, 0x08},// flicker 60Hz fix
67783 + {0x02, 0x12},//02 Flicker Dgain Mode
67785 + {0x62, 0x02},// Hue Control Enable
67788 + //{0x0c, 0x02},// Full YC Enable
67789 + {0x0C, 0x03},//Donghoon
67792 +//==========================================================
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
67815 +//==========================================================
67816 +// EDGE ENHANCEMENT
67817 +//==========================================================
67850 + {0x89, 0x00},// Edge Suppress On
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
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
67870 + {0x49, 0x31},// CSSEL EGSEL CS_DLY
67872 + {0x40, 0x41},// Y delay
67874 + // New Wide Luma Edge
68048 + {0x48, 0x40}, /* 2000K */
68057 + {0x50, 0x40}, /* 3000K */
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 */
68076 + * SUPPRESS FUNCTION
68113 + * GR/GB CORRECTION
68152 + * 1D-Y/C-SIGMA-LPF
68404 + {0x00, 0x02}, /* shading on */
68502 + * AE WINDOW WEIGHT
68641 + * Pixel Filter Setting
68675 + * Polygon AWB Region Tune
68678 + /* AWB3 - Polygon Region */
68724 + * Moving Equation Weight
68779 + * Green Stablity Enhance
68822 + {0x02, 0x02},//Donghoon
68826 +#error No samsung CIS moudule !
68830 +/* For VGA ( 640 x 480) on 4BA module */
68832 +s5k4xa_t s5k4ba_reg_vga[] =
68837 +/* For SVGA ( 800 x 600) on 4BA module */
68839 +s5k4xa_t s5k4ba_reg_svga[] =
68851 + {0x03,0x4b}, /* AE/AWB On */
68852 + {0x7e,0xf4}, /* Suppress On */
68853 + {0x89,0x03}, /* Edge Suppress On */
68856 + {0x02,0x0e}, /* sensor BPRoff */
68859 + {0x16,0x60}, /* Frame AE Start */
68862 + {0x30,0x90}, /* Analog offset */
68863 + {0x37,0x0d}, /* Global Gain */
68864 + {0x60,0x00}, /* Blank_Adrs */
68865 + {0x45,0x0e}, /* CDS Timing for Average Sub_Sampling */
68869 + {0x9F,0x05}, /* B */
68882 + {0x34,0x20}, /* APTCLP */
68883 + {0x35,0x08}, /* 9 - APTSC */
68885 + {0xfc,0x00}, /* flash 0821 */
68886 + {0x32,0x04}, /* AWB moving average 8 frame */
68889 + {0x01,0x01}, /* Pclk inversion */
68892 + {0x02,0x09}, /* 800 x 600 */
68895 + {0xFF,0xFF} /* REGISTER END */
68898 +/* For SXGA (1280 x 1024 = 1.3M) on 4BA module */
68900 +s5k4xa_t s5k4ba_reg_sxga[] =
68906 +/* For UXGA (1600 x 1200 = 2M) on 4BA module */
68908 +s5k4xa_t s5k4ba_reg_uxga[] =
68914 +/* For SQVGA on 4BA module */
68916 +s5k4xa_t s5k4ba_reg_qsvga[] =
68918 + /* Pclk inversion */
68922 + /* To setting CbCr selection on Table 14h */
68926 + /* To load table_11 H4V4 */
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)
68938 +#define S5K4BA_RISC_REGS 0xEB
68939 +#define S5K4BA_ISP_REGS 0xFB /* S5C7323X */
68940 +#define S5K4BA_CIS_REGS 0x2F /* S5K437LA03 */
68943 +#define S5K4BA_REGS (0x1000)
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
68952 +# Samsung CIS camera module
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
68959 +#ifndef __VIDEODEV2_S3C_H_
68960 +#define __VIDEODEV2_S3C_H_
68962 +#include <linux/videodev2.h>
68964 +#define V4L2_INPUT_TYPE_MSDMA 3
68965 +#define V4L2_INPUT_TYPE_INTERLACE 4
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)
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)
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)
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)
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 */
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 */
69021 +enum v4l2_msdma_input {
69022 + V4L2_MSDMA_CODEC = 1,
69023 + V4L2_MSDMA_PREVIEW = 2,
69026 +struct v4l2_msdma_format
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;
69034 +struct v4l2_interlace_format
69036 + __u32 width; /* INTERLACE INPUT : Source X size */
69037 + __u32 height; /* INTERLACE INPUT : Source Y size */
69040 +struct s3c_video_decoder_init {
69041 + unsigned char len;
69042 + const unsigned char *data;
69045 +struct s3c_video_decoder_capability { /* this name is too long */
69047 + int inputs; /* number of inputs */
69048 + int outputs; /* number of outputs */
69051 +static struct v4l2_input fimc_inputs[] = {
69054 + .name = "S3C FIMC External Camera Input",
69055 + .type = V4L2_INPUT_TYPE_CAMERA,
69058 + .std = V4L2_STD_PAL_BG | V4L2_STD_NTSC_M,
69063 + .name = "Memory Input (MSDMA)",
69064 + .type = V4L2_INPUT_TYPE_MSDMA,
69067 + .std = V4L2_STD_PAL_BG | V4L2_STD_NTSC_M,
69072 +static struct v4l2_output fimc_outputs[] = {
69075 + .name = "Pingpong Memory Output",
69083 + .name = "LCD FIFO Output",
69091 +const struct v4l2_fmtdesc fimc_codec_formats[] = {
69094 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
69095 + .flags = FORMAT_FLAGS_PACKED,
69096 + .description = "16 bpp RGB, le",
69097 + .pixelformat = V4L2_PIX_FMT_RGB565,
69101 + .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
69102 + .flags = FORMAT_FLAGS_PACKED,
69103 + .description = "32 bpp RGB, le",
69104 + .pixelformat = V4L2_PIX_FMT_BGR32,
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,
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,
69123 +const struct v4l2_fmtdesc fimc_preview_formats[] = {
69126 + .type = V4L2_BUF_TYPE_VIDEO_OVERLAY,
69127 + .flags = FORMAT_FLAGS_PACKED,
69128 + .description = "16 bpp RGB, le",
69129 + .pixelformat = V4L2_PIX_FMT_RGB565,
69133 + .type = V4L2_BUF_TYPE_VIDEO_OVERLAY,
69134 + .flags = FORMAT_FLAGS_PACKED,
69135 + .description = "24 bpp RGB, le",
69136 + .pixelformat = V4L2_PIX_FMT_RGB24,
69140 + .type = V4L2_BUF_TYPE_VIDEO_OVERLAY,
69141 + .flags = FORMAT_FLAGS_PACKED,
69142 + .description = "32 bpp RGB, le",
69143 + .pixelformat = V4L2_PIX_FMT_BGR32,
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,
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,
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)
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
69173 +/* Smedia Glamo 336x/337x driver
69175 + * (C) 2007 by Openmoko, Inc.
69176 + * Author: Harald Welte <laforge@openmoko.org>
69177 + * All rights reserved.
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.
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.
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
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>
69216 +#include <asm/io.h>
69217 +#include <asm/uaccess.h>
69218 +#include <asm/div64.h>
69220 +//#include <mach/regs-irq.h>
69223 +#include <linux/pm.h>
69226 +#include "glamo-regs.h"
69227 +#include "glamo-core.h"
69229 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
69231 +#define GLAMO_MEM_REFRESH_COUNT 0x100
69235 + * Glamo internal settings
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.
69242 + * you can override the faster default on kernel commandline using
69244 + * glamo3362.slow_memory=1
69249 +static int slow_memory = 0;
69250 +module_param(slow_memory, int, 0644);
69252 +struct reg_range {
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 }, */
69277 +static struct glamo_core *glamo_handle;
69279 +static inline void __reg_write(struct glamo_core *glamo,
69280 + u_int16_t reg, u_int16_t val)
69282 + writew(val, glamo->base + reg);
69285 +static inline u_int16_t __reg_read(struct glamo_core *glamo,
69288 + return readw(glamo->base + reg);
69291 +static void __reg_set_bit_mask(struct glamo_core *glamo,
69292 + u_int16_t reg, u_int16_t mask,
69299 + tmp = __reg_read(glamo, reg);
69302 + __reg_write(glamo, reg, tmp);
69305 +static void reg_set_bit_mask(struct glamo_core *glamo,
69306 + u_int16_t reg, u_int16_t mask,
69309 + spin_lock(&glamo->lock);
69310 + __reg_set_bit_mask(glamo, reg, mask, val);
69311 + spin_unlock(&glamo->lock);
69314 +static inline void __reg_set_bit(struct glamo_core *glamo,
69315 + u_int16_t reg, u_int16_t bit)
69317 + __reg_set_bit_mask(glamo, reg, bit, 0xffff);
69320 +static inline void __reg_clear_bit(struct glamo_core *glamo,
69321 + u_int16_t reg, u_int16_t bit)
69323 + __reg_set_bit_mask(glamo, reg, bit, 0);
69326 +static inline void glamo_vmem_write(struct glamo_core *glamo, u_int32_t addr,
69327 + u_int16_t *src, int len)
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);
69336 +static inline void glamo_vmem_read(struct glamo_core *glamo, u_int16_t *buf,
69337 + u_int32_t addr, int len)
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);
69347 +/***********************************************************************
69348 + * resources of sibling devices
69349 + ***********************************************************************/
69352 +static struct resource glamo_core_resources[] = {
69354 + .start = GLAMO_REGOFS_GENERIC,
69355 + .end = GLAMO_REGOFS_GENERIC + 0x400,
69356 + .flags = IORESOURCE_MEM,
69360 + .flags = IORESOURCE_IRQ,
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),
69371 +static struct resource glamo_jpeg_resources[] = {
69373 + .start = GLAMO_REGOFS_JPEG,
69374 + .end = GLAMO_REGOFS_MPEG - 1,
69375 + .flags = IORESOURCE_MEM,
69377 + .start = IRQ_GLAMO_JPEG,
69378 + .end = IRQ_GLAMO_JPEG,
69379 + .flags = IORESOURCE_IRQ,
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),
69389 +static struct resource glamo_mpeg_resources[] = {
69391 + .start = GLAMO_REGOFS_MPEG,
69392 + .end = GLAMO_REGOFS_LCD - 1,
69393 + .flags = IORESOURCE_MEM,
69395 + .start = IRQ_GLAMO_MPEG,
69396 + .end = IRQ_GLAMO_MPEG,
69397 + .flags = IORESOURCE_IRQ,
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),
69407 +static struct resource glamo_2d_resources[] = {
69409 + .start = GLAMO_REGOFS_2D,
69410 + .end = GLAMO_REGOFS_3D - 1,
69411 + .flags = IORESOURCE_MEM,
69413 + .start = IRQ_GLAMO_2D,
69414 + .end = IRQ_GLAMO_2D,
69415 + .flags = IORESOURCE_IRQ,
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),
69425 +static struct resource glamo_3d_resources[] = {
69427 + .start = GLAMO_REGOFS_3D,
69428 + .end = GLAMO_REGOFS_END - 1,
69429 + .flags = IORESOURCE_MEM,
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),
69439 +static struct platform_device glamo_spigpio_dev = {
69440 + .name = "glamo-spi-gpio",
69443 +static struct resource glamo_fb_resources[] = {
69444 + /* FIXME: those need to be incremented by parent base */
69446 + .name = "glamo-fb-regs",
69447 + .start = GLAMO_REGOFS_LCD,
69448 + .end = GLAMO_REGOFS_MMC - 1,
69449 + .flags = IORESOURCE_MEM,
69451 + .name = "glamo-fb-mem",
69452 + .start = GLAMO_OFFSET_FB,
69453 + .end = GLAMO_OFFSET_FB + GLAMO_FB_SIZE - 1,
69454 + .flags = IORESOURCE_MEM,
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),
69464 +static struct resource glamo_mmc_resources[] = {
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
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
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 |
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 */
69501 +EXPORT_SYMBOL_GPL(glamo_mci_def_pdata);
69505 +static void mangle_mem_resources(struct resource *res, int num_res,
69506 + struct resource *parent)
69510 + for (i = 0; i < num_res; i++) {
69511 + if (res[i].flags != IORESOURCE_MEM)
69513 + res[i].start += parent->start;
69514 + res[i].end += parent->start;
69515 + res[i].parent = parent;
69519 +/***********************************************************************
69520 + * IRQ demultiplexer
69521 + ***********************************************************************/
69522 +#define irq2glamo(x) (x - IRQ_GLAMO(0))
69524 +static void glamo_ack_irq(unsigned int irq)
69526 + /* clear interrupt source */
69527 + __reg_write(glamo_handle, GLAMO_REG_IRQ_CLEAR,
69528 + 1 << irq2glamo(irq));
69531 +static void glamo_mask_irq(unsigned int irq)
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);
69541 +static void glamo_unmask_irq(unsigned int irq)
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);
69551 +static struct irq_chip glamo_irq_chip = {
69552 + .ack = glamo_ack_irq,
69553 + .mask = glamo_mask_irq,
69554 + .unmask = glamo_unmask_irq,
69557 +static void glamo_irq_demux_handler(unsigned int irq, struct irq_desc *desc)
69559 + const unsigned int cpu = smp_processor_id();
69561 + desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
69563 + if (unlikely(desc->status & IRQ_INPROGRESS)) {
69564 + desc->status |= (IRQ_PENDING | IRQ_MASKED);
69565 + desc->chip->mask(irq);
69566 + desc->chip->ack(irq);
69570 + kstat_cpu(cpu).irqs[irq]++;
69571 + desc->chip->ack(irq);
69572 + desc->status |= IRQ_INPROGRESS;
69575 + u_int16_t irqstatus;
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;
69586 + desc->status &= ~IRQ_PENDING;
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));
69595 + } while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
69597 + desc->status &= ~IRQ_INPROGRESS;
69601 +static ssize_t regs_write(struct device *dev, struct device_attribute *attr,
69602 + const char *buf, size_t count)
69604 + unsigned long reg = simple_strtoul(buf, NULL, 10);
69605 + struct glamo_core *glamo = dev_get_drvdata(dev);
69607 + while (*buf && (*buf != ' '))
69611 + while (*buf && (*buf == ' '))
69616 + printk(KERN_INFO"reg 0x%02lX <-- 0x%04lX\n",
69617 + reg, simple_strtoul(buf, NULL, 10));
69619 + __reg_write(glamo, reg, simple_strtoul(buf, NULL, 10));
69624 +static ssize_t regs_read(struct device *dev, struct device_attribute *attr,
69627 + struct glamo_core *glamo = dev_get_drvdata(dev);
69628 + int n, n1 = 0, r;
69629 + char * end = buf;
69631 + spin_lock(&glamo->lock);
69633 + for (r = 0; r < ARRAY_SIZE(reg_range); r++) {
69634 + if (!reg_range[r].dump)
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));
69644 + end += sprintf(end, "\n");
69646 + printk("%s", buf);
69650 + spin_unlock(&glamo->lock);
69652 + return end - buf;
69655 +static DEVICE_ATTR(regs, 0644, regs_read, regs_write);
69656 +static struct attribute *glamo_sysfs_entries[] = {
69657 + &dev_attr_regs.attr,
69660 +static struct attribute_group glamo_attr_group = {
69662 + .attrs = glamo_sysfs_entries,
69667 +/***********************************************************************
69668 + * 'engine' support
69669 + ***********************************************************************/
69671 +int __glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine)
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);
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);
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);
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);
69721 + /* FIXME: Implementation */
69726 + glamo->engine_enabled_bitfield |= 1 << engine;
69731 +int glamo_engine_enable(struct glamo_core *glamo, enum glamo_engine engine)
69735 + spin_lock(&glamo->lock);
69737 + ret = __glamo_engine_enable(glamo, engine);
69739 + spin_unlock(&glamo->lock);
69743 +EXPORT_SYMBOL_GPL(glamo_engine_enable);
69745 +int __glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine)
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);
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);
69779 + glamo->engine_enabled_bitfield &= ~(1 << engine);
69783 +int glamo_engine_disable(struct glamo_core *glamo, enum glamo_engine engine)
69787 + spin_lock(&glamo->lock);
69789 + ret = __glamo_engine_disable(glamo, engine);
69791 + spin_unlock(&glamo->lock);
69795 +EXPORT_SYMBOL_GPL(glamo_engine_disable);
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,
69808 +void glamo_engine_clkreg_set(struct glamo_core *glamo,
69809 + enum glamo_engine engine,
69810 + u_int16_t mask, u_int16_t val)
69812 + reg_set_bit_mask(glamo, engine_clock_regs[engine], mask, val);
69814 +EXPORT_SYMBOL_GPL(glamo_engine_clkreg_set);
69816 +u_int16_t glamo_engine_clkreg_get(struct glamo_core *glamo,
69817 + enum glamo_engine engine)
69821 + spin_lock(&glamo->lock);
69822 + val = __reg_read(glamo, engine_clock_regs[engine]);
69823 + spin_unlock(&glamo->lock);
69827 +EXPORT_SYMBOL_GPL(glamo_engine_clkreg_get);
69829 +struct glamo_script reset_regs[] = {
69830 + [GLAMO_ENGINE_LCD] = {
69831 + GLAMO_REG_CLOCK_LCD, GLAMO_CLOCK_LCD_RESET
69834 + [GLAMO_ENGINE_HOST] = {
69835 + GLAMO_REG_CLOCK_HOST, GLAMO_CLOCK_HOST_RESET
69837 + [GLAMO_ENGINE_MEM] = {
69838 + GLAMO_REG_CLOCK_MEM, GLAMO_CLOCK_MEM_RESET
69841 + [GLAMO_ENGINE_MMC] = {
69842 + GLAMO_REG_CLOCK_MMC, GLAMO_CLOCK_MMC_RESET
69844 + [GLAMO_ENGINE_2D] = {
69845 + GLAMO_REG_CLOCK_2D, GLAMO_CLOCK_2D_RESET
69847 + [GLAMO_ENGINE_JPEG] = {
69848 + GLAMO_REG_CLOCK_JPEG, GLAMO_CLOCK_JPEG_RESET
69852 +void glamo_engine_reset(struct glamo_core *glamo, enum glamo_engine engine)
69854 + struct glamo_script *rst;
69856 + if (engine >= ARRAY_SIZE(reset_regs)) {
69857 + dev_warn(&glamo->pdev->dev, "unknown engine %u ", engine);
69861 + rst = &reset_regs[engine];
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);
69868 +EXPORT_SYMBOL_GPL(glamo_engine_reset);
69870 +void glamo_lcm_reset(int level)
69872 + if (!glamo_handle)
69875 + glamo_gpio_setpin(glamo_handle, GLAMO_GPIO4, level);
69876 + glamo_gpio_cfgpin(glamo_handle, GLAMO_GPIO4_OUTPUT);
69879 +EXPORT_SYMBOL_GPL(glamo_lcm_reset);
69886 +static int glamo_pll_rate(struct glamo_core *glamo,
69887 + enum glamo_pll pll)
69890 + unsigned int div = 512;
69891 + /* FIXME: move osci into platform_data */
69892 + unsigned int osci = 32768;
69894 + if (osci == 32768)
69899 + reg = __reg_read(glamo, GLAMO_REG_PLL_GEN1);
69902 + reg = __reg_read(glamo, GLAMO_REG_PLL_GEN3);
69907 + return (osci/div)*reg;
69910 +int glamo_engine_reclock(struct glamo_core *glamo,
69911 + enum glamo_engine engine,
69915 + u_int16_t reg, mask, val = 0;
69920 + switch (engine) {
69921 + case GLAMO_ENGINE_LCD:
69922 + pll = GLAMO_PLL1;
69923 + reg = GLAMO_REG_CLOCK_GEN7;
69927 + dev_warn(&glamo->pdev->dev,
69928 + "reclock of engine 0x%x not supported\n", engine);
69933 + pll = glamo_pll_rate(glamo, pll);
69934 + khz = 1000000000UL / ps;
69937 + val = (pll / khz) / 1000;
69939 + dev_dbg(&glamo->pdev->dev,
69940 + "PLL %d, kHZ %d, div %d\n", pll, khz, val);
69944 + reg_set_bit_mask(glamo, reg, mask, val);
69945 + mdelay(5); /* wait some time to stabilize */
69952 +EXPORT_SYMBOL_GPL(glamo_engine_reclock);
69954 +/***********************************************************************
69956 + ***********************************************************************/
69958 +int glamo_run_script(struct glamo_core *glamo, struct glamo_script *script,
69959 + int len, int may_sleep)
69963 + for (i = 0; i < len; i++) {
69964 + struct glamo_script *line = &script[i];
69966 + switch (line->reg) {
69971 + msleep(line->val);
69973 + mdelay(line->val * 4);
69976 + /* spin until PLLs lock */
69977 + while ((__reg_read(glamo, GLAMO_REG_PLL_GEN5) & 3) != 3)
69982 + * couple of people reported artefacts with 2.6.28 changes, this
69983 + * allows reversion to 2.6.24 settings
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);
69992 + case 2: /* 2 waits on Async BB R & W, Use PLL 1 for mem bus */
69993 + __reg_write(glamo, script[i].reg, 0xea0);
69995 + case 3: /* 1 waits on Async BB R & W, Use PLL 1 for mem bus */
69996 + __reg_write(glamo, script[i].reg, 0xe50);
69998 + case 4: /* 0 waits on Async BB R & W, Use PLL 1 for mem bus */
69999 + __reg_write(glamo, script[i].reg, 0xe00);
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);
70006 + case 6: /* 2 waits on Async BB R & W, Use PLL 2 for mem bus */
70007 + __reg_write(glamo, script[i].reg, 0xea3);
70009 + case 7: /* 1 waits on Async BB R & W, Use PLL 2 for mem bus */
70010 + __reg_write(glamo, script[i].reg, 0xe53);
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);
70020 + __reg_write(glamo, script[i].reg, script[i].val);
70027 +EXPORT_SYMBOL(glamo_run_script);
70029 +static struct glamo_script glamo_init_script[] = {
70030 + { GLAMO_REG_CLOCK_HOST, 0x1000 },
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*/ },
70048 + { GLAMO_REG_CLOCK_HOST, 0x0000 },
70049 + { GLAMO_REG_CLOCK_MEMORY, 0x0000 },
70050 + { GLAMO_REG_CLOCK_LCD, 0x0000 },
70051 + { GLAMO_REG_CLOCK_MMC, 0x0000 },
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 },
70065 + { GLAMO_REG_PLL_GEN1, 0x05db }, /* 48MHz */
70066 + { GLAMO_REG_PLL_GEN3, 0x0aba }, /* 90MHz */
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
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 },
70078 + * b7..b4 = 0 = no wait states on read or write
70079 + * b0 = 1 select PLL2 for Host interface, b1 = enable it
70081 + { 0x200, 0x0e03 /* this is replaced by script parser */ },
70082 + { 0x202, 0x07ff },
70083 + { 0x212, 0x0000 },
70084 + { 0x214, 0x4000 },
70085 + { 0x216, 0xf00e },
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 */
70092 + { GLAMO_REGOFS_HOSTBUS + 2, 0xffff }, /* enable on MMIO*/
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 },
70109 + { GLAMO_REG_MEM_DRAM1, 0xc100 },
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 },
70121 +static struct glamo_script glamo_resume_script[] = {
70123 + { GLAMO_REG_PLL_GEN1, 0x05db }, /* 48MHz */
70124 + { GLAMO_REG_PLL_GEN3, 0x0aba }, /* 90MHz */
70125 + { GLAMO_REG_DFT_GEN6, 1 },
70128 + { 0x200, 0x0e03 },
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
70134 + { GLAMO_REG_IRQ_ENABLE, 0x01ff },
70135 + { GLAMO_REG_CLOCK_HOST, 0x0018 },
70136 + { GLAMO_REG_CLOCK_GEN5_1, 0x18b1 },
70138 + { GLAMO_REG_MEM_DRAM1, 0x0000 },
70140 + { GLAMO_REG_MEM_DRAM1, 0xc100 },
70142 + { GLAMO_REG_MEM_DRAM1, 0xe100 },
70143 + { GLAMO_REG_MEM_DRAM2, 0x01d6 },
70144 + { GLAMO_REG_CLOCK_MEMORY, 0x000b },
70148 +enum glamo_power {
70150 + GLAMO_POWER_SUSPEND,
70153 +static void glamo_power(struct glamo_core *glamo,
70154 + enum glamo_power new_state)
70157 + unsigned long flags;
70159 + spin_lock_irqsave(&glamo->lock, flags);
70161 + dev_info(&glamo->pdev->dev, "***** glamo_power -> %d\n", new_state);
70165 +static const REG_VALUE_MASK_TYPE reg_powerOn[] =
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 }
70174 +static const REG_VALUE_MASK_TYPE reg_powerStandby[] =
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) }
70182 +static const REG_VALUE_MASK_TYPE reg_powerSuspend[] =
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) }
70191 + switch (new_state) {
70192 + case GLAMO_POWER_ON:
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.
70202 + (glamo->pdata->glamo_external_reset)(0);
70204 + (glamo->pdata->glamo_external_reset)(1);
70207 + glamo_run_script(glamo, glamo_init_script,
70208 + ARRAY_SIZE(glamo_init_script), 0);
70212 + case GLAMO_POWER_SUSPEND:
70214 + /* nuke interrupts */
70215 + __reg_write(glamo, GLAMO_REG_IRQ_ENABLE, 0x200);
70217 + /* stash a copy of which engines were running */
70218 + glamo->engine_enabled_bitfield_suspend =
70219 + glamo->engine_enabled_bitfield;
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);
70226 + /* enable self-refresh */
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);
70240 + /* force RAM into deep powerdown */
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 */
70249 + /* disable clocks to memory */
70250 + __reg_write(glamo, GLAMO_REG_CLOCK_MEMORY, 0);
70252 + /* all dividers from OSCI */
70253 + __reg_set_bit_mask(glamo, GLAMO_REG_CLOCK_GEN5_1, 0x400, 0x400);
70255 + /* PLL2 into bypass */
70256 + __reg_set_bit_mask(glamo, GLAMO_REG_PLL_GEN3, 1 << 12, 1 << 12);
70258 + __reg_write(glamo, 0x200, 0x0e00);
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);
70268 + spin_unlock_irqrestore(&glamo->lock, flags);
70272 +#define MEMDETECT_RETRY 6
70273 +static unsigned int detect_memsize(struct glamo_core *glamo)
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
70284 + for (i = 0; i < MEMDETECT_RETRY; i++) {
70285 + switch (glamo->type) {
70287 + __reg_write(glamo, GLAMO_REG_MEM_TYPE, 0x0072);
70288 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xc100);
70291 + switch (glamo->revision) {
70292 + case GLAMO_CORE_REV_A0:
70294 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
70297 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
70300 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0x0000);
70302 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xc100);
70306 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
70309 + __reg_write(glamo, GLAMO_REG_MEM_TYPE,
70312 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0x0000);
70314 + __reg_write(glamo, GLAMO_REG_MEM_DRAM1, 0xe100);
70325 + /* FIXME: finish implementation */
70326 + for (j = 0; j < 8; j++) {
70335 +/* Find out if we can support this version of the Glamo chip */
70336 +static int glamo_supported(struct glamo_core *glamo)
70338 + u_int16_t dev_id, rev_id; /*, memsize; */
70340 + dev_id = __reg_read(glamo, GLAMO_REG_DEVICE_ID);
70341 + rev_id = __reg_read(glamo, GLAMO_REG_REVISION_ID);
70343 + switch (dev_id) {
70345 + switch (rev_id) {
70346 + case GLAMO_CORE_REV_A2:
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);
70355 + dev_warn(&glamo->pdev->dev, "unknown glamo revision "
70356 + "%04x, your mileage may vary\n", rev_id);
70357 + /* maybe should abort ? */
70363 + dev_err(&glamo->pdev->dev, "unsupported Glamo device %04x\n",
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));
70376 +static int __init glamo_probe(struct platform_device *pdev)
70379 + struct glamo_core *glamo;
70380 + struct platform_device *glamo_mmc_dev;
70382 + if (glamo_handle) {
70383 + dev_err(&pdev->dev,
70384 + "This driver supports only one instance\n");
70388 + glamo = kmalloc(GFP_KERNEL, sizeof(*glamo));
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");
70404 + /* register a number of sibling devices whoise IOMEM resources
70405 + * are siblings of pdev's IOMEM resource */
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);
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");
70421 + platform_set_drvdata(pdev, glamo);
70423 + (glamo->pdata->glamo_external_reset)(0);
70425 + (glamo->pdata->glamo_external_reset)(1);
70429 + * finally set the mfd interrupts up
70430 + * can't do them earlier or sibling probes blow up
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);
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;
70446 + dev_err(&pdev->dev, "Glamo interrupt not used\n");
70447 + glamo->irq_works = 0;
70451 + /* confirm it isn't insane version */
70452 + if (!glamo_supported(glamo)) {
70453 + dev_err(&pdev->dev, "This Glamo is not supported\n");
70458 + rc = sysfs_create_group(&pdev->dev.kobj, &glamo_attr_group);
70460 + dev_err(&pdev->dev, "cannot create sysfs group\n");
70464 + /* init the chip with canned register set */
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);
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));
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;
70482 + /* start creating the siblings */
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);
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);
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);
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);
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);
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);
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);
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);
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");
70539 + disable_irq(glamo->irq);
70540 + set_irq_chained_handler(glamo->irq, NULL);
70542 + for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
70543 + set_irq_flags(irq, 0);
70544 + set_irq_chip(irq, NULL);
70547 + iounmap(glamo->base);
70549 + platform_set_drvdata(pdev, NULL);
70550 + glamo_handle = NULL;
70556 +static int glamo_remove(struct platform_device *pdev)
70558 + struct glamo_core *glamo = platform_get_drvdata(pdev);
70561 + disable_irq(glamo->irq);
70562 + set_irq_chained_handler(glamo->irq, NULL);
70564 + for (irq = IRQ_GLAMO(0); irq <= IRQ_GLAMO(8); irq++) {
70565 + set_irq_flags(irq, 0);
70566 + set_irq_chip(irq, NULL);
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;
70582 +static int glamo_suspend(struct platform_device *pdev, pm_message_t state)
70584 + glamo_handle->suspending = 1;
70585 + glamo_power(glamo_handle, GLAMO_POWER_SUSPEND);
70590 +static int glamo_resume(struct platform_device *pdev)
70592 + glamo_power(glamo_handle, GLAMO_POWER_ON);
70593 + glamo_handle->suspending = 0;
70599 +#define glamo_suspend NULL
70600 +#define glamo_resume NULL
70603 +static struct platform_driver glamo_driver = {
70604 + .probe = glamo_probe,
70605 + .remove = glamo_remove,
70606 + .suspend = glamo_suspend,
70607 + .resume = glamo_resume,
70609 + .name = "glamo3362",
70610 + .owner = THIS_MODULE,
70614 +static int __devinit glamo_init(void)
70616 + return platform_driver_register(&glamo_driver);
70619 +static void __exit glamo_cleanup(void)
70621 + platform_driver_unregister(&glamo_driver);
70624 +module_init(glamo_init);
70625 +module_exit(glamo_cleanup);
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
70634 +#ifndef __GLAMO_CORE_H
70635 +#define __GLAMO_CORE_H
70637 +#include <asm/system.h>
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)
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)
70652 +struct glamo_core {
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;
70661 + u_int16_t revision;
70663 + u32 engine_enabled_bitfield;
70664 + u32 engine_enabled_bitfield_suspend;
70668 +struct glamo_script {
70673 +int glamo_run_script(struct glamo_core *glamo,
70674 + struct glamo_script *script, int len, int may_sleep);
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,
70686 + GLAMO_ENGINE_MMC,
70687 + GLAMO_ENGINE_MICROP0,
70688 + GLAMO_ENGINE_RISC,
70689 + GLAMO_ENGINE_MICROP1_MPEG_ENC,
70690 + GLAMO_ENGINE_MICROP1_MPEG_DEC,
70692 + GLAMO_ENGINE_H264_DEC,
70693 + GLAMO_ENGINE_RISC1,
70694 + GLAMO_ENGINE_SPI,
70696 + __NUM_GLAMO_ENGINES
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);
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);
70719 +void glamo_engine_clkreg_set(struct glamo_core *glamo,
70720 + enum glamo_engine engine,
70721 + u_int16_t mask, u_int16_t val);
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
70730 +/* Smedia Glamo 336x/337x driver
70732 + * (C) 2007-2008 by Openmoko, Inc.
70733 + * Author: Harald Welte <laforge@openmoko.org>
70734 + * All rights reserved.
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.
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.
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
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>
70772 +#include <asm/div64.h>
70775 +#include <linux/pm.h>
70778 +#include <linux/glamofb.h>
70780 +#include "glamo-regs.h"
70781 +#include "glamo-core.h"
70784 +#define GLAMO_LOG(...)
70786 +#define GLAMO_LOG(...) \
70788 + printk(KERN_DEBUG "in %s:%s:%d", __FILE__, __func__, __LINE__); \
70789 + printk(KERN_DEBUG __VA_ARGS__); \
70794 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start)+1)
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;
70805 + u_int32_t pseudo_pal[16];
70806 + spinlock_t lock_cmd;
70807 + int angle; /* Current rotation angle */
70811 +/* 'sibling' spi device for lcm init */
70812 +static struct platform_device glamo_spi_dev = {
70813 + .name = "glamo-lcm-spi",
70817 +static int reg_read(struct glamofb_handle *glamo,
70822 + for (i = 0; i != 2; i++)
70825 + return readw(glamo->base + reg);
70828 +static void reg_write(struct glamofb_handle *glamo,
70829 + u_int16_t reg, u_int16_t val)
70833 + for (i = 0; i != 2; i++)
70836 + writew(val, glamo->base + reg);
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 */
70868 +static int glamofb_run_script(struct glamofb_handle *glamo,
70869 + struct glamo_script *script, int len)
70873 + if (glamo->mach_info->glamo->suspending) {
70874 + dev_err(&glamo->mach_info->glamo->pdev->dev,
70875 + "IGNORING glamofb_run_script while "
70880 + for (i = 0; i < len; i++) {
70881 + struct glamo_script *line = &script[i];
70883 + if (line->reg == 0xffff)
70885 + else if (line->reg == 0xfffe)
70886 + msleep(line->val);
70888 + reg_write(glamo, script[i].reg, script[i].val);
70894 +static int glamofb_check_var(struct fb_var_screeninfo *var,
70895 + struct fb_info *info)
70897 + struct glamofb_handle *glamo = info->par;
70899 + if (glamo->mach_info->glamo->suspending) {
70900 + dev_err(&glamo->mach_info->glamo->pdev->dev,
70901 + "IGNORING glamofb_check_var while "
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;
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;
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;
70921 + /* FIXME: set rgb positions */
70922 + switch (var->bits_per_pixel) {
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;
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;
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;
70959 + /* The Smedia Glamo doesn't support anything but 16bit color */
70961 + "Smedia driver does not [yet?] support 24/32bpp\n");
70968 +static void reg_set_bit_mask(struct glamofb_handle *glamo,
70969 + u_int16_t reg, u_int16_t mask,
70976 + tmp = reg_read(glamo, reg);
70979 + reg_write(glamo, reg, tmp);
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
70991 +enum orientation {ORIENTATION_PORTRAIT, ORIENTATION_LANDSCAPE};
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)
70998 + if (glamo->mach_info->glamo->suspending) {
70999 + dev_err(&glamo->mach_info->glamo->pdev->dev,
71000 + "IGNORING rotate_lcd while "
71005 + switch (rotation) {
71006 + case FB_ROTATE_UR:
71007 + glamo_rot = GLAMO_LCD_ROT_MODE_0;
71008 + glamo->angle = 0;
71010 + case FB_ROTATE_CW:
71011 + glamo_rot = GLAMO_LCD_ROT_MODE_90;
71012 + glamo->angle = 90;
71014 + case FB_ROTATE_UD:
71015 + glamo_rot = GLAMO_LCD_ROT_MODE_180;
71016 + glamo->angle = 180;
71018 + case FB_ROTATE_CCW:
71019 + glamo_rot = GLAMO_LCD_ROT_MODE_270;
71020 + glamo->angle = 270;
71023 + glamo->angle = 0;
71024 + glamo_rot = GLAMO_LCD_ROT_MODE_0;
71028 + reg_set_bit_mask(glamo,
71029 + GLAMO_REG_LCD_WIDTH,
71030 + GLAMO_LCD_ROT_MODE_MASK,
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);
71039 +static enum orientation get_orientation(struct fb_var_screeninfo *var)
71041 + if (var->xres <= var->yres)
71042 + return ORIENTATION_PORTRAIT;
71044 + return ORIENTATION_LANDSCAPE;
71047 +static int will_orientation_change(struct fb_var_screeninfo *var)
71049 + enum orientation orient = get_orientation(var);
71051 + switch (orient) {
71052 + case ORIENTATION_LANDSCAPE:
71053 + if (var->rotate == FB_ROTATE_UR || var->rotate == FB_ROTATE_UD)
71056 + case ORIENTATION_PORTRAIT:
71057 + if (var->rotate == FB_ROTATE_CW || var->rotate == FB_ROTATE_CCW)
71064 +#ifdef CONFIG_MFD_GLAMO_FB_XGLAMO_WORKAROUND
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.
71073 +static unsigned xglamo_hack_enabled = 1;
71075 +static ssize_t xglamo_hack_read(struct device *dev,
71076 + struct device_attribute *attr, char *buf)
71078 + return sprintf(buf, "%d\n", xglamo_hack_enabled);
71081 +static ssize_t xglamo_hack_write(struct device *dev,
71082 + struct device_attribute *attr, const char *buf,
71085 + unsigned long val;
71087 + if (!strict_strtoul(buf, 10, &val))
71088 + xglamo_hack_enabled = !!val;
71093 +static DEVICE_ATTR(xglamo_hack, S_IWUSR | S_IRUGO, xglamo_hack_read,
71094 + xglamo_hack_write);
71096 +static struct attribute *glamo_fb_sysfs_entries[] = {
71097 + &dev_attr_xglamo_hack.attr,
71101 +static struct attribute_group glamo_fb_attr_group = {
71103 + .attrs = glamo_fb_sysfs_entries,
71106 +/* This function implements the actual Xglamo hack. */
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)
71112 + int width, height;
71114 + if (glamo->angle == 90 || glamo->angle == 270) {
71116 + * But if we are going back to portrait mode from here,
71117 + * we get inverted values from Xglamo
71119 + if (!(var->rotate == FB_ROTATE_UR ||
71120 + var->rotate == FB_ROTATE_UD)) {
71121 + width = var->yres;
71122 + height = var->xres;
71124 + width = var->xres;
71125 + height = var->yres;
71129 + width = var->xres;
71130 + height = var->yres;
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;
71142 + var->xres_virtual = width;
71143 + var->yres_virtual = height * 2;
71144 + *pitch = width * var->bits_per_pixel / 8;
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;
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)
71165 +static void glamofb_update_lcd_controller(struct glamofb_handle *glamo,
71166 + struct fb_var_screeninfo *var)
71168 + int sync, bp, disp, fp, total, xres, yres, pitch;
71169 + int uninitialized_var(orientation_changing);
71170 + unsigned long flags;
71172 + if (!glamo || !var)
71175 + if (glamo->mach_info->glamo->suspending) {
71176 + dev_err(&glamo->mach_info->glamo->pdev->dev,
71177 + "IGNORING glamofb_update_lcd_controller while "
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);
71186 + if (glamofb_cmd_mode(glamo, 1))
71189 + if (var->pixclock)
71190 + glamo_engine_reclock(glamo->mach_info->glamo,
71191 + GLAMO_ENGINE_LCD,
71194 + if (xglamo_hack_enabled) {
71195 + glamofb_update_lcd_controller_hack(glamo, var, &xres, &yres,
71198 + xres = var->xres;
71199 + yres = var->yres;
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;
71206 + pitch = var->xres * var->bits_per_pixel / 8;
71209 + reg_set_bit_mask(glamo,
71210 + GLAMO_REG_LCD_WIDTH,
71211 + GLAMO_LCD_WIDTH_MASK,
71213 + reg_set_bit_mask(glamo,
71214 + GLAMO_REG_LCD_HEIGHT,
71215 + GLAMO_LCD_HEIGHT_MASK,
71217 + reg_set_bit_mask(glamo,
71218 + GLAMO_REG_LCD_PITCH,
71219 + GLAMO_LCD_PITCH_MASK,
71222 + /* honour the rotation request */
71223 + __rotate_lcd(glamo, var->rotate);
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;
71234 + var->xres_virtual = xres;
71235 + var->yres_virtual = yres;
71236 + var->yres_virtual *= 2;
71240 + /* update scannout timings */
71242 + bp = sync + var->hsync_len;
71243 + disp = bp + var->left_margin;
71244 + fp = disp + xres;
71245 + total = fp + var->right_margin;
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);
71259 + bp = sync + var->vsync_len;
71260 + disp = bp + var->upper_margin;
71261 + fp = disp + yres;
71262 + total = fp + var->lower_margin;
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);
71275 + glamofb_cmd_mode(glamo, 0);
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);
71283 +static int glamofb_pan_display(struct fb_var_screeninfo *var,
71284 + struct fb_info *info)
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);
71293 +static int glamofb_set_par(struct fb_info *info)
71295 + struct glamofb_handle *glamo = info->par;
71296 + struct fb_var_screeninfo *var = &info->var;
71298 + if (glamo->mach_info->glamo->suspending) {
71299 + dev_err(&glamo->mach_info->glamo->pdev->dev,
71300 + "IGNORING glamofb_set_par while "
71305 + switch (var->bits_per_pixel) {
71307 + info->fix.visual = FB_VISUAL_TRUECOLOR;
71310 + printk("Smedia driver doesn't support != 16bpp\n");
71314 + info->fix.line_length = (var->xres * var->bits_per_pixel) / 8;
71316 + glamofb_update_lcd_controller(glamo, var);
71322 +static void notify_blank(struct fb_info *info, int blank_mode)
71324 + struct fb_event event;
71326 + event.info = info;
71327 + event.data = &blank_mode;
71328 + fb_notifier_call_chain(FB_EVENT_CONBLANK, &event);
71332 +static int glamofb_blank(int blank_mode, struct fb_info *info)
71334 + struct glamofb_handle *gfb = info->par;
71335 + struct glamo_core *gcore = gfb->mach_info->glamo;
71337 + dev_dbg(gfb->dev, "glamofb_blank(%u)\n", blank_mode);
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 */
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);
71350 + /* LCM need notification before pixel clock is stopped */
71351 + notify_blank(info, blank_mode);
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;
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);
71367 + notify_blank(info, blank_mode);
71368 + gfb->blank_mode = blank_mode;
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. */
71378 +static inline unsigned int chan_to_field(unsigned int chan,
71379 + struct fb_bitfield *bf)
71382 + chan >>= 16 - bf->length;
71383 + return chan << bf->offset;
71386 +static int glamofb_setcolreg(unsigned regno,
71387 + unsigned red, unsigned green, unsigned blue,
71388 + unsigned transp, struct fb_info *info)
71390 + struct glamofb_handle *glamo = info->par;
71391 + unsigned int val;
71393 + if (glamo->mach_info->glamo->suspending) {
71394 + dev_err(&glamo->mach_info->glamo->pdev->dev,
71395 + "IGNORING glamofb_set_par while "
71400 + switch (glamo->fb->fix.visual) {
71401 + case FB_VISUAL_TRUECOLOR:
71402 + case FB_VISUAL_DIRECTCOLOR:
71403 + /* true-colour, use pseuo-palette */
71405 + if (regno < 16) {
71406 + u32 *pal = glamo->fb->pseudo_palette;
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);
71412 + pal[regno] = val;
71416 + return 1; /* unknown type */
71422 +#ifdef CONFIG_MFD_GLAMO_HWACCEL
71423 +static inline void glamofb_vsync_wait(struct glamofb_handle *glamo,
71424 + int line, int size, int range)
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);
71438 + * Enable/disable the hardware cursor mode altogether
71439 + * (for blinking and such, use glamofb_cursor()).
71441 +static void glamofb_cursor_onoff(struct glamofb_handle *glamo, int on)
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);
71449 + glamofb_vsync_wait(glamo, y, size, 30);
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;
71457 + /* Hide the cursor by default */
71458 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE, 0);
71461 +static int glamofb_cursor(struct fb_info *info, struct fb_cursor *cursor)
71463 + struct glamofb_handle *glamo = info->par;
71464 + unsigned long flags;
71466 + spin_lock_irqsave(&glamo->lock_cmd, flags);
71468 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_X_SIZE,
71469 + cursor->enable ? cursor->image.width : 0);
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);
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];
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);
71487 + if (cursor->set & FB_CUR_SETHOT)
71488 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_PRESET,
71489 + (cursor->hot.x << 8) | cursor->hot.y);
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;
71501 + if (cursor->image.depth > 1) {
71502 + spin_unlock_irqrestore(&glamo->lock_cmd, flags);
71506 + pitch = ((cursor->image.width + 7) >> 2) & ~1;
71507 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_PITCH,
71509 + reg_write(glamo, GLAMO_REG_LCD_CURSOR_Y_SIZE,
71510 + cursor->image.height);
71512 + for (y = 0; y < cursor->image.height; y++) {
71514 + for (x = 0; x < cursor->image.width; x++) {
71515 + if ((x % 8) == 0) {
71523 + if (cursor->rop == ROP_COPY)
71524 + op = (dmsk & 1) ?
71525 + (dcol & 1) ? 1 : 3 : 0;
71527 + op = ((dmsk & 1) << 1) |
71528 + ((dcol & 1) << 0);
71529 + byte |= op << ((x & 3) << 1);
71531 + if (x % 4 == 3) {
71532 + writeb(byte, dst + x / 4);
71537 + writeb(byte, dst + x / 4);
71545 + spin_unlock_irqrestore(&glamo->lock_cmd, flags);
71551 +static inline int glamofb_cmdq_empty(struct glamofb_handle *gfb)
71553 + /* DGCMdQempty -- 1 == command queue is empty */
71554 + return reg_read(gfb, GLAMO_REG_LCD_STATUS1) & (1 << 15);
71557 +/* call holding gfb->lock_cmd when locking, until you unlock */
71558 +int glamofb_cmd_mode(struct glamofb_handle *gfb, int on)
71560 + int timeout = 2000000;
71562 + if (gfb->mach_info->glamo->suspending) {
71563 + dev_err(&gfb->mach_info->glamo->pdev->dev,
71564 + "IGNORING glamofb_cmd_mode while "
71569 + dev_dbg(gfb->dev, "glamofb_cmd_mode(gfb=%p, on=%d)\n", gfb, on);
71571 + dev_dbg(gfb->dev, "%s: waiting for cmdq empty: ",
71573 + while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
71575 + if (timeout < 0) {
71576 + printk(KERN_ERR"*************"
71577 + "glamofb cmd_queue never got empty"
71578 + "*************\n");
71581 + dev_dbg(gfb->dev, "empty!\n");
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);
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)) &&
71594 + if (timeout < 0) {
71595 + printk(KERN_ERR"*************"
71596 + "glamofb lcd never idle"
71597 + "*************\n");
71603 + dev_dbg(gfb->dev, "cmd mode entered\n");
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);
71612 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1,
71613 + GLAMO_LCD_CMD_TYPE_DISP |
71614 + GLAMO_LCD_CMD_DATA_DISP_FIRE);
71619 +EXPORT_SYMBOL_GPL(glamofb_cmd_mode);
71622 +int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val)
71624 + int timeout = 200000;
71626 + if (gfb->mach_info->glamo->suspending) {
71627 + dev_err(&gfb->mach_info->glamo->pdev->dev,
71628 + "IGNORING glamofb_cmd_write while "
71633 + dev_dbg(gfb->dev, "%s: waiting for cmdq empty\n", __func__);
71634 + while ((!glamofb_cmdq_empty(gfb)) && (timeout--))
71636 + if (timeout < 0) {
71637 + printk(KERN_ERR"*************"
71638 + "glamofb cmd_queue never got empty"
71639 + "*************\n");
71642 + dev_dbg(gfb->dev, "idle, writing 0x%04x\n", val);
71644 + reg_write(gfb, GLAMO_REG_LCD_COMMAND1, val);
71648 +EXPORT_SYMBOL_GPL(glamofb_cmd_write);
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,
71660 + .fb_fillrect = cfb_fillrect,
71661 + .fb_copyarea = cfb_copyarea,
71662 + .fb_imageblit = cfb_imageblit,
71665 +static int glamofb_init_regs(struct glamofb_handle *glamo)
71667 + struct fb_info *info = glamo->fb;
71669 + glamofb_check_var(&info->var, info);
71670 + glamofb_run_script(glamo, glamo_regs, ARRAY_SIZE(glamo_regs));
71671 + glamofb_set_par(info);
71676 +static int __init glamofb_probe(struct platform_device *pdev)
71679 + struct fb_info *fbinfo;
71680 + struct glamofb_handle *glamofb;
71681 + struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
71683 + printk(KERN_INFO "SMEDIA Glamo frame buffer driver (C) 2007 "
71684 + "Openmoko, Inc.\n");
71686 + fbinfo = framebuffer_alloc(sizeof(struct glamofb_handle), &pdev->dev);
71690 + glamofb = fbinfo->par;
71691 + glamofb->fb = fbinfo;
71692 + glamofb->dev = &pdev->dev;
71694 + glamofb->angle = 0;
71695 + glamofb->blank_mode = FB_BLANK_POWERDOWN;
71697 + strcpy(fbinfo->fix.id, "SMedia Glamo");
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");
71707 + glamofb->fb_res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
71709 + if (!glamofb->fb_res) {
71710 + dev_err(&pdev->dev, "platform device with no memory ?\n");
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");
71722 + glamofb->fb_res = request_mem_region(glamofb->fb_res->start,
71723 + mach_info->fb_mem_size,
71725 + if (!glamofb->fb_res) {
71726 + dev_err(&pdev->dev, "failed to request vram region\n");
71727 + goto out_release_reg;
71730 + /* we want to remap only the registers required for this core
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;
71737 + fbinfo->fix.smem_start = (unsigned long) glamofb->fb_res->start;
71738 + fbinfo->fix.smem_len = mach_info->fb_mem_size;
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;
71746 + glamofb->cursor_addr = fbinfo->screen_base + 0x12C000;
71748 + platform_set_drvdata(pdev, glamofb);
71750 + glamofb->mach_info = pdev->dev.platform_data;
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;
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;
71767 + fbinfo->fbops = &glamofb_ops;
71768 + fbinfo->flags = FBINFO_FLAG_DEFAULT;
71769 + fbinfo->pseudo_palette = &glamofb->pseudo_pal;
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;
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;
71785 + memset(fbinfo->screen_base, 0,
71786 + mach_info->xres.max *
71787 + mach_info->yres.max *
71788 + mach_info->bpp.max / 8);
71790 + glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
71791 + glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
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);
71800 +#ifdef CONFIG_MFD_GLAMO_FB_XGLAMO_WORKAROUND
71802 + rc = sysfs_create_group(&pdev->dev.kobj, &glamo_fb_attr_group);
71804 + dev_err(&pdev->dev, "cannot create sysfs group\n");
71805 + goto out_unmap_fb;
71809 + rc = register_framebuffer(fbinfo);
71811 + dev_err(&pdev->dev, "failed to register framebuffer\n");
71812 + goto out_unmap_fb;
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);
71823 + printk(KERN_INFO "fb%d: %s frame buffer device\n",
71824 + fbinfo->node, fbinfo->fix.id);
71829 + iounmap(fbinfo->screen_base);
71830 + iounmap(glamofb->base);
71832 + release_mem_region(glamofb->fb_res->start, RESSIZE(glamofb->fb_res));
71834 + release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
71836 + framebuffer_release(fbinfo);
71840 +static int glamofb_remove(struct platform_device *pdev)
71842 + struct glamofb_handle *glamofb = platform_get_drvdata(pdev);
71844 + platform_set_drvdata(pdev, NULL);
71845 + iounmap(glamofb->base);
71846 + release_mem_region(glamofb->reg->start, RESSIZE(glamofb->reg));
71854 +static int glamofb_suspend(struct platform_device *pdev, pm_message_t state)
71856 + struct glamofb_handle *gfb = platform_get_drvdata(pdev);
71858 + /* we need to stop anything touching our framebuffer */
71859 + fb_set_suspend(gfb->fb, 1);
71861 + /* seriously -- nobody is allowed to touch glamo memory when we
71862 + * are suspended or we lock on nWAIT
71864 + /* iounmap(gfb->fb->screen_base); */
71869 +static int glamofb_resume(struct platform_device *pdev)
71871 + struct glamofb_handle *gfb = platform_get_drvdata(pdev);
71872 + struct glamofb_platform_data *mach_info = pdev->dev.platform_data;
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);
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);
71887 + fb_set_suspend(gfb->fb, 0);
71892 +#define glamofb_suspend NULL
71893 +#define glamofb_resume NULL
71896 +static struct platform_driver glamofb_driver = {
71897 + .probe = glamofb_probe,
71898 + .remove = glamofb_remove,
71899 + .suspend = glamofb_suspend,
71900 + .resume = glamofb_resume,
71902 + .name = "glamo-fb",
71903 + .owner = THIS_MODULE,
71907 +static int __devinit glamofb_init(void)
71909 + return platform_driver_register(&glamofb_driver);
71912 +static void __exit glamofb_cleanup(void)
71914 + platform_driver_unregister(&glamofb_driver);
71917 +module_init(glamofb_init);
71918 +module_exit(glamofb_cleanup);
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
71928 +#include <linux/kernel.h>
71929 +#include <linux/module.h>
71930 +#include <linux/spinlock.h>
71931 +#include <linux/io.h>
71933 +#include <linux/glamo-gpio.h>
71935 +#include "glamo-core.h"
71936 +#include "glamo-regs.h"
71938 +void glamo_gpio_setpin(struct glamo_core *glamo, unsigned int pin,
71939 + unsigned int value)
71941 + unsigned int reg = REG_OF_GPIO(pin);
71944 + spin_lock(&glamo->lock);
71945 + tmp = readw(glamo->base + reg);
71947 + tmp |= OUTPUT_BIT(pin);
71949 + tmp &= ~OUTPUT_BIT(pin);
71950 + writew(tmp, glamo->base + reg);
71951 + spin_unlock(&glamo->lock);
71953 +EXPORT_SYMBOL(glamo_gpio_setpin);
71955 +int glamo_gpio_getpin(struct glamo_core *glamo, unsigned int pin)
71957 + return readw(REG_OF_GPIO(pin)) & INPUT_BIT(pin) ? 1 : 0;
71959 +EXPORT_SYMBOL(glamo_gpio_getpin);
71961 +void glamo_gpio_cfgpin(struct glamo_core *glamo, unsigned int pinfunc)
71963 + unsigned int reg = REG_OF_GPIO(pinfunc);
71966 + spin_lock(&glamo->lock);
71967 + tmp = readw(glamo->base + reg);
71969 + if ((pinfunc & 0x00f0) == GLAMO_GPIO_F_FUNC) {
71970 + /* pin is a function pin: clear gpio bit */
71971 + tmp &= ~FUNC_BIT(pinfunc);
71973 + /* pin is gpio: set gpio bit */
71974 + tmp |= FUNC_BIT(pinfunc);
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);
71984 + writew(tmp, glamo->base + reg);
71985 + spin_unlock(&glamo->lock);
71987 +EXPORT_SYMBOL(glamo_gpio_cfgpin);
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
71994 + * Copyright (C) 2007 Openmoko, Inc.
71995 + * Author: Harald Welte <laforge@openmoko.org>
71997 + * Smedia Glamo GPIO based SPI driver
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.
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.
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>
72019 +#include <linux/spi/spi.h>
72020 +#include <linux/spi/spi_bitbang.h>
72021 +#include <linux/spi/glamo.h>
72023 +#include <linux/glamofb.h>
72025 +#include <mach/hardware.h>
72027 +#include "glamo-core.h"
72028 +#include "glamo-regs.h"
72030 +struct glamo_spi {
72031 + struct spi_bitbang bitbang;
72032 + struct spi_master *master;
72033 + struct glamo_spi_info *info;
72034 + struct device *dev;
72037 +static inline struct glamo_spi *to_gs(struct spi_device *spi)
72039 + return spi->controller_data;
72042 +static int glamo_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
72044 + unsigned int bpw;
72046 + bpw = t ? t->bits_per_word : spi->bits_per_word;
72048 + if (bpw != 9 && bpw != 8) {
72049 + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
72056 +static void glamo_spi_chipsel(struct spi_device *spi, int value)
72059 + struct glamo_spi *gs = to_gs(spi);
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);
72064 + glamofb_cmd_mode(gs->info->glamofb_handle, value);
72068 +static int glamo_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
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;
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);
72078 + if (spi->bits_per_word == 9)
72079 + nine_bits = (1 << 9);
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);
72089 + for (i = 0; i < t->len/sizeof(u_int16_t); i++) {
72090 + /* actually transfer the data */
72092 + glamofb_cmd_write(gs->info->glamofb_handle,
72093 + GLAMO_LCD_CMD_TYPE_SERIAL | nine_bits |
72094 + (1 << 10) | (1 << 11) | (ui16[i] & 0x1ff));
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);
72106 +static int glamo_spi_setup(struct spi_device *spi)
72110 + if (!spi->bits_per_word)
72111 + spi->bits_per_word = 9;
72113 + /* FIXME: hardware can do this */
72114 + if (spi->mode & SPI_LSB_FIRST)
72117 + ret = glamo_spi_setupxfer(spi, NULL);
72119 + dev_err(&spi->dev, "setupxfer returned %d\n", ret);
72123 + dev_dbg(&spi->dev, "%s: mode %d, %u bpw\n",
72124 + __FUNCTION__, spi->mode, spi->bits_per_word);
72129 +static int glamo_spi_probe(struct platform_device *pdev)
72131 + struct spi_master *master;
72132 + struct glamo_spi *sp;
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");
72143 + sp = spi_master_get_devdata(master);
72144 + memset(sp, 0, sizeof(struct glamo_spi));
72146 + sp->master = spi_master_get(master);
72147 + sp->info = pdev->dev.platform_data;
72149 + dev_err(&pdev->dev, "can't operate without platform data\n");
72151 + goto err_no_pdev;
72153 + dev_dbg(&pdev->dev, "sp->info(pdata) = %p\n", sp->info);
72155 + sp->dev = &pdev->dev;
72157 + platform_set_drvdata(pdev, sp);
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;
72165 + ret = spi_bitbang_start(&sp->bitbang);
72167 + goto err_no_bitbang;
72169 + /* register the chips to go with the board */
72171 + glamofb_cmd_mode(sp->info->glamofb_handle, 1);
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);
72178 + sp->info->board_info[i].controller_data = sp;
72179 + spi_new_device(master, sp->info->board_info + i);
72185 + platform_set_drvdata(pdev, NULL);
72187 + spi_master_put(sp->bitbang.master);
72193 +static int glamo_spi_remove(struct platform_device *pdev)
72195 + struct glamo_spi *sp = platform_get_drvdata(pdev);
72197 + spi_bitbang_stop(&sp->bitbang);
72198 + spi_master_put(sp->bitbang.master);
72203 +#define glamo_spi_suspend NULL
72204 +#define glamo_spi_resume NULL
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,
72212 + .name = "glamo-lcm-spi",
72213 + .owner = THIS_MODULE,
72217 +static int __init glamo_spi_init(void)
72219 + return platform_driver_register(&glamo_spi_drv);
72222 +static void __exit glamo_spi_exit(void)
72224 + platform_driver_unregister(&glamo_spi_drv);
72227 +module_init(glamo_spi_init);
72228 +module_exit(glamo_spi_exit);
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
72238 + * linux/drivers/mmc/host/glamo-mmc.c - Glamo MMC driver
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>
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.
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>
72262 +#include <asm/dma.h>
72263 +#include <asm/dma-mapping.h>
72264 +#include <asm/io.h>
72266 +#include "glamo-mci.h"
72267 +#include "glamo-core.h"
72268 +#include "glamo-regs.h"
72270 +/* from glamo-core.c */
72271 +extern struct glamo_mci_pdata glamo_mci_def_pdata;
72273 +static spinlock_t clock_lock;
72275 +#define DRIVER_NAME "glamo-mci"
72276 +#define RESSIZE(ressource) (((ressource)->end - (ressource)->start) + 1)
72278 +static void glamo_mci_send_request(struct mmc_host *mmc);
72281 + * Max SD clock rate
72283 + * held at /(3 + 1) due to concerns of 100R recommended series resistor
72284 + * allows 16MHz @ 4-bit --> 8MBytes/sec raw
72286 + * you can override this on kernel commandline using
72288 + * glamo_mci.sd_max_clk=10000000
72293 +static int sd_max_clk = 50000000 / 3;
72294 +module_param(sd_max_clk, int, 0644);
72297 + * Slow SD clock rate
72299 + * you can override this on kernel commandline using
72301 + * glamo_mci.sd_slow_ratio=8
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
72310 +static int sd_slow_ratio = 8;
72311 +module_param(sd_slow_ratio, int, 0644);
72314 + * Post-power SD clock rate
72316 + * you can override this on kernel commandline using
72318 + * glamo_mci.sd_post_power_clock=1000000
72322 + * After changing power to card, clock is held at this rate until first bulk
72323 + * transfer completes
72326 +static int sd_post_power_clock = 1000000;
72327 +module_param(sd_post_power_clock, int, 0644);
72331 + * SD Signal drive strength
72333 + * you can override this on kernel commandline using
72335 + * glamo_mci.sd_drive=0
72340 +static int sd_drive;
72341 +module_param(sd_drive, int, 0644);
72344 + * SD allow SD clock to run while idle
72346 + * you can override this on kernel commandline using
72348 + * glamo_mci.sd_idleclk=0
72353 +static int sd_idleclk = 0; /* disallow idle clock by default */
72354 +module_param(sd_idleclk, int, 0644);
72356 +/* used to stash real idleclk state in suspend: we force it to run in there */
72357 +static int suspend_sd_idleclk;
72360 +unsigned char CRC7(u8 * pu8, int cnt)
72367 + for (n = 0; n < 8; n++) {
72369 + if ((d & 0x80) ^ (crc & 0x80))
72374 + return (crc << 1) | 1;
72377 +static int get_data_buffer(struct glamo_mci_host *host,
72378 + volatile u32 *words, volatile u16 **pointer)
72380 + struct scatterlist *sg;
72385 + if (host->pio_active == XFER_NONE)
72388 + if ((!host->mrq) || (!host->mrq->data))
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);
72396 + sg = &host->mrq->data->sg[host->pio_sgptr];
72398 + *words = sg->length >> 1; /* we are working with a 16-bit data bus */
72399 + *pointer = page_address(sg_page(sg)) + sg->offset;
72401 + BUG_ON(((long)(*pointer)) & 1);
72403 + host->pio_sgptr++;
72405 + /* dev_info(&host->pdev->dev, "new buffer (%i/%i)\n",
72406 + host->pio_sgptr, host->mrq->data->sg_len); */
72410 +static void do_pio_read(struct glamo_mci_host *host)
72413 + u16 __iomem *from_ptr = host->base_data + (RESSIZE(host->mem_data) /
72414 + sizeof(u16) / 2);
72420 + res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);
72422 + host->pio_active = XFER_NONE;
72423 + host->complete_what = COMPLETION_FINALIZE;
72425 + dev_dbg(&host->pdev->dev, "pio_read(): "
72426 + "complete (no more data).\n");
72430 + dev_dbg(&host->pdev->dev, "pio_read(): host->pio_words: %d\n",
72431 + host->pio_words);
72433 + host->pio_count += host->pio_words << 1;
72436 + block = (u16 *)host->pio_ptr;
72437 + res = host->pio_words << 1;
72440 + /* u16-centric memcpy */
72441 + while (host->pio_words--)
72442 + *host->pio_ptr++ = *from_ptr++;
72444 + /* memcpy can be faster? */
72445 + memcpy((void *)host->pio_ptr, from_ptr, host->pio_words << 1);
72446 + host->pio_ptr += host->pio_words;
72450 + print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 16, 1,
72451 + (void *)block, res, 1);
72456 +static int do_pio_write(struct glamo_mci_host *host)
72459 + volatile u16 __iomem *to_ptr = host->base_data;
72462 + dev_dbg(&host->pdev->dev, "pio_write():\n");
72464 + res = get_data_buffer(host, &host->pio_words, &host->pio_ptr);
72468 + dev_dbg(&host->pdev->dev, "pio_write():new source: [%i]@[%p]\n",
72469 + host->pio_words, host->pio_ptr);
72471 + host->pio_count += host->pio_words << 1;
72472 + while (host->pio_words--)
72473 + writew(*host->pio_ptr++, to_ptr++);
72476 + dev_dbg(&host->pdev->dev, "pio_write(): complete\n");
72477 + host->pio_active = XFER_NONE;
72481 +static void __glamo_mci_fix_card_div(struct glamo_mci_host *host, int div)
72483 + unsigned long flags;
72485 + spin_lock_irqsave(&clock_lock, flags);
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);
72495 + /* set the nearest prescaler factor
72497 + * register shared with SCLK divisor -- no chance of race because
72498 + * we don't use sensor interface
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);
72509 + if (host->force_slow_during_powerup)
72510 + div = host->clk_rate / sd_post_power_clock;
72512 + if (host->pdata->glamo_mci_use_slow)
72513 + if ((host->pdata->glamo_mci_use_slow)())
72514 + div = div * sd_slow_ratio;
72520 + * set the nearest prescaler factor
72522 + * register shared with SCLK divisor -- no chance of race because
72523 + * we don't use sensor interface
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);
72534 + spin_unlock_irqrestore(&clock_lock, flags);
72537 +static int __glamo_mci_set_card_clock(struct glamo_mci_host *host, int freq,
72541 + int real_rate = 0;
72545 + for (div = 0; div < 256; div++) {
72546 + real_rate = host->clk_rate / (div + 1);
72547 + if (real_rate <= freq)
72556 + __glamo_mci_fix_card_div(host, div);
72561 + *division = 0xff;
72563 + if (!sd_idleclk && !host->force_slow_during_powerup)
72565 + __glamo_mci_fix_card_div(host, -1);
72568 + return real_rate;
72572 +static void glamo_mci_irq_worker(struct work_struct *work)
72574 + struct glamo_mci_host *host =
72575 + container_of(work, struct glamo_mci_host, irq_work);
72576 + struct mmc_command *cmd = host->mrq->cmd;
72578 + if (host->pio_active == XFER_READ)
72579 + do_pio_read(host);
72581 + host->mrq->data->bytes_xfered = host->pio_count;
72582 + dev_dbg(&host->pdev->dev, "count=%d\n", host->pio_count);
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;
72591 + if (!sd_idleclk && !host->force_slow_during_powerup)
72593 + __glamo_mci_fix_card_div(host, -1);
72595 + host->complete_what = COMPLETION_NONE;
72596 + host->mrq = NULL;
72597 + mmc_request_done(host->mmc, cmd->mrq);
72600 +static void glamo_mci_irq_host(struct glamo_mci_host *host)
72603 + struct mmc_command *cmd;
72604 + unsigned long iflags;
72606 + if (host->suspending) { /* bad news, dangerous time */
72607 + dev_err(&host->pdev->dev, "****glamo_mci_irq before resumed\n");
72613 + cmd = host->mrq->cmd;
72617 + spin_lock_irqsave(&host->complete_lock, iflags);
72619 + status = readw(host->base + GLAMO_REG_MMC_RB_STAT1);
72620 + dev_dbg(&host->pdev->dev, "status = 0x%04x\n", status);
72622 + /* ack this interrupt source */
72623 + writew(GLAMO_IRQ_MMC,
72624 + glamo_mci_def_pdata.pglamo->base + GLAMO_REG_IRQ_CLEAR);
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;
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);
72642 + * disable the initial slow start after first bulk transfer
72644 + if (host->force_slow_during_powerup)
72645 + host->force_slow_during_powerup--;
72648 + * we perform the memcpy out of Glamo memory outside of IRQ context
72649 + * so we don't block other interrupts
72651 + schedule_work(&host->irq_work);
72656 + host->complete_what = COMPLETION_NONE;
72657 + host->mrq = NULL;
72658 + mmc_request_done(host->mmc, cmd->mrq);
72660 + spin_unlock_irqrestore(&host->complete_lock, iflags);
72663 +static void glamo_mci_irq(unsigned int irq, struct irq_desc *desc)
72665 + struct glamo_mci_host *host = (struct glamo_mci_host *)
72666 + desc->handler_data;
72669 + glamo_mci_irq_host(host);
72673 +static int glamo_mci_send_command(struct glamo_mci_host *host,
72674 + struct mmc_command *cmd)
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);
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 */
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);
72701 + /* command index toggle */
72702 + fire |= (host->ccnt & 1) << 12;
72704 + /* set type of command */
72705 + switch (mmc_cmd_type(cmd)) {
72707 + fire |= GLAMO_FIRE_MMC_CMDT_BNR;
72709 + case MMC_CMD_BCR:
72710 + fire |= GLAMO_FIRE_MMC_CMDT_BR;
72713 + fire |= GLAMO_FIRE_MMC_CMDT_AND;
72715 + case MMC_CMD_ADTC:
72716 + fire |= GLAMO_FIRE_MMC_CMDT_AD;
72720 + * if it expects a response, set the type expected
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)
72732 + switch (mmc_resp_type(cmd)) {
72733 + case MMC_RSP_R6: /* same index as R7 and R1 */
72734 + fire |= GLAMO_FIRE_MMC_RSPT_R1;
72736 + case MMC_RSP_R1B:
72737 + fire |= GLAMO_FIRE_MMC_RSPT_R1b;
72740 + fire |= GLAMO_FIRE_MMC_RSPT_R2;
72743 + fire |= GLAMO_FIRE_MMC_RSPT_R3;
72745 + /* R4 and R5 supported by chip not defined in linux/mmc/core.h (sdio) */
72748 + * From the command index, set up the command class in the host ctrllr
72750 + * missing guys present on chip but couldn't figure out how to use yet:
72751 + * 0x0 "stream read"
72752 + * 0x9 "cancel running command"
72754 + switch (cmd->opcode) {
72755 + case MMC_READ_SINGLE_BLOCK:
72756 + fire |= GLAMO_FIRE_MMC_CC_SBR; /* single block read */
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;
72766 + /* multiblock with stop */
72767 + fire |= GLAMO_FIRE_MMC_CC_MBRS;
72769 + case MMC_WRITE_BLOCK:
72770 + fire |= GLAMO_FIRE_MMC_CC_SBW; /* single block write */
72772 + case MMC_WRITE_MULTIPLE_BLOCK:
72773 + if (cmd->mrq->stop)
72774 + /* multiblock with stop */
72775 + fire |= GLAMO_FIRE_MMC_CC_MBWS;
72777 +// /* multiblock NO stop-- 'RESERVED'? */
72778 + fire |= GLAMO_FIRE_MMC_CC_MBWNS;
72780 + case MMC_STOP_TRANSMISSION:
72781 + fire |= GLAMO_FIRE_MMC_CC_STOP; /* STOP */
72784 + fire |= GLAMO_FIRE_MMC_CC_BASIC; /* "basic command" */
72788 + /* always largest timeout */
72789 + writew(0xfff, host->base + GLAMO_REG_MMC_TIMEOUT);
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);
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);
72804 +static int glamo_mci_prepare_pio(struct glamo_mci_host *host,
72805 + struct mmc_data *data)
72808 + * the S-Media-internal RAM offset for our MMC buffer
72809 + * Read is halfway up the buffer and write is at the start
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);
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);
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);
72838 + host->pio_active = XFER_READ;
72842 +static void glamo_mci_send_request(struct mmc_host *mmc)
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);
72851 + int timeout = 1000000;
72852 + int insanity_timeout = 1000000;
72854 + if (host->suspending) {
72855 + dev_err(&host->pdev->dev, "IGNORING glamo_mci_send_request while "
72857 + cmd->error = -EIO;
72859 + cmd->data->error = -EIO;
72860 + mmc_request_done(mmc, mrq);
72866 + * somehow 2.6.24 MCI manages to issue MMC_WRITE_BLOCK *without* the
72867 + * MMC_DATA_WRITE flag, WTF? Work around the madness.
72869 + if (cmd->opcode == MMC_WRITE_BLOCK)
72871 + mrq->data->flags |= MMC_DATA_WRITE;
72873 + /* this guy has data to read/write? */
72874 + if ((!host->cmd_is_stop) && cmd->data) {
72877 + res = glamo_mci_prepare_pio(host, cmd->data);
72879 + cmd->error = -EIO;
72880 + cmd->data->error = -EIO;
72881 + mmc_request_done(mmc, mrq);
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,
72891 + /* resume requested clock rate
72892 + * scale it down by sd_slow_ratio if platform requests it
72894 + __glamo_mci_fix_card_div(host, host->clk_div);
72896 + if (glamo_mci_send_command(host, cmd))
72899 + /* we are deselecting card? because it isn't going to ack then... */
72900 + if ((cmd->opcode == 7) && (cmd->arg == 0))
72904 + * we must spin until response is ready or timed out
72905 + * -- we don't get interrupts unless there is a bulk rx
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--));
72916 + if (insanity_timeout < 0)
72917 + dev_info(&host->pdev->dev, "command timeout, continuing\n");
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;
72926 + if (host->cmd_is_stop)
72929 + if (cmd->error) {
72930 + dev_info(&host->pdev->dev, "Error after cmd: 0x%x\n", status);
72934 + * mangle the response registers in two different exciting
72935 + * undocumented ways discovered by trial and error
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(®_resp[n]);
72942 + for (n = 0; n < 3; n++) /* super mangle power 2 */
72943 + pu16[n] = (readw(®_resp[n]) >> 8) |
72944 + (readw(®_resp[n + 1]) << 8);
72946 + * if we don't have bulk data to take care of, we're done
72950 + if (!(cmd->data->flags & (MMC_DATA_READ | MMC_DATA_WRITE)))
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
72959 + dev_dbg(&host->pdev->dev, "Waiting for payload data\n");
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"
72965 + if (!glamo_mci_def_pdata.pglamo->irq_works) {
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
72971 + while ((!(readw(glamo_mci_def_pdata.pglamo->base +
72972 + GLAMO_REG_IRQ_STATUS) & GLAMO_IRQ_MMC)) &&
72976 + if (timeout < 0) {
72977 + if (cmd->data->error)
72978 + cmd->data->error = -ETIMEDOUT;
72979 + dev_err(&host->pdev->dev, "Payload timeout\n");
72983 + /* yay we are an interrupt controller! -- call the ISR
72984 + * it will stop clock to card
72986 + glamo_mci_irq_host(host);
72991 + host->complete_what = COMPLETION_NONE;
72992 + host->mrq = NULL;
72993 + mmc_request_done(host->mmc, cmd->mrq);
72995 + if (!sd_idleclk && !host->force_slow_during_powerup)
72996 + /* stop the clock to card */
72997 + __glamo_mci_fix_card_div(host, -1);
73000 +static void glamo_mci_request(struct mmc_host *mmc, struct mmc_request *mrq)
73002 + struct glamo_mci_host *host = mmc_priv(mmc);
73004 + host->cmd_is_stop = 0;
73006 + glamo_mci_send_request(mmc);
73010 +static void glamo_mci_reset(struct glamo_mci_host *host)
73012 + if (host->suspending) {
73013 + dev_err(&host->pdev->dev, "IGNORING glamo_mci_reset while "
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);
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);
73031 +static inline int glamo_mci_get_mv(int vdd)
73036 + mv += 350 + 100 * (vdd - 8);
73041 +static void glamo_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
73043 + struct glamo_mci_host *host = mmc_priv(mmc);
73044 + struct regulator *regulator;
73047 + int powering = 0;
73050 + if (host->suspending) {
73051 + dev_err(&host->pdev->dev, "IGNORING glamo_mci_set_ios while "
73056 + regulator = host->regulator;
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);
73067 + case MMC_POWER_ON:
73069 + * we should use very slow clock until first bulk
73070 + * transfer completes OK
73072 + host->force_slow_during_powerup = 1;
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);
73080 + host->vdd_current = ios->vdd;
73082 + if (host->power_mode_current == MMC_POWER_OFF) {
73083 + glamo_engine_enable(glamo_mci_def_pdata.pglamo,
73084 + GLAMO_ENGINE_MMC);
73089 + case MMC_POWER_OFF:
73091 + if (host->power_mode_current == MMC_POWER_OFF)
73093 + /* never want clocking with dead card */
73094 + __glamo_mci_fix_card_div(host, -1);
73096 + glamo_engine_disable(glamo_mci_def_pdata.pglamo,
73097 + GLAMO_ENGINE_MMC);
73098 + regulator_disable(regulator);
73099 + host->vdd_current = -1;
73102 + host->power_mode_current = ios->power_mode;
73104 + host->real_rate = __glamo_mci_set_card_clock(host, ios->clock, &div);
73105 + host->clk_div = div;
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...
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);
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);
73125 + dev_info(&host->pdev->dev, "glamo_mci_set_ios: power down.\n");
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);
73140 + * no physical write protect supported by us
73142 +static int glamo_mci_get_ro(struct mmc_host *mmc)
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,
73153 +static int glamo_mci_probe(struct platform_device *pdev)
73155 + struct mmc_host *mmc;
73156 + struct glamo_mci_host *host;
73159 + dev_info(&pdev->dev, "glamo_mci driver (C)2007 Openmoko, Inc\n");
73161 + mmc = mmc_alloc_host(sizeof(struct glamo_mci_host), &pdev->dev);
73167 + host = mmc_priv(mmc);
73169 + host->pdev = pdev;
73170 + host->pdata = &glamo_mci_def_pdata;
73171 + host->power_mode_current = MMC_POWER_OFF;
73173 + host->complete_what = COMPLETION_NONE;
73174 + host->pio_active = XFER_NONE;
73176 + spin_lock_init(&host->complete_lock);
73177 + INIT_WORK(&host->irq_work, glamo_mci_irq_worker);
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");
73185 + goto probe_free_host;
73188 + host->mem = request_mem_region(host->mem->start,
73189 + RESSIZE(host->mem), pdev->name);
73191 + if (!host->mem) {
73192 + dev_err(&pdev->dev, "failed to request io memory region.\n");
73194 + goto probe_free_host;
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");
73201 + goto probe_free_mem_region;
73204 + host->regulator = regulator_get(&pdev->dev, "SD_3V3");
73205 + if (!host->regulator) {
73206 + dev_err(&pdev->dev, "Cannot proceed without regulator.\n");
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);
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");
73221 + goto probe_iounmap;
73224 + host->mem_data = request_mem_region(host->mem_data->start,
73225 + RESSIZE(host->mem_data), pdev->name);
73227 + if (!host->mem_data) {
73228 + dev_err(&pdev->dev, "failed to request io memory region.\n");
73230 + goto probe_iounmap;
73232 + host->base_data = ioremap(host->mem_data->start,
73233 + RESSIZE(host->mem_data));
73234 + host->data_max_size = RESSIZE(host->mem_data);
73236 + if (host->base_data == 0) {
73237 + dev_err(&pdev->dev, "failed to ioremap() io memory region.\n");
73239 + goto probe_free_mem_region_data;
73242 + host->vdd_current = 0;
73243 + host->clk_rate = 50000000; /* really it's 49152000 */
73244 + host->clk_div = 16;
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;
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;
73262 + dev_info(&host->pdev->dev, "probe: mapped mci_base:%p irq:%u.\n",
73263 + host->base, host->irq);
73265 + platform_set_drvdata(pdev, mmc);
73267 + glamo_engine_enable(glamo_mci_def_pdata.pglamo, GLAMO_ENGINE_MMC);
73268 + glamo_mci_reset(host);
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;
73275 + dev_info(&pdev->dev,"initialisation done.\n");
73278 + probe_free_mem_region_data:
73279 + release_mem_region(host->mem_data->start, RESSIZE(host->mem_data));
73282 + iounmap(host->base);
73284 + probe_free_mem_region:
73285 + release_mem_region(host->mem->start, RESSIZE(host->mem));
73288 + mmc_free_host(mmc);
73293 +static int glamo_mci_remove(struct platform_device *pdev)
73295 + struct mmc_host *mmc = platform_get_drvdata(pdev);
73296 + struct glamo_mci_host *host = mmc_priv(mmc);
73297 + struct regulator *regulator;
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));
73307 + regulator = host->regulator;
73308 + regulator_put(regulator);
73310 + mmc_free_host(mmc);
73312 + glamo_engine_disable(glamo_mci_def_pdata.pglamo, GLAMO_ENGINE_MMC);
73319 +static int glamo_mci_suspend(struct platform_device *dev, pm_message_t state)
73321 + struct mmc_host *mmc = platform_get_drvdata(dev);
73322 + struct glamo_mci_host *host = mmc_priv(mmc);
73325 + cancel_work_sync(&host->irq_work);
73328 + * possible workaround for SD corruption during suspend - resume
73329 + * make sure the clock was running during suspend and consequently
73332 + __glamo_mci_fix_card_div(host, host->clk_div);
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
73338 + suspend_sd_idleclk = sd_idleclk;
73341 + ret = mmc_suspend_host(mmc, state);
73343 + host->suspending++;
73344 + /* so that when we resume, we use any modified max rate */
73345 + mmc->f_max = sd_max_clk;
73350 +int glamo_mci_resume(struct platform_device *dev)
73352 + struct mmc_host *mmc = platform_get_drvdata(dev);
73353 + struct glamo_mci_host *host = mmc_priv(mmc);
73358 + glamo_engine_enable(host->pdata->pglamo, GLAMO_ENGINE_MMC);
73359 + glamo_mci_reset(host);
73361 + host->suspending--;
73363 + ret = mmc_resume_host(mmc);
73365 + /* put sd_idleclk back to pre-suspend state */
73366 + sd_idleclk = suspend_sd_idleclk;
73370 +EXPORT_SYMBOL_GPL(glamo_mci_resume);
73372 +#else /* CONFIG_PM */
73373 +#define glamo_mci_suspend NULL
73374 +#define glamo_mci_resume NULL
73375 +#endif /* CONFIG_PM */
73378 +static struct platform_driver glamo_mci_driver =
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,
73387 +static int __init glamo_mci_init(void)
73389 + spin_lock_init(&clock_lock);
73390 + platform_driver_register(&glamo_mci_driver);
73394 +static void __exit glamo_mci_exit(void)
73396 + platform_driver_unregister(&glamo_mci_driver);
73399 +module_init(glamo_mci_init);
73400 +module_exit(glamo_mci_exit);
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
73410 + * linux/drivers/mmc/host/glamo-mmc.h - GLAMO MCI driver
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.
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.
73421 +#include <linux/regulator/consumer.h>
73423 +enum glamo_mci_waitfor {
73425 + COMPLETION_FINALIZE,
73426 + COMPLETION_CMDSENT,
73427 + COMPLETION_RSPFIN,
73428 + COMPLETION_XFERFINISH,
73429 + COMPLETION_XFERFINISH_RSPFIN,
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;
73439 + void __iomem *base;
73440 + u16 __iomem *base_data;
73444 + int data_max_size;
73448 + int power_mode_current;
73449 + unsigned int vdd_current;
73451 + unsigned long clk_rate;
73452 + unsigned long clk_div;
73453 + unsigned long real_rate;
73456 + int force_slow_during_powerup;
73458 + unsigned sdiimsk;
73461 + volatile int dmatogo;
73463 + struct mmc_request *mrq;
73465 + struct work_struct irq_work;
73467 + spinlock_t complete_lock;
73468 + volatile enum glamo_mci_waitfor
73471 + volatile int dma_complete;
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;
73484 + char dbgmsg_cmd[301];
73485 + char dbgmsg_dat[301];
73486 + volatile char *status;
73488 + unsigned int ccnt, dcnt;
73489 + struct tasklet_struct pio_tasklet;
73491 + struct regulator *regulator;
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
73497 +#ifndef _GLAMO_REGS_H
73498 +#define _GLAMO_REGS_H
73500 +/* Smedia Glamo 336x/337x driver
73502 + * (C) 2007 by Openmoko, Inc.
73503 + * Author: Harald Welte <laforge@openmoko.org>
73504 + * All rights reserved.
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.
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.
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
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,
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,
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,
73597 + GLAMO_REG_DFT_GEN5 = 0x01e0,
73598 + GLAMO_REG_DFT_GEN6 = 0x01f0,
73601 +#define GLAMO_REG_HOSTBUS(x) (GLAMO_REGOFS_HOSTBUS-2+(x*2))
73603 +#define REG_MEM(x) (GLAMO_REGOFS_MEMORY+(x))
73604 +#define GLAMO_REG_MEM_TIMING(x) (GLAMO_REG_MEM_TIMING1-2+(x*2))
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),
73638 +#define GLAMO_MEM_TYPE_MASK 0x03
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),
73649 +enum glamo_reg_mem_dram2 {
73650 + GLAMO_MEM_DRAM2_DEEP_PWRDOWN = (1 << 12),
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,
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),
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,
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,
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,
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,
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,
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,
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
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
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,
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,
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,
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,
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
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,
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,
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,
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,
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,
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,
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,
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 */
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,
73939 +/* LCD Controller */
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),
73957 + GLAMO_REG_LCD_HORIZ_TOTAL = REG_LCD(0x1c),
73959 + GLAMO_REG_LCD_HORIZ_RETR_START = REG_LCD(0x20),
73961 + GLAMO_REG_LCD_HORIZ_RETR_END = REG_LCD(0x24),
73963 + GLAMO_REG_LCD_HORIZ_DISP_START = REG_LCD(0x28),
73965 + GLAMO_REG_LCD_HORIZ_DISP_END = REG_LCD(0x2c),
73967 + GLAMO_REG_LCD_VERT_TOTAL = REG_LCD(0x30),
73969 + GLAMO_REG_LCD_VERT_RETR_START = REG_LCD(0x34),
73971 + GLAMO_REG_LCD_VERT_RETR_END = REG_LCD(0x38),
73973 + GLAMO_REG_LCD_VERT_DISP_START = REG_LCD(0x3c),
73975 + GLAMO_REG_LCD_VERT_DISP_END = REG_LCD(0x40),
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),
73993 + GLAMO_REG_LCD_CURSOR_BG_COLOR = REG_LCD(0x64),
73995 + GLAMO_REG_LCD_CURSOR_DST_COLOR = REG_LCD(0x68),
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),
74002 + GLAMO_REG_LCD_COMMAND1 = REG_LCD(0xa0),
74003 + GLAMO_REG_LCD_COMMAND2 = REG_LCD(0xa2),
74005 + GLAMO_REG_LCD_WFORM_DELAY1 = REG_LCD(0xb0),
74006 + GLAMO_REG_LCD_WFORM_DELAY2 = REG_LCD(0xb2),
74008 + GLAMO_REG_LCD_GAMMA_CORR = REG_LCD(0x100),
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),
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),
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),
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),
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,
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,
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,
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,
74073 + GLAMO_LCD_MODE3_RGB332 = 0x0000,
74074 + GLAMO_LCD_MODE3_RGB444 = 0x0100,
74075 + GLAMO_LCD_MODE3_RGB565 = 0x0200,
74076 + GLAMO_LCD_MODE3_RGB666 = 0x0300,
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,
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,
74093 +#define GLAMO_LCD_ROT_MODE_MASK 0xe000
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,
74101 +#define GLAMO_LCD_CMD_TYPE_MASK 0xc000
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 */
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,
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
74134 + * Copyright (C) 2007 Openmoko, Inc.
74135 + * Author: Harald Welte <laforge@openmoko.org>
74137 + * Smedia Glamo GPIO based SPI driver
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.
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.
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>
74159 +#include <linux/spi/spi.h>
74160 +#include <linux/spi/spi_bitbang.h>
74161 +#include <linux/spi/glamo.h>
74163 +#include <linux/glamofb.h>
74165 +#include <mach/hardware.h>
74167 +#include "glamo-core.h"
74168 +#include "glamo-regs.h"
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;
74177 +static inline struct glamo_spigpio *to_sg(struct spi_device *spi)
74179 + return dev_get_drvdata(&spi->master->dev);
74182 +static inline void setsck(struct spi_device *dev, int on)
74184 + struct glamo_spigpio *sg = to_sg(dev);
74185 + glamo_gpio_setpin(sg->glamo, sg->info->pin_clk, on ? 1 : 0);
74188 +static inline void setmosi(struct spi_device *dev, int on)
74190 + struct glamo_spigpio *sg = to_sg(dev);
74191 + glamo_gpio_setpin(sg->glamo, sg->info->pin_mosi, on ? 1 : 0);
74194 +static inline u32 getmiso(struct spi_device *dev)
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;
74203 +#define spidelay(x) ndelay(x)
74205 +#define EXPAND_BITBANG_TXRX
74206 +#include <linux/spi/spi_bitbang.h>
74208 +static u32 glamo_spigpio_txrx_mode0(struct spi_device *spi,
74209 + unsigned nsecs, u32 word, u8 bits)
74211 + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
74214 +static u32 glamo_spigpio_txrx_mode1(struct spi_device *spi,
74215 + unsigned nsecs, u32 word, u8 bits)
74217 + return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
74220 +static u32 glamo_spigpio_txrx_mode2(struct spi_device *spi,
74221 + unsigned nsecs, u32 word, u8 bits)
74223 + return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
74226 +static u32 glamo_spigpio_txrx_mode3(struct spi_device *spi,
74227 + unsigned nsecs, u32 word, u8 bits)
74229 + return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
74234 +static int glamo_spigpio_setupxfer(struct spi_device *spi,
74235 + struct spi_transfer *t)
74237 + struct glamo_spi *gs = to_sg(spi);
74238 + unsigned int bpw;
74240 + bpw = t ? t->bits_per_word : spi->bits_per_word;
74242 + if (bpw != 9 && bpw != 8) {
74243 + dev_err(&spi->dev, "invalid bits-per-word (%d)\n", bpw);
74251 +static void glamo_spigpio_chipsel(struct spi_device *spi, int value)
74253 + struct glamo_spigpio *gs = to_sg(spi);
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);
74258 + glamo_gpio_setpin(gs->glamo, gs->info->pin_cs, value ? 0 : 1);
74262 +static int glamo_spigpio_probe(struct platform_device *pdev)
74264 + struct spi_master *master;
74265 + struct glamo_spigpio *sp;
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");
74275 + sp = spi_master_get_devdata(master);
74276 + platform_set_drvdata(pdev, sp);
74277 + sp->info = pdev->dev.platform_data;
74279 + dev_err(&pdev->dev, "can't operate without platform data\n");
74281 + goto err_no_pdev;
74284 + master->num_chipselect = 1;
74285 + master->bus_num = 2; /* FIXME: use dynamic number */
74287 + sp->master = spi_master_get(master);
74288 + sp->glamo = sp->info->glamo;
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;
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);
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);
74308 + /* bring the LCM panel out of reset if it isn't already */
74310 + glamo_gpio_setpin(sp->glamo, GLAMO_GPIO4, 1);
74311 + glamo_gpio_cfgpin(sp->glamo, GLAMO_GPIO4_OUTPUT);
74315 + sp->dev = &pdev->dev;
74317 + sp->bitbang.setup_transfer = glamo_spi_setupxfer;
74318 + sp->bitbang.txrx_bufs = glamo_spi_txrx;
74319 + sp->bitbang.master->setup = glamo_spi_setup;
74322 + dev_set_drvdata(&sp->master->dev, sp);
74324 + ret = spi_bitbang_start(&sp->bitbang);
74326 + goto err_no_bitbang;
74331 + platform_set_drvdata(pdev, NULL);
74333 + spi_master_put(sp->bitbang.master);
74339 +static int glamo_spigpio_remove(struct platform_device *pdev)
74341 + struct glamo_spigpio *sp = platform_get_drvdata(pdev);
74343 + spi_bitbang_stop(&sp->bitbang);
74344 + spi_master_put(sp->bitbang.master);
74349 +/*#define glamo_spigpio_suspend NULL
74350 +#define glamo_spigpio_resume NULL
74355 +static int glamo_spigpio_suspend(struct platform_device *pdev, pm_message_t state)
74360 +static int glamo_spigpio_resume(struct platform_device *pdev)
74362 + struct glamo_spigpio *sp = platform_get_drvdata(pdev);
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);
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);
74382 +static struct platform_driver glamo_spi_drv = {
74383 + .probe = glamo_spigpio_probe,
74384 + .remove = glamo_spigpio_remove,
74386 + .suspend_late = glamo_spigpio_suspend,
74387 + .resume_early = glamo_spigpio_resume,
74390 + .name = "glamo-spi-gpio",
74391 + .owner = THIS_MODULE,
74395 +static int __init glamo_spi_init(void)
74397 + return platform_driver_register(&glamo_spi_drv);
74400 +static void __exit glamo_spi_exit(void)
74402 + platform_driver_unregister(&glamo_spi_drv);
74405 +module_init(glamo_spi_init);
74406 +module_exit(glamo_spi_exit);
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
74416 + bool "Smedia Glamo 336x/337x support"
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.
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
74429 + Frame buffer driver for the LCD controller in the Smedia Glamo
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>.
74437 + If unsure, say N.
74439 +config MFD_GLAMO_FB_XGLAMO_WORKAROUND
74440 + bool "Smedia Glamo 336x/337x Xglamo rotation workaround"
74441 + depends on MFD_GLAMO_FB
74443 + This is a workaround for a Xglamo bug. This should be fixed
74444 + in Xglamo and not in kernel space.
74446 + If unsure, say N.
74449 +config MFD_GLAMO_SPI_GPIO
74450 + tristate "Glamo GPIO SPI bitbang support"
74451 + depends on MFD_GLAMO
74453 + Enable a bitbanging SPI adapter driver for the Smedia Glamo.
74455 +config MFD_GLAMO_SPI_FB
74456 + tristate "Glamo LCM control channel SPI support"
74457 + depends on MFD_GLAMO_FB
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.
74463 +config MFD_GLAMO_MCI
74464 + tristate "Glamo S3C SD/MMC Card Interface support"
74465 + depends on MFD_GLAMO && MMC
74467 + This selects a driver for the MCI interface found in
74468 + the S-Media GLAMO chip, as used in Openmoko
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
74477 +# Makefile for the Smedia Glamo framebuffer driver
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
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
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
74496 +config MFD_PCF50606
74497 + tristate "Support for NXP PCF50606"
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.
74505 +config PCF50606_ADC
74506 + tristate "Support for NXP PCF50606 ADC"
74507 + depends on MFD_PCF50606
74509 + Say yes here if you want to include support for ADC in the
74510 + NXP PCF50606 chip.
74512 +config PCF50606_GPO
74513 + tristate "Support for NXP PCF50606 GPO"
74514 + depends on MFD_PCF50606
74516 + Say yes here if you want to include support GPO for pins on
74517 + the PCF50606 chip.
74520 +source "drivers/mfd/glamo/Kconfig"
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
74530 obj-$(CONFIG_MFD_SM501) += sm501.o
74531 obj-$(CONFIG_MFD_ASIC3) += asic3.o
74532 +obj-$(CONFIG_MFD_GLAMO) += glamo/
74534 obj-$(CONFIG_HTC_EGPIO) += htc-egpio.o
74535 obj-$(CONFIG_HTC_PASIC3) += htc-pasic3.o
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
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
74551 +/* Philips PCF50606 ADC Driver
74553 + * (C) 2006-2008 by Openmoko, Inc.
74554 + * Author: Balaji Rao <balajirrao@openmoko.org>
74555 + * All rights reserved.
74557 + * Broken down from monstrous PCF50606 driver mainly by
74558 + * Harald Welte, Andy Green, Werner Almesberger and Matt Hsu
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.
74565 + * NOTE: This driver does not yet support subtractive ADC mode, which means
74566 + * you can do only one measurement per read request.
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>
74576 +#include <linux/mfd/pcf50606/core.h>
74577 +#include <linux/mfd/pcf50606/adc.h>
74579 +struct pcf50606_adc_request {
74582 + void (*callback)(struct pcf50606 *, void *, int);
74583 + void *callback_param;
74585 + /* Used in case of sync requests */
74586 + struct completion completion;
74590 +#define PCF50606_MAX_ADC_FIFO_DEPTH 8
74592 +struct pcf50606_adc {
74593 + struct pcf50606 *pcf;
74595 + /* Private stuff */
74596 + struct pcf50606_adc_request *queue[PCF50606_MAX_ADC_FIFO_DEPTH];
74599 + struct mutex queue_mutex;
74602 +static inline struct pcf50606_adc *__to_adc(struct pcf50606 *pcf)
74604 + return platform_get_drvdata(pcf->adc_pdev);
74607 +static void adc_setup(struct pcf50606 *pcf, int channel)
74609 + channel &= PCF50606_ADCC2_ADCMUX_MASK;
74611 + /* start ADC conversion of selected channel */
74612 + pcf50606_reg_write(pcf, PCF50606_REG_ADCC2, channel |
74613 + PCF50606_ADCC2_ADCSTART | PCF50606_ADCC2_RES_10BIT);
74617 +static void trigger_next_adc_job_if_any(struct pcf50606 *pcf)
74619 + struct pcf50606_adc *adc = __to_adc(pcf);
74622 + mutex_lock(&adc->queue_mutex);
74624 + head = adc->queue_head;
74625 + tail = adc->queue_tail;
74627 + if (!adc->queue[head])
74630 + adc_setup(pcf, adc->queue[head]->mux);
74632 + mutex_unlock(&adc->queue_mutex);
74636 +adc_enqueue_request(struct pcf50606 *pcf, struct pcf50606_adc_request *req)
74638 + struct pcf50606_adc *adc = __to_adc(pcf);
74641 + mutex_lock(&adc->queue_mutex);
74642 + head = adc->queue_head;
74643 + tail = adc->queue_tail;
74645 + if (adc->queue[tail]) {
74646 + mutex_unlock(&adc->queue_mutex);
74650 + adc->queue[tail] = req;
74652 + adc->queue_tail =
74653 + (tail + 1) & (PCF50606_MAX_ADC_FIFO_DEPTH - 1);
74655 + mutex_unlock(&adc->queue_mutex);
74657 + trigger_next_adc_job_if_any(pcf);
74663 +pcf50606_adc_sync_read_callback(struct pcf50606 *pcf, void *param, int result)
74665 + struct pcf50606_adc_request *req;
74667 + /*We know here that the passed param is an adc_request object */
74668 + req = (struct pcf50606_adc_request *)param;
74670 + req->result = result;
74671 + complete(&req->completion);
74674 +int pcf50606_adc_sync_read(struct pcf50606 *pcf, int mux)
74677 + struct pcf50606_adc_request *req;
74680 + /* req is freed when the result is ready, in irq handler*/
74681 + req = kzalloc(sizeof(*req), GFP_KERNEL);
74686 + req->callback = pcf50606_adc_sync_read_callback;
74687 + req->callback_param = req;
74688 + init_completion(&req->completion);
74690 + adc_enqueue_request(pcf, req);
74692 + if (wait_for_completion_timeout(&req->completion, 5 * HZ) == 5 * HZ) {
74693 + dev_err(pcf->dev, "ADC read timed out \n");
74696 + result = req->result;
74700 +EXPORT_SYMBOL_GPL(pcf50606_adc_sync_read);
74702 +int pcf50606_adc_async_read(struct pcf50606 *pcf, int mux,
74703 + void (*callback)(struct pcf50606 *, void *, int),
74704 + void *callback_param)
74706 + struct pcf50606_adc_request *req;
74708 + /* req is freed when the result is ready, in pcf50606_work*/
74709 + req = kmalloc(sizeof(*req), GFP_KERNEL);
74714 + req->callback = callback;
74715 + req->callback_param = callback_param;
74717 + adc_enqueue_request(pcf, req);
74721 +EXPORT_SYMBOL_GPL(pcf50606_adc_async_read);
74723 +static int adc_result(struct pcf50606 *pcf)
74725 + u16 ret = (pcf50606_reg_read(pcf, PCF50606_REG_ADCS1) << 2) |
74726 + (pcf50606_reg_read(pcf, PCF50606_REG_ADCS2) & 0x03);
74728 + dev_dbg(pcf->dev, "adc result = %d\n", ret);
74733 +static void pcf50606_adc_irq(int irq, void *data)
74735 + struct pcf50606_adc *adc = data;
74736 + struct pcf50606 *pcf = adc->pcf;
74737 + struct pcf50606_adc_request *req;
74740 + mutex_lock(&adc->queue_mutex);
74741 + head = adc->queue_head;
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);
74750 + adc->queue[head] = NULL;
74751 + adc->queue_head = (head + 1) &
74752 + (PCF50606_MAX_ADC_FIFO_DEPTH - 1);
74754 + mutex_unlock(&adc->queue_mutex);
74756 + req->callback(pcf, req->callback_param, adc_result(pcf));
74759 + trigger_next_adc_job_if_any(pcf);
74762 +static int __devinit pcf50606_adc_probe(struct platform_device *pdev)
74764 + struct pcf50606_subdev_pdata *pdata = pdev->dev.platform_data;
74765 + struct pcf50606_adc *adc;
74767 + adc = kzalloc(sizeof(*adc), GFP_KERNEL);
74771 + adc->pcf = pdata->pcf;
74772 + platform_set_drvdata(pdev, adc);
74774 + pcf50606_register_irq(pdata->pcf, PCF50606_IRQ_ADCRDY,
74775 + pcf50606_adc_irq, adc);
74777 + mutex_init(&adc->queue_mutex);
74782 +static int __devexit pcf50606_adc_remove(struct platform_device *pdev)
74784 + struct pcf50606_adc *adc = platform_get_drvdata(pdev);
74787 + pcf50606_free_irq(adc->pcf, PCF50606_IRQ_ADCRDY);
74789 + mutex_lock(&adc->queue_mutex);
74790 + head = adc->queue_head;
74792 + if (WARN_ON(adc->queue[head]))
74793 + dev_err(adc->pcf->dev,
74794 + "adc driver removed with request pending\n");
74796 + for (i = 0; i < PCF50606_MAX_ADC_FIFO_DEPTH; i++)
74797 + kfree(adc->queue[i]);
74799 + mutex_unlock(&adc->queue_mutex);
74805 +struct platform_driver pcf50606_adc_driver = {
74807 + .name = "pcf50606-adc",
74809 + .probe = pcf50606_adc_probe,
74810 + .remove = __devexit_p(pcf50606_adc_remove),
74813 +static int __init pcf50606_adc_init(void)
74815 + return platform_driver_register(&pcf50606_adc_driver);
74817 +module_init(pcf50606_adc_init);
74819 +static void __exit pcf50606_adc_exit(void)
74821 + platform_driver_unregister(&pcf50606_adc_driver);
74823 +module_exit(pcf50606_adc_exit);
74825 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
74826 +MODULE_DESCRIPTION("PCF50606 adc driver");
74827 +MODULE_LICENSE("GPL");
74828 +MODULE_ALIAS("platform:pcf50606-adc");
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
74834 +/* Philips PCF50606 Power Management Unit (PMU) driver
74836 + * (C) 2006-2008 by Openmoko, Inc.
74837 + * Author: Harald Welte <laforge@openmoko.org>
74838 + * Matt Hsu <matt@openmoko.org>
74839 + * All rights reserved.
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.
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>
74861 +#include <linux/mfd/pcf50606/core.h>
74863 +static int __pcf50606_read(struct pcf50606 *pcf, u8 reg, int num, u8 *data)
74867 + ret = i2c_smbus_read_i2c_block_data(pcf->i2c_client, reg,
74870 + dev_err(pcf->dev, "Error reading %d regs at %d\n", num, reg);
74875 +static int __pcf50606_write(struct pcf50606 *pcf, u8 reg, int num, u8 *data)
74879 + ret = i2c_smbus_write_i2c_block_data(pcf->i2c_client, reg,
74882 + dev_err(pcf->dev, "Error writing %d regs at %d\n", num, reg);
74888 +/* Read a block of upto 32 regs */
74889 +int pcf50606_read_block(struct pcf50606 *pcf, u8 reg,
74890 + int nr_regs, u8 *data)
74894 + mutex_lock(&pcf->lock);
74895 + ret = __pcf50606_read(pcf, reg, nr_regs, data);
74896 + mutex_unlock(&pcf->lock);
74900 +EXPORT_SYMBOL_GPL(pcf50606_read_block);
74902 +/* Write a block of upto 32 regs */
74903 +int pcf50606_write_block(struct pcf50606 *pcf , u8 reg,
74904 + int nr_regs, u8 *data)
74908 + mutex_lock(&pcf->lock);
74909 + ret = __pcf50606_write(pcf, reg, nr_regs, data);
74910 + mutex_unlock(&pcf->lock);
74914 +EXPORT_SYMBOL_GPL(pcf50606_write_block);
74916 +u8 pcf50606_reg_read(struct pcf50606 *pcf, u8 reg)
74920 + mutex_lock(&pcf->lock);
74921 + __pcf50606_read(pcf, reg, 1, &val);
74922 + mutex_unlock(&pcf->lock);
74926 +EXPORT_SYMBOL_GPL(pcf50606_reg_read);
74928 +int pcf50606_reg_write(struct pcf50606 *pcf, u8 reg, u8 val)
74932 + mutex_lock(&pcf->lock);
74933 + ret = __pcf50606_write(pcf, reg, 1, &val);
74934 + mutex_unlock(&pcf->lock);
74938 +EXPORT_SYMBOL_GPL(pcf50606_reg_write);
74940 +int pcf50606_reg_set_bit_mask(struct pcf50606 *pcf, u8 reg, u8 mask, u8 val)
74947 + mutex_lock(&pcf->lock);
74948 + ret = __pcf50606_read(pcf, reg, 1, &tmp);
74954 + ret = __pcf50606_write(pcf, reg, 1, &tmp);
74957 + mutex_unlock(&pcf->lock);
74961 +EXPORT_SYMBOL_GPL(pcf50606_reg_set_bit_mask);
74963 +int pcf50606_reg_clear_bits(struct pcf50606 *pcf, u8 reg, u8 val)
74968 + mutex_lock(&pcf->lock);
74969 + ret = __pcf50606_read(pcf, reg, 1, &tmp);
74974 + ret = __pcf50606_write(pcf, reg, 1, &tmp);
74977 + mutex_unlock(&pcf->lock);
74981 +EXPORT_SYMBOL_GPL(pcf50606_reg_clear_bits);
74983 +/* sysfs attributes */
74984 +static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr,
74987 + struct pcf50606 *pcf = dev_get_drvdata(dev);
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 */
74998 + for (n = 0; n < 256; n += sizeof(dump)) {
74999 + for (n1 = 0; n1 < sizeof(dump); n1++)
75000 + if (n == address_no_read[idx]) {
75004 + dump[n1] = pcf50606_reg_read(pcf, n + n1);
75006 + hex_dump_to_buffer(dump, sizeof(dump), 16, 1, buf1, 128, 0);
75007 + buf1 += strlen(buf1);
75012 + return buf1 - buf;
75014 +static DEVICE_ATTR(dump_regs, 0400, show_dump_regs, NULL);
75016 +static ssize_t show_resume_reason(struct device *dev,
75017 + struct device_attribute *attr, char *buf)
75019 + struct pcf50606 *pcf = dev_get_drvdata(dev);
75022 + n = sprintf(buf, "%02x%02x%02x\n",
75023 + pcf->resume_reason[0],
75024 + pcf->resume_reason[1],
75025 + pcf->resume_reason[2]);
75029 +static DEVICE_ATTR(resume_reason, 0400, show_resume_reason, NULL);
75031 +static struct attribute *pcf_sysfs_entries[] = {
75032 + &dev_attr_dump_regs.attr,
75033 + &dev_attr_resume_reason.attr,
75037 +static struct attribute_group pcf_attr_group = {
75038 + .name = NULL, /* put in device directory */
75039 + .attrs = pcf_sysfs_entries,
75042 +int pcf50606_register_irq(struct pcf50606 *pcf, int irq,
75043 + void (*handler) (int, void *), void *data)
75045 + if (irq < 0 || irq > PCF50606_NUM_IRQ || !handler)
75048 + if (WARN_ON(pcf->irq_handler[irq].handler))
75051 + mutex_lock(&pcf->lock);
75052 + pcf->irq_handler[irq].handler = handler;
75053 + pcf->irq_handler[irq].data = data;
75054 + mutex_unlock(&pcf->lock);
75058 +EXPORT_SYMBOL_GPL(pcf50606_register_irq);
75060 +int pcf50606_free_irq(struct pcf50606 *pcf, int irq)
75062 + if (irq < 0 || irq > PCF50606_NUM_IRQ)
75065 + mutex_lock(&pcf->lock);
75066 + pcf->irq_handler[irq].handler = NULL;
75067 + mutex_unlock(&pcf->lock);
75071 +EXPORT_SYMBOL_GPL(pcf50606_free_irq);
75073 +static int __pcf50606_irq_mask_set(struct pcf50606 *pcf, int irq, u8 mask)
75075 + u8 reg, bits, tmp;
75076 + int ret = 0, idx;
75079 + reg = PCF50606_REG_INT1M + idx;
75080 + bits = 1 << (irq & 0x07);
75082 + mutex_lock(&pcf->lock);
75085 + ret = __pcf50606_read(pcf, reg, 1, &tmp);
75091 + ret = __pcf50606_write(pcf, reg, 1, &tmp);
75095 + pcf->mask_regs[idx] &= ~bits;
75096 + pcf->mask_regs[idx] |= bits;
75098 + ret = __pcf50606_read(pcf, reg, 1, &tmp);
75104 + ret = __pcf50606_write(pcf, reg, 1, &tmp);
75108 + pcf->mask_regs[idx] &= ~bits;
75111 + mutex_unlock(&pcf->lock);
75116 +int pcf50606_irq_mask(struct pcf50606 *pcf, int irq)
75118 + dev_info(pcf->dev, "Masking IRQ %d\n", irq);
75120 + return __pcf50606_irq_mask_set(pcf, irq, 1);
75122 +EXPORT_SYMBOL_GPL(pcf50606_irq_mask);
75124 +int pcf50606_irq_unmask(struct pcf50606 *pcf, int irq)
75126 + dev_info(pcf->dev, "Unmasking IRQ %d\n", irq);
75128 + return __pcf50606_irq_mask_set(pcf, irq, 0);
75130 +EXPORT_SYMBOL_GPL(pcf50606_irq_unmask);
75132 +int pcf50606_irq_mask_get(struct pcf50606 *pcf, int irq)
75137 + bits = (1 << (irq % 8));
75139 + return pcf->mask_regs[reg] & bits;
75141 +EXPORT_SYMBOL_GPL(pcf50606_irq_mask_get);
75143 +static void pcf50606_irq_call_handler(struct pcf50606 *pcf,
75146 + if (pcf->irq_handler[irq].handler)
75147 + pcf->irq_handler[irq].handler(irq, pcf->irq_handler[irq].data);
75150 +#define PCF50606_ONKEY1S_TIMEOUT 8
75152 +#define PCF50606_REG_MBCS1 0x2c
75154 +static void pcf50606_irq_worker(struct work_struct *work)
75156 + struct pcf50606 *pcf;
75158 + u8 pcf_int[3], chgstat;
75160 + pcf = container_of(work, struct pcf50606, irq_work);
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");
75169 + * If this doesn't ACK the interrupt to the chip, we'll be
75170 + * called once again as we're level triggered.
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);
75182 + pcf_int[1] &= ~(1 << PCF50606_INT2_CHGINS);
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]);
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);
75198 + if (pcf_int[0] & PCF50606_INT1_ONKEY1S) {
75199 + dev_info(pcf->dev, "ONKEY1S held\n");
75200 + pcf->onkey1s_held = 1 ;
75202 + /* Unmask IRQ_SECOND */
75203 + pcf50606_reg_clear_bits(pcf, PCF50606_REG_INT1M,
75204 + PCF50606_INT1_SECOND);
75206 + /* Unmask IRQ_ONKEYF */
75207 + pcf50606_reg_clear_bits(pcf, PCF50606_REG_INT1M,
75208 + PCF50606_INT1_ONKEYF);
75211 + if ((pcf_int[0] & PCF50606_INT1_ONKEYR) && pcf->onkey1s_held) {
75212 + pcf->onkey1s_held = 0;
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);
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);
75228 + /* Have we just resumed ? */
75229 + if (pcf->is_suspended) {
75231 + pcf->is_suspended = 0;
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];
75238 + /* Make sure we don't pass on ONKEY events to
75239 + * userspace now */
75240 + pcf_int[1] &= ~(PCF50606_INT1_ONKEYR | PCF50606_INT1_ONKEYF);
75243 + for (i = 0; i < ARRAY_SIZE(pcf_int); i++) {
75244 + /* Unset masked interrupts */
75245 + pcf_int[i] &= ~pcf->mask_regs[i];
75247 + for (j = 0; j < 8 ; j++)
75248 + if (pcf_int[i] & (1 << j))
75249 + pcf50606_irq_call_handler(pcf, (i * 8) + j);
75253 + put_device(pcf->dev);
75254 + enable_irq(pcf->irq);
75257 +static irqreturn_t pcf50606_irq(int irq, void *data)
75259 + struct pcf50606 *pcf = data;
75261 + get_device(pcf->dev);
75262 + disable_irq(pcf->irq);
75263 + schedule_work(&pcf->irq_work);
75265 + return IRQ_HANDLED;
75269 +pcf50606_client_dev_register(struct pcf50606 *pcf, const char *name,
75270 + struct platform_device **pdev)
75272 + struct pcf50606_subdev_pdata subdev_pdata;
75275 + *pdev = platform_device_alloc(name, -1);
75277 + dev_err(pcf->dev, "Falied to allocate %s\n", name);
75281 + subdev_pdata.pcf = pcf;
75282 + platform_device_add_data(*pdev, &subdev_pdata, sizeof(subdev_pdata));
75284 + (*pdev)->dev.parent = pcf->dev;
75286 + ret = platform_device_add(*pdev);
75288 + dev_err(pcf->dev, "Failed to register %s: %d\n", name, ret);
75289 + platform_device_put(*pdev);
75295 +static int pcf50606_suspend(struct device *dev, pm_message_t state)
75297 + struct pcf50606 *pcf;
75301 + pcf = dev_get_drvdata(dev);
75303 + /* Make sure our interrupt handlers are not called
75305 + disable_irq(pcf->irq);
75307 + /* Make sure that any running IRQ worker has quit */
75308 + cancel_work_sync(&pcf->irq_work);
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);
75315 + dev_err(pcf->dev, "error saving irq masks\n");
75319 + /* Write wakeup irq masks */
75320 + for (i = 0; i < ARRAY_SIZE(res); i++)
75321 + res[i] = ~pcf->pdata->resumers[i];
75323 + ret = pcf50606_write_block(pcf, PCF50606_REG_INT1M,
75324 + ARRAY_SIZE(res), &res[0]);
75326 + dev_err(pcf->dev, "error writing wakeup irq masks\n");
75330 + pcf->is_suspended = 1;
75336 +static int pcf50606_resume(struct device *dev)
75338 + struct pcf50606 *pcf;
75341 + pcf = dev_get_drvdata(dev);
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);
75348 + dev_err(pcf->dev, "Error restoring saved suspend masks\n");
75350 + get_device(pcf->dev);
75353 + * Clear any pending interrupts and set resume reason if any.
75354 + * This will leave with enable_irq()
75356 + pcf50606_irq_worker(&pcf->irq_work);
75361 +#define pcf50606_suspend NULL
75362 +#define pcf50606_resume NULL
75365 +static int pcf50606_probe(struct i2c_client *client,
75366 + const struct i2c_device_id *ids)
75368 + struct pcf50606 *pcf;
75369 + struct pcf50606_platform_data *pdata = client->dev.platform_data;
75371 + int version, variant;
75373 + pcf = kzalloc(sizeof(*pcf), GFP_KERNEL);
75377 + pcf->pdata = pdata;
75379 + mutex_init(&pcf->lock);
75381 + i2c_set_clientdata(client, pcf);
75382 + pcf->dev = &client->dev;
75383 + pcf->i2c_client = client;
75384 + pcf->irq = client->irq;
75386 + INIT_WORK(&pcf->irq_work, pcf50606_irq_worker);
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");
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);
75404 + pcf50606_client_dev_register(pcf, "pcf50606-input",
75405 + &pcf->input_pdev);
75406 + pcf50606_client_dev_register(pcf, "pcf50606-rtc",
75408 + pcf50606_client_dev_register(pcf, "pcf50606-mbc",
75410 + pcf50606_client_dev_register(pcf, "pcf50606-adc",
75412 + pcf50606_client_dev_register(pcf, "pcf50606-wdt",
75414 + for (i = 0; i < PCF50606_NUM_REGULATORS; i++) {
75415 + struct platform_device *pdev;
75417 + pdev = platform_device_alloc("pcf50606-regltr", i);
75419 + dev_err(pcf->dev, "Cannot create regulator\n");
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;
75428 + platform_device_add(pdev);
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);
75437 + dev_err(pcf->dev, "Failed to request IRQ %d\n", ret);
75441 + dev_err(pcf->dev, "No IRQ configured\n");
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);
75449 + ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
75451 + dev_err(pcf->dev, "error creating sysfs entries\n");
75453 + if (pdata->probe_done)
75454 + pdata->probe_done(pcf);
75463 +static int pcf50606_remove(struct i2c_client *client)
75465 + struct pcf50606 *pcf = i2c_get_clientdata(client);
75468 + free_irq(pcf->irq, pcf);
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);
75475 + for (i = 0; i < PCF50606_NUM_REGULATORS; i++)
75476 + platform_device_unregister(pcf->regulator_pdev[i]);
75483 +static struct i2c_device_id pcf50606_id_table[] = {
75484 + {"pcf50606", 0x08},
75487 +static struct i2c_driver pcf50606_driver = {
75489 + .name = "pcf50606",
75490 + .suspend = pcf50606_suspend,
75491 + .resume = pcf50606_resume,
75493 + .id_table = pcf50606_id_table,
75494 + .probe = pcf50606_probe,
75495 + .remove = pcf50606_remove,
75498 +static int __init pcf50606_init(void)
75500 + return i2c_add_driver(&pcf50606_driver);
75503 +static void pcf50606_exit(void)
75505 + i2c_del_driver(&pcf50606_driver);
75508 +MODULE_DESCRIPTION("I2C chip driver for NXP PCF50606 PMU");
75509 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
75510 +MODULE_LICENSE("GPL");
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
75518 +/* Philips PCF50606 GPO Driver
75520 + * (C) 2006-2008 by Openmoko, Inc.
75521 + * Author: Balaji Rao <balajirrao@openmoko.org>
75522 + * All rights reserved.
75524 + * Broken down from monstrous PCF50606 driver mainly by
75525 + * Harald Welte, Andy Green Werner Almesberger and Matt Hsu
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.
75533 +#include <linux/kernel.h>
75535 +#include <linux/mfd/pcf50606/core.h>
75536 +#include <linux/mfd/pcf50606/gpo.h>
75538 +void pcf50606_gpo_set_active(struct pcf50606 *pcf, int gpo, int val)
75540 + u8 reg, value, mask;
75546 + if (gpo == PCF50606_GPO2) {
75547 + value = val << 4;
75548 + mask = 0x07 << 4;
75550 + pcf50606_reg_set_bit_mask(pcf, reg, mask, value);
75552 +EXPORT_SYMBOL_GPL(pcf50606_gpo_set_active);
75554 +int pcf50606_gpo_get_active(struct pcf50606 *pcf, int gpo)
75556 + u8 reg, value, shift = 0;
75559 + if (gpo == PCF50606_GPO2)
75562 + value = pcf50606_reg_read(pcf, reg);
75564 + return (value >> shift) & 0x07;
75566 +EXPORT_SYMBOL_GPL(pcf50606_gpo_get_active);
75568 +void pcf50606_gpo_set_standby(struct pcf50606 *pcf, int gpo, int val)
75572 + if (gpo == PCF50606_GPO1 || gpo == PCF50606_GPO2) {
75573 + dev_err(pcf->dev, "Can't set standby settings for GPO[12]n");
75579 + pcf50606_reg_set_bit_mask(pcf, gpo, 0x07 << 3, val);
75581 +EXPORT_SYMBOL_GPL(pcf50606_gpo_set_standby);
75583 +int pcf50606_gpo_get_standby(struct pcf50606 *pcf, int gpo)
75587 + if (gpo == PCF50606_GPO1 || gpo == PCF50606_GPO2) {
75588 + dev_err(pcf->dev, "Can't get standby settings for GPO[12]n");
75593 + value = pcf50606_reg_read(pcf, reg);
75595 + return (value >> 3) & 0x07;
75597 +EXPORT_SYMBOL_GPL(pcf50606_gpo_get_standby);
75599 +void pcf50606_gpo_invert_set(struct pcf50606 *pcf, int gpo, int invert)
75601 + u8 reg, value, mask;
75604 + value = !!invert << 6;
75605 + mask = 0x01 << 6;
75607 + if (gpo == PCF50606_GPO1) {
75608 + mask = 0x01 << 4;
75609 + value = !!invert << 4;
75611 + else if (gpo == PCF50606_GPO2) {
75612 + mask = 0x01 << 7;
75613 + value = !!invert << 7;
75616 + pcf50606_reg_set_bit_mask(pcf, reg, mask, value);
75618 +EXPORT_SYMBOL_GPL(pcf50606_gpo_invert_set);
75620 +int pcf50606_gpo_invert_get(struct pcf50606 *pcf, int gpo)
75622 + u8 reg, value, shift;
75627 + if (gpo == PCF50606_GPO1)
75629 + else if (gpo == PCF50606_GPO2)
75632 + value = pcf50606_reg_read(pcf, reg);
75634 + return (value >> shift) & 0x01;
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 @@
75644 + pcf50633_reg_write(pcf, PCF50633_REG_OOCSHDWN, 0x04 ); /* defeat 8s death from lowsys on A5 */
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 @@
75651 get_device(pcf->dev);
75652 disable_irq(pcf->irq);
75654 schedule_work(&pcf->irq_work);
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"
75664 +config MACH_NEO1973
75667 + Common machine code for Openmoko GTAxx hardware
75669 endif # MISC_DEVICES
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
75675 obj-$(CONFIG_HP_ILO) += hpilo.o
75676 obj-$(CONFIG_C2PORT) += c2port/
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
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
75688 + * Charging LED sysfs for the FIC Neo1973 GSM Phone
75689 + * (currently only implemented in GTA02 but ready for GTA01 implementation)
75691 + * (C) 2008 by Openmoko Inc.
75692 + * Author: Andy Green <andy@openmoko.com>
75693 + * All rights reserved.
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
75701 +#include <linux/module.h>
75702 +#include <linux/init.h>
75703 +#include <linux/kernel.h>
75704 +#include <linux/platform_device.h>
75706 +#include <asm/hardware.h>
75707 +#include <asm/mach-types.h>
75709 +#ifdef CONFIG_MACH_NEO1973_GTA02
75710 +#include <asm/arch/gta02.h>
75712 +static enum neo1973_charging_led_modes charging_mode;
75714 +static char *charging_led_mode_names[] = {
75720 +static ssize_t charging_led_read(struct device *dev,
75721 + struct device_attribute *attr, char *buf)
75723 + return sprintf(buf, "0x%03X\n", gta02_get_pcb_revision());
75726 +static ssize_t charging_led_read(struct device *dev,
75727 + struct device_attribute *attr, char *buf)
75729 + return sprintf(buf, "0x%03X\n", gta02_get_pcb_revision());
75733 +static DEVICE_ATTR(pcb, 0644, charging_led_read, charging_led_write);
75735 +static struct attribute *neo1973_charging_led_sysfs_entries[] = {
75736 + &dev_attr_pcb.attr,
75740 +static struct attribute_group neo1973_charging_led_attr_group = {
75742 + .attrs = neo1973_charging_led_sysfs_entries,
75745 +static int __init neo1973_charging_led_probe(struct platform_device *pdev)
75747 + dev_info(&pdev->dev, "starting\n");
75749 + switch (machine_arch_type) {
75750 +#ifdef CONFIG_MACH_NEO1973_GTA01
75751 + case MACH_TYPE_NEO1973_GTA01:
75753 +#endif /* CONFIG_MACH_NEO1973_GTA01 */
75758 + return sysfs_create_group(&pdev->dev.kobj,
75759 + &neo1973_charging_led_attr_group);
75762 +static int neo1973_charging_led_remove(struct platform_device *pdev)
75764 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_charging_led_attr_group);
75768 +static struct platform_driver neo1973_charging_led_driver = {
75769 + .probe = neo1973_charging_led_probe,
75770 + .remove = neo1973_charging_led_remove,
75772 + .name = "neo1973-charging-led",
75776 +static int __devinit neo1973_charging_led_init(void)
75778 + return platform_driver_register(&neo1973_charging_led_driver);
75781 +static void neo1973_charging_led_exit(void)
75783 + platform_driver_unregister(&neo1973_charging_led_driver);
75786 +module_init(neo1973_charging_led_init);
75787 +module_exit(neo1973_charging_led_exit);
75789 +MODULE_LICENSE("GPL");
75790 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
75791 +MODULE_DESCRIPTION("Neo1973 PCB charging_led");
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
75798 + * Bluetooth PM code for the FIC Neo1973 GSM Phone
75800 + * (C) 2007 by Openmoko Inc.
75801 + * Author: Harald Welte <laforge@openmoko.org>
75802 + * All rights reserved.
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
75810 +#include <linux/module.h>
75811 +#include <linux/init.h>
75812 +#include <linux/kernel.h>
75813 +#include <linux/platform_device.h>
75815 +#include <mach/hardware.h>
75816 +#include <asm/mach-types.h>
75818 +#ifdef CONFIG_MACH_NEO1973_GTA02
75819 +#include <mach/gta02.h>
75820 +#include <linux/mfd/pcf50633/gpio.h>
75822 +static ssize_t pm_host_read(struct device *dev, struct device_attribute *attr,
75825 + return sprintf(buf, "%d\n",
75826 + pcf50633_gpio_get(gta02_pcf, PCF50633_GPO)
75827 + == PCF50633_GPOCFG_GPOSEL_1);
75830 +static ssize_t pm_host_write(struct device *dev, struct device_attribute *attr,
75831 + const char *buf, size_t count)
75833 + unsigned long on = simple_strtoul(buf, NULL, 10);
75837 + val = PCF50633_GPOCFG_GPOSEL_1;
75839 + val = PCF50633_GPOCFG_GPOSEL_0;
75842 + pcf50633_gpio_set(gta02_pcf, PCF50633_GPO, val);
75847 +static DEVICE_ATTR(hostmode, 0644, pm_host_read, pm_host_write);
75849 +static struct attribute *neo1973_pm_host_sysfs_entries[] = {
75850 + &dev_attr_hostmode.attr,
75854 +static struct attribute_group neo1973_pm_host_attr_group = {
75856 + .attrs = neo1973_pm_host_sysfs_entries,
75859 +static int __init neo1973_pm_host_probe(struct platform_device *pdev)
75861 + dev_info(&pdev->dev, "starting\n");
75863 + switch (machine_arch_type) {
75864 +#ifdef CONFIG_MACH_NEO1973_GTA01
75865 + case MACH_TYPE_NEO1973_GTA01:
75867 +#endif /* CONFIG_MACH_NEO1973_GTA01 */
75872 + return sysfs_create_group(&pdev->dev.kobj, &neo1973_pm_host_attr_group);
75875 +static int neo1973_pm_host_remove(struct platform_device *pdev)
75877 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_pm_host_attr_group);
75881 +static struct platform_driver neo1973_pm_host_driver = {
75882 + .probe = neo1973_pm_host_probe,
75883 + .remove = neo1973_pm_host_remove,
75885 + .name = "neo1973-pm-host",
75889 +static int __devinit neo1973_pm_host_init(void)
75891 + return platform_driver_register(&neo1973_pm_host_driver);
75894 +static void neo1973_pm_host_exit(void)
75896 + platform_driver_unregister(&neo1973_pm_host_driver);
75899 +module_init(neo1973_pm_host_init);
75900 +module_exit(neo1973_pm_host_exit);
75902 +MODULE_LICENSE("GPL");
75903 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
75904 +MODULE_DESCRIPTION("Neo1973 USB Host Power Management");
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
75911 + * Resume reason sysfs for the FIC Neo1973 GSM Phone
75913 + * (C) 2008 by Openmoko Inc.
75914 + * Author: Andy Green <andy@openmoko.com>
75915 + * All rights reserved.
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
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>
75929 +#include <mach/hardware.h>
75930 +#include <asm/mach-types.h>
75932 +#ifdef CONFIG_MACH_NEO1973_GTA02
75933 +#include <mach/gta02.h>
75934 +#include <linux/mfd/pcf50633/core.h>
75937 +static unsigned int *gstatus4_mapped;
75938 +static char *resume_reasons[][17] = { { /* GTA01 */
75946 + "EINT07_HOLDKEY",
75959 + "EINT02_BLUETOOTH",
75960 + "EINT03_DEBUGBRD",
75964 + "EINT07_HOLDKEY",
75976 +static ssize_t resume_reason_read(struct device *dev,
75977 + struct device_attribute *attr,
75982 + int gta = !!machine_is_neo1973_gta02();
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]);
75988 + end += sprintf(end, " %s\n", resume_reasons[gta][bit]);
75990 +#ifdef CONFIG_MACH_NEO1973_GTA02
75991 + if ((gta) && (bit == 9)); /* PMU */
75992 +// end += pcf50633_report_resumers(gta02_pcf_pdata.pcf, end);
75996 + return end - buf;
76000 +static DEVICE_ATTR(resume_reason, 0644, resume_reason_read, NULL);
76002 +static struct attribute *neo1973_resume_reason_sysfs_entries[] = {
76003 + &dev_attr_resume_reason.attr,
76007 +static struct attribute_group neo1973_resume_reason_attr_group = {
76009 + .attrs = neo1973_resume_reason_sysfs_entries,
76012 +static int __init neo1973_resume_reason_probe(struct platform_device *pdev)
76014 + dev_info(&pdev->dev, "starting\n");
76016 + gstatus4_mapped = ioremap(0x560000BC /* GSTATUS4 */, 0x4);
76017 + if (!gstatus4_mapped) {
76018 + dev_err(&pdev->dev, "failed to ioremap() memory region\n");
76022 + return sysfs_create_group(&pdev->dev.kobj,
76023 + &neo1973_resume_reason_attr_group);
76026 +static int neo1973_resume_reason_remove(struct platform_device *pdev)
76028 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_resume_reason_attr_group);
76029 + iounmap(gstatus4_mapped);
76033 +static struct platform_driver neo1973_resume_reason_driver = {
76034 + .probe = neo1973_resume_reason_probe,
76035 + .remove = neo1973_resume_reason_remove,
76037 + .name = "neo1973-resume",
76041 +static int __devinit neo1973_resume_reason_init(void)
76043 + return platform_driver_register(&neo1973_resume_reason_driver);
76046 +static void neo1973_resume_reason_exit(void)
76048 + platform_driver_unregister(&neo1973_resume_reason_driver);
76051 +module_init(neo1973_resume_reason_init);
76052 +module_exit(neo1973_resume_reason_exit);
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
76062 + * Bluetooth PM code for the FIC Neo1973 GSM Phone
76064 + * (C) 2007 by OpenMoko Inc.
76065 + * Author: Harald Welte <laforge@openmoko.org>
76066 + * All rights reserved.
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
76074 +#include <linux/module.h>
76075 +#include <linux/init.h>
76076 +#include <linux/kernel.h>
76077 +#include <linux/platform_device.h>
76079 +#include <asm/hardware.h>
76080 +#include <asm/mach-types.h>
76082 +#ifdef CONFIG_MACH_NEO1973_GTA02
76083 +#include <asm/arch/gta02.h>
76084 +#include <linux/pcf50633.h>
76087 +static ssize_t pm_usbhost_read(struct device *dev, struct device_attribute *attr,
76090 + return sprintf(buf, "%d\n",
76091 + pcf50633_gpio_get(pcf50633_global, PCF50633_GPO));
76094 +static ssize_t pm_usbhost_write(struct device *dev, struct device_attribute *attr,
76095 + const char *buf, size_t count)
76097 + unsigned long on = simple_strtoul(buf, NULL, 10);
76099 + pcf50633_gpio_set(pcf50633_global, PCF50633_GPO, on);
76104 +static DEVICE_ATTR(hostmode, 0644, pm_usbhost_read, pm_usbhost_write);
76107 +static int neo1973_usbhost_suspend(struct platform_device *pdev, pm_message_t state)
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? */
76117 +static int neo1973_usbhost_resume(struct platform_device *pdev)
76119 + dev_dbg(&pdev->dev, "resuming\n");
76124 +#define neo1973_usbhost_suspend NULL
76125 +#define neo1973_usbhost_resume NULL
76128 +static struct attribute *neo1973_usbhost_sysfs_entries[] = {
76129 + &dev_attr_hostmode.attr,
76133 +static struct attribute_group neo1973_usbhost_attr_group = {
76135 + .attrs = neo1973_usbhost_sysfs_entries,
76138 +static int __init neo1973_usbhost_probe(struct platform_device *pdev)
76140 + dev_info(&pdev->dev, "starting\n");
76142 + switch (machine_arch_type) {
76144 +#ifdef CONFIG_MACH_NEO1973_GTA01
76145 + case MACH_TYPE_NEO1973_GTA01:
76147 +#endif /* CONFIG_MACH_NEO1973_GTA01 */
76149 +#ifdef CONFIG_MACH_NEO1973_GTA02
76150 + case MACH_TYPE_NEO1973_GTA02:
76152 +/* pcf50633_gpio_set(pcf50633_global, PCF50633_GPO, 0); */
76154 +#endif /* CONFIG_MACH_NEO1973_GTA02 */
76157 + return sysfs_create_group(&pdev->dev.kobj, &neo1973_usbhost_attr_group);
76160 +static int neo1973_usbhost_remove(struct platform_device *pdev)
76162 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_usbhost_attr_group);
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,
76173 + .name = "neo1973-pm-host",
76177 +static int __devinit neo1973_usbhost_init(void)
76179 + return platform_driver_register(&neo1973_usbhost_driver);
76182 +static void neo1973_usbhost_exit(void)
76184 + platform_driver_unregister(&neo1973_usbhost_driver);
76187 +module_init(neo1973_usbhost_init);
76188 +module_exit(neo1973_usbhost_exit);
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
76198 + * PCB version sysfs for the FIC Neo1973 GSM Phone
76200 + * (C) 2007 by Openmoko Inc.
76201 + * Author: Andy Green <andy@openmoko.com>
76202 + * All rights reserved.
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
76210 +#include <linux/module.h>
76211 +#include <linux/init.h>
76212 +#include <linux/kernel.h>
76213 +#include <linux/platform_device.h>
76215 +#include <mach/hardware.h>
76216 +#include <asm/mach-types.h>
76218 +#ifdef CONFIG_MACH_NEO1973_GTA02
76219 +#include <mach/gta02.h>
76221 +static ssize_t version_read(struct device *dev, struct device_attribute *attr,
76224 + return sprintf(buf, "0x%03X\n", gta02_get_pcb_revision());
76228 +static DEVICE_ATTR(pcb, 0644, version_read, NULL);
76230 +static struct attribute *neo1973_version_sysfs_entries[] = {
76231 + &dev_attr_pcb.attr,
76235 +static struct attribute_group neo1973_version_attr_group = {
76237 + .attrs = neo1973_version_sysfs_entries,
76240 +static int __init neo1973_version_probe(struct platform_device *pdev)
76242 + dev_info(&pdev->dev, "starting\n");
76244 + switch (machine_arch_type) {
76245 +#ifdef CONFIG_MACH_NEO1973_GTA01
76246 + case MACH_TYPE_NEO1973_GTA01:
76248 +#endif /* CONFIG_MACH_NEO1973_GTA01 */
76253 + return sysfs_create_group(&pdev->dev.kobj, &neo1973_version_attr_group);
76256 +static int neo1973_version_remove(struct platform_device *pdev)
76258 + sysfs_remove_group(&pdev->dev.kobj, &neo1973_version_attr_group);
76262 +static struct platform_driver neo1973_version_driver = {
76263 + .probe = neo1973_version_probe,
76264 + .remove = neo1973_version_remove,
76266 + .name = "neo1973-version",
76270 +static int __devinit neo1973_version_init(void)
76272 + return platform_driver_register(&neo1973_version_driver);
76275 +static void neo1973_version_exit(void)
76277 + platform_driver_unregister(&neo1973_version_driver);
76280 +module_init(neo1973_version_init);
76281 +module_exit(neo1973_version_exit);
76283 +MODULE_LICENSE("GPL");
76284 +MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
76285 +MODULE_DESCRIPTION("Neo1973 PCB version");
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
76291 +/* linux/drivers/misc/smdk6410-sleeptest.c
76293 + * Copyright 2008 Simtec Electronics
76294 + * Ben Dooks <ben@simtec.co.uk>
76295 + * http://armlinux.simtec.co.uk/
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.
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>
76310 +#include <plat/gpio-cfg.h>
76312 +static irqreturn_t sleep_action(int irq, void *pw)
76314 + printk(KERN_INFO "%s: irq %d\n", __func__, irq);
76315 + return IRQ_HANDLED;
76318 +static void sleep_setup(unsigned int irq, unsigned int gpio)
76322 + WARN_ON(s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2)) < 0);
76323 + WARN_ON(s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP) < 0);
76325 + ret = request_irq(irq, sleep_action, IRQF_TRIGGER_FALLING,
76328 + printk(KERN_ERR "%s: request_irq() failed\n", __func__);
76330 + ret = set_irq_wake(irq, 1);
76332 + printk(KERN_ERR "%s: set_irq_wake() failed\n", __func__);
76335 +static void sleep_led(unsigned int gpio)
76337 +// gpio_request(gpio, "sleep led");
76338 +// gpio_direction_output(gpio, 0);
76341 +static __init int smdk6410_sleeptest_init(void)
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));
76352 +module_init(smdk6410_sleeptest_init);
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 @@
76361 * Internal function. Flush all scheduled work from the MMC work queue.
76363 -static void mmc_flush_scheduled_work(void)
76364 +void mmc_flush_scheduled_work(void)
76366 flush_workqueue(workqueue);
76368 +EXPORT_SYMBOL_GPL(mmc_flush_scheduled_work);
76371 * mmc_request_done - finish processing an MMC request
76372 @@ -572,7 +573,13 @@
76374 static void mmc_power_up(struct mmc_host *host)
76376 - int bit = fls(host->ocr_avail) - 1;
76379 + /* If ocr is set, we use it */
76381 + bit = ffs(host->ocr) - 1;
76383 + bit = fls(host->ocr_avail) - 1;
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
76394 +config MMC_SDHCI_S3C
76395 + tristate "SDHCI support on Samsung S3C SoC"
76396 + depends on MMC_SDHCI && (PLAT_S3C24XX || PLAT_S3C64XX)
76398 + This selects the Secure Digital Host Controller Interface (SDHCI)
76399 + often referrered to as the HSMMC block in some of the Samsung S3C
76402 + If you have a controller with this interface, say Y or M here.
76404 + If unsure, say N.
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
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
76424 * linux/drivers/mmc/s3cmci.h - Samsung S3C MCI driver
76426 * Copyright (C) 2004-2006 maintech GmbH, Thomas Kleffel <tk@maintech.de>
76427 + * Copyright (C) 2007 Harald Welte <laforge@gnumonks.org>
76429 * Current driver maintained by Ben Dooks and Simtec Electronics
76430 * Copyright (C) 2008 Simtec Electronics <ben-linux@fluff.org>
76433 #include <mach/regs-sdi.h>
76434 #include <mach/regs-gpio.h>
76435 +#include <mach/hardware.h>
76437 #include <plat/mci.h>
76439 +#include <asm/dma.h>
76440 +#include <asm/dma-mapping.h>
76442 +#include <asm/io.h>
76443 +#include <mach/regs-gpio.h>
76444 +#include <mach/mci.h>
76445 +#include <mach/dma.h>
76447 #include "s3cmci.h"
76449 #define DRIVER_NAME "s3c-mci"
76451 static const int dbgmap_info = dbg_info | dbg_conf;
76452 static const int dbgmap_debug = dbg_err | dbg_debug;
76454 +static int f_max = -1; /* override maximum frequency limit */
76455 +static int persist; /* keep interface alive across suspend/resume */
76457 #define dbg(host, channels, args...) \
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;
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;
76484 host->pio_bytes -= fifo;
76485 host->pio_count += fifo;
76486 @@ -373,7 +392,6 @@
76488 struct s3cmci_host *host = (struct s3cmci_host *) data;
76491 disable_irq(host->irq);
76493 if (host->pio_active == XFER_WRITE)
76494 @@ -614,7 +632,6 @@
76496 spin_unlock_irqrestore(&host->complete_lock, iflags);
76497 return IRQ_HANDLED;
76502 @@ -789,12 +806,11 @@
76504 last_source = source;
76506 - s3c2410_dma_devconfig(host->dma, source, 3,
76507 + s3c2410_dma_devconfig(host->dma, source,
76508 host->mem->start + host->sdidata);
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);
76520 cmd->data->error = res;
76521 + cmd->data->error = -EIO;
76523 mmc_request_done(mmc, mrq);
76525 @@ -1264,10 +1281,8 @@
76526 host->is2440 = is2440;
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;
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;
76541 + if (f_max >= 0) {
76542 + unsigned f = f_max;
76544 + if (f < mmc->f_min)
76546 + if (mmc->f_max > f) {
76547 + dev_info(&pdev->dev, "f_max lowered from %u to %u Hz\n",
76553 if (host->pdata->ocr_avail)
76554 mmc->ocr_avail = host->pdata->ocr_avail;
76556 @@ -1492,18 +1519,60 @@
76560 +static int save_regs(struct mmc_host *mmc)
76562 + struct s3cmci_host *host = mmc_priv(mmc);
76563 + unsigned long flags;
76565 + u32 *to = host->saved;
76567 + mmc_flush_scheduled_work();
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);
76579 +static int restore_regs(struct mmc_host *mmc)
76581 + struct s3cmci_host *host = mmc_priv(mmc);
76582 + unsigned long flags;
76584 + u32 *from = host->saved;
76587 + * Before we begin with the necromancy, make sure we don't
76588 + * inadvertently start something we'll regret microseconds later.
76590 + from[S3C2410_SDICMDCON - S3C2410_SDICON] = 0;
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);
76602 static int s3cmci_suspend(struct platform_device *dev, pm_message_t state)
76604 struct mmc_host *mmc = platform_get_drvdata(dev);
76606 - return mmc_suspend_host(mmc, state);
76607 + return persist ? save_regs(mmc) : mmc_suspend_host(mmc, state);
76610 static int s3cmci_resume(struct platform_device *dev)
76612 struct mmc_host *mmc = platform_get_drvdata(dev);
76614 - return mmc_resume_host(mmc);
76615 + return persist ? restore_regs(mmc) : mmc_resume_host(mmc);
76618 #else /* CONFIG_PM */
76619 @@ -1561,9 +1630,13 @@
76620 module_init(s3cmci_init);
76621 module_exit(s3cmci_exit);
76623 +module_param(f_max, int, 0644);
76624 +module_param(persist, int, 0644);
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");
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
76637 * published by the Free Software Foundation.
76641 +#include <mach/regs-sdi.h>
76642 +#include <linux/regulator/consumer.h>
76644 /* FIXME: DMA Resource management ?! */
76645 #define S3CMCI_DMA 0
76648 unsigned int ccnt, dcnt;
76649 struct tasklet_struct pio_tasklet;
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.
76656 + u32 saved[(S3C2410_SDIIMSK-S3C2410_SDICON)/4];
76658 #ifdef CONFIG_CPU_FREQ
76659 struct notifier_block freq_transition;
76662 + struct regulator *regulator;
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
76668 readl(host->ioaddr + SDHCI_CAPABILITIES),
76669 readl(host->ioaddr + SDHCI_MAX_CURRENT));
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));
76676 printk(KERN_DEBUG DRIVER_NAME ": ===========================================\n");
76679 @@ -736,6 +741,23 @@
76680 writew(mode, host->ioaddr + SDHCI_TRANSFER_MODE);
76683 +static void shdci_check_dma_overrun(struct sdhci_host *host, struct mmc_data *data)
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;
76689 + /* Test whether we ended up moving more data than
76690 + * was originally requested. */
76692 + if (dma_pos <= dma_end)
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);
76700 static void sdhci_finish_data(struct sdhci_host *host)
76702 struct mmc_data *data;
76703 @@ -749,6 +771,8 @@
76704 if (host->flags & SDHCI_USE_ADMA)
76705 sdhci_adma_table_post(host, data);
76707 + shdci_check_dma_overrun(host, data);
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 @@
76714 static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock)
76716 + if (clock == host->clock)
76719 + host->ops->change_clock(host, clock);
76722 +void sdhci_change_clock(struct sdhci_host *host, unsigned int clock)
76726 unsigned long timeout;
76728 - if (clock == host->clock)
76731 writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
76734 @@ -931,6 +960,8 @@
76735 host->clock = clock;
76738 +EXPORT_SYMBOL_GPL(sdhci_set_clock);
76740 static void sdhci_set_power(struct sdhci_host *host, unsigned short power)
76743 @@ -1004,12 +1035,13 @@
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);
76755 sdhci_send_command(host, mrq->cmd);
76758 @@ -1038,6 +1070,9 @@
76762 + if (host->ops->set_ios)
76763 + host->ops->set_ios(host, ios);
76765 sdhci_set_clock(host, ios->clock);
76767 if (ios->power_mode == MMC_POWER_OFF)
76768 @@ -1141,7 +1176,7 @@
76769 host = (struct sdhci_host*)param;
76771 spin_lock_irqsave(&host->lock, flags);
76774 if (!(readl(host->ioaddr + SDHCI_PRESENT_STATE) & SDHCI_CARD_PRESENT)) {
76776 printk(KERN_ERR "%s: Card removed during transfer!\n",
76777 @@ -1156,7 +1191,7 @@
76778 tasklet_schedule(&host->finish_tasklet);
76783 spin_unlock_irqrestore(&host->lock, flags);
76785 mmc_detect_change(host->mmc, msecs_to_jiffies(200));
76786 @@ -1288,11 +1323,24 @@
76789 if (host->cmd->flags & MMC_RSP_BUSY) {
76792 if (host->cmd->data)
76793 DBG("Cannot wait for busy signal when also "
76794 "doing a data transfer");
76796 + else if (!(host->quirks & SDHCI_QUIRK_NO_TCIRQ_ON_NOT_BUSY))
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
76805 + present = readl(host->ioaddr + SDHCI_PRESENT_STATE);
76806 + DBG("busy? present %08x, intstat %08x\n", present, intmask);
76808 + /* fall through and take the SDHCI_INT_RESPONSE */
76811 if (intmask & SDHCI_INT_RESPONSE)
76812 @@ -1609,17 +1657,23 @@
76813 mmc_dev(host->mmc)->dma_mask = &host->dma_mask;
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);
76821 + host->max_clk = (caps & SDHCI_CLOCK_BASE_MASK) >> SDHCI_CLOCK_BASE_SHIFT;
76822 + host->max_clk *= 1000000;
76824 if (host->max_clk == 0) {
76825 printk(KERN_ERR "%s: Hardware doesn't specify base clock "
76826 "frequency.\n", mmc_hostname(mmc));
76829 - host->max_clk *= 1000000;
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);
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
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))
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)
76859 int irq; /* Device IRQ */
76860 void __iomem * ioaddr; /* Mapped address */
76861 @@ -267,6 +270,14 @@
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);
76868 + void (*change_clock)(struct sdhci_host *host,
76869 + unsigned int clock);
76871 + void (*set_ios)(struct sdhci_host *host,
76872 + struct mmc_ios *ios);
76876 @@ -274,6 +285,8 @@
76878 extern void sdhci_free_host(struct sdhci_host *host);
76880 +extern void sdhci_change_clock(struct sdhci_host *host, unsigned int clock);
76882 static inline void *sdhci_priv(struct sdhci_host *host)
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 @@
76890 static struct sdhci_ops sdhci_pci_ops = {
76891 .enable_dma = sdhci_pci_enable_dma,
76892 + .change_clock = sdhci_change_clock,
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
76900 +/* linux/drivers/mmc/host/sdhci-s3c.c
76902 + * Copyright 2008 Openmoko Inc.
76903 + * Copyright 2008 Simtec Electronics
76904 + * Ben Dooks <ben@simtec.co.uk>
76905 + * http://armlinux.simtec.co.uk/
76907 + * SDHCI (HSMMC) support for Samsung SoC
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.
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>
76920 +#include <linux/mmc/host.h>
76922 +#include <plat/regs-sdhci.h>
76923 +#include <plat/sdhci.h>
76925 +#include "sdhci.h"
76927 +#define MAX_BUS_CLK (4)
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;
76936 + struct clk *clk_io; /* clock for io bus */
76937 + struct clk *clk_bus[MAX_BUS_CLK];
76940 +static inline struct sdhci_s3c *to_s3c(struct sdhci_host *host)
76942 + return sdhci_priv(host);
76945 +static u32 get_curclk(u32 ctrl2)
76947 + ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
76948 + ctrl2 >>= S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
76953 +static void sdhci_s3c_check_sclk(struct sdhci_host *host)
76955 + struct sdhci_s3c *ourhost = to_s3c(host);
76956 + u32 tmp = readl(host->ioaddr + S3C_SDHCI_CONTROL2);
76958 + if (get_curclk(tmp) != ourhost->cur_clk) {
76959 + dev_dbg(&ourhost->pdev->dev, "restored ctrl2 clock setting\n");
76961 + tmp &= ~S3C_SDHCI_CTRL2_SELBASECLK_MASK;
76962 + tmp |= ourhost->cur_clk << S3C_SDHCI_CTRL2_SELBASECLK_SHIFT;
76963 + writel(tmp, host->ioaddr + 0x80);
76967 +static unsigned int sdhci_s3c_get_max_clk(struct sdhci_host *host)
76969 + struct sdhci_s3c *ourhost = to_s3c(host);
76970 + struct clk *busclk;
76971 + unsigned int rate, max;
76974 + /* note, a reset will reset the clock source */
76976 + sdhci_s3c_check_sclk(host);
76978 + for (max = 0, clk = 0; clk < MAX_BUS_CLK; clk++) {
76979 + busclk = ourhost->clk_bus[clk];
76983 + rate = clk_get_rate(busclk);
76991 +static unsigned int sdhci_s3c_get_timeout_clk(struct sdhci_host *host)
76993 + return sdhci_s3c_get_max_clk(host) / 1000000;
76996 +static void sdhci_s3c_set_ios(struct sdhci_host *host,
76997 + struct mmc_ios *ios)
76999 + struct sdhci_s3c *ourhost = to_s3c(host);
77000 + struct s3c_sdhci_platdata *pdata = ourhost->pdata;
77003 + sdhci_s3c_check_sclk(host);
77005 + if (ios->power_mode != MMC_POWER_OFF) {
77006 + switch (ios->bus_width) {
77007 + case MMC_BUS_WIDTH_4:
77010 + case MMC_BUS_WIDTH_1:
77017 + if (pdata->cfg_gpio)
77018 + pdata->cfg_gpio(ourhost->pdev, width);
77021 + if (pdata->cfg_card)
77022 + pdata->cfg_card(ourhost->pdev, host->ioaddr,
77023 + ios, host->mmc->card);
77026 +static unsigned int sdhci_s3c_consider_clock(struct sdhci_s3c *ourhost,
77027 + unsigned int src,
77028 + unsigned int wanted)
77030 + unsigned long rate;
77031 + struct clk *clksrc = ourhost->clk_bus[src];
77037 + rate = clk_get_rate(clksrc);
77039 + for (div = 1; div < 256; div *= 2) {
77040 + if ((rate / div) <= wanted)
77044 + dev_dbg(&ourhost->pdev->dev, "clk %d: rate %ld, want %d, got %ld\n",
77045 + src, rate, wanted, rate / div);
77047 + return (wanted - (rate / div));
77050 +static void sdhci_s3c_change_clock(struct sdhci_host *host, unsigned int clock)
77052 + struct sdhci_s3c *ourhost = to_s3c(host);
77053 + unsigned int best = UINT_MAX;
77054 + unsigned int delta;
77055 + int best_src = 0;
77059 + for (src = 0; src < MAX_BUS_CLK; src++) {
77060 + delta = sdhci_s3c_consider_clock(ourhost, src, clock);
77061 + if (delta < best) {
77067 + dev_dbg(&ourhost->pdev->dev,
77068 + "selected source %d, clock %d, delta %d\n",
77069 + best_src, clock, best);
77071 + /* turn clock off to card before changing clock source */
77072 + writew(0, host->ioaddr + SDHCI_CLOCK_CONTROL);
77074 + /* select the new clock source */
77076 + if (ourhost->cur_clk != best_src) {
77077 + struct clk *clk = ourhost->clk_bus[best_src];
77079 + ourhost->cur_clk = best_src;
77080 + host->max_clk = clk_get_rate(clk);
77081 + host->timeout_clk = host->max_clk / 1000000;
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);
77089 + sdhci_change_clock(host, clock);
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,
77100 + * call this when you need sd stack to recognize insertion or removal of card
77101 + * that can't be told by SDHCI regs
77104 +void sdhci_s3c_force_presence_change(struct platform_device *pdev)
77106 + struct s3c_sdhci_platdata *pdata = pdev->dev.platform_data;
77108 + dev_info(&pdev->dev, "sdhci_s3c_force_presence_change called\n");
77109 + mmc_detect_change(pdata->sdhci_host->mmc, msecs_to_jiffies(200));
77111 +EXPORT_SYMBOL_GPL(sdhci_s3c_force_presence_change);
77114 +static int __devinit sdhci_s3c_probe(struct platform_device *pdev)
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;
77124 + dev_err(dev, "no device data specified\n");
77128 + irq = platform_get_irq(pdev, 0);
77130 + dev_err(dev, "no irq specified\n");
77134 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
77136 + dev_err(dev, "no memory specified\n");
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);
77146 + pdata->sdhci_host = host;
77148 + sc = sdhci_priv(host);
77152 + sc->pdata = pdata;
77154 + platform_set_drvdata(pdev, host);
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);
77163 + /* enable the local io clock and keep it running for the moment. */
77164 + clk_enable(sc->clk_io);
77166 + for (clks = 0, ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
77168 + char *name = pdata->clocks[ptr];
77170 + if (name == NULL)
77173 + clk = clk_get(dev, name);
77174 + if (IS_ERR(clk)) {
77175 + dev_err(dev, "failed to get clock %s\n", name);
77180 + sc->clk_bus[ptr] = clk;
77183 + dev_info(dev, "clock source %d: %s (%ld Hz)\n",
77184 + ptr, name, clk_get_rate(clk));
77188 + dev_err(dev, "failed to find any bus clocks\n");
77190 + goto err_no_busclks;
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");
77198 + goto err_req_regs;
77201 + host->ioaddr = ioremap_nocache(res->start, resource_size(res));
77202 + if (!host->ioaddr) {
77203 + dev_err(dev, "failed to map registers\n");
77205 + goto err_req_regs;
77208 + /* Ensure we have minimal gpio selected CMD/CLK/Detect */
77209 + if (pdata->cfg_gpio)
77210 + pdata->cfg_gpio(pdev, 0);
77212 + sdhci_s3c_check_sclk(host);
77214 + host->hw_name = "samsung-hsmmc";
77215 + host->ops = &sdhci_s3c_ops;
77216 + host->quirks = 0;
77219 + /* Setup quirks for the controller */
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;
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;
77232 + host->quirks |= (SDHCI_QUIRK_32BIT_DMA_ADDR |
77233 + SDHCI_QUIRK_32BIT_DMA_SIZE);
77235 + ret = sdhci_add_host(host);
77237 + dev_err(dev, "sdhci_add_host() failed\n");
77238 + goto err_add_host;
77244 + release_resource(sc->ioarea);
77245 + kfree(sc->ioarea);
77248 + for (ptr = 0; ptr < MAX_BUS_CLK; ptr++) {
77249 + clk_disable(sc->clk_bus[ptr]);
77250 + clk_put(sc->clk_bus[ptr]);
77254 + clk_disable(sc->clk_io);
77255 + clk_put(sc->clk_io);
77258 + sdhci_free_host(host);
77263 +static int __devexit sdhci_s3c_remove(struct platform_device *pdev)
77270 +static int sdhci_s3c_suspend(struct platform_device *dev, pm_message_t pm)
77272 + struct sdhci_host *host = platform_get_drvdata(dev);
77274 + sdhci_suspend_host(host, pm);
77278 +static int sdhci_s3c_resume(struct platform_device *dev)
77280 + struct sdhci_host *host = platform_get_drvdata(dev);
77282 + sdhci_resume_host(host);
77287 +#define sdhci_s3c_suspend NULL
77288 +#define sdhci_s3c_resume NULL
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,
77297 + .owner = THIS_MODULE,
77298 + .name = "s3c-sdhci",
77302 +static int __init sdhci_s3c_init(void)
77304 + return platform_driver_register(&sdhci_s3c_driver);
77307 +static void __exit sdhci_s3c_exit(void)
77309 + platform_driver_unregister(&sdhci_s3c_driver);
77312 +module_init(sdhci_s3c_init);
77313 +module_exit(sdhci_s3c_exit);
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 @@
77326 - dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
77328 local_irq_save(flags);
77330 cfg = readl(info->regs + S3C2410_NFCONF);
77331 @@ -240,6 +238,8 @@
77333 writel(cfg, info->regs + S3C2410_NFCONF);
77335 + dev_dbg(info->device, "NF_CONF is 0x%lx\n", cfg);
77337 local_irq_restore(flags);
77340 @@ -438,7 +438,7 @@
77341 if ((diff0 & ~(1<<fls(diff0))) == 0)
77349 @@ -530,7 +530,12 @@
77350 static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len)
77352 struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd);
77353 + u8 *ptr = buf + (len & ~3);
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);
77361 static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len)
77362 @@ -645,17 +650,31 @@
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)
77371 + struct mtd_partition *part_info;
77375 return add_mtd_device(&mtd->mtd);
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,
77384 + if (set->nr_partitions > 0 && set->partitions != NULL) {
77385 + nr_part = set->nr_partitions;
77386 + part_info = set->partitions;
77390 + if (nr_part > 0 && part_info)
77391 + return add_mtd_partitions(&mtd->mtd, part_info, nr_part);
77393 return add_mtd_device(&mtd->mtd);
77396 @@ -684,9 +703,13 @@
77397 chip->select_chip = s3c2410_nand_select_chip;
77398 chip->chip_delay = 50;
77400 - chip->options = 0;
77401 chip->controller = &info->controller;
77403 + if (set->flags & S3C2410_NAND_BBT)
77404 + chip->options = NAND_USE_FLASH_BBT;
77406 + chip->options = 0;
77408 switch (info->cpu_type) {
77410 chip->IO_ADDR_W = regs + S3C2410_NFDATA;
77411 @@ -726,7 +749,7 @@
77412 nmtd->mtd.owner = THIS_MODULE;
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 @@
77426 zlib_inflateEnd(&state->strm);
77427 - kfree(state->strm.workspace);
77428 + vfree(state->strm.workspace);
77432 @@ -346,8 +346,7 @@
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)
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
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 */ },
77454 .helper = "sd8686_helper.bin",
77455 .firmware = "sd8686.bin",
77461 + .helper = "sd8688_helper.bin",
77462 + .firmware = "sd8688.bin",
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
77472 bool "Plug and Play support"
77473 depends on HAS_IOMEM
77474 - depends on ISA || ACPI
77475 + depends on ISA || ACPI || SDIO
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 @@
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 @@
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
77503 + * Driver for batteries with bq27000 chips inside via HDQ
77505 + * Copyright 2008 Openmoko, Inc
77506 + * Andy Green <andy@openmoko.com>
77508 + * based on ds2760 driver, original copyright notice for that --->
77510 + * Copyright © 2007 Anton Vorontsov
77511 + * 2004-2007 Matt Reimer
77512 + * 2004 Szabolcs Gyurko
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.
77518 + * Author: Anton Vorontsov <cbou@mail.ru>
77521 + * Matt Reimer <mreimer@vpop.net>
77522 + * April 2004, 2005, 2007
77524 + * Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>
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>
77538 +enum bq27000_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 */
77545 + /* read-only after this */
77546 + BQ27000_ARTTE_L, /* At-Rate Time To Empty H L */
77548 + BQ27000_TEMP_L, /* Reported Temperature H L */
77550 + BQ27000_VOLT_L, /* Reported Voltage H L */
77552 + BQ27000_FLAGS, /* Status Flags */
77553 + BQ27000_RSOC, /* Relative State of Charge */
77554 + BQ27000_NAC_L, /* Nominal Available Capacity H L */
77556 + BQ27000_CACD_L, /* Discharge Compensated H L */
77558 + BQ27000_CACT_L, /* Temperature Compensated H L */
77560 + BQ27000_LMD_L, /* Last measured discharge H L */
77562 + BQ27000_AI_L, /* Average Current H L */
77564 + BQ27000_TTE_L, /* Time to Empty H L */
77566 + BQ27000_TTF_L, /* Time to Full H L */
77568 + BQ27000_SI_L, /* Standby Current H L */
77570 + BQ27000_STTE_L, /* Standby Time To Empty H L */
77572 + BQ27000_MLI_L, /* Max Load Current H L */
77574 + BQ27000_MLTTE_L, /* Max Load Time To Empty H L */
77576 + BQ27000_SAE_L, /* Available Energy H L */
77578 + BQ27000_AP_L, /* Available Power H L */
77580 + BQ27000_TTECP_L, /* Time to Empty at Constant Power H L */
77582 + BQ27000_CYCL_L, /* Cycle count since learning cycle H L */
77584 + BQ27000_CYCT_L, /* Cycle Count Total H L */
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 */
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 */
77613 +#define NANOVOLTS_UNIT 3750
77615 +struct bq27000_bat_regs {
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;
77634 + struct bq27000_bat_regs regs;
77637 +static unsigned int cache_time = 5000;
77638 +module_param(cache_time, uint, 0644);
77639 +MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
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
77648 +static int hdq_read16(struct bq27000_device_info *di, int address)
77654 + while (retries--) {
77656 + high = (di->pdata->hdq_read)(address + 1); /* high part */
77660 + acc = (di->pdata->hdq_read)(address);
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;
77672 +static void bq27000_battery_external_power_changed(struct power_supply *psy)
77674 + struct bq27000_device_info *di = container_of(psy, struct bq27000_device_info, bat);
77676 + dev_dbg(di->dev, "%s\n", __FUNCTION__);
77677 + schedule_delayed_work(&di->work, 0);
77680 +static int bq27000_battery_get_property(struct power_supply *psy,
77681 + enum power_supply_property psp,
77682 + union power_supply_propval *val)
77685 + struct bq27000_device_info *di = container_of(psy, struct bq27000_device_info, bat);
77688 + case POWER_SUPPLY_PROP_STATUS:
77689 + val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
77691 + if (!di->pdata->get_charger_online_status)
77693 + if ((di->pdata->get_charger_online_status)()) {
77695 + * charger is definitively present
77696 + * we report our state in terms of what it says it
77699 + if (!di->pdata->get_charger_active_status)
77702 + if ((di->pdata->get_charger_active_status)()) {
77703 + val->intval = POWER_SUPPLY_STATUS_CHARGING;
77706 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
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 --->
77716 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
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.
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;
77732 + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
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;
77741 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
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;
77751 + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
77752 + if (di->regs.volt < 0)
77753 + return di->regs.volt;
77755 + val->intval = di->regs.volt * 1000;
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;
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;
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;
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;
77780 + case POWER_SUPPLY_PROP_TECHNOLOGY:
77781 + val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
77783 + case POWER_SUPPLY_PROP_CAPACITY:
77784 + val->intval = di->regs.rsoc;
77785 + if (val->intval < 0)
77786 + return val->intval;
77788 + case POWER_SUPPLY_PROP_PRESENT:
77789 + val->intval = !(di->regs.rsoc < 0);
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;
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;
77801 + case POWER_SUPPLY_PROP_ONLINE:
77802 + if (di->pdata->get_charger_online_status)
77803 + val->intval = (di->pdata->get_charger_online_status)();
77814 +static void bq27000_battery_work(struct work_struct *work)
77816 + struct bq27000_device_info *di =
77817 + container_of(work, struct bq27000_device_info, work.work);
77819 + if ((di->pdata->hdq_initialized)()) {
77820 + struct bq27000_bat_regs regs;
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);
77831 + if (memcmp (®s, &di->regs, sizeof(regs)) != 0) {
77833 + power_supply_changed(&di->bat);
77837 + if (!schedule_delayed_work(&di->work, cache_time))
77838 + dev_err(di->dev, "battery service reschedule failed\n");
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
77856 +static int bq27000_battery_probe(struct platform_device *pdev)
77859 + struct bq27000_device_info *di;
77860 + struct bq27000_platform_data *pdata;
77862 + dev_info(&pdev->dev, "BQ27000 Battery Driver (C) 2008 Openmoko, Inc\n");
77864 + di = kzalloc(sizeof(*di), GFP_KERNEL);
77866 + retval = -ENOMEM;
77867 + goto di_alloc_failed;
77870 + platform_set_drvdata(pdev, di);
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;
77885 + retval = power_supply_register(&pdev->dev, &di->bat);
77887 + dev_err(di->dev, "failed to register battery\n");
77888 + goto batt_failed;
77891 + INIT_DELAYED_WORK(&di->work, bq27000_battery_work);
77893 + if (!schedule_delayed_work(&di->work, 0))
77894 + dev_err(di->dev, "failed to schedule bq27000_battery_work\n");
77904 +static int bq27000_battery_remove(struct platform_device *pdev)
77906 + struct bq27000_device_info *di = platform_get_drvdata(pdev);
77908 + cancel_delayed_work(&di->work);
77910 + power_supply_unregister(&di->bat);
77915 +void bq27000_charging_state_change(struct platform_device *pdev)
77917 + struct bq27000_device_info *di = platform_get_drvdata(pdev);
77922 +EXPORT_SYMBOL_GPL(bq27000_charging_state_change);
77926 +static int bq27000_battery_suspend(struct platform_device *pdev,
77927 + pm_message_t state)
77929 + struct bq27000_device_info *di = platform_get_drvdata(pdev);
77931 + cancel_delayed_work(&di->work);
77935 +static int bq27000_battery_resume(struct platform_device *pdev)
77937 + struct bq27000_device_info *di = platform_get_drvdata(pdev);
77939 + schedule_delayed_work(&di->work, 0);
77945 +#define bq27000_battery_suspend NULL
77946 +#define bq27000_battery_resume NULL
77948 +#endif /* CONFIG_PM */
77950 +static struct platform_driver bq27000_battery_driver = {
77952 + .name = "bq27000-battery",
77954 + .probe = bq27000_battery_probe,
77955 + .remove = bq27000_battery_remove,
77956 + .suspend = bq27000_battery_suspend,
77957 + .resume = bq27000_battery_resume,
77960 +static int __init bq27000_battery_init(void)
77962 + return platform_driver_register(&bq27000_battery_driver);
77965 +static void __exit bq27000_battery_exit(void)
77967 + platform_driver_unregister(&bq27000_battery_driver);
77970 +module_init(bq27000_battery_init);
77971 +module_exit(bq27000_battery_exit);
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
77981 + * Dumb driver for gta01 battery
77983 + * Copyright 2009 Openmoko, Inc
77984 + * Balaji Rao <balajirrao@openmoko.org>
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>
77995 +struct gta01_battery {
77996 + struct power_supply psy;
77997 + struct gta01_bat_platform_data *pdata;
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,
78007 +static int gta01_bat_get_property(struct power_supply *psy,
78008 + enum power_supply_property psp,
78009 + union power_supply_propval *val)
78011 + struct gta01_battery *bat = container_of(psy, struct gta01_battery, psy);
78014 + case POWER_SUPPLY_PROP_STATUS:
78015 + if (bat->pdata->get_charging_status())
78016 + val->intval = POWER_SUPPLY_STATUS_CHARGING;
78018 + val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
78020 + case POWER_SUPPLY_PROP_VOLTAGE_NOW:
78021 + val->intval = bat->pdata->get_voltage();
78023 + case POWER_SUPPLY_PROP_CURRENT_NOW:
78024 + val->intval = bat->pdata->get_current();
78026 + case POWER_SUPPLY_PROP_PRESENT:
78027 + val->intval = 1; /* You must never run GTA01 without battery. */
78036 +static void gta01_bat_ext_changed(struct power_supply *psy)
78038 + struct gta01_battery *bat = container_of(psy, struct gta01_battery, psy);
78039 + power_supply_changed(&bat->psy);
78042 +static int gta01_battery_probe(struct platform_device *pdev)
78044 + struct gta01_battery *gta01_bat;
78046 + gta01_bat = kzalloc(sizeof(*gta01_bat), GFP_KERNEL);
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;
78057 + gta01_bat->pdata = pdev->dev.platform_data;
78058 + power_supply_register(&pdev->dev, >a01_bat->psy);
78063 +static int gta01_battery_remove(struct platform_device *pdev)
78065 + struct gta01_battery *bat = platform_get_drvdata(pdev);
78067 + power_supply_unregister(&bat->psy);
78073 +static struct platform_driver gta01_battery_driver = {
78075 + .name = "gta01_battery",
78077 + .probe = gta01_battery_probe,
78078 + .remove = gta01_battery_remove,
78081 +static int __init gta01_battery_init(void)
78083 + return platform_driver_register(>a01_battery_driver);
78086 +static void __exit gta01_battery_exit(void)
78088 + platform_driver_unregister(>a01_battery_driver);
78091 +module_init(gta01_battery_init);
78092 +module_exit(gta01_battery_exit);
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
78102 + * HDQ generic GPIO bitbang driver using FIQ
78104 + * (C) 2006-2007 by Openmoko, Inc.
78105 + * Author: Andy Green <andy@openmoko.com>
78106 + * All rights reserved.
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.
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>
78120 +#define HDQ_READ 0
78121 +#define HDQ_WRITE 0x80
78123 +enum hdq_bitbang_states {
78126 + HDQB_TX_BREAK_RECOVERY,
78131 + HDQB_DATA_RX_LOW,
78132 + HDQB_DATA_RX_HIGH,
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 */
78150 + u8 hdq_tx_data_done;
78151 + enum hdq_bitbang_states hdq_state;
78152 + int reported_error;
78154 + struct hdq_platform_data *pdata;
78158 +static void hdq_bad(void)
78160 + if (!hdq_priv.reported_error)
78161 + printk(KERN_ERR "HDQ error: %d\n", hdq_priv.hdq_error);
78162 + hdq_priv.reported_error = 1;
78165 +static void hdq_good(void)
78167 + if (hdq_priv.reported_error)
78168 + printk(KERN_INFO "HDQ responds again\n");
78169 + hdq_priv.reported_error = 0;
78172 +int hdq_fiq_handler(void)
78174 + if (!hdq_priv.hdq_probed)
78177 + switch (hdq_priv.hdq_state) {
78179 + if (hdq_priv.hdq_request_ctr == hdq_priv.hdq_transaction_ctr)
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;
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);
78196 + case HDQB_TX_BREAK_RECOVERY: /* issue low for > 40us */
78197 + if (--hdq_priv.hdq_ctr)
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;
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);
78217 + case HDQB_ADS_LOW:
78218 + if (--hdq_priv.hdq_ctr)
78220 + hdq_priv.pdata->gpio_set(1);
78221 + hdq_priv.hdq_state = HDQB_ADS_HIGH;
78224 + case HDQB_ADS_HIGH:
78225 + if (--hdq_priv.hdq_ctr2 > 1) /* account for HDQB_ADS_CALC */
78227 + if (hdq_priv.hdq_bit) { /* more bits to do */
78228 + hdq_priv.hdq_state = HDQB_ADS_CALC;
78231 + /* no more bits, wait it out until hdq_priv.hdq_ctr2 exhausted */
78232 + if (hdq_priv.hdq_ctr2)
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;
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();
78251 + case HDQB_WAIT_TX: /* issue low for > 40us */
78252 + if (--hdq_priv.hdq_ctr)
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 */
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();
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 */
78274 + hdq_priv.hdq_ctr = 500 / HDQ_SAMPLE_PERIOD_US;
78275 + hdq_priv.hdq_state = HDQB_DATA_RX_LOW;
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 */
78286 + * HDQ basically works by measuring the low time of the bit cell
78287 + * 32-50us --> '1', 80 - 145us --> '0'
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;
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;
78301 + hdq_priv.hdq_state = HDQB_IDLE;
78303 + hdq_priv.hdq_state = HDQB_DATA_RX_HIGH;
78305 + hdq_priv.hdq_ctr = 1000 / HDQ_SAMPLE_PERIOD_US;
78306 + hdq_priv.hdq_ctr2 = 1;
78309 + hdq_priv.hdq_ctr2++;
78310 + if (--hdq_priv.hdq_ctr)
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 */
78318 + case HDQB_DATA_RX_HIGH:
78319 + if (!hdq_priv.pdata->gpio_get()) {
78320 + /* it talks to us! */
78321 + hdq_priv.hdq_ctr2 = 1;
78323 + hdq_priv.hdq_ctr = 400 / HDQ_SAMPLE_PERIOD_US;
78324 + hdq_priv.hdq_state = HDQB_DATA_RX_LOW;
78327 + if (--hdq_priv.hdq_ctr)
78329 + /* timed out, error */
78330 + hdq_priv.hdq_error = 3;
78331 + hdq_priv.hdq_transaction_ctr = hdq_priv.hdq_request_ctr;
78333 + /* we're in input mode already */
78334 + hdq_priv.hdq_state = HDQB_IDLE; /* abort */
78338 + /* Are we interested in keeping the FIQ source alive ? */
78339 + if (hdq_priv.hdq_state != HDQB_IDLE)
78344 +static int fiq_busy(void)
78346 + int request = (volatile u8)hdq_priv.hdq_request_ctr;
78347 + int transact = (volatile u8)hdq_priv.hdq_transaction_ctr;
78350 + return (request != transact);
78353 +int hdq_initialized(void)
78355 + return hdq_priv.hdq_probed;
78357 +EXPORT_SYMBOL_GPL(hdq_initialized);
78359 +int hdq_read(int address)
78361 + int count_sleeps = 5;
78362 + int ret = -ETIME;
78364 + if (!hdq_priv.hdq_probed)
78367 + mutex_lock(&hdq_priv.hdq_lock);
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();
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
78378 + while (count_sleeps--) {
78379 + msleep(10); /* valid transaction always completes in < 10ms */
78384 + if (hdq_priv.hdq_error) {
78386 + goto done; /* didn't see a response in good time */
78390 + ret = hdq_priv.hdq_rx_data;
78395 + mutex_unlock(&hdq_priv.hdq_lock);
78398 +EXPORT_SYMBOL_GPL(hdq_read);
78400 +int hdq_write(int address, u8 data)
78402 + int count_sleeps = 5;
78403 + int ret = -ETIME;
78405 + if (!hdq_priv.hdq_probed)
78408 + mutex_lock(&hdq_priv.hdq_lock);
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();
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
78420 + while (count_sleeps--) {
78421 + msleep(10); /* valid transaction always completes in < 10ms */
78424 + continue; /* something bad with FIQ */
78426 + if (hdq_priv.hdq_error) {
78428 + goto done; /* didn't see a response in good time */
78437 + mutex_unlock(&hdq_priv.hdq_lock);
78440 +EXPORT_SYMBOL_GPL(hdq_write);
78444 +static ssize_t hdq_sysfs_dump(struct device *dev, struct device_attribute *attr,
78449 + u8 u8a[128]; /* whole address space for HDQ */
78452 + if (!hdq_priv.hdq_probed)
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
78458 + for (n = 0; n < sizeof(u8a); n++) {
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);
78471 + return (end - buf);
78474 + return sprintf(buf, "ERROR %d\n", v);
78477 +/* you write by <address> <data>, eg, "34 128" */
78479 +#define atoi(str) simple_strtoul(((str != NULL) ? str : ""), NULL, 0)
78481 +static ssize_t hdq_sysfs_write(struct device *dev,
78482 + struct device_attribute *attr,
78483 + const char *buf, size_t count)
78485 + const char *end = buf + count;
78486 + int address = atoi(buf);
78488 + if (!hdq_priv.hdq_probed)
78491 + while ((buf != end) && (*buf != ' '))
78495 + while ((buf < end) && (*buf == ' '))
78500 + hdq_write(address, atoi(buf));
78505 +static DEVICE_ATTR(dump, 0400, hdq_sysfs_dump, NULL);
78506 +static DEVICE_ATTR(write, 0600, NULL, hdq_sysfs_write);
78508 +static struct attribute *hdq_sysfs_entries[] = {
78509 + &dev_attr_dump.attr,
78510 + &dev_attr_write.attr,
78514 +static struct attribute_group hdq_attr_group = {
78516 + .attrs = hdq_sysfs_entries,
78521 +static int hdq_suspend(struct platform_device *pdev, pm_message_t state)
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();
78529 +static int hdq_resume(struct platform_device *pdev)
78531 + hdq_priv.pdata->gpio_set(1);
78532 + hdq_priv.pdata->gpio_dir_out();
78533 + hdq_priv.pdata->enable_fiq();
78538 +static int __init hdq_probe(struct platform_device *pdev)
78540 + struct resource *r = platform_get_resource(pdev, 0, 0);
78542 + struct hdq_platform_data *pdata = pdev->dev.platform_data;
78544 + if (!r || !pdata)
78547 + platform_set_drvdata(pdev, NULL);
78549 + mutex_init(&hdq_priv.hdq_lock);
78551 + /* set our HDQ comms pin from the platform data */
78552 + hdq_priv.hdq_gpio_pin = r->start;
78553 + hdq_priv.pdata = pdata;
78555 + hdq_priv.pdata->gpio_set(1);
78556 + hdq_priv.pdata->gpio_dir_out();
78558 + /* Initialize FIQ */
78559 + if (hdq_priv.pdata->enable_fiq() < 0) {
78560 + dev_err(&pdev->dev, "Could not enable FIQ source\n");
78564 + ret = sysfs_create_group(&pdev->dev.kobj, &hdq_attr_group);
78568 + hdq_priv.hdq_probed = 1; /* we are ready to do stuff now */
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
78575 + if (pdata->attach_child_devices)
78576 + (pdata->attach_child_devices)(&pdev->dev);
78578 + hdq_priv.pdata = pdata;
78583 +static int hdq_remove(struct platform_device *pdev)
78585 + sysfs_remove_group(&pdev->dev.kobj, &hdq_attr_group);
78589 +static struct platform_driver hdq_driver = {
78590 + .probe = hdq_probe,
78591 + .remove = hdq_remove,
78593 + .suspend = hdq_suspend,
78594 + .resume = hdq_resume,
78601 +static int __init hdq_init(void)
78603 + return platform_driver_register(&hdq_driver);
78606 +static void __exit hdq_exit(void)
78608 + platform_driver_unregister(&hdq_driver);
78611 +module_init(hdq_init);
78612 +module_exit(hdq_exit);
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
78621 Say Y to include support for NXP PCF50633 Main Battery Charger.
78623 +config BATTERY_BQ27000_HDQ
78624 + tristate "BQ27000 HDQ battery monitor driver"
78626 + Say Y to enable support for the battery on the Neo Freerunner
78628 +config HDQ_GPIO_BITBANG
78629 + bool "Generic gpio based HDQ bitbang"
78631 + Say Y to enable supoort for generic gpio based HDQ bitbang driver.
78632 + This can not be built as a module.
78634 +config CHARGER_PCF50606
78635 + tristate "Support for NXP PCF50606 MBC"
78636 + depends on MFD_PCF50606
78638 + Say Y to include support for NXP PCF50606 Battery Charger.
78640 +config BATTERY_GTA01
78641 + tristate "GTA01 battery driver"
78643 + Say Y here to enable this dumb driver for dumb gta01 batteries
78645 endif # POWER_SUPPLY
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
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
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
78667 +/* NXP PCF50606 Main Battery Charger Driver
78669 + * (C) 2006-2008 by Openmoko, Inc.
78670 + * Author: Balaji Rao <balajirrao@openmoko.org>
78671 + * All rights reserved.
78673 + * Broken down from monstrous PCF50606 driver mainly by
78674 + * Harald Welte, Andy Green and Werner Almesberger
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.
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>
78692 +#include <linux/mfd/pcf50606/core.h>
78693 +#include <linux/mfd/pcf50606/mbc.h>
78695 +struct pcf50606_mbc {
78696 + struct pcf50606 *pcf;
78698 + int charger_online;
78699 + struct power_supply charger;
78702 +void pcf50606_charge_fast(struct pcf50606 *pcf, int on)
78704 + struct pcf50606_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
78707 + * This is a fix to work around boot-time ordering problems if
78708 + * the s3c2410_udc is initialized before the pcf50606 mbc is
78715 + pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_MBCC1,
78716 + PCF50606_MBCC1_AUTOFST,
78717 + PCF50606_MBCC1_AUTOFST);\
78718 + mbc->charger_online = 1;
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;
78730 +EXPORT_SYMBOL_GPL(pcf50606_charge_fast);
78733 +show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
78735 + struct pcf50606_mbc *mbc = dev_get_drvdata(dev);
78737 + u8 mbcc1 = pcf50606_reg_read(mbc->pcf, PCF50606_REG_MBCC1);
78738 + u8 chgmod = (mbcc1 & PCF50606_MBCC1_CHGMOD_MASK);
78740 + return sprintf(buf, "%d\n", chgmod);
78743 +static ssize_t set_chgmode(struct device *dev, struct device_attribute *attr,
78744 + const char *buf, size_t count)
78746 + struct pcf50606_mbc *mbc = dev_get_drvdata(dev);
78747 + u_int8_t mbcc1 = pcf50606_reg_read(mbc->pcf, PCF50606_REG_MBCC1);
78749 + mbcc1 &= ~PCF50606_MBCC1_CHGMOD_MASK;
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;
78765 + pcf50606_reg_write(mbc->pcf, PCF50606_REG_MBCC1, mbcc1);
78770 +static DEVICE_ATTR(chgmode, S_IRUGO, show_chgmode, set_chgmode);
78773 +static struct attribute *pcf50606_mbc_sysfs_entries[] = {
78774 + &dev_attr_chgmode.attr,
78778 +static struct attribute_group mbc_attr_group = {
78779 + .name = NULL, /* put in device directory */
78780 + .attrs = pcf50606_mbc_sysfs_entries,
78784 +pcf50606_mbc_irq_handler(int irq, void *data)
78786 + struct pcf50606_mbc *mbc = data;
78788 + power_supply_changed(&mbc->charger);
78790 + if (mbc->pcf->pdata->mbc_event_callback)
78791 + mbc->pcf->pdata->mbc_event_callback(mbc->pcf, irq);
78794 +static int charger_get_property(struct power_supply *psy,
78795 + enum power_supply_property psp,
78796 + union power_supply_propval *val)
78798 + struct pcf50606_mbc *mbc = container_of(psy, struct pcf50606_mbc, charger);
78802 + case POWER_SUPPLY_PROP_ONLINE:
78803 + val->intval = mbc->charger_online;
78812 +static enum power_supply_property power_props[] = {
78813 + POWER_SUPPLY_PROP_ONLINE,
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,
78825 +static int __devinit pcf50606_mbc_probe(struct platform_device *pdev)
78827 + struct pcf50606_mbc *mbc;
78828 + struct pcf50606_subdev_pdata *pdata = pdev->dev.platform_data;
78833 + mbc = kzalloc(sizeof(*mbc), GFP_KERNEL);
78837 + platform_set_drvdata(pdev, mbc);
78838 + mbc->pcf = pdata->pcf;
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);
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;
78853 + ret = power_supply_register(&pdev->dev, &mbc->charger);
78855 + dev_err(mbc->pcf->dev, "failed to register charger\n");
78860 + ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
78862 + dev_err(mbc->pcf->dev, "failed to create sysfs entries\n");
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);
78871 +static int __devexit pcf50606_mbc_remove(struct platform_device *pdev)
78873 + struct pcf50606_mbc *mbc = platform_get_drvdata(pdev);
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]);
78880 + power_supply_unregister(&mbc->charger);
78887 +static struct platform_driver pcf50606_mbc_driver = {
78889 + .name = "pcf50606-mbc",
78891 + .probe = pcf50606_mbc_probe,
78892 + .remove = __devexit_p(pcf50606_mbc_remove),
78895 +static int __init pcf50606_mbc_init(void)
78897 + return platform_driver_register(&pcf50606_mbc_driver);
78899 +module_init(pcf50606_mbc_init);
78901 +static void __exit pcf50606_mbc_exit(void)
78903 + platform_driver_unregister(&pcf50606_mbc_driver);
78905 +module_exit(pcf50606_mbc_exit);
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
78916 struct power_supply usb;
78917 struct power_supply adapter;
78918 + struct power_supply ac;
78920 + struct delayed_work charging_restart_work;
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);
78928 + int charging_start = 1;
78929 + u8 mbcs2, chgmod;
78930 + unsigned int mbcc5;
78933 + if (ma >= 1000) {
78934 bits = PCF50633_MBCC7_USB_1000mA;
78935 - else if (ma >= 500)
78937 + } else if (ma >= 500) {
78938 bits = PCF50633_MBCC7_USB_500mA;
78939 - else if (ma >= 100)
78941 + } else if (ma >= 100) {
78942 bits = PCF50633_MBCC7_USB_100mA;
78946 bits = PCF50633_MBCC7_USB_SUSPEND;
78947 + charging_start = 0;
78951 ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC7,
78952 PCF50633_MBCC7_USB_MASK, bits);
78955 dev_info(pcf->dev, "usb curlim to %d mA\n", ma);
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
78968 + mbcc5 = (ma << 8) / mbc->pcf->pdata->chg_ref_current_ma;
78971 + pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
78973 + mbcs2 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2);
78974 + chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
78976 + /* If chgmod == BATFULL, setting chgena has no effect.
78977 + * We need to set resume instead.
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);
78983 + pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1,
78984 + PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME);
78986 + mbc->usb_active = charging_start;
78988 power_supply_changed(&mbc->usb);
78991 @@ -84,21 +127,6 @@
78993 EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status);
78995 -void pcf50633_mbc_set_status(struct pcf50633 *pcf, int what, int status)
78997 - struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
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;
79008 -EXPORT_SYMBOL_GPL(pcf50633_mbc_set_status);
79011 show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
79013 @@ -149,9 +177,44 @@
79015 static DEVICE_ATTR(usb_curlim, S_IRUGO | S_IWUSR, show_usblim, set_usblim);
79018 +show_chglim(struct device *dev, struct device_attribute *attr, char *buf)
79020 + struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
79021 + u8 mbcc5 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC5);
79024 + ma = (mbc->pcf->pdata->chg_ref_current_ma * mbcc5) >> 8;
79026 + return sprintf(buf, "%u\n", ma);
79029 +static ssize_t set_chglim(struct device *dev,
79030 + struct device_attribute *attr, const char *buf, size_t count)
79032 + struct pcf50633_mbc *mbc = dev_get_drvdata(dev);
79033 + unsigned long ma;
79034 + unsigned int mbcc5;
79037 + ret = strict_strtoul(buf, 10, &ma);
79041 + mbcc5 = (ma << 8) / mbc->pcf->pdata->chg_ref_current_ma;
79044 + pcf50633_reg_write(mbc->pcf, PCF50633_REG_MBCC5, mbcc5);
79049 +static DEVICE_ATTR(chg_curlim, S_IRUGO | S_IWUSR, show_chglim, set_chglim);
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,
79058 @@ -160,10 +223,44 @@
79059 .attrs = pcf50633_mbc_sysfs_entries,
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%.
79067 + * This work_struct function restarts charging every few seconds and makes
79068 + * sure we don't discharge too much
79071 +static void pcf50633_mbc_charging_restart(struct work_struct *work)
79073 + struct pcf50633_mbc *mbc;
79074 + u8 mbcs2, chgmod;
79076 + mbc = container_of(work, struct pcf50633_mbc,
79077 + charging_restart_work.work);
79079 + mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
79080 + chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
79082 + if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL)
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);
79091 + dev_info(mbc->pcf->dev, "Charging restarted\n");
79095 pcf50633_mbc_irq_handler(int irq, void *data)
79097 struct pcf50633_mbc *mbc = data;
79098 + int chg_restart_interval =
79099 + mbc->pcf->pdata->charging_restart_interval;
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);
79113 @@ -186,10 +284,18 @@
79114 if (irq == PCF50633_IRQ_BATFULL) {
79115 mbc->usb_active = 0;
79116 mbc->adapter_active = 0;
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;
79127 power_supply_changed(&mbc->usb);
79128 power_supply_changed(&mbc->adapter);
79129 + power_supply_changed(&mbc->ac);
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)
79137 - struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
79138 + struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, adapter);
79142 @@ -219,10 +325,34 @@
79144 struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, usb);
79146 + u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
79147 + PCF50633_MBCC7_USB_MASK;
79150 + case POWER_SUPPLY_PROP_ONLINE:
79151 + val->intval = mbc->usb_online &&
79152 + (usblim <= PCF50633_MBCC7_USB_500mA);
79161 +static int ac_get_property(struct power_supply *psy,
79162 + enum power_supply_property psp,
79163 + union power_supply_propval *val)
79165 + struct pcf50633_mbc *mbc = container_of(psy, struct pcf50633_mbc, ac);
79167 + u8 usblim = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCC7) &
79168 + PCF50633_MBCC7_USB_MASK;
79171 case POWER_SUPPLY_PROP_ONLINE:
79172 - val->intval = mbc->usb_online;
79173 + val->intval = mbc->usb_online &&
79174 + (usblim == PCF50633_MBCC7_USB_1000mA);
79178 @@ -287,6 +417,17 @@
79179 mbc->usb.supplied_to = mbc->pcf->pdata->batteries;
79180 mbc->usb.num_supplicants = mbc->pcf->pdata->num_batteries;
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;
79190 + INIT_DELAYED_WORK(&mbc->charging_restart_work,
79191 + pcf50633_mbc_charging_restart);
79193 ret = power_supply_register(&pdev->dev, &mbc->adapter);
79195 dev_err(mbc->pcf->dev, "failed to register adapter\n");
79196 @@ -302,6 +443,15 @@
79200 + ret = power_supply_register(&pdev->dev, &mbc->ac);
79202 + dev_err(mbc->pcf->dev, "failed to register ac\n");
79203 + power_supply_unregister(&mbc->adapter);
79204 + power_supply_unregister(&mbc->usb);
79209 ret = sysfs_create_group(&pdev->dev.kobj, &mbc_attr_group);
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);
79216 + cancel_delayed_work_sync(&mbc->charging_restart_work);
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;
79228 - mutex_lock(&rdev->mutex);
79229 - if (regulator->enabled == 1) {
79230 - ret = _regulator_disable(rdev);
79232 - regulator->uA_load = 0;
79233 - } else if (WARN(regulator->enabled <= 0,
79234 - "unbalanced disables for supply %s\n",
79235 - regulator->supply_name))
79238 - regulator->enabled--;
79239 - mutex_unlock(&rdev->mutex);
79240 + if (!regulator->enabled) {
79241 + printk(KERN_ERR "%s: not in use by this consumer\n",
79247 + mutex_lock(®ulator->rdev->mutex);
79248 + regulator->enabled = 0;
79249 + regulator->uA_load = 0;
79250 + ret = _regulator_disable(regulator->rdev);
79251 + mutex_unlock(®ulator->rdev->mutex);
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
79260 Say Y here to support the voltage regulators and convertors
79263 +config REGULATOR_PCF50606
79264 + bool "PCF50606 regulator driver"
79265 + depends on MFD_PCF50606
79267 + Say Y here to support the voltage regulators and convertors
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
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
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
79284 +/* NXP PCF50606 PMIC Driver
79286 + * (C) 2006-2008 by Openmoko, Inc.
79287 + * Author: Balaji Rao <balajirrao@openmoko.org>
79288 + * All rights reserved.
79290 + * Broken down from monstrous PCF50606 driver mainly by
79291 + * Harald Welte and Andy Green and Werner Almesberger
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.
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>
79307 +#include <linux/mfd/pcf50606/core.h>
79308 +#include <linux/mfd/pcf50606/pmic.h>
79310 +#define PCF50606_REGULATOR(_name, _id) \
79314 + .ops = &pcf50606_regulator_ops, \
79315 + .type = REGULATOR_VOLTAGE, \
79316 + .owner = THIS_MODULE, \
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,
79330 +static u8 dcudc_voltage(unsigned int millivolts)
79332 + if (millivolts < 900)
79334 + if (millivolts > 5500)
79336 + if (millivolts <= 3300) {
79337 + millivolts -= 900;
79338 + return millivolts/300;
79340 + if (millivolts < 4000)
79343 + millivolts -= 4000;
79344 + return millivolts/100;
79348 +static unsigned int dcudc_2voltage(u8 bits)
79352 + return 900 + bits * 300;
79353 + else if (bits < 0x10)
79356 + return 4000 + bits * 100;
79359 +static u8 dcdec_voltage(unsigned int millivolts)
79361 + if (millivolts < 900)
79363 + else if (millivolts > 3300)
79366 + millivolts -= 900;
79367 + return millivolts/300;
79370 +static unsigned int dcdec_2voltage(u8 bits)
79373 + return 900 + bits*300;
79376 +static u8 dcdc_voltage(unsigned int millivolts)
79378 + if (millivolts < 900)
79380 + else if (millivolts > 3600)
79383 + if (millivolts < 1500) {
79384 + millivolts -= 900;
79385 + return millivolts/25;
79387 + millivolts -= 1500;
79388 + return 0x18 + millivolts/300;
79392 +static unsigned int dcdc_2voltage(u8 bits)
79395 + if ((bits & 0x18) == 0x18)
79396 + return 1500 + ((bits & 0x7) * 300);
79398 + return 900 + (bits * 25);
79401 +static u8 dx_voltage(unsigned int millivolts)
79403 + if (millivolts < 900)
79405 + else if (millivolts > 3300)
79408 + millivolts -= 900;
79409 + return millivolts/100;
79412 +static unsigned int dx_2voltage(u8 bits)
79415 + return 900 + (bits * 100);
79418 +static int pcf50606_regulator_set_voltage(struct regulator_dev *rdev,
79419 + int min_uV, int max_uV)
79421 + struct pcf50606 *pcf;
79422 + int regulator_id, millivolts, rc;
79423 + u8 volt_bits, regnr;
79425 + pcf = rdev_get_drvdata(rdev);
79427 + regulator_id = rdev_get_id(rdev);
79428 + if (regulator_id >= PCF50606_NUM_REGULATORS)
79431 + millivolts = min_uV / 1000;
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,
79439 + case PCF50606_REGULATOR_DCDE:
79440 + volt_bits = dcdec_voltage(millivolts);
79441 + rc = pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_DCDEC1, 0x0f,
79444 + case PCF50606_REGULATOR_DCUD:
79445 + volt_bits = dcudc_voltage(millivolts);
79446 + rc = pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_DCUDC1, 0x1f,
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);
79457 + case PCF50606_REGULATOR_LPREG:
79458 + volt_bits = dx_voltage(millivolts);
79459 + rc = pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_LPREGC1, 0x1f,
79462 + case PCF50606_REGULATOR_IOREG:
79463 + if (millivolts < 1800)
79465 + volt_bits = dx_voltage(millivolts);
79466 + rc = pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_IOREGC, 0x1f,
79476 +static int pcf50606_regulator_get_voltage(struct regulator_dev *rdev)
79478 + struct pcf50606 *pcf;
79479 + u8 volt_bits, regnr;
79480 + int rc = 0, regulator_id;
79483 + pcf = rdev_get_drvdata(rdev);
79485 + regulator_id = rdev_get_id(rdev);
79486 + if (regulator_id >= PCF50606_NUM_REGULATORS)
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);
79494 + case PCF50606_REGULATOR_DCDE:
79495 + volt_bits = pcf50606_reg_read(pcf, PCF50606_REG_DCDEC1) & 0x0f;
79496 + rc = dcdec_2voltage(volt_bits);
79498 + case PCF50606_REGULATOR_DCUD:
79499 + volt_bits = pcf50606_reg_read(pcf, PCF50606_REG_DCUDC1) & 0x1f;
79500 + rc = dcudc_2voltage(volt_bits);
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);
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);
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);
79527 + return rc * 1000;
79531 +static int pcf50606_regulator_enable(struct regulator_dev *rdev)
79533 + struct pcf50606 *pcf = rdev_get_drvdata(rdev);
79534 + int regulator_id;
79537 + regulator_id = rdev_get_id(rdev);
79538 + if (regulator_id >= PCF50606_NUM_REGULATORS)
79541 + regnr = pcf50606_regulator_registers[regulator_id];
79543 + return pcf50606_reg_set_bit_mask(pcf, regnr, 0xe0, 0xe0);
79546 +static int pcf50606_regulator_disable(struct regulator_dev *rdev)
79548 + struct pcf50606 *pcf = rdev_get_drvdata(rdev);
79549 + int regulator_id;
79552 + regulator_id = rdev_get_id(rdev);
79553 + if (regulator_id >= PCF50606_NUM_REGULATORS)
79556 + /* IOREG cannot be powered off since it powers the PMU I2C */
79557 + if (regulator_id == PCF50606_REGULATOR_IOREG)
79560 + regnr = pcf50606_regulator_registers[regulator_id];
79562 + return pcf50606_reg_set_bit_mask(pcf, regnr, 0xe0, 0);
79565 +static int pcf50606_regulator_is_enabled(struct regulator_dev *rdev)
79567 + struct pcf50606 *pcf = rdev_get_drvdata(rdev);
79568 + int regulator_id = rdev_get_id(rdev);
79571 + regulator_id = rdev_get_id(rdev);
79572 + if (regulator_id >= PCF50606_NUM_REGULATORS)
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;
79579 + /* PWREN1 = 1, PWREN2 = 1, see table 16 of datasheet */
79580 + if (val == 0 || val == 5)
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,
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),
79613 +static int __devinit pcf50606_regulator_probe(struct platform_device *pdev)
79615 + struct regulator_dev *rdev;
79616 + struct pcf50606 *pcf;
79618 + /* Already set by core driver */
79619 + pcf = platform_get_drvdata(pdev);
79621 + rdev = regulator_register(®ulators[pdev->id], &pdev->dev, pcf);
79622 + if (IS_ERR(rdev))
79623 + return PTR_ERR(rdev);
79625 + if (pcf->pdata->regulator_registered)
79626 + pcf->pdata->regulator_registered(pcf, pdev->id);
79631 +static int __devexit pcf50606_regulator_remove(struct platform_device *pdev)
79633 + struct regulator_dev *rdev = platform_get_drvdata(pdev);
79635 + regulator_unregister(rdev);
79640 +static struct platform_driver pcf50606_regulator_driver = {
79642 + .name = "pcf50606-regltr",
79644 + .probe = pcf50606_regulator_probe,
79645 + .remove = __devexit_p(pcf50606_regulator_remove),
79648 +static int __init pcf50606_regulator_init(void)
79650 + return platform_driver_register(&pcf50606_regulator_driver);
79652 +module_init(pcf50606_regulator_init);
79654 +static void __exit pcf50606_regulator_exit(void)
79656 + platform_driver_unregister(&pcf50606_regulator_driver);
79658 +module_exit(pcf50606_regulator_exit);
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.
79671 +config RTC_DRV_PCF50606
79672 + depends on MFD_PCF50606
79673 + tristate "Philips PCF50606"
79675 + If you say yes here you get support for the Philips PCF50606
79678 config RTC_DRV_M41T80
79679 tristate "ST M41T65/M41T80/81/82/83/84/85/87"
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
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
79693 +/* NXP PCF50606 RTC Driver
79695 + * (C) 2006-2008 by Openmoko, Inc.
79696 + * Author: Balaji Rao <balajirrao@openmoko.org>
79697 + * All rights reserved.
79699 + * Broken down from monstrous PCF50606 driver mainly by
79700 + * Harald Welte, Andy Green and Werner Almesberger
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.
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>
79718 +#include <linux/mfd/pcf50606/core.h>
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 */
79735 +enum pcf50606_time_indexes {
79738 + PCF50606_TI_HOUR,
79739 + PCF50606_TI_WKDAY,
79741 + PCF50606_TI_MONTH,
79742 + PCF50606_TI_YEAR,
79743 + PCF50606_TI_EXTENT /* always last */
79746 +struct pcf50606_time {
79747 + u_int8_t time[PCF50606_TI_EXTENT];
79750 +struct pcf50606_rtc {
79751 + int alarm_enabled;
79752 + int second_enabled;
79754 + struct pcf50606 *pcf;
79755 + struct rtc_device *rtc_dev;
79758 +static void pcf2rtc_time(struct rtc_time *rtc, struct pcf50606_time *pcf)
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;
79769 +static void rtc2pcf_time(struct pcf50606_time *pcf, struct rtc_time *rtc)
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);
79781 +pcf50606_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
79783 + struct pcf50606_rtc *rtc = dev_get_drvdata(dev);
79786 + case RTC_AIE_OFF:
79787 + rtc->alarm_enabled = 0;
79788 + pcf50606_irq_mask(rtc->pcf, PCF50606_IRQ_ALARM);
79791 + rtc->alarm_enabled = 1;
79792 + pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_ALARM);
79794 + case RTC_UIE_OFF:
79795 + rtc->second_enabled = 0;
79796 + pcf50606_irq_mask(rtc->pcf, PCF50606_IRQ_SECOND);
79799 + rtc->second_enabled = 1;
79800 + pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_SECOND);
79804 + return -ENOIOCTLCMD;
79807 +static int pcf50606_rtc_read_time(struct device *dev, struct rtc_time *tm)
79809 + struct pcf50606_rtc *rtc;
79810 + struct pcf50606_time pcf_tm;
79813 + rtc = dev_get_drvdata(dev);
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");
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]);
79831 + pcf2rtc_time(tm, &pcf_tm);
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);
79837 + return rtc_valid_tm(tm);
79840 +static int pcf50606_rtc_set_time(struct device *dev, struct rtc_time *tm)
79842 + struct pcf50606_rtc *rtc;
79843 + struct pcf50606_time pcf_tm;
79844 + int second_masked, alarm_masked, ret = 0;
79846 + rtc = dev_get_drvdata(dev);
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);
79852 + rtc2pcf_time(&pcf_tm, tm);
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]);
79863 + second_masked = pcf50606_irq_mask_get(rtc->pcf, PCF50606_IRQ_SECOND);
79864 + alarm_masked = pcf50606_irq_mask_get(rtc->pcf, PCF50606_IRQ_ALARM);
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);
79871 + /* Returns 0 on success */
79872 + ret = pcf50606_write_block(rtc->pcf, PCF50606_REG_RTCSC,
79873 + PCF50606_TI_EXTENT,
79874 + &pcf_tm.time[0]);
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);
79884 +static int pcf50606_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
79886 + struct pcf50606_rtc *rtc;
79887 + struct pcf50606_time pcf_tm;
79890 + rtc = dev_get_drvdata(dev);
79892 + alrm->enabled = rtc->alarm_enabled;
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");
79901 + pcf2rtc_time(&alrm->time, &pcf_tm);
79903 + return rtc_valid_tm(&alrm->time);
79906 +static int pcf50606_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
79908 + struct pcf50606_rtc *rtc;
79909 + struct pcf50606_time pcf_tm;
79910 + int alarm_masked, ret = 0;
79912 + rtc = dev_get_drvdata(dev);
79914 + rtc2pcf_time(&pcf_tm, &alrm->time);
79916 + /* do like mktime does and ignore tm_wday */
79917 + pcf_tm.time[PCF50606_TI_WKDAY] = 7;
79919 + alarm_masked = pcf50606_irq_mask_get(rtc->pcf, PCF50606_IRQ_ALARM);
79921 + /* disable alarm interrupt */
79922 + if (!alarm_masked)
79923 + pcf50606_irq_mask(rtc->pcf, PCF50606_IRQ_ALARM);
79925 + /* Returns 0 on success */
79926 + ret = pcf50606_write_block(rtc->pcf, PCF50606_REG_RTCSCA,
79927 + PCF50606_TI_EXTENT, &pcf_tm.time[0]);
79929 + if (!alarm_masked)
79930 + pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_ALARM);
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,
79943 +static void pcf50606_rtc_irq(int irq, void *data)
79945 + struct pcf50606_rtc *rtc = data;
79948 + case PCF50606_IRQ_ALARM:
79949 + rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
79951 + case PCF50606_IRQ_SECOND:
79952 + rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
79957 +static int __devinit pcf50606_rtc_probe(struct platform_device *pdev)
79959 + struct pcf50606_subdev_pdata *pdata;
79960 + struct pcf50606_rtc *rtc;
79963 + rtc = kzalloc(sizeof(*rtc), GFP_KERNEL);
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);
79973 + if (IS_ERR(rtc->rtc_dev)) {
79975 + return PTR_ERR(rtc->rtc_dev);
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);
79987 +static int __devexit pcf50606_rtc_remove(struct platform_device *pdev)
79989 + struct pcf50606_rtc *rtc;
79991 + rtc = platform_get_drvdata(pdev);
79993 + pcf50606_free_irq(rtc->pcf, PCF50606_IRQ_ALARM);
79994 + pcf50606_free_irq(rtc->pcf, PCF50606_IRQ_SECOND);
79996 + rtc_device_unregister(rtc->rtc_dev);
80004 +static struct platform_driver pcf50606_rtc_driver = {
80006 + .name = "pcf50606-rtc",
80008 + .probe = pcf50606_rtc_probe,
80009 + .remove = __devexit_p(pcf50606_rtc_remove),
80012 +static int __init pcf50606_rtc_init(void)
80014 + return platform_driver_register(&pcf50606_rtc_driver);
80016 +module_init(pcf50606_rtc_init);
80018 +static void __exit pcf50606_rtc_exit(void)
80020 + platform_driver_unregister(&pcf50606_rtc_driver);
80022 +module_exit(pcf50606_rtc_exit);
80024 +MODULE_DESCRIPTION("PCF50606 RTC driver");
80025 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
80026 +MODULE_LICENSE("GPL");
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
80032 struct pcf50633_rtc {
80034 int second_enabled;
80035 + int alarm_pending;
80037 struct pcf50633 *pcf;
80038 struct rtc_device *rtc_dev;
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;
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);
80057 @@ -209,6 +210,7 @@
80058 rtc = dev_get_drvdata(dev);
80060 alrm->enabled = rtc->alarm_enabled;
80061 + alrm->pending = rtc->alarm_pending;
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;
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;
80079 @@ -267,6 +272,7 @@
80081 case PCF50633_IRQ_ALARM:
80082 rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
80083 + rtc->alarm_pending = 1;
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
80091 #include <linux/serial.h>
80093 #include <asm/irq.h>
80095 #include <mach/hardware.h>
80097 #include <plat/regs-serial.h>
80100 static int s3c2410_serial_probe(struct platform_device *dev)
80102 + dbg("s3c2410_serial_probe: dev=%p\n", dev);
80103 return s3c24xx_serial_probe(dev, &s3c2410_uart_inf);
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,
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
80121 #include <mach/map.h>
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>
80129 #include "samsung.h"
80131 @@ -235,8 +239,8 @@
80134 if (unlikely(uerstat & S3C2410_UERSTAT_ANY)) {
80135 - dbg("rxerr: port ch=0x%02x, rxs=0x%08x\n",
80137 + printk(KERN_DEBUG "rxerr: port=%d ch=0x%02x, rxs=0x%08x\n",
80138 + port->line, ch, uerstat);
80140 /* check for break */
80141 if (uerstat & S3C2410_UERSTAT_BREAK) {
80142 @@ -265,8 +269,8 @@
80143 if (uart_handle_sysrq_char(port, ch))
80146 - uart_insert_char(port, uerstat, S3C2410_UERSTAT_OVERRUN,
80148 + if ((uerstat & port->ignore_status_mask & ~S3C2410_UERSTAT_OVERRUN) == 0)
80149 + tty_insert_flip_char(tty, ch, flag);
80153 @@ -508,6 +512,7 @@
80155 struct s3c24xx_uart_clksrc *clksrc;
80157 + unsigned int divslot;
80161 @@ -517,6 +522,7 @@
80162 struct s3c24xx_uart_clksrc *clksrc,
80165 + struct s3c24xx_uart_port *ourport = to_ourport(port);
80166 unsigned long rate;
80168 calc->src = clk_get(port->dev, clksrc->name);
80169 @@ -527,8 +533,24 @@
80170 rate /= clksrc->divisor;
80172 calc->clksrc = clksrc;
80173 - calc->quot = (rate + (8 * baud)) / (16 * baud);
80174 - calc->calc = (rate / (calc->quot * 16));
80176 + if (ourport->info->has_divslot) {
80177 + unsigned long div = rate / baud;
80179 + /* The UDIVSLOT register on the newer UARTs allows us to
80180 + * get a divisor adjustment of 1/16th on the baud clock.
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.
80187 + calc->quot = div / 16;
80188 + calc->calc = rate / div;
80190 + calc->quot = (rate + (8 * baud)) / (16 * baud);
80191 + calc->calc = (rate / (calc->quot * 16));
80196 @@ -611,6 +633,30 @@
80200 +/* udivslot_table[]
80202 + * This table takes the fractional value of the baud divisor and gives
80203 + * the recommended setting for the UDIVSLOT register.
80205 +static u16 udivslot_table[16] = {
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;
80234 * We don't support modem control lines.
80235 @@ -644,6 +691,7 @@
80236 /* check to see if we need to change clock source */
80238 if (ourport->clksrc != clksrc || ourport->baudclk != clk) {
80239 + dbg("selecting clock %p\n", clk);
80240 s3c24xx_serial_setsource(port, clksrc);
80242 if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
80243 @@ -658,6 +706,13 @@
80244 ourport->baudclk_rate = clk ? clk_get_rate(clk) : 0;
80247 + if (ourport->info->has_divslot) {
80248 + unsigned int div = ourport->baudclk_rate / baud;
80250 + udivslot = udivslot_table[div & 15];
80251 + dbg("udivslot = %04x (div %d)\n", udivslot, div & 15);
80254 switch (termios->c_cflag & CSIZE) {
80256 dbg("config: 5bits/char\n");
80257 @@ -697,12 +752,16 @@
80259 spin_lock_irqsave(&port->lock, flags);
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);
80265 wr_regl(port, S3C2410_ULCON, ulcon);
80266 wr_regl(port, S3C2410_UBRDIV, quot);
80267 wr_regl(port, S3C2410_UMCON, umcon);
80269 + if (ourport->info->has_divslot)
80270 + wr_regl(port, S3C2443_DIVSLOT, udivslot);
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 @@
80279 +#ifdef CONFIG_MACH_NEO1973_GTA02
80280 +static void s3c24xx_serial_force_debug_port_up(void)
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;
80288 + s3c24xx_serial_getclk(&ourport->port, &clksrc, &clk, 115200);
80290 + tmp = __raw_readl(S3C2410_CLKCON);
80292 + /* re-start uart clocks */
80293 + tmp |= S3C2410_CLKCON_UART0;
80294 + tmp |= S3C2410_CLKCON_UART1;
80295 + tmp |= S3C2410_CLKCON_UART2;
80297 + __raw_writel(tmp, S3C2410_CLKCON);
80300 + s3c24xx_serial_setsource(&ourport->port, clksrc);
80302 + if (ourport->baudclk != NULL && !IS_ERR(ourport->baudclk)) {
80303 + clk_disable(ourport->baudclk);
80304 + ourport->baudclk = NULL;
80309 + ourport->clksrc = clksrc;
80310 + ourport->baudclk = clk;
80313 +static void s3c2410_printascii(const char *sz)
80315 + struct s3c24xx_uart_port *ourport = &s3c24xx_serial_ports[
80316 + CONFIG_DEBUG_S3C_UART];
80317 + struct uart_port *port = &ourport->port;
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);
80329 + int timeout = 10000000;
80331 + /* spin on it being busy */
80332 + while ((!(rd_regl(port, S3C2410_UTRSTAT) & 2)) && timeout--)
80335 + /* transmit register */
80336 + wr_regl(port, S3C2410_UTXH, *sz);
80343 /* s3c24xx_serial_resetport
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;
80350 - if (uport->info == NULL)
80351 + if (uport->info == NULL) {
80352 + printk(KERN_WARNING "%s: info NULL\n", __func__);
80356 tty = uport->info->port.tty;
80359 + if (tty == NULL) {
80360 + printk(KERN_WARNING "%s: tty is NULL\n", __func__);
80364 termios = tty->termios;
80366 @@ -1092,6 +1219,7 @@
80368 ourport = &s3c24xx_serial_ports[probe_index];
80370 + init_resume_dependency_list(&ourport->resume_dependency);
80372 dbg("%s: initialising port %p...\n", __func__, ourport);
80374 @@ -1148,6 +1276,16 @@
80378 +void s3c24xx_serial_register_resume_dependency(struct resume_dependency *
80379 + resume_dependency, int uart_index)
80381 + struct s3c24xx_uart_port *ourport = &s3c24xx_serial_ports[uart_index];
80383 + register_resume_dependency(&ourport->resume_dependency,
80384 + resume_dependency);
80386 +EXPORT_SYMBOL(s3c24xx_serial_register_resume_dependency);
80388 static int s3c24xx_serial_resume(struct platform_device *dev)
80390 struct uart_port *port = s3c24xx_dev_to_port(&dev->dev);
80391 @@ -1159,6 +1297,9 @@
80392 clk_disable(ourport->clk);
80394 uart_resume_port(&s3c24xx_uart_drv, port);
80396 + callback_all_resume_dependencies(&ourport->resume_dependency);
80401 @@ -1169,6 +1310,12 @@
80402 struct s3c24xx_uart_info *info)
80404 dbg("s3c24xx_serial_init(%p,%p)\n", drv, info);
80405 +#ifdef CONFIG_MACH_NEO1973_GTA02
80406 + /* set up the emergency debug UART functions */
80408 + printk_emergency_debug_spew_init = s3c24xx_serial_force_debug_port_up;
80409 + printk_emergency_debug_spew_send_string = s3c2410_printascii;
80413 drv->suspend = s3c24xx_serial_suspend;
80414 @@ -1208,6 +1355,13 @@
80415 #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
80417 static struct uart_port *cons_uart;
80418 +static int cons_silenced;
80420 +void s3c24xx_serial_console_set_silence(int silenced)
80422 + cons_silenced = silenced;
80424 +EXPORT_SYMBOL(s3c24xx_serial_console_set_silence);
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)
80431 unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON);
80432 + unsigned int umcon = rd_regl(cons_uart, S3C2410_UMCON);
80434 + if (cons_silenced)
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));
80441 while (!s3c24xx_serial_console_txrdy(port, ufcon))
80443 wr_regb(cons_uart, S3C2410_UTXH, ch);
80445 + if (umcon & S3C2410_UMCOM_AFC)
80446 + wr_regl(port, S3C2410_UMCON, umcon);
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
80454 * published by the Free Software Foundation.
80457 +#include <linux/resume-dependency.h>
80459 struct s3c24xx_uart_info {
80463 unsigned long tx_fifoshift;
80464 unsigned long tx_fifofull;
80466 + /* uart port features */
80468 + unsigned int has_divslot:1;
80470 /* clock source control */
80472 int (*get_clksrc)(struct uart_port *, struct s3c24xx_uart_clksrc *clk);
80474 #ifdef CONFIG_CPU_FREQ
80475 struct notifier_block freq_transition;
80478 + struct resume_dependency resume_dependency;
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.
80489 +config SPI_S3C64XX_GPIO
80490 + tristate "Samsung S3C64XX series SPI by GPIO"
80491 + depends on ARCH_S3C64XX && EXPERIMENTAL
80492 + select SPI_BITBANG
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.
80499 # Add new SPI protocol masters in alphabetical order above this line
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
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 ...
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.
80520 +/* Synchronous non blocking transfer */
80522 +spi_bitbang_transfer_sync(struct spi_device *spi, struct spi_message *m)
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;
80530 + int (*setup_transfer)(struct spi_device *, struct spi_transfer *);
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?
80539 + setup_transfer = NULL;
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;
80551 + if (setup_transfer) {
80552 + status = setup_transfer(spi, t);
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
80565 + bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
80569 + cs_change = t->cs_change;
80570 + if (!t->tx_buf && !t->rx_buf && t->len) {
80571 + status = -EINVAL;
80575 + /* transfer data. the lower level code handles any
80576 + * new dma mappings it needs. our caller always gave
80577 + * us dma-safe buffers.
80580 + /* REVISIT dma API still needs a designated
80581 + * DMA_ADDR_INVALID; ~0 might be better.
80583 + if (!m->is_dma_mapped)
80584 + t->rx_dma = t->tx_dma = 0;
80585 + status = bitbang->txrx_bufs(spi, t);
80589 + m->actual_length += status;
80590 + if (status != t->len) {
80591 + /* always report some kind of error */
80593 + status = -EREMOTEIO;
80597 + /* protocol tweaks before next transfer */
80598 + if (t->delay_usecs)
80599 + udelay(t->delay_usecs);
80602 + if (t->transfer_list.next == &m->transfers)
80604 + /* sometimes a short mid-message deselect of the chip
80605 + * may be needed to terminate a mode or command
80608 + bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
80612 + m->status = status;
80614 + m->complete(m->context);
80616 + /* restore speed and wordsize */
80617 + if (setup_transfer)
80618 + setup_transfer(spi, NULL);
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.
80624 + if (!(status == 0 && cs_change)) {
80626 + bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
80630 + local_irq_restore(flags);
80634 +EXPORT_SYMBOL_GPL(spi_bitbang_transfer_sync);
80636 static void bitbang_work(struct work_struct *work)
80638 struct spi_bitbang *bitbang =
80639 @@ -274,120 +391,13 @@
80641 while (!list_empty(&bitbang->queue)) {
80642 struct spi_message *m;
80643 - struct spi_device *spi;
80645 - struct spi_transfer *t = NULL;
80647 - unsigned cs_change;
80649 - int (*setup_transfer)(struct spi_device *,
80650 - struct spi_transfer *);
80652 m = container_of(bitbang->queue.next, struct spi_message,
80654 list_del_init(&m->queue);
80655 - spin_unlock_irqrestore(&bitbang->lock, flags);
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?
80667 - setup_transfer = NULL;
80669 - list_for_each_entry (t, &m->transfers, transfer_list) {
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;
80679 - if (setup_transfer) {
80680 - status = setup_transfer(spi, t);
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
80692 - bitbang->chipselect(spi, BITBANG_CS_ACTIVE);
80695 - cs_change = t->cs_change;
80696 - if (!t->tx_buf && !t->rx_buf && t->len) {
80697 - status = -EINVAL;
80701 - /* transfer data. the lower level code handles any
80702 - * new dma mappings it needs. our caller always gave
80703 - * us dma-safe buffers.
80706 - /* REVISIT dma API still needs a designated
80707 - * DMA_ADDR_INVALID; ~0 might be better.
80709 - if (!m->is_dma_mapped)
80710 - t->rx_dma = t->tx_dma = 0;
80711 - status = bitbang->txrx_bufs(spi, t);
80714 - m->actual_length += status;
80715 - if (status != t->len) {
80716 - /* always report some kind of error */
80718 - status = -EREMOTEIO;
80723 - /* protocol tweaks before next transfer */
80724 - if (t->delay_usecs)
80725 - udelay(t->delay_usecs);
80729 - if (t->transfer_list.next == &m->transfers)
80732 - /* sometimes a short mid-message deselect of the chip
80733 - * may be needed to terminate a mode or command
80736 - bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
80740 - m->status = status;
80741 - m->complete(m->context);
80743 - /* restore speed and wordsize */
80744 - if (setup_transfer)
80745 - setup_transfer(spi, NULL);
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.
80751 - if (!(status == 0 && cs_change)) {
80753 - bitbang->chipselect(spi, BITBANG_CS_INACTIVE);
80757 + spin_unlock_irqrestore(&bitbang->lock, flags);
80758 + spi_bitbang_transfer_sync(m->spi, m);
80759 spin_lock_irqsave(&bitbang->lock, flags);
80762 @@ -459,6 +469,9 @@
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;
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
80776 struct s3c2410_spigpio *sg = spidev_to_sg(dev);
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);
80783 static int s3c2410_spigpio_probe(struct platform_device *dev)
80784 @@ -112,14 +112,17 @@
80786 platform_set_drvdata(dev, sp);
80788 - /* copy in the plkatform data */
80789 + /* copy in the platform data */
80790 info = sp->info = dev->dev.platform_data;
80792 + master->num_chipselect = info->num_chipselect;
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;
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
80807 +/* linux/drivers/spi/spi_s3c64xx_gpio.c
80809 + * Copyright (c) 2009 Openmoko Inc.
80810 + * Author: Matt Hsu <matt_hsu@openmoko.org>
80812 + * S3C64XX GPIO-SPI driver.
80813 + * This driver is based on spi_s3c24xx_gpio.c
80815 + * Copyright (c) 2006 Ben Dooks
80816 + * Copyright (c) 2006 Simtec Electronics
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.
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>
80832 +#include <linux/spi/spi.h>
80833 +#include <linux/spi/spi_bitbang.h>
80835 +#include <plat/gpio-cfg.h>
80836 +#include <mach/spi-gpio.h>
80838 +struct s3c64xx_spigpio {
80839 + struct spi_bitbang bitbang;
80840 + struct s3c64xx_spigpio_info *info;
80841 + struct platform_device *dev;
80844 +static inline struct s3c64xx_spigpio *spidev_to_sg(struct spi_device *spi)
80846 + return dev_get_drvdata(&spi->master->dev);
80849 +static inline void setsck(struct spi_device *dev, int on)
80851 + struct s3c64xx_spigpio *sg = spidev_to_sg(dev);
80852 + gpio_direction_output(sg->info->pin_clk, on ? 1 : 0);
80855 +static inline void setmosi(struct spi_device *dev, int on)
80857 + struct s3c64xx_spigpio *sg = spidev_to_sg(dev);
80858 + gpio_direction_output(sg->info->pin_mosi, on ? 1 : 0);
80861 +static inline u32 getmiso(struct spi_device *dev)
80863 + struct s3c64xx_spigpio *sg = spidev_to_sg(dev);
80864 + return gpio_direction_input(sg->info->pin_miso) ? 1 : 0;
80867 +#define spidelay(x) ndelay(x)
80869 +#define EXPAND_BITBANG_TXRX
80870 +#include <linux/spi/spi_bitbang.h>
80872 +static u32 s3c64xx_spigpio_txrx_mode0(struct spi_device *spi,
80873 + unsigned nsecs, u32 word, u8 bits)
80875 + return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits);
80878 +static u32 s3c64xx_spigpio_txrx_mode1(struct spi_device *spi,
80879 + unsigned nsecs, u32 word, u8 bits)
80881 + return bitbang_txrx_be_cpha1(spi, nsecs, 0, word, bits);
80884 +static u32 s3c64xx_spigpio_txrx_mode2(struct spi_device *spi,
80885 + unsigned nsecs, u32 word, u8 bits)
80887 + return bitbang_txrx_be_cpha0(spi, nsecs, 1, word, bits);
80890 +static u32 s3c64xx_spigpio_txrx_mode3(struct spi_device *spi,
80891 + unsigned nsecs, u32 word, u8 bits)
80893 + return bitbang_txrx_be_cpha1(spi, nsecs, 1, word, bits);
80895 +static void s3c64xx_spigpio_chipselect(struct spi_device *dev, int value)
80897 + struct s3c64xx_spigpio *sg = spidev_to_sg(dev);
80899 + if (sg && sg->info && sg->info->chip_select)
80900 + (sg->info->chip_select)(sg->info, dev->chip_select, value);
80903 +static int s3c64xx_spigpio_probe(struct platform_device *dev)
80905 + struct s3c64xx_spigpio_info *info;
80906 + struct spi_master *master;
80907 + struct s3c64xx_spigpio *spi;
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");
80918 + spi = spi_master_get_devdata(master);
80920 + /* copy in the platform data */
80921 + info = spi->info = dev->dev.platform_data;
80923 + master->num_chipselect = info->num_chipselect;
80925 + /* setup spi bitbang adaptor */
80926 + spi->bitbang.master = spi_master_get(master);
80927 + spi->bitbang.master->bus_num = info->bus_num;
80929 + spi->bitbang.chipselect = s3c64xx_spigpio_chipselect;
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;
80936 + /* set state of spi pins. */
80937 + gpio_direction_output(info->pin_clk, 0);
80938 + s3c_gpio_cfgpin(info->pin_clk, S3C_GPIO_OUTPUT);
80940 + dev_set_drvdata(&master->dev, spi);
80942 + ret = spi_bitbang_start(&spi->bitbang);
80944 + goto err_no_bitbang;
80949 + spi_master_put(spi->bitbang.master);
80954 +static int s3c64xx_spigpio_remove(struct platform_device *dev)
80956 + struct s3c64xx_spigpio *sp = platform_get_drvdata(dev);
80958 + spi_bitbang_stop(&sp->bitbang);
80959 + spi_master_put(sp->bitbang.master);
80964 +#define s3c64xx_spigpio_suspend NULL
80965 +#define s3c64xx_spigpio_resume NULL
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,
80973 + .name = "spi_s3c64xx_gpio",
80974 + .owner = THIS_MODULE,
80978 +static int __init s3c64xx_spigpio_init(void)
80980 + return platform_driver_register(&s3c64xx_spigpio_drv);
80983 +static void __exit s3c64xx_spigpio_exit(void)
80985 + platform_driver_unregister(&s3c64xx_spigpio_drv);
80988 +module_init(s3c64xx_spigpio_init);
80989 +module_exit(s3c64xx_spigpio_exit);
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
80998 +/* drivers/rtc/alarm.c
81000 + * Copyright (C) 2007 Google, Inc.
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.
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.
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>
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)
81031 +#define ANDROID_ALARM_DPRINTF_MASK (~0)
81032 +#define ANDROID_ALARM_DPRINTF(debug_level_mask, args...) \
81034 + if (ANDROID_ALARM_DPRINTF_MASK & debug_level_mask) { \
81039 +#define ANDROID_ALARM_DPRINTF(args...)
81042 +#define ANDROID_ALARM_WAKEUP_MASK ( \
81043 + ANDROID_ALARM_RTC_WAKEUP_MASK | \
81044 + ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP_MASK)
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)
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;
81065 +static void alarm_start_hrtimer(enum android_alarm_type alarm_type)
81067 + struct timespec hr_alarm_time;
81068 + if (!(alarm_enabled & (1U << alarm_type)))
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);
81083 +static long alarm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
81086 + unsigned long flags;
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;
81095 + if (alarm_type >= ANDROID_ALARM_TYPE_COUNT)
81098 + if (ANDROID_ALARM_BASE_CMD(cmd) != ANDROID_ALARM_GET_TIME(0)) {
81099 + if ((file->f_flags & O_ACCMODE) == O_RDONLY)
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);
81108 + alarm_opened = 1;
81109 + file->private_data = (void *)1;
81110 + spin_unlock_irqrestore(&alarm_slock, flags);
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);
81125 + alarm_enabled &= ~alarm_type_mask;
81126 + spin_unlock_irqrestore(&alarm_slock, flags);
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)) {
81135 + new_alarm_time.tv_nsec = 0;
81136 + goto from_old_alarm_set;
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))) {
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)
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;
81165 + spin_unlock_irqrestore(&alarm_slock, flags);
81166 + rv = wait_event_interruptible(alarm_wait_queue, alarm_pending);
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);
81177 + case ANDROID_ALARM_SET_RTC:
81178 + if (copy_from_user(&new_rtc_time, (void __user *)arg,
81179 + sizeof(new_rtc_time))) {
81183 + rtc_time_to_tm(new_rtc_time.tv_sec, &rtc_new_rtc_time);
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);
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);
81207 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_ERRORS,
81208 + "Failed to set time\n");
81209 + mutex_unlock(&alarm_setrtc_mutex);
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);
81219 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_ERRORS,
81220 + "Failed to set RTC, time will be lost on reboot\n");
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);
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))) {
81251 +static int alarm_open(struct inode *inode, struct file *file)
81253 + file->private_data = NULL;
81257 +static int alarm_release(struct inode *inode, struct file *file)
81260 + unsigned long flags;
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, "
81270 + !!(alarm_pending & alarm_type_mask));
81271 + alarm_enabled &= ~alarm_type_mask;
81273 + spin_unlock_irqrestore(&alarm_slock, flags);
81274 + hrtimer_cancel(&alarm_timer[i]);
81275 + spin_lock_irqsave(&alarm_slock, flags);
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;
81286 + alarm_opened = 0;
81288 + spin_unlock_irqrestore(&alarm_slock, flags);
81292 +static enum hrtimer_restart alarm_timer_triggered(struct hrtimer *timer)
81294 + unsigned long flags;
81295 + enum android_alarm_type alarm_type = (timer - alarm_timer);
81296 + uint32_t alarm_type_mask = 1U << alarm_type;
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);
81308 + spin_unlock_irqrestore(&alarm_slock, flags);
81309 + return HRTIMER_NORESTART;
81312 +static void alarm_triggered_func(void *p)
81314 + struct rtc_device *rtc = alarm_rtc_dev;
81315 + if (!(rtc->irq_data & RTC_AF))
81317 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INT, "rtc alarm triggered\n");
81318 + wake_lock_timeout(&alarm_rtc_wake_lock, 1 * HZ);
81321 +int alarm_suspend(struct platform_device *pdev, pm_message_t state)
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;
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");
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]);
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;
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);
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);
81393 + spin_unlock_irqrestore(&alarm_slock, flags);
81397 + spin_unlock_irqrestore(&alarm_slock, flags);
81402 +int alarm_resume(struct platform_device *pdev)
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);
81417 +static struct rtc_task alarm_rtc_task = {
81418 + .func = alarm_triggered_func
81421 +static struct file_operations alarm_fops = {
81422 + .owner = THIS_MODULE,
81423 + .unlocked_ioctl = alarm_ioctl,
81424 + .open = alarm_open,
81425 + .release = alarm_release,
81428 +static struct miscdevice alarm_device = {
81429 + .minor = MISC_DYNAMIC_MINOR,
81431 + .fops = &alarm_fops,
81434 +static int rtc_alarm_add_device(struct device *dev,
81435 + struct class_interface *class_intf)
81438 + struct rtc_device *rtc = to_rtc_device(dev);
81440 + mutex_lock(&alarm_setrtc_mutex);
81442 + if (alarm_rtc_dev) {
81447 + err = misc_register(&alarm_device);
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);
81456 + err = rtc_irq_register(rtc, &alarm_rtc_task);
81459 + alarm_rtc_dev = rtc;
81460 + mutex_unlock(&alarm_setrtc_mutex);
81462 + ANDROID_ALARM_DPRINTF(ANDROID_ALARM_PRINT_INFO, "alarm: parent %p\n",
81463 + alarm_platform_dev->dev.power.pm_parent);
81467 + platform_device_unregister(alarm_platform_dev);
81469 + misc_deregister(&alarm_device);
81471 + mutex_unlock(&alarm_setrtc_mutex);
81475 +static void rtc_alarm_remove_device(struct device *dev,
81476 + struct class_interface *class_intf)
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;
81486 +static struct class_interface rtc_alarm_interface = {
81487 + .add_dev = &rtc_alarm_add_device,
81488 + .remove_dev = &rtc_alarm_remove_device,
81491 +static struct platform_driver alarm_driver = {
81492 + .suspend = alarm_suspend,
81493 + .resume = alarm_resume,
81499 +static int __init alarm_late_init(void)
81501 + unsigned long flags;
81502 + struct timespec system_time;
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))
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);
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);
81521 +static int __init alarm_init(void)
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;
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);
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);
81546 + wake_lock_destroy(&alarm_rtc_wake_lock);
81547 + wake_lock_destroy(&alarm_wake_lock);
81548 + platform_driver_unregister(&alarm_driver);
81553 +static void __exit alarm_exit(void)
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);
81561 +late_initcall(alarm_late_init);
81562 +module_init(alarm_init);
81563 +module_exit(alarm_exit);
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
81569 #define SZ_4M 0x400000
81573 +#if !defined(__i386__) && !defined(__arm__)
81574 #define FORBIDDEN_MMAP_FLAGS (VM_WRITE | VM_EXEC)
81576 #define FORBIDDEN_MMAP_FLAGS (VM_WRITE)
81577 @@ -2649,14 +2649,14 @@
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);
81585 static void binder_vma_close(struct vm_area_struct *vma)
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);
81594 @@ -2677,7 +2677,7 @@
81595 vma->vm_end = vma->vm_start + SZ_4M;
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);
81601 if (vma->vm_flags & FORBIDDEN_MMAP_FLAGS) {
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
81607 +/* kernel/power/consoleearlysuspend.c
81609 + * Copyright (C) 2005-2008 Google, Inc.
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.
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.
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>
81629 +#define EARLY_SUSPEND_CONSOLE (MAX_NR_CONSOLES-1)
81631 +static int orig_fgconsole;
81632 +static void console_early_suspend(struct early_suspend *h)
81634 + acquire_console_sem();
81635 + orig_fgconsole = fg_console;
81636 + if (vc_allocate(EARLY_SUSPEND_CONSOLE))
81638 + if (set_console(EARLY_SUSPEND_CONSOLE))
81640 + release_console_sem();
81642 + if (vt_waitactive(EARLY_SUSPEND_CONSOLE))
81643 + pr_warning("console_early_suspend: Can't switch VCs.\n");
81646 + pr_warning("console_early_suspend: Can't set console\n");
81647 + release_console_sem();
81650 +static void console_late_resume(struct early_suspend *h)
81653 + acquire_console_sem();
81654 + ret = set_console(orig_fgconsole);
81655 + release_console_sem();
81657 + pr_warning("console_late_resume: Can't set console.\n");
81661 + if (vt_waitactive(orig_fgconsole))
81662 + pr_warning("console_late_resume: Can't switch VCs.\n");
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,
81671 +static int __init console_early_suspend_init(void)
81673 + register_early_suspend(&console_early_suspend_desc);
81677 +static void __exit console_early_suspend_exit(void)
81679 + unregister_early_suspend(&console_early_suspend_desc);
81682 +module_init(console_early_suspend_init);
81683 +module_exit(console_early_suspend_exit);
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
81689 +/* kernel/power/earlysuspend.c
81691 + * Copyright (C) 2005-2008 Google, Inc.
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.
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.
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>
81712 +#include "power.h"
81715 + DEBUG_USER_STATE = 1U << 0,
81716 + DEBUG_SUSPEND = 1U << 2,
81718 +static int debug_mask = DEBUG_USER_STATE;
81719 +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
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);
81729 + SUSPEND_REQUESTED = 0x1,
81731 + SUSPEND_REQUESTED_AND_SUSPENDED = SUSPEND_REQUESTED | SUSPENDED,
81735 +void register_early_suspend(struct early_suspend *handler)
81737 + struct list_head *pos;
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)
81746 + list_add_tail(&handler->link, pos);
81747 + if ((state & SUSPENDED) && handler->suspend)
81748 + handler->suspend(handler);
81749 + mutex_unlock(&early_suspend_lock);
81751 +EXPORT_SYMBOL(register_early_suspend);
81753 +void unregister_early_suspend(struct early_suspend *handler)
81755 + mutex_lock(&early_suspend_lock);
81756 + list_del(&handler->link);
81757 + mutex_unlock(&early_suspend_lock);
81759 +EXPORT_SYMBOL(unregister_early_suspend);
81761 +static void early_suspend(struct work_struct *work)
81763 + struct early_suspend *pos;
81764 + unsigned long irqflags;
81767 + mutex_lock(&early_suspend_lock);
81768 + spin_lock_irqsave(&state_lock, irqflags);
81769 + if (state == SUSPEND_REQUESTED)
81770 + state |= SUSPENDED;
81773 + spin_unlock_irqrestore(&state_lock, irqflags);
81776 + if (debug_mask & DEBUG_SUSPEND)
81777 + pr_info("early_suspend: abort, state %d\n", state);
81778 + mutex_unlock(&early_suspend_lock);
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);
81788 + mutex_unlock(&early_suspend_lock);
81790 + if (debug_mask & DEBUG_SUSPEND)
81791 + pr_info("early_suspend: sync\n");
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);
81801 +static void late_resume(struct work_struct *work)
81803 + struct early_suspend *pos;
81804 + unsigned long irqflags;
81807 + mutex_lock(&early_suspend_lock);
81808 + spin_lock_irqsave(&state_lock, irqflags);
81809 + if (state == SUSPENDED)
81810 + state &= ~SUSPENDED;
81813 + spin_unlock_irqrestore(&state_lock, irqflags);
81816 + if (debug_mask & DEBUG_SUSPEND)
81817 + pr_info("late_resume: abort, state %d\n", state);
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");
81828 + mutex_unlock(&early_suspend_lock);
81831 +void request_suspend_state(suspend_state_t new_state)
81833 + unsigned long irqflags;
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);
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);
81859 + requested_suspend_state = new_state;
81860 + spin_unlock_irqrestore(&state_lock, irqflags);
81863 +suspend_state_t get_suspend_state(void)
81865 + return requested_suspend_state;
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
81871 +/* kernel/power/fbearlysuspend.c
81873 + * Copyright (C) 2005-2008 Google, Inc.
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.
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.
81886 +#include <linux/earlysuspend.h>
81887 +#include <linux/module.h>
81888 +#include <linux/wait.h>
81890 +#include "power.h"
81892 +static wait_queue_head_t fb_state_wq;
81893 +static DEFINE_SPINLOCK(fb_state_lock);
81895 + FB_STATE_STOPPED_DRAWING,
81896 + FB_STATE_REQUEST_STOP_DRAWING,
81897 + FB_STATE_DRAWING_OK,
81900 +/* tell userspace to stop drawing, wait for it to stop */
81901 +static void stop_drawing_early_suspend(struct early_suspend *h)
81904 + unsigned long irq_flags;
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);
81910 + wake_up_all(&fb_state_wq);
81911 + ret = wait_event_timeout(fb_state_wq,
81912 + fb_state == FB_STATE_STOPPED_DRAWING,
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");
81919 +/* tell userspace to start drawing */
81920 +static void start_drawing_late_resume(struct early_suspend *h)
81922 + unsigned long irq_flags;
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);
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,
81936 +static ssize_t wait_for_fb_sleep_show(struct kobject *kobj,
81937 + struct kobj_attribute *attr, char *buf)
81942 + ret = wait_event_interruptible(fb_state_wq,
81943 + fb_state != FB_STATE_DRAWING_OK);
81944 + if (ret && fb_state == FB_STATE_DRAWING_OK)
81947 + s += sprintf(buf, "sleeping");
81951 +static ssize_t wait_for_fb_wake_show(struct kobject *kobj,
81952 + struct kobj_attribute *attr, char *buf)
81956 + unsigned long irq_flags;
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);
81963 + spin_unlock_irqrestore(&fb_state_lock, irq_flags);
81965 + ret = wait_event_interruptible(fb_state_wq,
81966 + fb_state == FB_STATE_DRAWING_OK);
81967 + if (ret && fb_state != FB_STATE_DRAWING_OK)
81970 + s += sprintf(buf, "awake");
81975 +#define power_ro_attr(_name) \
81976 +static struct kobj_attribute _name##_attr = { \
81978 + .name = __stringify(_name), \
81981 + .show = _name##_show, \
81985 +power_ro_attr(wait_for_fb_sleep);
81986 +power_ro_attr(wait_for_fb_wake);
81988 +static struct attribute *g[] = {
81989 + &wait_for_fb_sleep_attr.attr,
81990 + &wait_for_fb_wake_attr.attr,
81994 +static struct attribute_group attr_group = {
81998 +static int __init android_power_init(void)
82002 + init_waitqueue_head(&fb_state_wq);
82003 + fb_state = FB_STATE_DRAWING_OK;
82005 + ret = sysfs_create_group(power_kobj, &attr_group);
82007 + pr_err("android_power_init: sysfs_create_group failed\n");
82011 + register_early_suspend(&stop_drawing_early_suspend_desc);
82015 +static void __exit android_power_exit(void)
82017 + unregister_early_suspend(&stop_drawing_early_suspend_desc);
82018 + sysfs_remove_group(power_kobj, &attr_group);
82021 +module_init(android_power_init);
82022 +module_exit(android_power_exit);
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
82029 Register processes to be killed when memory is low
82031 +config ANDROID_HAS_WAKELOCK
82034 +config ANDROID_HAS_EARLYSUSPEND
82037 +config ANDROID_WAKELOCK
82039 + depends on PM && RTC_CLASS
82041 + select ANDROID_HAS_WAKELOCK
82043 + Enable wakelocks. When user space request a sleep state the
82044 + sleep request will be delayed until no wake locks are held.
82046 +config ANDROID_WAKELOCK_STAT
82047 + bool "Wake lock stats"
82048 + depends on WAKELOCK
82051 + Report wake lock stats in /proc/wakelocks
82053 +config ANDROID_USER_WAKELOCK
82054 + bool "Userspace wake locks"
82055 + depends on ANDROID_WAKELOCK
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
82063 +config ANDROID_EARLYSUSPEND
82064 + bool "Early suspend"
82065 + depends on ANDROID_WAKELOCK
82067 + select ANDROID_HAS_EARLYSUSPEND
82069 + Call early suspend handlers when the user requested sleep state
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
82078 + config NO_USER_SPACE_SCREEN_ACCESS_CONTROL
82081 + config ANDROID_CONSOLE_EARLYSUSPEND
82082 + bool "Console switch on early-suspend"
82083 + depends on ANDROID_HAS_EARLYSUSPEND && VT
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.
82089 + config ANDROID_FB_EARLYSUSPEND
82090 + bool "Sysfs interface"
82091 + depends on ANDROID_HAS_EARLYSUSPEND
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.
82098 +config ANDROID_POWER_ALARM
82099 + bool "Android alarm driver"
82100 + depends on ANDROID_WAKELOCK
82103 +config ANDROID_PARANOID_NETWORK
82104 + bool "Only allow certain groups to create sockets"
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
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
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
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>
82136 #include "timed_gpio.h"
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
82142 +/* kernel/power/userwakelock.c
82144 + * Copyright (C) 2005-2008 Google, Inc.
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.
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.
82157 +#include <linux/ctype.h>
82158 +#include <linux/module.h>
82159 +#include <linux/wakelock.h>
82161 +#include "power.h"
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),
82170 +static int debug_mask = DEBUG_FAILURE;
82171 +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
82173 +static DEFINE_MUTEX(tree_lock);
82175 +struct user_wake_lock {
82176 + struct rb_node node;
82177 + struct wake_lock wake_lock;
82180 +struct rb_root user_wake_locks;
82182 +static struct user_wake_lock *lookup_wake_lock_name(
82183 + const char *buf, int allocate, long *timeoutptr)
82185 + struct rb_node **p = &user_wake_locks.rb_node;
82186 + struct rb_node *parent = NULL;
82187 + struct user_wake_lock *l;
82193 + /* Find length of lock name and start of optional timeout string */
82195 + while (*arg && !isspace(*arg))
82197 + name_len = arg - buf;
82200 + while (isspace(*arg))
82203 + /* Process timeout string */
82204 + if (timeoutptr && *arg) {
82205 + timeout = simple_strtoull(arg, (char **)&arg, 0);
82206 + while (isspace(*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)
82215 + *timeoutptr = timeout;
82218 + else if (timeoutptr)
82221 + /* Lookup wake lock in rbtree */
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])
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);
82233 + p = &(*p)->rb_left;
82234 + else if (diff > 0)
82235 + p = &(*p)->rb_right;
82240 + /* Allocate and add new wakelock to rbtree */
82242 + if (debug_mask & DEBUG_ERROR)
82243 + pr_info("lookup_wake_lock_name: %.*s not found\n",
82245 + return ERR_PTR(-EINVAL);
82247 + l = kzalloc(sizeof(*l) + name_len + 1, GFP_KERNEL);
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);
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);
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);
82269 +ssize_t wake_lock_show(
82270 + struct kobject *kobj, struct kobj_attribute *attr, char *buf)
82273 + char *end = buf + PAGE_SIZE;
82274 + struct rb_node *n;
82275 + struct user_wake_lock *l;
82277 + mutex_lock(&tree_lock);
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);
82284 + s += scnprintf(s, end - s, "\n");
82286 + mutex_unlock(&tree_lock);
82287 + return (s - buf);
82290 +ssize_t wake_full_lock_store(
82291 + struct kobject *kobj, struct kobj_attribute *attr,
82292 + const char *buf, size_t n)
82295 + struct user_wake_lock *l;
82297 + mutex_lock(&tree_lock);
82298 + l = lookup_wake_lock_name(buf, 1, &timeout);
82304 + if (debug_mask & DEBUG_ACCESS)
82305 + pr_info("wake_full_lock_store: %s, timeout %ld\n", l->name, timeout);
82307 + if (timeout == 0)
82308 + timeout = INT_MAX;
82311 + wake_lock_timeout(&l->wake_lock, timeout);
82313 + mutex_unlock(&tree_lock);
82317 +ssize_t wake_lock_store(
82318 + struct kobject *kobj, struct kobj_attribute *attr,
82319 + const char *buf, size_t n)
82322 + struct user_wake_lock *l;
82324 + mutex_lock(&tree_lock);
82325 + l = lookup_wake_lock_name(buf, 1, &timeout);
82331 + if (debug_mask & DEBUG_ACCESS)
82332 + pr_info("wake_lock_store: %s, timeout %ld\n", l->name, timeout);
82335 + wake_lock_timeout(&l->wake_lock, timeout);
82337 + wake_lock(&l->wake_lock);
82339 + mutex_unlock(&tree_lock);
82344 +ssize_t wake_unlock_show(
82345 + struct kobject *kobj, struct kobj_attribute *attr, char *buf)
82348 + char *end = buf + PAGE_SIZE;
82349 + struct rb_node *n;
82350 + struct user_wake_lock *l;
82352 + mutex_lock(&tree_lock);
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);
82359 + s += scnprintf(s, end - s, "\n");
82361 + mutex_unlock(&tree_lock);
82362 + return (s - buf);
82365 +ssize_t wake_unlock_store(
82366 + struct kobject *kobj, struct kobj_attribute *attr,
82367 + const char *buf, size_t n)
82369 + struct user_wake_lock *l;
82371 + mutex_lock(&tree_lock);
82372 + l = lookup_wake_lock_name(buf, 0, NULL);
82378 + if (debug_mask & DEBUG_ACCESS)
82379 + pr_info("wake_unlock_store: %s\n", l->name);
82381 + wake_unlock(&l->wake_lock);
82383 + mutex_unlock(&tree_lock);
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
82391 +/* kernel/power/wakelock.c
82393 + * Copyright (C) 2005-2008 Google, Inc.
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.
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.
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>
82415 +#include "power.h"
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,
82424 +static int debug_mask = DEBUG_EXIT_SUSPEND | DEBUG_WAKEUP;
82426 +module_param_named(debug_mask, debug_mask, int, S_IRUGO | S_IWUSR | S_IWGRP);
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)
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;
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;
82448 +int get_expired_time(struct wake_lock *lock, ktime_t *expire_time)
82450 + struct timespec ts;
82451 + struct timespec kt;
82452 + struct timespec tomono;
82453 + struct timespec delta;
82454 + unsigned long seq;
82457 + if (!(lock->flags & WAKE_LOCK_AUTO_EXPIRE))
82460 + seq = read_seqbegin(&xtime_lock);
82461 + timeout = lock->expires - jiffies;
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);
82475 +static int print_lock_stat(char *buf, struct wake_lock *lock)
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);
82487 + now = ktime_get();
82488 + add_time = ktime_sub(now, lock->stat.last_time);
82491 + active_time = add_time;
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;
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));
82511 +static int wakelocks_read_proc(char *page, char **start, off_t off,
82512 + int count, int *eof, void *data)
82514 + unsigned long irqflags;
82515 + struct wake_lock *lock;
82520 + spin_lock_irqsave(&list_lock, irqflags);
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);
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);
82531 + spin_unlock_irqrestore(&list_lock, irqflags);
82533 + *start = page + off;
82541 + return len < count ? len : count;
82544 +static void wake_unlock_stat_locked(struct wake_lock *lock, int expired)
82546 + ktime_t duration;
82548 + if (!(lock->flags & WAKE_LOCK_ACTIVE))
82550 + if (get_expired_time(lock, &now))
82553 + now = ktime_get();
82554 + lock->stat.count++;
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;
82570 +static void update_sleep_wait_stats_locked(int done)
82572 + struct wake_lock *lock;
82573 + ktime_t now, etime, elapsed, add;
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) {
82582 + add = ktime_sub(etime, last_sleep_time_update);
82585 + lock->stat.prevent_suspend_time = ktime_add(
82586 + lock->stat.prevent_suspend_time, add);
82588 + if (done || expired)
82589 + lock->flags &= ~WAKE_LOCK_PREVENTING_SUSPEND;
82591 + lock->flags |= WAKE_LOCK_PREVENTING_SUSPEND;
82593 + last_sleep_time_update = now;
82598 +static void expire_wake_lock(struct wake_lock *lock)
82600 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82601 + wake_unlock_stat_locked(lock, 1);
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);
82610 +static void print_active_locks(int type)
82612 + unsigned long irqflags;
82613 + struct wake_lock *lock;
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);
82623 + pr_info("active wake lock %s, time left %ld\n",
82624 + lock->name, timeout);
82626 + pr_info("active wake lock %s\n", lock->name);
82628 + spin_unlock_irqrestore(&list_lock, irqflags);
82631 +static long has_wake_lock_locked(int type)
82633 + struct wake_lock *lock, *n;
82634 + long max_timeout = 0;
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;
82647 + return max_timeout;
82650 +long has_wake_lock(int type)
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);
82660 +static void suspend(struct work_struct *work)
82663 + int entry_event_num;
82665 + if (has_wake_lock(WAKE_LOCK_SUSPEND)) {
82666 + if (debug_mask & DEBUG_SUSPEND)
82667 + pr_info("suspend: abort suspend\n");
82671 + entry_event_num = current_event_num;
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);
82686 + /* Openmoko needs more times to resume and a timeout is necessary
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);
82693 + /* create a temp lock to avoid autosuspend */
82694 + wake_lock_timeout(&unknown_wakeup, 5 * HZ);
82698 +static DECLARE_WORK(suspend_work, suspend);
82700 +static void expire_wake_locks(unsigned long data)
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);
82716 +static DEFINE_TIMER(expire_timer, expire_wake_locks, 0, 0);
82718 +static int power_suspend_late(struct platform_device *pdev, pm_message_t state)
82720 + int ret = has_wake_lock(WAKE_LOCK_SUSPEND) ? -EAGAIN : 0;
82721 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82722 + wait_for_wakeup = 1;
82724 + if (debug_mask & DEBUG_SUSPEND)
82725 + pr_info("power_suspend_late return %d\n", ret);
82729 +static struct platform_driver power_driver = {
82730 + .driver.name = "power",
82731 + .suspend_late = power_suspend_late,
82733 +static struct platform_device power_device = {
82737 +void wake_lock_init(struct wake_lock *lock, int type, const char *name)
82739 + unsigned long irqflags = 0;
82742 + lock->name = name;
82743 + BUG_ON(!lock->name);
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);
82756 + lock->flags = (type & WAKE_LOCK_TYPE_MASK) | WAKE_LOCK_INITIALIZED;
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);
82763 +EXPORT_SYMBOL(wake_lock_init);
82765 +void wake_lock_destroy(struct wake_lock *lock)
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);
82787 + list_del(&lock->link);
82788 + spin_unlock_irqrestore(&list_lock, irqflags);
82790 +EXPORT_SYMBOL(wake_lock_destroy);
82792 +static void wake_lock_internal(
82793 + struct wake_lock *lock, long timeout, int has_timeout)
82796 + unsigned long irqflags;
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++;
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();
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();
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]);
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]);
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);
82847 + expire_in = has_wake_lock_locked(type);
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);
82856 + if (del_timer(&expire_timer))
82857 + if (debug_mask & DEBUG_EXPIRE)
82858 + pr_info("wake_lock: %s, stop expire timer\n",
82860 + if (expire_in == 0)
82861 + queue_work(suspend_work_queue, &suspend_work);
82864 + spin_unlock_irqrestore(&list_lock, irqflags);
82867 +void wake_lock(struct wake_lock *lock)
82869 + wake_lock_internal(lock, 0, 0);
82871 +EXPORT_SYMBOL(wake_lock);
82873 +void wake_lock_timeout(struct wake_lock *lock, long timeout)
82875 + wake_lock_internal(lock, timeout, 1);
82877 +EXPORT_SYMBOL(wake_lock_timeout);
82879 +void wake_unlock(struct wake_lock *lock)
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);
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);
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);
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);
82916 + spin_unlock_irqrestore(&list_lock, irqflags);
82918 +EXPORT_SYMBOL(wake_unlock);
82920 +int wake_lock_active(struct wake_lock *lock)
82922 + return !!(lock->flags & WAKE_LOCK_ACTIVE);
82924 +EXPORT_SYMBOL(wake_lock_active);
82926 +static int __init wakelocks_init(void)
82931 + for (i = 0; i < ARRAY_SIZE(active_wake_locks); i++)
82932 + INIT_LIST_HEAD(&active_wake_locks[i]);
82934 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82935 + wake_lock_init(&deleted_wake_locks, WAKE_LOCK_SUSPEND,
82936 + "deleted_wake_locks");
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");
82942 + ret = platform_device_register(&power_device);
82944 + pr_err("wakelocks_init: platform_device_register failed\n");
82945 + goto err_platform_device_register;
82947 + ret = platform_driver_register(&power_driver);
82949 + pr_err("wakelocks_init: platform_driver_register failed\n");
82950 + goto err_platform_driver_register;
82953 + suspend_work_queue = create_singlethread_workqueue("suspend");
82954 + if (suspend_work_queue == NULL) {
82956 + goto err_suspend_work_queue;
82959 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82960 + create_proc_read_entry("wakelocks", S_IRUGO, NULL,
82961 + wakelocks_read_proc, NULL);
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);
82979 +static void __exit wakelocks_exit(void)
82981 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
82982 + remove_proc_entry("wakelocks", NULL);
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);
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 /*-------------------------------------------------------------------------*/
83002 static struct usb_gadget_driver composite_driver = {
83003 +#ifdef CONFIG_USB_GADGET_DUALSPEED
83004 .speed = USB_SPEED_HIGH,
83006 + .speed = USB_SPEED_FULL,
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))
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))
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))
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.
83041 /* Thanks to NetChip Technologies for donating this product ID.
83042 * It's for devices with only CDC Ethernet configurations.
83044 #define CDC_VENDOR_NUM 0x0525 /* NetChip */
83045 #define CDC_PRODUCT_NUM 0xa4a1 /* Linux-USB Ethernet Gadget */
83047 +#define CDC_VENDOR_NUM 0x1457 /* First International Computer */
83048 +#define CDC_PRODUCT_NUM 0x5117 /* Linux-USB Ethernet Gadget */
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.
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 */
83062 /*-------------------------------------------------------------------------*/
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);
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);
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
83084 +#ifdef CONFIG_USB_GADGET_S3C_OTGD_HS
83085 +#define gadget_is_s3c64xx(g) !strcmp("s3c-otg-device", (g)->name)
83087 +#define gadget_is_s3c64xx(g) 0
83090 #ifdef CONFIG_USB_GADGET_AT91
83091 #define gadget_is_at91(g) !strcmp("at91_udc", (g)->name)
83093 @@ -231,6 +237,8 @@
83095 else if (gadget_is_ci13xxx(gadget))
83097 + else if (gadget_is_s3c64xx(gadget))
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
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
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.
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
83126 # Controllers available in both integrated and discrete versions
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
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
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 @@
83147 +#ifdef CONFIG_USB_GADGET_DEBUG_FS
83148 static int s3c2410_udc_debugfs_seq_show(struct seq_file *m, void *p)
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,
83159 @@ -843,6 +846,7 @@
83164 if (likely (!list_empty(&ep->queue)))
83165 req = list_entry(ep->queue.next,
83166 struct s3c2410_request, queue);
83167 @@ -882,6 +886,8 @@
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;
83176 @@ -1707,6 +1713,7 @@
83177 if (driver->disconnect)
83178 driver->disconnect(&udc->gadget);
83180 + driver->unbind(&udc->gadget);
83181 device_del(&udc->gadget.dev);
83182 udc->driver = NULL;
83184 @@ -1897,6 +1904,7 @@
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");
83198 dev_dbg(dev, "probe ok\n");
83200 @@ -2013,12 +2022,14 @@
83202 dprintk(DEBUG_NORMAL, "%s: version %s\n", gadget_name, DRIVER_VERSION);
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;
83213 retval = platform_driver_register(&udc_driver_2410);
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
83220 + * drivers/usb/gadget/s3c_hs_otg.c
83221 + * Samsung S3C on-chip full/high speed USB OTG 2.0 device controllers
83223 + * Copyright (C) 2008 Samsung Electronics
83224 + * Minkyu Kang <mk7.kang@samsung.com>
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.
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.
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
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>
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"
83259 +#define S3C_USB_DBG_LEVEL 0
83261 +#define DBG(level, fmt, args...) do { \
83262 + if (level >= S3C_USB_DBG_LEVEL) { \
83263 + printk(KERN_INFO "[%s] " fmt, \
83264 + __func__, ##args); \
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"
83273 +struct s3c_udc *the_controller;
83275 +static const char driver_name[] = "s3c-otg-device";
83276 +static const char driver_desc[] = DRIVER_DESC;
83277 +static const char ep0name[] = "ep0-control";
83279 +static u32 tx_ep_num = 2;
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;
83285 +struct usb_ctrlrequest ctrl;
83286 +static int reset_available = 1;
83288 +#ifdef CONFIG_USB_GADGET_DEBUG_FILES
83290 +static const char proc_node_name[] = "driver/otg";
83293 +udc_proc_read(char *page, char **start, off_t off, int count,
83294 + int *eof, void *_dev)
83296 + char *buf = page;
83297 + struct s3c_udc *dev = _dev;
83298 + char *next = buf;
83299 + unsigned size = count;
83300 + unsigned long flags;
83306 + local_irq_save(flags);
83308 + /* basic device status */
83309 + t = scnprintf(next, size,
83311 + "%s version: %s\n"
83312 + "Gadget driver: %s\n"
83314 + driver_name, DRIVER_VERSION,
83315 + dev->driver ? dev->driver->driver.name : "(none)");
83319 + local_irq_restore(flags);
83321 + return count - size;
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)
83329 +#else /* !CONFIG_USB_GADGET_DEBUG_FILES */
83331 +#define create_proc_files() do {} while (0)
83332 +#define remove_proc_files() do {} while (0)
83334 +#endif /* CONFIG_USB_GADGET_DEBUG_FILES */
83337 +static u32 s3c_otg_readl(struct s3c_udc *dev, u32 reg)
83339 + return __raw_readl((u32)dev->reg_base + reg);
83342 +static void s3c_otg_writel(struct s3c_udc *dev, u32 val, u32 reg)
83344 + __raw_writel(val, ((u32)dev->reg_base) + reg);
83347 +static void s3c_otg_orl(struct s3c_udc *dev, u32 val, u32 reg)
83349 + u32 temp = __raw_readl(((u32)dev->reg_base) + reg);
83351 + __raw_writel(val|temp, ((u32)dev->reg_base) + reg);
83355 + * retire a request
83357 +static void s3c_otg_done(struct s3c_ep *ep, struct s3c_request *req, int status)
83359 + unsigned int stopped = ep->stopped;
83361 + DBG(1, "%s %p, stopped = %d\n", ep->ep.name, ep, stopped);
83362 + list_del_init(&req->queue);
83364 + if (req->req.status == -EINPROGRESS)
83365 + req->req.status = status;
83367 + status = req->req.status;
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);
83373 + /* don't modify queue heads during completion callback */
83376 + spin_unlock(&ep->dev->lock);
83377 + req->req.complete(&ep->ep, &req->req);
83378 + spin_lock(&ep->dev->lock);
83380 + ep->stopped = stopped;
83384 + * dequeue ALL requests
83386 +void s3c_otg_nuke(struct s3c_ep *ep, int status)
83388 + struct s3c_request *req;
83390 + DBG(1, "%s %p\n", ep->ep.name, ep);
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);
83399 +static void s3c_otg_ep_control(int ep, int dir, u32 val, int update)
83406 + epctrl = (u32)S3C_UDC_OTG_DIEPCTL0;
83408 + epctrl = (u32)S3C_UDC_OTG_DOEPCTL0;
83412 + epctrl = -EOPNOTSUPP;
83414 + epctrl = (u32)S3C_UDC_OTG_DOEPCTL1;
83418 + epctrl = (u32)S3C_UDC_OTG_DIEPCTL2;
83420 + epctrl = -EOPNOTSUPP;
83424 + epctrl = (u32)S3C_UDC_OTG_DIEPCTL3;
83426 + epctrl = -EOPNOTSUPP;
83429 + DBG(3, "ep%d is unused Endpoint", ep);
83433 + if (epctrl < 0) {
83434 + DBG(3, "ep%d - %s is invalid direction\n",
83435 + ep, dir ? "IN" : "OUT");
83440 + s3c_otg_orl(the_controller, val, epctrl);
83442 + s3c_otg_writel(the_controller, val, epctrl);
83445 +static int s3c_otg_write_packet(struct s3c_ep *ep,
83446 + struct s3c_request *req, int max)
83451 + u32 fifo = ep->fifo;
83454 + buf = req->req.buf + req->req.actual;
83457 + length = req->req.length - req->req.actual;
83458 + length = min(length, max);
83459 + req->req.actual += length;
83461 + DBG(1, "%s: %d/%d, fifo=0x%x\n", ep->ep.name, length, max, fifo);
83463 + switch (ep_index(ep)) {
83465 + epsize = (u32)S3C_UDC_OTG_DIEPTSIZ0;
83468 + epsize = (u32)S3C_UDC_OTG_DIEPTSIZ2;
83471 + epsize = (u32)S3C_UDC_OTG_DIEPTSIZ3;
83474 + DBG(3, "ep%d is unused Endpoint", ep_index(ep));
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);
83482 + for (count = 0; count < length; count += 4)
83483 + s3c_otg_writel(ep->dev, *buf++, fifo);
83488 +static int s3c_otg_write_fifo_ep0(struct s3c_ep *ep, struct s3c_request *req)
83494 + max = ep_maxpacket(ep);
83495 + count = s3c_otg_write_packet(ep, req, max);
83497 + /* last packet is usually short (or a zlp) */
83498 + if (count != max) {
83501 + if ((req->req.length != req->req.actual) || req->req.zero)
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);
83511 + /* requests complete when all IN data is in the FIFO */
83515 +static int s3c_otg_read_fifo_ep0(struct s3c_ep *ep, struct s3c_request *req)
83519 + unsigned bufferspace;
83521 + unsigned is_short;
83523 + u32 fifo = ep->fifo;
83525 + csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GRXSTSP);
83526 + bytes = BYTE_COUNT(csr);
83528 + buf = req->req.buf + req->req.actual;
83530 + bufferspace = req->req.length - req->req.actual;
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);
83541 + is_short = (bytes < ep->ep.maxpacket);
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);
83547 + while (count--) {
83548 + u32 byte = s3c_otg_readl(ep->dev, fifo);
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.
83555 + if (req->req.status != -EOVERFLOW)
83556 + DBG(3, "%s overflow %d\n", ep->ep.name, count);
83557 + req->req.status = -EOVERFLOW;
83560 + bufferspace -= 4;
83565 + if (is_short || req->req.actual == req->req.length)
83571 +static int s3c_otg_write_ep0(struct s3c_udc *dev)
83573 + struct s3c_request *req;
83574 + struct s3c_ep *ep = &dev->ep[0];
83576 + int need_zlp = 0;
83578 + if (list_empty(&ep->queue))
83581 + req = list_entry(ep->queue.next, struct s3c_request, queue);
83584 + DBG(2, "NULL REQ\n");
83588 + DBG(2, "length = 0x%x, actual = 0x%x\n",
83589 + req->req.length, req->req.actual);
83591 + if (req->req.length == 0) {
83592 + dev->ep0state = WAIT_FOR_SETUP;
83593 + s3c_otg_done(ep, req, 0);
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)
83602 + ret = s3c_otg_write_fifo_ep0(ep, req);
83604 + if ((ret == 1) && !need_zlp) {
83605 + /* Last packet */
83606 + DBG(1, "finished, waiting for status\n");
83607 + dev->ep0state = WAIT_FOR_SETUP;
83611 + DBG(1, "Need ZLP!\n");
83612 + dev->ep0state = DATA_STATE_NEED_ZLP;
83616 + s3c_otg_done(ep, req, 0);
83621 +static int first_time = 1;
83623 +static int s3c_otg_read_ep0(struct s3c_udc *dev)
83625 + struct s3c_request *req;
83626 + struct s3c_ep *ep = &dev->ep[0];
83629 + if (!list_empty(&ep->queue))
83630 + req = list_entry(ep->queue.next, struct s3c_request, queue);
83632 + DBG(3, "---> BUG\n");
83637 + DBG(2, "length = 0x%x, actual = 0x%x\n",
83638 + req->req.length, req->req.actual);
83640 + if (req->req.length == 0) {
83641 + dev->ep0state = WAIT_FOR_SETUP;
83643 + s3c_otg_done(ep, req, 0);
83647 + if (!req->req.actual && first_time) {
83652 + ret = s3c_otg_read_fifo_ep0(ep, req);
83655 + s3c_otg_done(ep, req, 0);
83657 + dev->ep0state = WAIT_FOR_SETUP;
83663 +static void s3c_otg_kick_ep0(struct s3c_udc *dev, struct s3c_ep *ep)
83667 + DBG(1, "ep_is_in = %d\n", ep_is_in(ep));
83669 + if (ep_is_in(ep)) {
83670 + dev->ep0state = DATA_STATE_XMIT;
83672 + res = s3c_otg_write_ep0(dev);
83674 + dev->ep0state = DATA_STATE_RECV;
83675 + s3c_otg_read_ep0(dev);
83680 + * Write request to FIFO
83682 +static int s3c_otg_write_fifo(struct s3c_ep *ep, struct s3c_request *req)
83688 + int is_short = 0;
83690 + gintmsk = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GINTMSK);
83692 + max = le16_to_cpu(ep->desc->wMaxPacketSize);
83693 + count = s3c_otg_write_packet(ep, req, max);
83695 + /* last packet is usually short (or a zlp) */
83696 + if (count != max) {
83700 + if ((req->req.length != req->req.actual) || req->req.zero)
83705 + /* interrupt/iso maxpacket may not fill the fifo */
83706 + is_short = (max < ep_maxpacket(ep));
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);
83714 + /* requests complete when all IN data is in the FIFO */
83716 + if (ep_index(ep) == 0) {
83717 + DBG(3, "--> EP0 must not come here!\n");
83721 + s3c_otg_writel(ep->dev, gintmsk & (~INT_TX_FIFO_EMPTY),
83722 + (u32)S3C_UDC_OTG_GINTMSK);
83723 + s3c_otg_done(ep, req, 0);
83728 + s3c_otg_writel(ep->dev, gintmsk|INT_TX_FIFO_EMPTY,
83729 + (u32)S3C_UDC_OTG_GINTMSK);
83735 + * Read to request from FIFO (max read == bytes in fifo)
83737 +static int s3c_otg_read_fifo(struct s3c_ep *ep, struct s3c_request *req)
83742 + unsigned bufferspace;
83744 + unsigned is_short = 0;
83746 + u32 fifo = ep->fifo;
83748 + csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GRXSTSP);
83749 + bytes = BYTE_COUNT(csr);
83750 + gintmsk = readl(S3C_UDC_OTG_GINTMSK);
83753 + DBG(2, "%d bytes\n", bytes);
83754 + s3c_otg_orl(ep->dev, INT_RX_FIFO_NOT_EMPTY,
83755 + (u32)S3C_UDC_OTG_GINTMSK);
83759 + buf = req->req.buf + req->req.actual;
83761 + bufferspace = req->req.length - req->req.actual;
83763 + count = bytes / 4 + (bytes % 4 ? 1 : 0);
83764 + req->req.actual += min(bytes, bufferspace);
83766 + is_short = (bytes < ep->ep.maxpacket);
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);
83772 + while (count--) {
83773 + u32 byte = s3c_otg_readl(ep->dev, fifo);
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.
83780 + if (req->req.status != -EOVERFLOW)
83781 + DBG(3, "%s overflow %d\n", ep->ep.name, count);
83782 + req->req.status = -EOVERFLOW;
83785 + bufferspace -= 4;
83789 + s3c_otg_writel(ep->dev, gintmsk|INT_RX_FIFO_NOT_EMPTY,
83790 + (u32)S3C_UDC_OTG_GINTMSK);
83793 + if (is_short || req->req.actual == req->req.length) {
83794 + s3c_otg_done(ep, req, 0);
83798 + /* finished that packet. the next one may be waiting... */
83802 +static struct usb_request *s3c_otg_alloc_request(
83803 + struct usb_ep *ep, gfp_t gfp_flags)
83805 + struct s3c_request *req;
83810 + DBG(1, "%s %p\n", ep->name, ep);
83812 + req = kzalloc(sizeof *req, gfp_flags);
83816 + INIT_LIST_HEAD(&req->queue);
83818 + return &req->req;
83821 +static void s3c_otg_free_request(struct usb_ep *ep, struct usb_request *_req)
83823 + struct s3c_request *req;
83828 + DBG(1, "%s %p\n", ep->name, ep);
83833 + req = container_of(_req, struct s3c_request, req);
83835 + WARN_ON(!list_empty(&req->queue));
83840 + * Queue one request
83841 + * Kickstart transfer if needed
83843 +static int s3c_otg_queue(struct usb_ep *_ep,
83844 + struct usb_request *_req, gfp_t gfp_flags)
83846 + struct s3c_request *req;
83847 + struct s3c_ep *ep;
83848 + struct s3c_udc *dev;
83849 + unsigned long flags;
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");
83859 + ep = container_of(_ep, struct s3c_ep, ep);
83860 + if (!_ep || (!ep->desc && ep->ep.name != ep0name)) {
83861 + DBG(3, "bad ep\n");
83866 + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
83867 + DBG(3, "bogus device state %p\n", dev->driver);
83868 + return -ESHUTDOWN;
83871 + DBG(2, "%s queue req %p, len %d buf %p\n",
83872 + _ep->name, _req, _req->length, _req->buf);
83874 + spin_lock_irqsave(&dev->lock, flags);
83876 + _req->status = -EINPROGRESS;
83877 + _req->actual = 0;
83879 + DBG(2, "ep=%d, Q empty=%d, stopped=%d\n",
83880 + ep_index(ep), list_empty(&ep->queue), ep->stopped);
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);
83888 + } else if (ep_is_in(ep)) {
83889 + csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GINTSTS);
83891 + if ((csr & INT_TX_FIFO_EMPTY) &&
83892 + (s3c_otg_write_fifo(ep, req) == 1))
83895 + tx_ep_num = ep_index(ep);
83897 + csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GINTSTS);
83899 + if ((csr & INT_RX_FIFO_NOT_EMPTY) &&
83900 + (s3c_otg_read_fifo(ep, req) == 1))
83905 + /* pio or dma irq handler advances the queue. */
83907 + list_add_tail(&req->queue, &ep->queue);
83909 + spin_unlock_irqrestore(&dev->lock, flags);
83915 + * dequeue JUST ONE request
83917 +static int s3c_otg_dequeue(struct usb_ep *_ep, struct usb_request *_req)
83919 + struct s3c_ep *ep;
83920 + struct s3c_request *req;
83921 + unsigned long flags;
83923 + ep = container_of(_ep, struct s3c_ep, ep);
83924 + if (!_ep || ep->ep.name == ep0name)
83927 + spin_lock_irqsave(&ep->dev->lock, flags);
83929 + /* make sure it's actually queued on this endpoint */
83930 + list_for_each_entry(req, &ep->queue, queue) {
83931 + if (&req->req == _req)
83935 + if (&req->req != _req) {
83936 + spin_unlock_irqrestore(&ep->dev->lock, flags);
83940 + s3c_otg_done(ep, req, -ECONNRESET);
83942 + spin_unlock_irqrestore(&ep->dev->lock, flags);
83947 +static int s3c_otg_set_halt(struct usb_ep *_ep, int value)
83952 +static int s3c_otg_fifo_status(struct usb_ep *_ep)
83955 + struct s3c_ep *ep;
83957 + ep = container_of(_ep, struct s3c_ep, ep);
83959 + DBG(3, "bad ep\n");
83963 + /* LPD can't report unclaimed bytes from IN fifos */
83964 + if (ep_is_in(ep))
83965 + return -EOPNOTSUPP;
83970 +static void s3c_otg_fifo_flush(struct usb_ep *_ep)
83972 + struct s3c_ep *ep;
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");
83981 +static int s3c_otg_ep_enable(struct usb_ep *_ep,
83982 + const struct usb_endpoint_descriptor *desc)
83984 + struct s3c_ep *ep;
83985 + struct s3c_udc *dev;
83986 + unsigned long flags;
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");
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);
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);
84015 + if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
84016 + DBG(3, "bogus device state\n");
84017 + return -ESHUTDOWN;
84020 + spin_lock_irqsave(&ep->dev->lock, flags);
84024 + ep->pio_irqs = 0;
84025 + ep->ep.maxpacket = le16_to_cpu(desc->wMaxPacketSize);
84027 + /* Reset halt state */
84028 + s3c_otg_set_halt(_ep, 0);
84030 + spin_unlock_irqrestore(&ep->dev->lock, flags);
84032 + DBG(2, "enabled %s, stopped = %d, maxpacket = %d\n",
84033 + _ep->name, ep->stopped, ep->ep.maxpacket);
84037 +static int s3c_otg_ep_disable(struct usb_ep *_ep)
84039 + struct s3c_ep *ep;
84040 + unsigned long flags;
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);
84048 + spin_lock_irqsave(&ep->dev->lock, flags);
84050 + /* Nuke all pending requests */
84051 + s3c_otg_nuke(ep, -ESHUTDOWN);
84056 + spin_unlock_irqrestore(&ep->dev->lock, flags);
84058 + DBG(2, "disabled %s\n", _ep->name);
84062 +static struct usb_ep_ops s3c_ep_ops = {
84063 + .enable = s3c_otg_ep_enable,
84064 + .disable = s3c_otg_ep_disable,
84066 + .alloc_request = s3c_otg_alloc_request,
84067 + .free_request = s3c_otg_free_request,
84069 + .queue = s3c_otg_queue,
84070 + .dequeue = s3c_otg_dequeue,
84072 + .set_halt = s3c_otg_set_halt,
84073 + .fifo_status = s3c_otg_fifo_status,
84074 + .fifo_flush = s3c_otg_fifo_flush,
84077 +void s3c_otg_set_ep(struct s3c_udc *dev, enum usb_device_speed speed)
84079 + u32 ep0_mps = DEPCTL0_MPS_64;
84081 + if (speed == USB_SPEED_FULL) {
84082 + ep0_fifo_size = 8;
84083 + ep_fifo_size = 64;
84084 + ep_fifo_size2 = 64;
84086 + ep0_mps = DEPCTL0_MPS_8;
84089 + dev->gadget.speed = speed;
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;
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);
84105 + /* EP1 - Bulk Data OUT */
84106 + s3c_otg_ep_control(1, USB_DIR_OUT, ep_fifo_size, 1);
84108 + /* EP2 - Bulk Data IN */
84109 + s3c_otg_ep_control(2, USB_DIR_IN, ep_fifo_size, 1);
84111 + /* EP3 - INTR Data IN */
84112 + s3c_otg_ep_control(3, USB_DIR_IN, ep_fifo_size, 1);
84114 + DBG(2, "%s Speed Detection\n",
84115 + speed == USB_SPEED_HIGH ? "High" : "Full");
84119 + * set the USB address for this device
84121 + * Called from control endpoint function
84122 + * after it decodes a set address setup packet.
84124 +static void s3c_otg_set_address(struct s3c_udc *dev, unsigned char addr)
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);
84129 + DBG(2, "USB OTG 2.0 Device Address=%d\n", addr);
84131 + dev->usb_address = addr;
84134 +static inline int s3c_otg_read_setup(struct s3c_ep *ep, u32 *ctrl, int max)
84138 + u32 csr = s3c_otg_readl(ep->dev, S3C_UDC_OTG_GRXSTSP);
84140 + bytes = BYTE_COUNT(csr);
84142 + /* 32 bits interface */
84143 + count = bytes / 4;
84146 + *ctrl++ = s3c_otg_readl(ep->dev, S3C_UDC_OTG_EP0_FIFO);
84151 +static void s3c_otg_setup(struct s3c_udc *dev)
84153 + struct s3c_ep *ep = &dev->ep[0];
84158 + /* Nuke all previous transfers */
84159 + s3c_otg_nuke(ep, -EPROTO);
84161 + /* read control req from fifo (8 bytes) */
84162 + bytes = s3c_otg_read_setup(ep, (u32 *)&ctrl, 8);
84164 + DBG(2, "SETUP REQ %02x %02x %04x %04x %d\n",
84165 + ctrl.bRequestType, ctrl.bRequest,
84166 + ctrl.wValue, ctrl.wIndex, ctrl.wLength);
84168 + /* Set direction of EP0 */
84169 + if (ctrl.bRequestType & USB_DIR_IN) {
84170 + ep->bEndpointAddress |= USB_DIR_IN;
84173 + ep->bEndpointAddress &= ~USB_DIR_IN;
84177 + dev->req_pending = 1;
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))
84185 + s3c_otg_set_address(dev, ctrl.wValue);
84188 + case USB_REQ_SET_INTERFACE:
84189 + DBG(2, "USB_REQ_SET_INTERFACE (%d)\n", ctrl.wValue);
84190 + /* FALLTHROUGH */
84192 + case USB_REQ_SET_CONFIGURATION:
84193 + DBG(2, "USB_REQ_SET_CONFIGURATION (%d)\n", ctrl.wValue);
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);
84205 + reset_available = 1;
84206 + dev->req_config = 1;
84209 + case USB_REQ_GET_DESCRIPTOR:
84210 + DBG(2, "USB_REQ_GET_DESCRIPTOR\n");
84213 + case USB_REQ_GET_CONFIGURATION:
84214 + DBG(2, "USB_REQ_GET_CONFIGURATION\n");
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);
84222 + case USB_REQ_CLEAR_FEATURE:
84223 + DBG(2, "USB_REQ_CLEAR_FEATURE\n");
84226 + case USB_REQ_SET_FEATURE:
84227 + DBG(2, "USB_REQ_SET_FEATURE\n");
84231 + DBG(3, "Default of ctrl.bRequest=0x%x\n", ctrl.bRequest);
84235 + if (dev->driver) {
84236 + /* device-2-host (IN) or no data setup command,
84237 + * process immediately */
84238 + spin_unlock(&dev->lock);
84240 + DBG(1, "usb_ctrlrequest will be passed to fsg_setup()\n");
84242 + ret = dev->driver->setup(&dev->gadget, &ctrl);
84243 + spin_lock(&dev->lock);
84246 + /* setup processing failed, force stall */
84247 + DBG(3, "gadget setup FAILED (stalling) - %d\n", ret);
84248 + dev->ep0state = WAIT_FOR_SETUP;
84254 + * handle ep0 interrupt
84256 +static void s3c_otg_handle_ep0(struct s3c_udc *dev)
84258 + if (dev->ep0state == WAIT_FOR_SETUP)
84259 + s3c_otg_setup(dev);
84261 + DBG(3, "strange state!! - %s\n", state_names[dev->ep0state]);
84264 +static void s3c_otg_handle_ep_out(struct s3c_udc *dev, u32 ep_num)
84266 + struct s3c_ep *ep = &dev->ep[ep_num];
84267 + struct s3c_request *req;
84269 + if (unlikely(!(ep->desc))) {
84270 + /* Throw packet away.. */
84271 + DBG(3, "No descriptor?!?\n");
84275 + if (list_empty(&ep->queue))
84278 + req = list_entry(ep->queue.next, struct s3c_request, queue);
84280 + if (unlikely(!req))
84281 + DBG(2, "NULL REQ on OUT EP-%d\n", ep_num);
84283 + s3c_otg_read_fifo(ep, req);
84286 +static void s3c_otg_handle_ep_in(struct s3c_udc *dev, u32 ep_num)
84288 + struct s3c_ep *ep = &dev->ep[ep_num];
84289 + struct s3c_request *req;
84291 + if (list_empty(&ep->queue))
84294 + req = list_entry(ep->queue.next, struct s3c_request, queue);
84296 + if (unlikely(!req)) {
84297 + DBG(2, "NULL REQ on IN EP-%d\n", ep_num);
84300 + s3c_otg_write_fifo(ep, req);
84303 +static void s3c_otg_handle_ep(struct s3c_udc *dev, u32 gintmsk)
84306 + u32 packet_status;
84310 + gintmsk &= ~INT_RX_FIFO_NOT_EMPTY;
84311 + s3c_otg_writel(dev, gintmsk, S3C_UDC_OTG_GINTMSK);
84313 + csr = s3c_otg_readl(dev, S3C_UDC_OTG_GRXSTSR);
84315 + packet_status = PKT_STS(csr);
84316 + bytes = BYTE_COUNT(csr);
84317 + ep_num = EP_NUM(csr);
84319 + switch (packet_status) {
84320 + case SETUP_PKT_RECEIVED:
84321 + DBG(2, "SETUP received : %d bytes\n", bytes);
84325 + s3c_otg_handle_ep0(dev);
84326 + gintmsk |= INT_RX_FIFO_NOT_EMPTY;
84329 + case OUT_PKT_RECEIVED:
84333 + if (ep_num == 0) {
84334 + DBG(2, "CONTROL OUT received : %d bytes\n", bytes);
84336 + dev->ep0state = DATA_STATE_RECV;
84337 + s3c_otg_read_ep0(dev);
84339 + gintmsk |= INT_RX_FIFO_NOT_EMPTY;
84340 + } else if (ep_num == 1) {
84341 + DBG(2, " Bulk OUT received : %d bytes\n", bytes);
84343 + s3c_otg_handle_ep_out(dev, 1);
84344 + gintmsk = s3c_otg_readl(dev,S3C_UDC_OTG_GINTMSK);
84346 + s3c_otg_ep_control(1, USB_DIR_OUT, DEPCTL_CNAK, 1);
84348 + DBG(2, "Unused EP%d: %d bytes\n", ep_num, bytes);
84351 + case SETUP_COMPLETED:
84352 + DBG(2, "SETUP_COMPLETED\n");
84353 + s3c_otg_ep_control(0, USB_DIR_OUT, DEPCTL_CNAK, 1);
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);
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);
84369 + csr = s3c_otg_readl(dev, S3C_UDC_OTG_GRXSTSP);
84370 + gintmsk |= INT_RX_FIFO_NOT_EMPTY;
84373 + s3c_otg_writel(dev, gintmsk, S3C_UDC_OTG_GINTMSK);
84377 + * disable USB device controller
84379 +static void s3c_otg_disable(struct s3c_udc *dev)
84381 + s3c_otg_set_address(dev, 0);
84383 + dev->ep0state = WAIT_FOR_SETUP;
84384 + dev->gadget.speed = USB_SPEED_UNKNOWN;
84385 + dev->usb_address = 0;
84387 + s3c_otg_orl(dev, ANALOG_PWR_DOWN, S3C_USBOTG_PHYPWR);
84391 + * initialize software state
84393 +static void s3c_otg_reinit(struct s3c_udc *dev)
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;
84402 + /* basic endpoint records init */
84403 + for (i = 0; i < S3C_MAX_ENDPOINTS; i++) {
84404 + struct s3c_ep *ep = &dev->ep[i];
84407 + list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
84411 + INIT_LIST_HEAD(&ep->queue);
84412 + ep->pio_irqs = 0;
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)
84420 +#define GINTMSK_INIT (INT_RESUME|INT_ENUMDONE| \
84421 + INT_RESET|INT_SUSPEND|INT_RX_FIFO_NOT_EMPTY)
84423 +#define DOEPMSK_INIT (AHB_ERROR)
84425 +#define DIEPMSK_INIT (IN_EP_TIMEOUT|AHB_ERROR)
84427 +#define GAHBCFG_INIT (PTXFE_HALF|NPTXFE_HALF| \
84428 + MODE_SLAVE|BURST_INCR16|GBL_INT_UNMASK)
84430 +static void s3c_otg_config(struct s3c_udc *dev)
84434 + /* OTG USB configuration */
84435 + s3c_otg_writel(dev, GUSBCFG_INIT, S3C_UDC_OTG_GUSBCFG);
84437 + /* Soft-reset OTG Core and then unreset again */
84438 + s3c_otg_writel(dev, CORE_SOFT_RESET, S3C_UDC_OTG_GRSTCTL);
84440 + /* Put the OTG device core in the disconnected state */
84441 + s3c_otg_orl(dev, SOFT_DISCONNECT, S3C_UDC_OTG_DCTL);
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);
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);
84454 + /* Unmask the core interrupts */
84455 + s3c_otg_writel(dev, GINTMSK_INIT, S3C_UDC_OTG_GINTMSK);
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);
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);
84477 + /* Unmask device OUT EP common interrupts */
84478 + s3c_otg_writel(dev, DOEPMSK_INIT, S3C_UDC_OTG_DOEPMSK);
84480 + /* Unmask device IN EP common interrupts */
84481 + s3c_otg_writel(dev, DIEPMSK_INIT, S3C_UDC_OTG_DIEPMSK);
84483 + /* Set Rx FIFO Size */
84484 + s3c_otg_writel(dev, RX_FIFO_SIZE, S3C_UDC_OTG_GRXFSIZ);
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);
84490 + /* Clear NAK bit of EP0 For Slave mode */
84491 + s3c_otg_ep_control(0, USB_DIR_OUT, DEPCTL_EPDIS|DEPCTL_CNAK, 0);
84493 + /* Initialize OTG Link Core */
84494 + s3c_otg_writel(dev, GAHBCFG_INIT, S3C_UDC_OTG_GAHBCFG);
84497 +static int s3c_otg_enable(struct s3c_udc *dev)
84499 + /* USB_SIG_MASK */
84500 + __raw_writel(S3C64XX_OTHERS_USBMASK | __raw_readl(S3C64XX_OTHERS),
84503 + /* Initializes OTG Phy. */
84504 + s3c_otg_writel(dev, SUSPEND_DISABLE, S3C_USBOTG_PHYPWR);
84506 + s3c_otg_writel(dev, dev->phyclk, S3C_USBOTG_PHYCLK);
84508 + s3c_otg_writel(dev, SW_RST_ON, S3C_USBOTG_RSTCON);
84511 + s3c_otg_writel(dev, SW_RST_OFF, S3C_USBOTG_RSTCON);
84514 + s3c_otg_config(dev);
84516 + DBG(2, "S3C USB 2.0 OTG Controller Core Initialized\n");
84518 + dev->gadget.speed = USB_SPEED_UNKNOWN;
84524 + * usb client interrupt handler.
84526 +static irqreturn_t s3c_otg_irq(int irq, void *_dev)
84528 + struct s3c_udc *dev = _dev;
84533 + spin_lock(&dev->lock);
84535 + intr_status = s3c_otg_readl(dev, S3C_UDC_OTG_GINTSTS);
84536 + gintmsk = s3c_otg_readl(dev, S3C_UDC_OTG_GINTMSK);
84538 + DBG(1, "GINTSTS=0x%x(on state %s), GINTMSK : 0x%x\n",
84539 + intr_status, state_names[dev->ep0state], gintmsk);
84541 + if (!intr_status) {
84542 + spin_unlock(&dev->lock);
84543 + return IRQ_HANDLED;
84546 + if (intr_status & INT_ENUMDONE) {
84547 + DBG(2, "Speed Detection interrupt\n");
84548 + s3c_otg_writel(dev, INT_ENUMDONE, S3C_UDC_OTG_GINTSTS);
84550 + usb_status = ENUM_SPEED(s3c_otg_readl(dev, S3C_UDC_OTG_DSTS));
84552 + if (usb_status & (USB_FULL_30_60MHZ | USB_FULL_48MHZ))
84553 + s3c_otg_set_ep(dev, USB_SPEED_FULL);
84555 + s3c_otg_set_ep(dev, USB_SPEED_HIGH);
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);
84563 + if (intr_status & INT_SUSPEND) {
84564 + DBG(2, "Suspend interrupt\n");
84565 + s3c_otg_writel(dev, INT_SUSPEND, S3C_UDC_OTG_GINTSTS);
84567 + if (dev->gadget.speed != USB_SPEED_UNKNOWN
84569 + && dev->driver->suspend) {
84570 + dev->driver->suspend(&dev->gadget);
84574 + if (intr_status & INT_RESUME) {
84575 + DBG(2, "Resume interrupt\n");
84576 + s3c_otg_writel(dev, INT_RESUME, S3C_UDC_OTG_GINTSTS);
84578 + if (dev->gadget.speed != USB_SPEED_UNKNOWN
84580 + && dev->driver->resume) {
84581 + dev->driver->resume(&dev->gadget);
84585 + if (intr_status & INT_RESET) {
84586 + DBG(2, "Reset interrupt\n");
84587 + s3c_otg_writel(dev, INT_RESET, S3C_UDC_OTG_GINTSTS);
84589 + usb_status = s3c_otg_readl(dev, S3C_UDC_OTG_GOTGCTL);
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;
84598 + reset_available = 1;
84599 + DBG(2, "RESET handling skipped\n");
84603 + if (intr_status & INT_RX_FIFO_NOT_EMPTY) {
84604 + s3c_otg_handle_ep(dev, gintmsk);
84605 + spin_unlock(&dev->lock);
84607 + return IRQ_HANDLED;
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);
84616 + spin_unlock(&dev->lock);
84618 + return IRQ_HANDLED;
84621 +static void s3c_otg_stop_activity(struct s3c_udc *dev,
84622 + struct usb_gadget_driver *driver)
84626 + /* don't disconnect drivers more than once */
84627 + if (dev->gadget.speed == USB_SPEED_UNKNOWN)
84629 + dev->gadget.speed = USB_SPEED_UNKNOWN;
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];
84635 + s3c_otg_nuke(ep, -ESHUTDOWN);
84638 + /* report disconnect; the driver is already quiesced */
84640 + spin_unlock(&dev->lock);
84641 + driver->disconnect(&dev->gadget);
84642 + spin_lock(&dev->lock);
84645 + /* re-init driver-visible data structures */
84646 + s3c_otg_reinit(dev);
84650 + * Register the gadget driver. Used by gadget drivers when
84651 + * registering themselves with the controller.
84653 +int usb_gadget_register_driver(struct usb_gadget_driver *driver)
84655 + struct s3c_udc *dev = the_controller;
84659 + || driver->speed != USB_SPEED_HIGH
84661 + || !driver->setup)
84665 + DBG(3, "No device\n");
84669 + if (dev->driver) {
84670 + DBG(3, "Already bound to %s\n", driver->driver.name);
84674 + /* first hook up the driver ... */
84675 + dev->driver = driver;
84676 + dev->gadget.dev.driver = &driver->driver;
84677 + retval = device_add(&dev->gadget.dev);
84679 + if (retval) { /* TODO */
84680 + DBG(3, "target device_add failed, error %d\n", retval);
84684 + retval = driver->bind(&dev->gadget);
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);
84691 + dev->gadget.dev.driver = 0;
84695 + dev_info(&dev->gadget.dev, "Registered gadget driver '%s'\n",
84696 + driver->driver.name);
84697 + s3c_otg_enable(dev);
84699 + enable_irq(IRQ_OTG);
84703 +EXPORT_SYMBOL(usb_gadget_register_driver);
84706 + Unregister entry point for the peripheral controller driver.
84708 +int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
84710 + struct s3c_udc *dev = the_controller;
84711 + unsigned long flags;
84716 + if (!driver || driver != dev->driver)
84719 + spin_lock_irqsave(&dev->lock, flags);
84722 + s3c_otg_stop_activity(dev, driver);
84724 + spin_unlock_irqrestore(&dev->lock, flags);
84726 + if (driver->unbind)
84727 + driver->unbind(&dev->gadget);
84729 + device_del(&dev->gadget.dev);
84731 + disable_irq(IRQ_OTG);
84733 + dev_info(&dev->gadget.dev, "Unregistered gadget driver '%s'\n",
84734 + driver->driver.name);
84736 + s3c_otg_disable(dev);
84740 +EXPORT_SYMBOL(usb_gadget_unregister_driver);
84743 + * device-scoped parts of the api to the usb controller hardware
84745 +static int s3c_otg_get_frame(struct usb_gadget *gadget)
84747 + u32 frame = s3c_otg_readl(the_controller, S3C_UDC_OTG_DSTS);
84748 + return FRAME_CNT(frame);
84751 +static int s3c_otg_wakeup(struct usb_gadget *gadget)
84753 + return -EOPNOTSUPP;
84756 +static int s3c_otg_set_selfpowered(
84757 + struct usb_gadget *gadget, int is_selfpowered)
84759 + return -EOPNOTSUPP;
84762 +static int s3c_otg_pullup(struct usb_gadget *gadget, int is_on)
84764 + return -EOPNOTSUPP;
84767 +static int s3c_otg_vbus_session(struct usb_gadget *gadget, int is_active)
84769 + return -EOPNOTSUPP;
84772 +static int s3c_otg_vbus_draw(struct usb_gadget *gadget, unsigned mA)
84774 + return -EOPNOTSUPP;
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,
84786 +static void nop_release(struct device *dev)
84788 + DBG(2, "%s\n", dev->bus_id);
84791 +static struct s3c_udc memory = {
84792 + .usb_address = 0,
84794 + .ops = &s3c_udc_ops,
84795 + .ep0 = &memory.ep[0].ep,
84796 + .name = driver_name,
84798 + .bus_id = "gadget",
84799 + .release = nop_release,
84805 + .ops = &s3c_ep_ops,
84806 + .maxpacket = EP0_FIFO_SIZE,
84810 + .bEndpointAddress = 0,
84811 + .bmAttributes = 0,
84813 + .ep_type = ep_control,
84814 + .fifo = (u32) S3C_UDC_OTG_EP0_FIFO,
84818 + .name = "ep1-bulk",
84819 + .ops = &s3c_ep_ops,
84820 + .maxpacket = EP_FIFO_SIZE,
84824 + .bEndpointAddress = 1,
84825 + .bmAttributes = USB_ENDPOINT_XFER_BULK,
84827 + .ep_type = ep_bulk_out,
84828 + .fifo = (u32) S3C_UDC_OTG_EP1_FIFO,
84832 + .name = "ep2-bulk",
84833 + .ops = &s3c_ep_ops,
84834 + .maxpacket = EP_FIFO_SIZE,
84838 + .bEndpointAddress = USB_DIR_IN | 2,
84839 + .bmAttributes = USB_ENDPOINT_XFER_BULK,
84841 + .ep_type = ep_bulk_in,
84842 + .fifo = (u32) S3C_UDC_OTG_EP2_FIFO,
84847 + .name = "ep3-int",
84848 + .ops = &s3c_ep_ops,
84849 + .maxpacket = EP_FIFO_SIZE,
84853 + .bEndpointAddress = USB_DIR_IN | 3,
84854 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84856 + .ep_type = ep_interrupt,
84857 + .fifo = (u32) S3C_UDC_OTG_EP3_FIFO,
84861 + .name = "ep4-int",
84862 + .ops = &s3c_ep_ops,
84863 + .maxpacket = EP_FIFO_SIZE,
84867 + .bEndpointAddress = USB_DIR_IN | 4,
84868 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84870 + .ep_type = ep_interrupt,
84871 + .fifo = (u32) S3C_UDC_OTG_EP4_FIFO,
84875 + .name = "ep5-int",
84876 + .ops = &s3c_ep_ops,
84877 + .maxpacket = EP_FIFO_SIZE2,
84881 + .bEndpointAddress = USB_DIR_IN | 5,
84882 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84884 + .ep_type = ep_interrupt,
84885 + .fifo = (u32) S3C_UDC_OTG_EP5_FIFO,
84889 + .name = "ep6-int",
84890 + .ops = &s3c_ep_ops,
84891 + .maxpacket = EP_FIFO_SIZE2,
84895 + .bEndpointAddress = USB_DIR_IN | 6,
84896 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84898 + .ep_type = ep_interrupt,
84899 + .fifo = (u32) S3C_UDC_OTG_EP6_FIFO,
84903 + .name = "ep7-int",
84904 + .ops = &s3c_ep_ops,
84905 + .maxpacket = EP_FIFO_SIZE2,
84909 + .bEndpointAddress = USB_DIR_IN | 7,
84910 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84912 + .ep_type = ep_interrupt,
84913 + .fifo = (u32) S3C_UDC_OTG_EP7_FIFO,
84917 + .name = "ep8-int",
84918 + .ops = &s3c_ep_ops,
84919 + .maxpacket = EP_FIFO_SIZE2,
84923 + .bEndpointAddress = USB_DIR_IN | 8,
84924 + .bmAttributes = USB_ENDPOINT_XFER_INT,
84926 + .ep_type = ep_interrupt,
84927 + .fifo = (u32) S3C_UDC_OTG_EP8_FIFO,
84931 +static struct clk *otg_clock;
84934 + * binds to the platform device
84936 +static int s3c_otg_probe(struct platform_device *pdev)
84938 + struct s3c_udc *dev = &memory;
84939 + struct s3c_plat_otg_data *pdata = pdev->dev.platform_data;
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");
84950 + DBG(2, "%p\n", pdev);
84952 + spin_lock_init(&dev->lock);
84955 + device_initialize(&dev->gadget.dev);
84956 + dev->gadget.dev.parent = &pdev->dev;
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;
84965 + dev->phyclk = pdata->phyclk;
84967 + the_controller = dev;
84968 + platform_set_drvdata(pdev, dev);
84970 + otg_clock = clk_get(&pdev->dev, "otg");
84971 + if (otg_clock == NULL) {
84972 + DBG(3, "failed to find otg clock source\n");
84975 + clk_enable(otg_clock);
84977 + s3c_otg_reinit(dev);
84979 + local_irq_disable();
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);
84985 + if (retval != 0) {
84986 + DBG(3, "%s: can't get irq %i - %d\n",
84987 + driver_name, IRQ_OTG, retval);
84991 + disable_irq(IRQ_OTG);
84992 + local_irq_enable();
84993 + create_proc_files();
84998 +static int s3c_otg_remove(struct platform_device *pdev)
85000 + struct s3c_udc *dev = platform_get_drvdata(pdev);
85002 + if (otg_clock != NULL) {
85003 + clk_disable(otg_clock);
85004 + clk_put(otg_clock);
85005 + otg_clock = NULL;
85008 + remove_proc_files();
85009 + usb_gadget_unregister_driver(dev->driver);
85011 + free_irq(IRQ_OTG, dev);
85013 + platform_set_drvdata(pdev, 0);
85015 + the_controller = 0;
85017 + if (dev->reg_base)
85018 + iounmap(dev->reg_base);
85024 +static int s3c_otg_suspend(struct platform_device *pdev, pm_message_t state)
85026 + struct s3c_udc *dev = the_controller;
85028 + if (dev->driver) {
85029 + disable_irq(IRQ_OTG);
85030 + s3c_otg_disable(dev);
85031 + clk_disable(otg_clock);
85037 +static int s3c_otg_resume(struct platform_device *pdev)
85039 + struct s3c_udc *dev = the_controller;
85041 + if (dev->driver) {
85042 + clk_enable(otg_clock);
85043 + s3c_otg_enable(dev);
85044 + s3c_otg_reinit(dev);
85045 + enable_irq(IRQ_OTG);
85051 +#define s3c_otg_suspend NULL
85052 +#define s3c_otg_resume NULL
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,
85062 + .owner = THIS_MODULE,
85063 + .name = "s3c-otg-usbgadget",
85067 +static int __init otg_init(void)
85071 + ret = platform_driver_register(&s3c_otg_driver);
85073 + printk(KERN_INFO "Loaded %s version %s %s\n",
85074 + driver_name, DRIVER_VERSION, "(Slave Mode)");
85079 +static void __exit otg_exit(void)
85081 + platform_driver_unregister(&s3c_otg_driver);
85082 + printk(KERN_INFO "Unloaded %s version %s\n",
85083 + driver_name, DRIVER_VERSION);
85086 +module_init(otg_init);
85087 +module_exit(otg_exit);
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
85098 + * drivers/usb/gadget/s3c-udc.h
85099 + * Samsung S3C on-chip full/high speed USB device controllers
85101 + * Copyright (C) 2008 Samsung Electronics
85102 + * Minkyu Kang <mk7.kang@samsung.com>
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.
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.
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
85120 +#ifndef __S3C_UDC_H
85121 +#define __S3C_UDC_H
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>
85148 +#include <linux/usb/ch9.h>
85149 +#include <linux/usb/gadget.h>
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
85162 +#define EP0_FIFO_SIZE 64
85163 +#define EP_FIFO_SIZE 512
85164 +#define EP_FIFO_SIZE2 1024
85165 +#define S3C_MAX_ENDPOINTS 16
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
85175 + ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt
85179 + struct usb_ep ep;
85180 + struct s3c_udc *dev;
85182 + const struct usb_endpoint_descriptor *desc;
85183 + struct list_head queue;
85184 + unsigned long pio_irqs;
85187 + u8 bEndpointAddress;
85192 +#ifdef CONFIG_USB_GADGET_S3C_FS
85198 +struct s3c_request {
85199 + struct usb_request req;
85200 + struct list_head queue;
85204 + struct usb_gadget gadget;
85205 + struct usb_gadget_driver *driver;
85206 + struct platform_device *dev;
85212 + struct s3c_ep ep[S3C_MAX_ENDPOINTS];
85214 + unsigned char usb_address;
85216 + unsigned req_pending:1;
85217 + unsigned req_std:1;
85218 + unsigned req_config:1;
85221 +extern struct s3c_udc *the_controller;
85223 +#define ep_is_in(EP) (((EP)->bEndpointAddress & USB_DIR_IN) \
85225 +#define ep_index(EP) ((EP)->bEndpointAddress & 0xF)
85226 +#define ep_maxpacket(EP) ((EP)->ep.maxpacket)
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
85236 -#ifdef CONFIG_ARCH_S3C2410
85237 +#ifdef CONFIG_PLAT_S3C
85238 #include "ohci-s3c2410.c"
85239 #define PLATFORM_DRIVER ohci_hcd_s3c2410_driver
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
85246 #include <linux/platform_device.h>
85247 #include <linux/clk.h>
85249 #include <mach/hardware.h>
85250 -#include <mach/usb-control.h>
85251 +#include <mach/regs-gpio.h>
85252 +#include <plat/usb-control.h>
85254 #define valid_port(idx) ((idx) == 1 || (idx) == 2)
85258 info->report_oc = s3c2410_hcd_oc;
85260 - if (info->enable_oc != NULL) {
85261 + if (info->enable_oc != NULL)
85262 (info->enable_oc)(info, 1);
85268 info->report_oc = NULL;
85271 - if (info->enable_oc != NULL) {
85272 + if (info->enable_oc != NULL)
85273 (info->enable_oc)(info, 0);
85278 @@ -90,14 +88,14 @@
85282 -ohci_s3c2410_hub_status_data (struct usb_hcd *hcd, char *buf)
85283 +ohci_s3c2410_hub_status_data(struct usb_hcd *hcd, char *buf)
85285 struct s3c2410_hcd_info *info = to_s3c2410_info(hcd);
85286 struct s3c2410_hcd_port *port;
85290 - orig = ohci_hub_status_data (hcd, buf);
85291 + orig = ohci_hub_status_data(hcd, buf);
85295 @@ -147,7 +145,7 @@
85299 -static int ohci_s3c2410_hub_control (
85300 +static int ohci_s3c2410_hub_control(
85301 struct usb_hcd *hcd,
85304 @@ -201,9 +199,8 @@
85305 dev_dbg(hcd->self.controller,
85306 "ClearPortFeature: OVER_CURRENT\n");
85308 - if (valid_port(wIndex)) {
85309 + if (valid_port(wIndex))
85310 info->port[wIndex-1].oc_status = 0;
85315 @@ -244,28 +241,28 @@
85316 desc->wHubCharacteristics |= cpu_to_le16(0x0001);
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);
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);
85334 case GetPortStatus:
85335 /* check port status */
85337 dev_dbg(hcd->self.controller, "GetPortStatus(%d)\n", wIndex);
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);
85345 - if (info->port[wIndex-1].oc_status) {
85346 + if (info->port[wIndex-1].oc_status)
85347 *data |= cpu_to_le32(RH_PS_POCI);
85352 @@ -308,6 +305,42 @@
85353 local_irq_restore(flags);
85356 +/* switching of USB pads */
85357 +static ssize_t show_usb_mode(struct device *dev, struct device_attribute *attr,
85360 + if (__raw_readl(S3C24XX_MISCCR) & S3C2410_MISCCR_USBHOST)
85361 + return sprintf(buf, "host\n");
85363 + return sprintf(buf, "device\n");
85366 +static ssize_t set_usb_mode(struct device *dev, struct device_attribute *attr,
85367 + const char *buf, size_t count)
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);
85374 + * - call machine-specific disable-pullup function i
85375 + * - enable +Vbus (if hardware supports it)
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);
85383 + printk(KERN_WARNING "s3c2410: unknown mode\n");
85390 +static DEVICE_ATTR(usb_mode, S_IRUGO | S_IWUSR, show_usb_mode, set_usb_mode);
85392 /* may be called without controller electrically present */
85393 /* may be called with controller, bus, and devices active */
85395 @@ -323,8 +356,9 @@
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)
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.
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)
85415 struct usb_hcd *hcd = NULL;
85417 @@ -392,9 +426,16 @@
85421 + retval = device_create_file(&dev->dev, &dev_attr_usb_mode);
85429 + usb_remove_hcd(hcd);
85432 s3c2410_stop_hc(dev);
85433 iounmap(hcd->regs);
85435 @@ -413,17 +454,19 @@
85436 /*-------------------------------------------------------------------------*/
85439 -ohci_s3c2410_start (struct usb_hcd *hcd)
85440 +ohci_s3c2410_start(struct usb_hcd *hcd)
85442 - struct ohci_hcd *ohci = hcd_to_ohci (hcd);
85443 + struct ohci_hcd *ohci = hcd_to_ohci(hcd);
85446 - if ((ret = ohci_init(ohci)) < 0)
85447 + ret = ohci_init(ohci);
85451 - if ((ret = ohci_run (ohci)) < 0) {
85452 - err ("can't start %s", hcd->self.bus_name);
85454 + ret = ohci_run(ohci);
85456 + err("can't start %s", hcd->self.bus_name);
85461 @@ -488,15 +531,23 @@
85465 +static int ohci_hcd_s3c2410_drv_resume(struct platform_device *pdev)
85467 + struct usb_hcd *hcd = platform_get_drvdata(pdev);
85469 + ohci_finish_controller_resume(hcd);
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,
85481 .owner = THIS_MODULE,
85482 - .name = "s3c2410-ohci",
85483 + .name = "s3c-ohci",
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
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
85504 + * Backlight Driver for FIC GTA01 (Neo1973) GSM Phone
85506 + * Copyright (C) 2006-2007 by Openmoko, Inc.
85507 + * Author: Harald Welte <laforge@openmoko.org>
85508 + * All rights reserved.
85510 + * based on corgi_cl.c, Copyright (c) 2004-2006 Richard Purdie
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.
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.
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
85526 + * Javi Roman <javiroman@kernel-labs.org>:
85527 + * implement PWM, instead of simple on/off switching
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>
85540 +#include <mach/hardware.h>
85541 +#include <mach/gta01.h>
85542 +#include <plat/pwm.h>
85544 +#include <plat/regs-timer.h>
85545 +#include <asm/plat-s3c24xx/neo1973.h>
85547 +static struct backlight_properties gta01bl_prop;
85548 +static struct backlight_device *gta01_backlight_device;
85549 +static struct gta01bl_machinfo *bl_machinfo;
85551 +static unsigned long gta01bl_flags;
85553 +struct gta01bl_data {
85555 + struct mutex mutex;
85557 + struct s3c2410_pwm pwm;
85560 +static struct gta01bl_data gta01bl;
85562 +static int gta01bl_defer_resume_backlight;
85564 +#define GTA01BL_SUSPENDED 0x01
85565 +#define GTA01BL_BATTLOW 0x02
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
85575 +static int gta01bl_send_intensity(struct backlight_device *bd)
85577 + int intensity = bd->props.brightness;
85579 + if (bd->props.power != FB_BLANK_UNBLANK)
85581 + if (bd->props.fb_blank != FB_BLANK_UNBLANK)
85583 + if (gta01bl_flags & GTA01BL_SUSPENDED)
85585 + if (gta01bl_flags & GTA01BL_BATTLOW)
85586 + intensity &= bl_machinfo->limit_mask;
85588 + mutex_lock(>a01bl.mutex);
85589 +#ifdef GTA01_BACKLIGHT_ONOFF_ONLY
85591 + neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 1);
85593 + neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 0);
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);
85599 + s3c2410_pwm_duty_cycle(intensity & 0xffff, >a01bl.pwm);
85600 + s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPB0_TOUT0);
85603 + mutex_unlock(>a01bl.mutex);
85605 + gta01bl.intensity = intensity;
85609 +static int gta01bl_init_hw(void)
85613 + rc = s3c2410_pwm_init(>a01bl.pwm);
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;
85623 + rc = s3c2410_pwm_enable(>a01bl.pwm);
85627 + s3c2410_pwm_start(>a01bl.pwm);
85629 + gta01bl_prop.max_brightness = gta01bl.pwm.counter;
85635 +static int gta01bl_suspend(struct platform_device *dev, pm_message_t state)
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);
85644 +void gta01bl_deferred_resume(void)
85646 + mutex_lock(>a01bl.mutex);
85647 + gta01bl_init_hw();
85648 + mutex_unlock(>a01bl.mutex);
85650 + gta01bl_flags &= ~GTA01BL_SUSPENDED;
85651 + gta01bl_send_intensity(gta01_backlight_device);
85653 +EXPORT_SYMBOL_GPL(gta01bl_deferred_resume);
85655 +static int gta01bl_resume(struct platform_device *dev)
85657 + if (!gta01bl_defer_resume_backlight)
85658 + gta01bl_deferred_resume();
85662 +#define gta01bl_suspend NULL
85663 +#define gta01bl_resume NULL
85666 +static int gta01bl_get_intensity(struct backlight_device *bd)
85668 + return gta01bl.intensity;
85671 +static int gta01bl_set_intensity(struct backlight_device *bd)
85673 + gta01bl_send_intensity(gta01_backlight_device);
85678 + * Called when the battery is low to limit the backlight intensity.
85679 + * If limit==0 clear any limit, otherwise limit the intensity
85681 +void gta01bl_limit_intensity(int limit)
85684 + gta01bl_flags |= GTA01BL_BATTLOW;
85686 + gta01bl_flags &= ~GTA01BL_BATTLOW;
85687 + gta01bl_send_intensity(gta01_backlight_device);
85689 +EXPORT_SYMBOL_GPL(gta01bl_limit_intensity);
85692 +static struct backlight_ops gta01bl_ops = {
85693 + .get_brightness = gta01bl_get_intensity,
85694 + .update_status = gta01bl_set_intensity,
85697 +static int __init gta01bl_probe(struct platform_device *pdev)
85699 + struct gta01bl_machinfo *machinfo = pdev->dev.platform_data;
85702 +#ifdef GTA01_BACKLIGHT_ONOFF_ONLY
85703 + s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
85704 + gta01bl_prop.max_brightness = 1;
85706 + rc = gta01bl_init_hw();
85710 + mutex_init(>a01bl.mutex);
85712 + if (!machinfo->limit_mask)
85713 + machinfo->limit_mask = -1;
85715 + gta01bl_defer_resume_backlight = machinfo->defer_resume_backlight;
85717 + gta01_backlight_device = backlight_device_register("gta01-bl",
85718 + &pdev->dev, NULL,
85720 + if (IS_ERR(gta01_backlight_device))
85721 + return PTR_ERR(gta01_backlight_device);
85723 + gta01bl_prop.power = FB_BLANK_UNBLANK;
85724 + gta01bl_prop.brightness = gta01bl_prop.max_brightness;
85725 + memcpy(>a01_backlight_device->props,
85726 + >a01bl_prop, sizeof(gta01bl_prop));
85727 + gta01bl_send_intensity(gta01_backlight_device);
85732 +static int gta01bl_remove(struct platform_device *dev)
85734 +#ifndef GTA01_BACKLIGHT_ONOFF_ONLY
85735 + s3c2410_pwm_disable(>a01bl.pwm);
85737 + backlight_device_unregister(gta01_backlight_device);
85738 + mutex_destroy(>a01bl.mutex);
85740 + s3c2410_gpio_cfgpin(GTA01_GPIO_BACKLIGHT, S3C2410_GPIO_OUTPUT);
85741 + neo1973_gpb_setpin(GTA01_GPIO_BACKLIGHT, 1);
85746 +static struct platform_driver gta01bl_driver = {
85747 + .probe = gta01bl_probe,
85748 + .remove = gta01bl_remove,
85749 + .suspend = gta01bl_suspend,
85750 + .resume = gta01bl_resume,
85752 + .name = "gta01-bl",
85756 +static int __init gta01bl_init(void)
85758 + return platform_driver_register(>a01bl_driver);
85761 +static void __exit gta01bl_exit(void)
85763 + platform_driver_unregister(>a01bl_driver);
85766 +module_init(gta01bl_init);
85767 +module_exit(gta01bl_exit);
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.
85779 +config BACKLIGHT_GTA01
85780 + tristate "FIC Neo1973 GTA01 Backlight Driver"
85781 + depends on BACKLIGHT_CLASS_DEVICE && MACH_NEO1973_GTA01
85784 + If you have a FIC Neo1973 GTA01, say y to enable the backlight driver.
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
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 @@
85808 + if (info->state != FBINFO_STATE_RUNNING)
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
85818 +/* Linux kernel driver for the tpo JBT6K74-AS LCM ASIC
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.
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.
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.
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
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>
85853 +enum jbt_register {
85854 + JBT_REG_SLEEP_IN = 0x10,
85855 + JBT_REG_SLEEP_OUT = 0x11,
85857 + JBT_REG_DISPLAY_OFF = 0x28,
85858 + JBT_REG_DISPLAY_ON = 0x29,
85860 + JBT_REG_RGB_FORMAT = 0x3a,
85861 + JBT_REG_QUAD_RATE = 0x3b,
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,
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,
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,
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,
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,
85912 + JBT_REG_HCLOCK_VGA = 0xec,
85913 + JBT_REG_HCLOCK_QVGA = 0xed,
85918 + JBT_STATE_DEEP_STANDBY,
85920 + JBT_STATE_NORMAL,
85921 + JBT_STATE_QVGA_NORMAL,
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",
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;
85937 + u16 reg_cache[0xEE];
85938 + struct timespec last_sleep;
85941 +#define JBT_COMMAND 0x000
85942 +#define JBT_DATA 0x100
85944 +static inline unsigned int timespec_sub_ms(struct timespec lhs,
85945 + struct timespec rhs)
85947 + struct timespec ts = timespec_sub(lhs, rhs);
85948 + return (ts.tv_sec * MSEC_PER_SEC) + (ts.tv_nsec / NSEC_PER_MSEC);
85951 +static int jbt_reg_write_nodata(struct jbt_info *jbt, u8 reg)
85955 + jbt->tx_buf[0] = JBT_COMMAND | reg;
85956 + rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
85959 + jbt->reg_cache[reg] = 0;
85961 + printk(KERN_ERR"jbt_reg_write_nodata spi_write ret %d\n",
85968 +static int jbt_reg_write(struct jbt_info *jbt, u8 reg, u8 data)
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,
85977 + jbt->reg_cache[reg] = data;
85979 + printk(KERN_ERR"jbt_reg_write spi_write ret %d\n", rc);
85984 +static int jbt_reg_write16(struct jbt_info *jbt, u8 reg, u16 data)
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);
85992 + rc = spi_write(jbt->spi_dev, (u8 *)jbt->tx_buf,
85995 + jbt->reg_cache[reg] = data;
85997 + printk(KERN_ERR"jbt_reg_write16 spi_write ret %d\n", rc);
86002 +static int jbt_init_regs(struct jbt_info *jbt)
86006 + dev_dbg(&jbt->spi_dev->dev, "entering %cVGA mode\n",
86007 + jbt->normal_state == JBT_STATE_QVGA_NORMAL ? 'Q' : ' ');
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);
86022 + * default of 0x02 in JBT_REG_ASW_SLEW responsible for 72Hz requirement
86023 + * to avoid red / blue flicker
86025 + rc |= jbt_reg_write(jbt, JBT_REG_ASW_SLEW, 0x04);
86026 + rc |= jbt_reg_write(jbt, JBT_REG_DUMMY_DISPLAY, 0x00);
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);
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);
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);
86046 + rc |= jbt_reg_write(jbt, JBT_REG_CKV_ON_OFF, 0x01);
86047 + rc |= jbt_reg_write16(jbt, JBT_REG_CKV_1_2, 0x0000);
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);
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);
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);
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);
86065 + return rc ? -EIO : 0;
86068 +static int standby_to_sleep(struct jbt_info *jbt)
86072 + /* three times command zero */
86073 + rc = jbt_reg_write_nodata(jbt, 0x00);
86075 + rc |= jbt_reg_write_nodata(jbt, 0x00);
86077 + rc |= jbt_reg_write_nodata(jbt, 0x00);
86080 + /* deep standby out */
86081 + rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x11);
86083 + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x28);
86085 + /* (re)initialize register set */
86086 + rc |= jbt_init_regs(jbt);
86088 + return rc ? -EIO : 0;
86091 +static int sleep_to_normal(struct jbt_info *jbt)
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);
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);
86105 + /* Quad mode off */
86106 + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x00);
86108 + /* RGB I/F on, RAM wirte off, QVGA through, SIGCON enable */
86109 + rc = jbt_reg_write(jbt, JBT_REG_DISPLAY_MODE, 0x81);
86111 + /* Quad mode on */
86112 + rc |= jbt_reg_write(jbt, JBT_REG_QUAD_RATE, 0x22);
86115 + /* AVDD on, XVDD on */
86116 + rc |= jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x16);
86118 + /* Output control */
86119 + rc |= jbt_reg_write16(jbt, JBT_REG_OUTPUT_CONTROL, 0xfff9);
86121 + /* Turn on display */
86122 + rc |= jbt_reg_write_nodata(jbt, JBT_REG_DISPLAY_ON);
86124 + /* Sleep mode off */
86125 + rc |= jbt_reg_write_nodata(jbt, JBT_REG_SLEEP_OUT);
86126 + jbt->last_sleep = current_kernel_time();
86128 + /* Allow the booster and display controller to restart stably */
86131 + return rc ? -EIO : 0;
86134 +static int normal_to_sleep(struct jbt_info *jbt)
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);
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();
86149 + /* Allow the internal circuits to stop automatically */
86152 + return rc ? -EIO : 0;
86155 +static int sleep_to_standby(struct jbt_info *jbt)
86157 + return jbt_reg_write(jbt, JBT_REG_POWER_ON_OFF, 0x00);
86160 +/* frontend function */
86161 +int jbt6k74_enter_state(struct jbt_info *jbt, enum jbt_state new_state)
86163 + int rc = -EINVAL;
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]);
86169 + mutex_lock(&jbt->lock);
86171 + if (new_state == JBT_STATE_NORMAL ||
86172 + new_state == JBT_STATE_QVGA_NORMAL)
86173 + jbt->normal_state = new_state;
86175 + switch (jbt->state) {
86176 + case JBT_STATE_DEEP_STANDBY:
86177 + switch (new_state) {
86178 + case JBT_STATE_DEEP_STANDBY:
86181 + case JBT_STATE_SLEEP:
86182 + rc = standby_to_sleep(jbt);
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);
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);
86198 + case JBT_STATE_SLEEP:
86199 + switch (new_state) {
86200 + case JBT_STATE_SLEEP:
86203 + case JBT_STATE_DEEP_STANDBY:
86204 + rc = sleep_to_standby(jbt);
86206 + case JBT_STATE_NORMAL:
86207 + case JBT_STATE_QVGA_NORMAL:
86208 + rc = sleep_to_normal(jbt);
86212 + case JBT_STATE_NORMAL:
86213 + switch (new_state) {
86214 + case JBT_STATE_NORMAL:
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);
86223 + case JBT_STATE_SLEEP:
86224 + rc = normal_to_sleep(jbt);
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);
86238 + case JBT_STATE_QVGA_NORMAL:
86239 + switch (new_state) {
86240 + case JBT_STATE_QVGA_NORMAL:
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);
86249 + case JBT_STATE_SLEEP:
86250 + rc = normal_to_sleep(jbt);
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);
86267 + jbt->state = new_state;
86269 + dev_err(&jbt->spi_dev->dev, "Failed enter state '%s')\n",
86270 + jbt_state_names[new_state]);
86272 + mutex_unlock(&jbt->lock);
86276 +EXPORT_SYMBOL_GPL(jbt6k74_enter_state);
86278 +static ssize_t state_read(struct device *dev, struct device_attribute *attr,
86281 + struct jbt_info *jbt = dev_get_drvdata(dev);
86283 + if (jbt->state >= ARRAY_SIZE(jbt_state_names))
86286 + return sprintf(buf, "%s\n", jbt_state_names[jbt->state]);
86289 +static ssize_t state_write(struct device *dev, struct device_attribute *attr,
86290 + const char *buf, size_t count)
86292 + struct jbt_info *jbt = dev_get_drvdata(dev);
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);
86308 +static DEVICE_ATTR(state, 0644, state_read, state_write);
86310 +static int reg_by_string(const char *name)
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;
86319 + return JBT_REG_GAMMA1_BLUE_OFFSET;
86322 +static ssize_t gamma_read(struct device *dev, struct device_attribute *attr,
86325 + struct jbt_info *jbt = dev_get_drvdata(dev);
86326 + int reg = reg_by_string(attr->attr.name);
86329 + mutex_lock(&jbt->lock);
86330 + val = jbt->reg_cache[reg];
86331 + mutex_unlock(&jbt->lock);
86333 + return sprintf(buf, "0x%04x\n", val);
86336 +static ssize_t gamma_write(struct device *dev, struct device_attribute *attr,
86337 + const char *buf, size_t count)
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);
86343 + dev_info(dev, "writing gama %lu\n", val & 0xff);
86345 + mutex_lock(&jbt->lock);
86346 + jbt_reg_write(jbt, reg, val & 0xff);
86347 + mutex_unlock(&jbt->lock);
86352 +static ssize_t reset_write(struct device *dev, struct device_attribute *attr,
86353 + const char *buf, size_t count)
86356 + struct jbt_info *jbt = dev_get_drvdata(dev);
86357 + struct jbt6k74_platform_data *pdata = jbt->spi_dev->dev.platform_data;
86359 + dev_info(dev, "reset\n");
86361 + mutex_lock(&jbt->lock);
86363 + jbt->state = JBT_STATE_DEEP_STANDBY;
86365 + /* hard reset the jbt6k74 */
86366 + (pdata->reset)(0, 0);
86368 + (pdata->reset)(0, 1);
86371 + rc = jbt_reg_write_nodata(jbt, 0x01);
86373 + dev_err(&jbt->spi_dev->dev, "cannot soft reset\n");
86376 + mutex_unlock(&jbt->lock);
86378 + jbt6k74_enter_state(jbt, jbt->normal_state);
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);
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,
86399 +static struct attribute_group jbt_attr_group = {
86401 + .attrs = jbt_sysfs_entries,
86404 +static int fb_notifier_callback(struct notifier_block *self,
86405 + unsigned long event, void *data)
86407 + struct jbt_info *jbt;
86408 + struct fb_event *evdata = data;
86411 + jbt = container_of(self, struct jbt_info, fb_notif);
86413 + dev_dbg(&jbt->spi_dev->dev, "event=%lu\n", event);
86415 + if (event != FB_EVENT_BLANK && event != FB_EVENT_CONBLANK)
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);
86424 + case FB_BLANK_NORMAL:
86425 + dev_dbg(&jbt->spi_dev->dev, "blank\n");
86427 + case FB_BLANK_VSYNC_SUSPEND:
86428 + dev_dbg(&jbt->spi_dev->dev, "vsync suspend\n");
86430 + case FB_BLANK_HSYNC_SUSPEND:
86431 + dev_dbg(&jbt->spi_dev->dev, "hsync suspend\n");
86433 + case FB_BLANK_POWERDOWN:
86434 + dev_dbg(&jbt->spi_dev->dev, "powerdown\n");
86435 + jbt6k74_enter_state(jbt, JBT_STATE_SLEEP);
86442 +/* linux device model infrastructure */
86444 +static int __devinit jbt_probe(struct spi_device *spi)
86447 + struct jbt_info *jbt;
86448 + struct jbt6k74_platform_data *pdata = spi->dev.platform_data;
86450 + /* the controller doesn't have a MISO pin; we can't do detection */
86452 + spi->mode = SPI_CPOL | SPI_CPHA;
86453 + spi->bits_per_word = 9;
86455 + rc = spi_setup(spi);
86457 + dev_err(&spi->dev,
86458 + "error during spi_setup of jbt6k74 driver\n");
86462 + jbt = kzalloc(sizeof(*jbt), GFP_KERNEL);
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);
86472 + dev_set_drvdata(&spi->dev, jbt);
86474 + rc = jbt6k74_enter_state(jbt, JBT_STATE_NORMAL);
86476 + dev_err(&spi->dev, "cannot enter NORMAL state\n");
86477 + goto err_free_drvdata;
86480 + rc = sysfs_create_group(&spi->dev.kobj, &jbt_attr_group);
86482 + dev_err(&spi->dev, "cannot create sysfs group\n");
86483 + goto err_standby;
86486 + jbt->fb_notif.notifier_call = fb_notifier_callback;
86487 + rc = fb_register_client(&jbt->fb_notif);
86489 + dev_err(&spi->dev, "cannot register notifier\n");
86493 + if (pdata->probe_completed)
86494 + (pdata->probe_completed)(&spi->dev);
86499 + sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group);
86501 + jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
86503 + dev_set_drvdata(&spi->dev, NULL);
86509 +static int __devexit jbt_remove(struct spi_device *spi)
86511 + struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
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);
86517 + fb_unregister_client(&jbt->fb_notif);
86518 + sysfs_remove_group(&spi->dev.kobj, &jbt_attr_group);
86519 + dev_set_drvdata(&spi->dev, NULL);
86526 +static int jbt_suspend(struct spi_device *spi, pm_message_t state)
86528 + struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
86530 + jbt6k74_enter_state(jbt, JBT_STATE_DEEP_STANDBY);
86532 + dev_info(&spi->dev, "suspended\n");
86537 +int jbt6k74_resume(struct spi_device *spi)
86539 + struct jbt_info *jbt = dev_get_drvdata(&spi->dev);
86540 + struct jbt6k74_platform_data *pdata = spi->dev.platform_data;
86542 + jbt6k74_enter_state(jbt, jbt->normal_state);
86544 + if (pdata->resuming)
86545 + (pdata->resuming)(0);
86547 + dev_info(&spi->dev, "resumed\n");
86551 +EXPORT_SYMBOL_GPL(jbt6k74_resume);
86554 +#define jbt_suspend NULL
86555 +#define jbt6k74_resume NULL
86558 +static struct spi_driver jbt6k74_driver = {
86560 + .name = "jbt6k74",
86561 + .owner = THIS_MODULE,
86564 + .probe = jbt_probe,
86565 + .remove = __devexit_p(jbt_remove),
86566 + .suspend = jbt_suspend,
86567 + .resume = jbt6k74_resume,
86570 +static int __init jbt_init(void)
86572 + return spi_register_driver(&jbt6k74_driver);
86575 +static void __exit jbt_exit(void)
86577 + spi_unregister_driver(&jbt6k74_driver);
86580 +MODULE_DESCRIPTION("SPI driver for tpo JBT6K74-AS LCM control interface");
86581 +MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
86582 +MODULE_LICENSE("GPL");
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
86590 comment "Display hardware drivers"
86591 depends on DISPLAY_SUPPORT
86593 +config DISPLAY_JBT6K74
86594 + tristate "TPO JBT6K74-AS TFT display ASIC control interface"
86595 + depends on SPI_MASTER && SYSFS
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.
86601 + The control interface is required for display operation, as it
86602 + controls power management, display timing and gamma calibration.
86604 +config DISPLAY_L1K002
86605 + tristate "TP0 L1K0-02 TFT ASIC control interface"
86606 + depends on SPI_MASTER && SYSFS
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.
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
86618 + * Copyright (C) 2009 Openmoko, Inc.
86620 + * Author: Matt Hsu <matt_hsu@openmoko.org>
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.
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.
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.
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>
86644 +#include <linux/l1k002.h>
86646 +struct l1k002_data {
86647 + struct spi_device *spi;
86648 + struct mutex lock;
86650 + u8 reg_cache[0x40];
86653 +enum l1k002_regs_table {
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,
86693 +static int l1k002_reg_write(struct l1k002_data *l1k002, u8 reg, u8 data)
86697 + mutex_lock(&l1k002->lock);
86699 + l1k002->mosi_buf[0] = reg;
86700 + l1k002->mosi_buf[1] = data;
86702 + ret = spi_write(l1k002->spi, (u8 *)l1k002->mosi_buf, 2*sizeof(u8));
86704 + l1k002->reg_cache[reg] = data;
86706 + dev_err(&l1k002->spi->dev, "reg spi_write ret: %d\n", ret);
86708 + mutex_unlock(&l1k002->lock);
86712 +static int l1k002_init_reg(struct l1k002_data *l1k002)
86716 + /* software reset */
86717 + ret = l1k002_reg_write(l1k002, L1K002_REG_CMDR, 0x01);
86718 + ret |= l1k002_reg_write(l1k002, L1K002_REG_CMDR, 0x00);
86720 + /* setup color mode and direction */
86721 + ret |= l1k002_reg_write(l1k002, L1K002_REG_MISC, 0xd9);
86723 + /* dclk initial */
86724 + ret |= l1k002_reg_write(l1k002, L1K002_REG_SYNCP_SEL, 0x00);
86726 + /* start vertical data */
86727 + ret |= l1k002_reg_write(l1k002, L1K002_REG_VSTS, 0x04);
86729 + /* start horizonal data */
86730 + ret |= l1k002_reg_write(l1k002, L1K002_REG_HSTS, 0x14);
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);
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);
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);
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);
86754 + /* driving voltage */
86755 + ret |= l1k002_reg_write(l1k002, L1K002_REG_DA_VCOM, 0x66);
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);
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);
86778 + ret |= l1k002_reg_write(l1k002, 0x07, 0xc9);
86781 + dev_info(&l1k002->spi->dev, "initialize OK \n");
86783 + dev_err(&l1k002->spi->dev, "initialize failed ret: %d\n", ret);
86787 +static int l1k002_probe(struct spi_device *spi)
86790 + struct l1k002_data *l1k002;
86791 + struct l1k002_platform_data *l1k002_pdata = spi->dev.platform_data;
86793 + if (l1k002_pdata == NULL) {
86794 + dev_err(&spi->dev,
86795 + "no platform data available \n");
86799 + spi->mode = SPI_CPOL | SPI_CPHA;
86800 + spi->bits_per_word = 8;
86802 + ret = spi_setup(spi);
86804 + dev_err(&spi->dev,
86805 + "error during spi_setup of l1k002 driver\n");
86809 + l1k002 = kzalloc(sizeof(*l1k002), GFP_KERNEL);
86813 + l1k002->spi = spi;
86814 + dev_set_drvdata(&spi->dev, l1k002);
86816 + mutex_init(&l1k002->lock);
86818 + /* hard reset l1k002 */
86819 + (l1k002_pdata->pwr_onoff)(1);
86821 + ret = l1k002_init_reg(l1k002);
86825 + /* FIXME: sysfs should be added here */
86834 +static int __devexit l1k002_remove(struct spi_device *spi)
86836 + struct l1k002 *l1k002 = dev_get_drvdata(&spi->dev);
86838 + dev_set_drvdata(&spi->dev, NULL);
86844 +static int l1k002_suspend(struct spi_device *spi, pm_message_t state)
86846 + struct l1k002_platform_data *l1k002_pdata = spi->dev.platform_data;
86848 + /* l1k002 doesn't have sleep mode
86849 + * it should be powered down as entering suspend state
86851 + (l1k002_pdata->pwr_onoff)(0);
86855 +static int l1k002_resume(struct spi_device *spi)
86857 + struct l1k002_platform_data *l1k002_pdata = spi->dev.platform_data;
86858 + struct l1k002_data *l1k002 = dev_get_drvdata(&spi->dev);
86860 + (l1k002_pdata->pwr_onoff)(1);
86861 + return l1k002_init_reg(l1k002);
86864 +#define l1k002_suspend NULL
86865 +#define l1k002_resume NULL
86868 +static struct spi_driver l1k002_driver = {
86870 + .name = "l1k002",
86871 + .owner = THIS_MODULE,
86874 + .probe = l1k002_probe,
86875 + .remove = __devexit_p(l1k002_remove),
86876 + .suspend = l1k002_suspend,
86877 + .resume = l1k002_resume,
86880 +static int __init l1k002_init(void)
86882 + return spi_register_driver(&l1k002_driver);
86885 +static void __exit l1k002_exit(void)
86887 + spi_unregister_driver(&l1k002_driver);
86890 +MODULE_AUTHOR("Matt Hsu <matt_hsu@openmoko.org>");
86891 +MODULE_LICENSE("GPL v2");
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
86899 display-objs := display-sysfs.o
86901 obj-$(CONFIG_DISPLAY_SUPPORT) += display.o
86902 +obj-$(CONFIG_DISPLAY_JBT6K74) += jbt6k74.o
86903 +obj-$(CONFIG_DISPLAY_L1K002) += l1k002.o
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 @@
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
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.
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.
86928 + Currently the support is only for the S3C6400 and S3C6410 SoCs.
86930 +config FB_S3C_DEBUG_REGWRITE
86931 + bool "Debug register writes"
86932 + depends on FB_S3C
86934 + Show all register writes via printk(KERN_DEBUG)
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 @@
86955 s3c2410fb_init_registers(fbinfo);
86957 + s3c2410fb_set_par(fbinfo);
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
86966 +/* linux/drivers/video/s3c-fb.c
86968 + * Copyright 2008 Openmoko Inc.
86969 + * Copyright 2008 Simtec Electronics
86970 + * Ben Dooks <ben@simtec.co.uk>
86971 + * http://armlinux.simtec.co.uk/
86973 + * Samsung SoC Framebuffer driver
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.
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>
86990 +#include <mach/map.h>
86991 +#include <mach/regs-fb.h>
86992 +#include <plat/fb.h>
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.
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.
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.
87009 +#ifdef CONFIG_FB_S3C_DEBUG_REGWRITE
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 */
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.
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;
87034 + u32 *palette_buffer;
87035 + u32 pseudo_palette[16];
87036 + unsigned int index;
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.
87050 + struct device *dev;
87051 + struct resource *regs_res;
87052 + struct clk *bus_clk;
87053 + void __iomem *regs;
87055 + unsigned char enabled;
87057 + struct s3c_fb_platdata *pdata;
87058 + struct s3c_fb_win *windows[S3C_FB_MAX_WIN];
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.
87066 + * Work out if the given window supports palletised data at the specified bpp.
87068 +static int s3c_fb_win_has_palette(unsigned int win, unsigned int bpp)
87070 + return s3c_fb_win_pal_size(win) <= (1 << bpp);
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.
87078 + * Framebuffer layer call to verify the given information and allow us to
87079 + * update various information depending on the hardware capabilities.
87081 +static int s3c_fb_check_var(struct fb_var_screeninfo *var,
87082 + struct fb_info *info)
87084 + struct s3c_fb_win *win = info->par;
87085 + struct s3c_fb_pd_win *windata = win->windata;
87086 + struct s3c_fb *sfb = win->parent;
87088 + dev_dbg(sfb->dev, "checking parameters\n");
87090 + var->xres_virtual = max((unsigned int)windata->virtual_x, var->xres);
87091 + var->yres_virtual = max((unsigned int)windata->virtual_y, var->yres);
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);
87099 + /* always ensure these are zero, for drop through cases below */
87100 + var->transp.offset = 0;
87101 + var->transp.length = 0;
87103 + switch (var->bits_per_pixel) {
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;
87119 + var->red.offset = 0;
87120 + var->red.length = var->bits_per_pixel;
87121 + var->green = var->red;
87122 + var->blue = var->red;
87127 + /* 666 with one bit alpha/transparency */
87128 + var->transp.offset = 18;
87129 + var->transp.length = 1;
87131 + var->bits_per_pixel = 32;
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;
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;
87154 + var->transp.length = var->bits_per_pixel - 24;
87155 + var->transp.offset = 24;
87156 + /* drop through */
87158 + /* our 24bpp is unpacked, so 32bpp */
87159 + var->bits_per_pixel = 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;
87170 + dev_err(sfb->dev, "invalid bpp\n");
87173 + dev_dbg(sfb->dev, "%s: verified parameters\n", __func__);
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.
87182 + * Given the specified pixel clock, work out the necessary divider to get
87183 + * close to the output frequency.
87185 +static int s3c_fb_calc_pixclk(struct s3c_fb *sfb, unsigned int pixclk)
87187 + unsigned long clk = clk_get_rate(sfb->bus_clk);
87188 + unsigned long long tmp;
87189 + unsigned int result;
87191 + tmp = (unsigned long long)clk;
87194 + do_div(tmp, 1000000000UL);
87195 + result = (unsigned int)tmp / 1000;
87197 + dev_dbg(sfb->dev, "pixclk=%u, clk=%lu, div=%d (%lu)\n",
87198 + pixclk, clk, result, clk / result);
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.
87208 + * Align the given pixel count so that it will start on an 32bit word
87211 +static int s3c_fb_align_word(unsigned int bpp, unsigned int pix)
87213 + int pix_per_word;
87218 + pix_per_word = (8 * 32) / bpp;
87219 + return ALIGN(pix, pix_per_word);
87223 + * s3c_fb_set_par() - framebuffer request to set new framebuffer state.
87224 + * @info: The framebuffer to change.
87226 + * Framebuffer layer request to set a new mode for the specified framebuffer
87228 +static int s3c_fb_set_par(struct fb_info *info)
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;
87239 + dev_dbg(sfb->dev, "setting framebuffer parameters\n");
87241 + switch (var->bits_per_pixel) {
87246 + info->fix.visual = FB_VISUAL_TRUECOLOR;
87249 + if (s3c_fb_win_has_palette(win_no, 8))
87250 + info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
87252 + info->fix.visual = FB_VISUAL_TRUECOLOR;
87255 + info->fix.visual = FB_VISUAL_MONO01;
87258 + info->fix.visual = FB_VISUAL_PSEUDOCOLOR;
87262 + info->fix.line_length = (var->xres_virtual * var->bits_per_pixel) / 8;
87264 + /* disable the window whilst we update it */
87265 + writel(0, regs + WINCON(win_no));
87267 + /* use window 0 as the basis for the lcd output timings */
87269 + if (win_no == 0) {
87270 + clkdiv = s3c_fb_calc_pixclk(sfb, var->pixclock);
87272 + data = sfb->pdata->vidcon0;
87273 + data &= ~(VIDCON0_CLKVAL_F_MASK | VIDCON0_CLKDIR);
87276 + data |= VIDCON0_CLKVAL_F(clkdiv-1) | VIDCON0_CLKDIR;
87278 + data &= ~VIDCON0_CLKDIR; /* 1:1 clock */
87280 + /* write the timing data to the panel */
87282 + data |= VIDCON0_ENVID | VIDCON0_ENVID_F;
87283 + writel(data, regs + VIDCON0);
87285 + data = VIDTCON0_VBPD(var->upper_margin - 1) |
87286 + VIDTCON0_VFPD(var->lower_margin - 1) |
87287 + VIDTCON0_VSPW(var->vsync_len - 1);
87289 + writel(data, regs + VIDTCON0);
87291 + data = VIDTCON1_HBPD(var->left_margin - 1) |
87292 + VIDTCON1_HFPD(var->right_margin - 1) |
87293 + VIDTCON1_HSPW(var->hsync_len - 1);
87295 + writel(data, regs + VIDTCON1);
87297 + data = VIDTCON2_LINEVAL(var->yres - 1) |
87298 + VIDTCON2_HOZVAL(var->xres - 1);
87299 + writel(data, regs + VIDTCON2);
87302 + /* write the buffer address */
87304 + writel(info->fix.smem_start, regs + VIDW_BUF_START(win_no));
87306 + data = info->fix.smem_start + info->fix.line_length * var->yres;
87307 + writel(data, regs + VIDW_BUF_END(win_no));
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));
87314 + /* write 'OSD' registers to control position of framebuffer */
87316 + data = VIDOSDxA_TOPLEFT_X(0) | VIDOSDxA_TOPLEFT_Y(0);
87317 + writel(data, regs + VIDOSD_A(win_no));
87319 + data = VIDOSDxB_BOTRIGHT_X(s3c_fb_align_word(var->bits_per_pixel,
87320 + var->xres - 1)) |
87321 + VIDOSDxB_BOTRIGHT_Y(var->yres - 1);
87323 + writel(data, regs + VIDOSD_B(win_no));
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));
87330 + writel(data, regs + VIDOSD_C(win_no));
87332 + data = WINCONx_ENWIN;
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. */
87338 + switch (var->bits_per_pixel) {
87340 + data |= WINCON0_BPPMODE_1BPP;
87341 + data |= WINCONx_BITSWP;
87342 + data |= WINCONx_BURSTLEN_4WORD;
87345 + data |= WINCON0_BPPMODE_2BPP;
87346 + data |= WINCONx_BITSWP;
87347 + data |= WINCONx_BURSTLEN_8WORD;
87350 + data |= WINCON0_BPPMODE_4BPP;
87351 + data |= WINCONx_BITSWP;
87352 + data |= WINCONx_BURSTLEN_8WORD;
87355 + if (var->transp.length != 0)
87356 + data |= WINCON1_BPPMODE_8BPP_1232;
87358 + data |= WINCON0_BPPMODE_8BPP_PALETTE;
87359 + data |= WINCONx_BURSTLEN_8WORD;
87360 + data |= WINCONx_BYTSWP;
87363 + if (var->transp.length != 0)
87364 + data |= WINCON1_BPPMODE_16BPP_A1555;
87366 + data |= WINCON0_BPPMODE_16BPP_565;
87367 + data |= WINCONx_HAWSWP;
87368 + data |= WINCONx_BURSTLEN_16WORD;
87372 + if (var->red.length == 6) {
87373 + if (var->transp.length != 0)
87374 + data |= WINCON1_BPPMODE_19BPP_A1666;
87376 + data |= WINCON1_BPPMODE_18BPP_666;
87377 + } else if (var->transp.length != 0)
87378 + data |= WINCON1_BPPMODE_25BPP_A1888;
87380 + data |= WINCON0_BPPMODE_24BPP_888;
87382 + data |= WINCONx_BURSTLEN_16WORD;
87386 + writel(data, regs + WINCON(win_no));
87387 + writel(0x0, regs + WINxMAP(win_no));
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.
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.
87403 + * At the moment, since we have no VSYNC interrupt support, we simply set
87404 + * the palette entry directly.
87406 +static void s3c_fb_update_palette(struct s3c_fb *sfb,
87407 + struct s3c_fb_win *win,
87408 + unsigned int reg,
87411 + void __iomem *palreg;
87414 + palreg = sfb->regs + s3c_fb_pal_reg(win->index, reg);
87416 + dev_dbg(sfb->dev, "%s: win %d, reg %d (%p): %08x\n",
87417 + __func__, win->index, reg, palreg, value);
87419 + win->palette_buffer[reg] = value;
87421 + palcon = readl(sfb->regs + WPALCON);
87422 + writel(palcon | WPALCON_PAL_UPDATE, sfb->regs + WPALCON);
87424 + if (s3c_fb_pal_is16(win->index))
87425 + writew(value, palreg);
87427 + writel(value, palreg);
87429 + writel(palcon, sfb->regs + WPALCON);
87432 +static inline unsigned int chan_to_field(unsigned int chan,
87433 + struct fb_bitfield *bf)
87436 + chan >>= 16 - bf->length;
87437 + return chan << bf->offset;
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.
87449 +static int s3c_fb_setcolreg(unsigned regno,
87450 + unsigned red, unsigned green, unsigned blue,
87451 + unsigned transp, struct fb_info *info)
87453 + struct s3c_fb_win *win = info->par;
87454 + struct s3c_fb *sfb = win->parent;
87455 + unsigned int val;
87457 + dev_dbg(sfb->dev, "%s: win %d: %d => rgb=%d/%d/%d\n",
87458 + __func__, win->index, regno, red, green, blue);
87460 + switch (info->fix.visual) {
87461 + case FB_VISUAL_TRUECOLOR:
87462 + /* true-colour, use pseudo-palette */
87464 + if (regno < 16) {
87465 + u32 *pal = info->pseudo_palette;
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);
87471 + pal[regno] = val;
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);
87481 + s3c_fb_update_palette(sfb, win, regno, val);
87487 + return 1; /* unknown type */
87494 + * s3c_fb_enable() - Set the state of the main LCD output
87495 + * @sfb: The main framebuffer state.
87496 + * @enable: The state to set.
87498 +static void s3c_fb_enable(struct s3c_fb *sfb, int enable)
87500 + u32 vidcon0 = readl(sfb->regs + VIDCON0);
87503 + vidcon0 |= VIDCON0_ENVID | VIDCON0_ENVID_F;
87505 + /* see the note in the framebuffer datasheet about
87506 + * why you cannot take both of these bits down at the
87509 + if (!(vidcon0 & VIDCON0_ENVID))
87512 + vidcon0 |= VIDCON0_ENVID;
87513 + vidcon0 &= ~VIDCON0_ENVID_F;
87516 + writel(vidcon0, sfb->regs + VIDCON0);
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.
87524 + * Framebuffer layer request to change the power state.
87526 +static int s3c_fb_blank(int blank_mode, struct fb_info *info)
87528 + struct s3c_fb_win *win = info->par;
87529 + struct s3c_fb *sfb = win->parent;
87530 + unsigned int index = win->index;
87533 + dev_dbg(sfb->dev, "blank mode %d\n", blank_mode);
87535 + wincon = readl(sfb->regs + WINCON(index));
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 */
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));
87549 + case FB_BLANK_UNBLANK:
87550 + writel(0x0, sfb->regs + WINxMAP(index));
87551 + wincon |= WINCONx_ENWIN;
87552 + sfb->enabled |= (1 << index);
87555 + case FB_BLANK_VSYNC_SUSPEND:
87556 + case FB_BLANK_HSYNC_SUSPEND:
87561 + writel(wincon, sfb->regs + WINCON(index));
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
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.
87574 + * s3c_fb_enable(sfb, sfb->enabled ? 1 : 0);
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.
87581 + s3c_fb_enable(sfb, blank_mode != FB_BLANK_POWERDOWN ? 1 : 0);
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,
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.
87602 + * Allocate memory for the given framebuffer.
87604 +static int __devinit s3c_fb_alloc_memory(struct s3c_fb *sfb,
87605 + struct s3c_fb_win *win)
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;
87612 + dev_dbg(sfb->dev, "allocating memory for display\n");
87614 + real_size = windata->win_mode.xres * windata->win_mode.yres;
87615 + virt_size = windata->virtual_x * windata->virtual_y;
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);
87621 + size = (real_size > virt_size) ? real_size : virt_size;
87622 + size *= (windata->max_bpp > 16) ? 32 : windata->max_bpp;
87625 + fbi->fix.smem_len = size;
87626 + size = PAGE_ALIGN(size);
87628 + dev_dbg(sfb->dev, "want %u bytes for window\n", size);
87630 + fbi->screen_base = dma_alloc_writecombine(sfb->dev, size,
87631 + &map_dma, GFP_KERNEL);
87632 + if (!fbi->screen_base)
87635 + dev_dbg(sfb->dev, "mapped %x to %p\n",
87636 + (unsigned int)map_dma, fbi->screen_base);
87638 + memset(fbi->screen_base, 0x0, size);
87639 + fbi->fix.smem_start = map_dma;
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.
87649 + * Free the display memory allocated by s3c_fb_alloc_memory().
87651 +static void s3c_fb_free_memory(struct s3c_fb *sfb, struct s3c_fb_win *win)
87653 + struct fb_info *fbi = win->fbinfo;
87655 + dma_free_writecombine(sfb->dev, PAGE_ALIGN(fbi->fix.smem_len),
87656 + fbi->screen_base, fbi->fix.smem_start);
87660 + * s3c_fb_release_win() - release resources for a framebuffer window.
87661 + * @win: The window to cleanup the resources for.
87663 + * Release the resources that where claimed for the hardware window,
87664 + * such as the framebuffer instance and any memory claimed for it.
87666 +static void s3c_fb_release_win(struct s3c_fb *sfb, struct s3c_fb_win *win)
87668 + fb_dealloc_cmap(&win->fbinfo->cmap);
87669 + unregister_framebuffer(win->fbinfo);
87670 + s3c_fb_free_memory(sfb, win);
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.
87678 + * Allocate and do the basic initialisation for one of the hardware's graphics
87681 +static int __devinit s3c_fb_probe_win(struct s3c_fb *sfb, unsigned int win_no,
87682 + struct s3c_fb_win **res)
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;
87692 + dev_dbg(sfb->dev, "probing window %d\n", win_no);
87694 + palette_size = s3c_fb_win_pal_size(win_no);
87696 + fbinfo = framebuffer_alloc(sizeof(struct s3c_fb_win) +
87697 + palette_size * sizeof(u32), sfb->dev);
87699 + dev_err(sfb->dev, "failed to allocate framebuffer\n");
87703 + windata = sfb->pdata->win[win_no];
87704 + initmode = &windata->win_mode;
87706 + WARN_ON(windata->max_bpp == 0);
87707 + WARN_ON(windata->win_mode.xres == 0);
87708 + WARN_ON(windata->win_mode.yres == 0);
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);
87718 + ret = s3c_fb_alloc_memory(sfb, win);
87720 + dev_err(sfb->dev, "failed to allocate display memory\n");
87721 + goto err_framebuffer;
87724 + /* setup the r/b/g positions for the window's palette */
87725 + s3c_fb_init_palette(win_no, &win->palette);
87727 + /* setup the initial video mode from the window */
87728 + fb_videomode_to_var(&fbinfo->var, initmode);
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;
87739 + /* prepare to actually start the framebuffer */
87741 + ret = s3c_fb_check_var(&fbinfo->var, fbinfo);
87743 + dev_err(sfb->dev, "check_var failed on initial video params\n");
87744 + goto err_alloc_mem;
87747 + /* create initial colour map */
87749 + ret = fb_alloc_cmap(&fbinfo->cmap, s3c_fb_win_pal_size(win_no), 1);
87751 + fb_set_cmap(&fbinfo->cmap, fbinfo);
87753 + dev_err(sfb->dev, "failed to allocate fb cmap\n");
87755 + s3c_fb_set_par(fbinfo);
87757 + dev_dbg(sfb->dev, "about to register framebuffer\n");
87759 + /* run the check_var and set_par on our configuration. */
87761 + ret = register_framebuffer(fbinfo);
87763 + dev_err(sfb->dev, "failed to register framebuffer\n");
87764 + goto err_alloc_mem;
87768 + dev_info(sfb->dev, "window %d: fb %s\n", win_no, fbinfo->fix.id);
87773 + s3c_fb_free_memory(sfb, win);
87776 + unregister_framebuffer(fbinfo);
87781 + * s3c_fb_clear_win() - clear hardware window registers.
87782 + * @sfb: The base resources for the hardware.
87783 + * @win: The window to process.
87785 + * Reset the specific window registers to a known state.
87787 +static void s3c_fb_clear_win(struct s3c_fb *sfb, int win)
87789 + void __iomem *regs = sfb->regs;
87791 + writel(0, regs + WINCON(win));
87792 + writel(0xffffff, regs + WxKEYCONy(win, 0));
87793 + writel(0xffffff, regs + WxKEYCONy(win, 1));
87795 + writel(0, regs + VIDOSD_A(win));
87796 + writel(0, regs + VIDOSD_B(win));
87797 + writel(0, regs + VIDOSD_C(win));
87800 +static int __devinit s3c_fb_probe(struct platform_device *pdev)
87802 + struct device *dev = &pdev->dev;
87803 + struct s3c_fb_platdata *pd;
87804 + struct s3c_fb *sfb;
87805 + struct resource *res;
87809 + pd = pdev->dev.platform_data;
87811 + dev_err(dev, "no platform data specified\n");
87815 + sfb = kzalloc(sizeof(struct s3c_fb), GFP_KERNEL);
87817 + dev_err(dev, "no memory for framebuffers\n");
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");
87830 + clk_enable(sfb->bus_clk);
87832 + res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
87834 + dev_err(dev, "failed to find registers\n");
87839 + sfb->regs_res = request_mem_region(res->start, resource_size(res),
87841 + if (!sfb->regs_res) {
87842 + dev_err(dev, "failed to claim register region\n");
87847 + sfb->regs = ioremap(res->start, resource_size(res));
87848 + if (!sfb->regs) {
87849 + dev_err(dev, "failed to map registers\n");
87851 + goto err_req_region;
87854 + dev_dbg(dev, "got resources (regs %p), probing windows\n", sfb->regs);
87856 + /* setup gpio and output polarity controls */
87858 + pd->setup_gpio();
87860 + writel(pd->vidcon1, sfb->regs + VIDCON1);
87862 + /* zero all windows before we do anything */
87864 + for (win = 0; win < S3C_FB_MAX_WIN; win++)
87865 + s3c_fb_clear_win(sfb, win);
87867 + /* we have the register setup, start allocating framebuffers */
87869 + for (win = 0; win < S3C_FB_MAX_WIN; win++) {
87870 + if (!pd->win[win])
87873 + ret = s3c_fb_probe_win(sfb, win, &sfb->windows[win]);
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;
87882 + platform_set_drvdata(pdev, sfb);
87887 + iounmap(sfb->regs);
87890 + release_resource(sfb->regs_res);
87891 + kfree(sfb->regs_res);
87894 + clk_disable(sfb->bus_clk);
87895 + clk_put(sfb->bus_clk);
87903 + * s3c_fb_remove() - Cleanup on module finalisation
87904 + * @pdev: The platform device we are bound to.
87906 + * Shutdown and then release all the resources that the driver allocated
87907 + * on initialisation.
87909 +static int __devexit s3c_fb_remove(struct platform_device *pdev)
87911 + struct s3c_fb *sfb = platform_get_drvdata(pdev);
87914 + for (win = 0; win <= S3C_FB_MAX_WIN; win++)
87915 + s3c_fb_release_win(sfb, sfb->windows[win]);
87917 + iounmap(sfb->regs);
87919 + clk_disable(sfb->bus_clk);
87920 + clk_put(sfb->bus_clk);
87922 + release_resource(sfb->regs_res);
87923 + kfree(sfb->regs_res);
87931 +static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state)
87933 + struct s3c_fb *sfb = platform_get_drvdata(pdev);
87934 + struct s3c_fb_win *win;
87937 + for (win_no = S3C_FB_MAX_WIN; win_no >= 0; win_no--) {
87938 + win = sfb->windows[win_no];
87942 + /* use the blank function to push into power-down */
87943 + s3c_fb_blank(FB_BLANK_POWERDOWN, win->fbinfo);
87946 + clk_disable(sfb->bus_clk);
87950 +static int s3c_fb_resume(struct platform_device *pdev)
87952 + struct s3c_fb *sfb = platform_get_drvdata(pdev);
87953 + struct s3c_fb_win *win;
87956 + clk_enable(sfb->bus_clk);
87958 + for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) {
87959 + win = sfb->windows[win_no];
87963 + dev_dbg(&pdev->dev, "resuming window %d\n", win_no);
87964 + s3c_fb_set_par(win->fbinfo);
87970 +#define s3c_fb_suspend NULL
87971 +#define s3c_fb_resume NULL
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,
87980 + .name = "s3c-fb",
87981 + .owner = THIS_MODULE,
87985 +static int __init s3c_fb_init(void)
87987 + return platform_driver_register(&s3c_fb_driver);
87990 +static void __exit s3c_fb_cleanup(void)
87992 + platform_driver_unregister(&s3c_fb_driver);
87995 +module_init(s3c_fb_init);
87996 +module_exit(s3c_fb_cleanup);
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
88009 +config PCF50606_WATCHDOG
88010 + depends on MFD_PCF50606
88011 + tristate "Philips PCF50606 watchdog"
88013 + If you say yes here you get support for the Philips PCF50606
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
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
88034 +/* Philips PCF50606 Watchdog Timer Driver
88036 + * (C) 2006-2008 by Openmoko, Inc.
88037 + * Author: Balaji Rao <balajirrao@openmoko.org>
88038 + * All rights reserved.
88040 + * Broken down from monstrous PCF50606 driver mainly by
88041 + * Harald Welte, Matt Hsu, Andy Green and Werner Almesberger
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.
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>
88060 +#include <linux/mfd/pcf50606/core.h>
88062 +static struct pcf50606 *pcf = NULL;
88063 +static unsigned long wdt_status;
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
88070 +static int allow_close;
88071 +#define CLOSE_STATE_NOT 0x0000
88072 +#define CLOSE_STATE_ALLOW 0x2342
88074 +#define PCF50606_REG_OOCC1 0x08
88075 +#define PCF50606_REG_OOCS 0x01
88077 +#define PCF50606_OOCS_WDTEXP 0x80
88078 +#define PCF50606_OOCC1_WDTRST 0x08
88080 +static void pcf50606_wdt_start(void)
88082 + pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_OOCC1, PCF50606_OOCC1_WDTRST,
88083 + PCF50606_OOCC1_WDTRST);
88086 +static void pcf50606_wdt_stop(void)
88088 + pcf50606_reg_clear_bits(pcf, PCF50606_REG_OOCS, PCF50606_OOCS_WDTEXP);
88091 +static void pcf50606_wdt_keepalive(void)
88093 + pcf50606_wdt_start();
88096 +static int pcf50606_wdt_open(struct inode *inode, struct file *file)
88098 + if (test_and_set_bit(WDT_IN_USE, &wdt_status))
88101 + pcf50606_wdt_start();
88103 + return nonseekable_open(inode, file);
88106 +static int pcf50606_wdt_release(struct inode *inode, struct file *file)
88108 + if (allow_close == CLOSE_STATE_ALLOW)
88109 + pcf50606_wdt_stop();
88111 + printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n");
88112 + pcf50606_wdt_keepalive();
88115 + allow_close = CLOSE_STATE_NOT;
88116 + clear_bit(WDT_IN_USE, &wdt_status);
88121 +static ssize_t pcf50606_wdt_write(struct file *file, const char __user *data,
88122 + size_t len, loff_t *ppos)
88127 + for (i = 0; i != len; i++) {
88129 + if (get_user(c, data + i))
88132 + allow_close = CLOSE_STATE_ALLOW;
88134 + pcf50606_wdt_keepalive();
88140 +static struct watchdog_info pcf50606_wdt_ident = {
88141 + .options = WDIOF_MAGICCLOSE,
88142 + .firmware_version = 0,
88143 + .identity = "PCF50606 Watchdog",
88146 +static int pcf50606_wdt_ioctl(struct inode *inode, struct file *file,
88147 + unsigned int cmd, unsigned long arg)
88149 + void __user *argp = (void __user *)arg;
88150 + int __user *p = argp;
88153 + case WDIOC_GETSUPPORT:
88154 + return copy_to_user(argp, &pcf50606_wdt_ident,
88155 + sizeof(pcf50606_wdt_ident)) ? -EFAULT : 0;
88157 + case WDIOC_GETSTATUS:
88158 + case WDIOC_GETBOOTSTATUS:
88159 + return put_user(0, p);
88160 + case WDIOC_KEEPALIVE:
88161 + pcf50606_wdt_keepalive();
88163 + case WDIOC_GETTIMEOUT:
88164 + return put_user(8, p);
88166 + return -ENOIOCTLCMD;
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,
88179 +static struct miscdevice pcf50606_wdt_miscdev = {
88180 + .minor = WATCHDOG_MINOR,
88181 + .name = "watchdog",
88182 + .fops = &pcf50606_wdt_fops,
88185 +static void pcf50606_wdt_irq(int irq, void *unused)
88187 + pcf50606_reg_set_bit_mask(pcf, PCF50606_REG_OOCC1,
88188 + PCF50606_OOCC1_WDTRST,
88189 + PCF50606_OOCC1_WDTRST);
88192 +int __init pcf50606_wdt_probe(struct platform_device *pdev)
88194 + struct pcf50606_subdev_pdata *pdata;
88198 + dev_err(pcf->dev, "Only one instance of WDT supported\n");
88202 + pdata = pdev->dev.platform_data;
88204 + dev_err(&pdev->dev, "No platform data available\n");
88208 + pcf = pdata->pcf;
88210 + err = misc_register(&pcf50606_wdt_miscdev);
88212 + dev_err(&pdev->dev, "cannot register miscdev on "
88213 + "minor=%d (%d)\n", WATCHDOG_MINOR, err);
88216 + set_bit(WDT_DEVICE_INITED, &wdt_status);
88218 + pcf50606_register_irq(pcf, PCF50606_IRQ_CHGWD10S, pcf50606_wdt_irq, NULL);
88223 +static int __devexit pcf50606_wdt_remove(struct platform_device *pdev)
88225 + pcf50606_free_irq(pcf, PCF50606_IRQ_CHGWD10S);
88226 + misc_deregister(&pcf50606_wdt_miscdev);
88232 +struct platform_driver pcf50606_wdt_driver = {
88234 + .name = "pcf50606-wdt",
88236 + .probe = pcf50606_wdt_probe,
88237 + .remove = __devexit_p(pcf50606_wdt_remove),
88240 +static int __init pcf50606_wdt_init(void)
88242 + return platform_driver_register(&pcf50606_wdt_driver);
88244 +module_init(pcf50606_wdt_init);
88246 +static void __exit pcf50606_wdt_exit(void)
88248 + platform_driver_unregister(&pcf50606_wdt_driver);
88250 +module_exit(pcf50606_wdt_exit);
88252 +MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
88253 +MODULE_DESCRIPTION("PCF50606 wdt driver");
88254 +MODULE_LICENSE("GPL");
88255 +MODULE_ALIAS("platform:pcf50606-wdt");
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);
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. */
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 -
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));
88283 /* Put_super will send a SIGKILL and then wait on the sem.
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
88290 + * include/asm-arm/plat-s3c24xx/neo1973.h
88292 + * Common utility code for GTA01 and GTA02
88294 + * Copyright (C) 2008 by Openmoko, Inc.
88295 + * Author: Holger Hans Peter Freyther <freyther@openmoko.org>
88296 + * All rights reserved.
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.
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.
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
88318 +void neo1973_gpb_add_shadow_gpio(unsigned int gpio);
88319 +void neo1973_gpb_setpin(unsigned int pin, unsigned to);
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
88326 -/* arch/arm/mach-s3c2410/include/mach/regs-iis.h
88328 - * Copyright (c) 2003 Simtec Electronics <linux@simtec.co.uk>
88329 - * http://www.simtec.co.uk/products/SWLINUX/
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.
88335 - * S3C2410 IIS register definition
88338 -#ifndef __ASM_ARCH_REGS_IIS_H
88339 -#define __ASM_ARCH_REGS_IIS_H
88341 -#define S3C2410_IISCON (0x00)
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)
88353 -#define S3C2410_IISMOD (0x04)
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)
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)
88381 -#define S3C2410_IISFCON (0x0c)
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)
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)
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
88407 -/* linux/include/asm-arm/plat-s3c24xx/regs-s3c2412-iis.h
88409 - * Copyright 2007 Simtec Electronics <linux@simtec.co.uk>
88410 - * http://armlinux.simtec.co.uk/
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.
88416 - * S3C2412 IIS register definition
88419 -#ifndef __ASM_ARCH_REGS_S3C2412_IIS_H
88420 -#define __ASM_ARCH_REGS_S3C2412_IIS_H
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)
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)
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)
88468 -#define S3C2412_IISPSR_PSREN (1 << 15)
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)
88477 -#endif /* __ASM_ARCH_REGS_S3C2412_IIS_H */
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
88483 +/* include/linux/android_aid.h
88485 + * Copyright (C) 2008 Google, Inc.
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.
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.
88498 +#ifndef _LINUX_ANDROID_AID_H
88499 +#define _LINUX_ANDROID_AID_H
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
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
88512 +/* include/linux/android_alarm.h
88514 + * Copyright (C) 2006-2007 Google, Inc.
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.
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.
88527 +#ifndef _LINUX_ANDROID_ALARM_H
88528 +#define _LINUX_ANDROID_ALARM_H
88530 +#include <linux/ioctl.h>
88531 +#include <linux/time.h>
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,
88541 + ANDROID_ALARM_TYPE_COUNT,
88543 + /* return code bit numbers */
88544 + /* ANDROID_ALARM_TIME_CHANGE = 16 */
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
88558 +/* Disable alarm */
88559 +#define ANDROID_ALARM_CLEAR(type) _IO('a', 0 | ((type) << 4))
88561 +/* Ack last alarm and wait for next */
88562 +#define ANDROID_ALARM_WAIT _IO('a', 1)
88564 +#define ALARM_IOW(c, type, size) _IOW('a', (c) | ((type) << 4), size)
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)
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
88579 + * include/linux/ashmem.h
88581 + * Copyright 2008 Google Inc.
88582 + * Author: Robert Love
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.
88589 +#ifndef _LINUX_ASHMEM_H
88590 +#define _LINUX_ASHMEM_H
88592 +#include <linux/limits.h>
88593 +#include <linux/ioctl.h>
88595 +#define ASHMEM_NAME_LEN 256
88597 +#define ASHMEM_NAME_DEF "dev/ashmem"
88599 +/* Return values from ASHMEM_PIN: Was the mapping purged while unpinned? */
88600 +#define ASHMEM_NOT_PURGED 0
88601 +#define ASHMEM_WAS_PURGED 1
88603 +/* Return values from ASHMEM_GET_PIN_STATUS: Is the mapping pinned? */
88604 +#define ASHMEM_IS_UNPINNED 0
88605 +#define ASHMEM_IS_PINNED 1
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 */
88612 +#define __ASHMEMIOC 0x77
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)
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
88630 +#ifndef __BQ27000_BATTERY_H__
88631 +#define __BQ27000_BATTERY_H__
88633 +void bq27000_charging_state_change(struct platform_device *pdev);
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);
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
88650 struct bus_attribute *);
88651 extern void bus_remove_file(struct bus_type *, struct bus_attribute *);
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);
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
88665 +/* include/linux/earlysuspend.h
88667 + * Copyright (C) 2007-2008 Google, Inc.
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.
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.
88680 +#ifndef _LINUX_EARLYSUSPEND_H
88681 +#define _LINUX_EARLYSUSPEND_H
88683 +#ifdef CONFIG_ANDROID_HAS_EARLYSUSPEND
88684 +#include <linux/list.h>
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.
88698 + EARLY_SUSPEND_LEVEL_BLANK_SCREEN = 50,
88699 + EARLY_SUSPEND_LEVEL_STOP_DRAWING = 100,
88700 + EARLY_SUSPEND_LEVEL_DISABLE_FB = 150,
88702 +struct early_suspend {
88703 +#ifdef CONFIG_ANDROID_HAS_EARLYSUSPEND
88704 + struct list_head link;
88706 + void (*suspend)(struct early_suspend *h);
88707 + void (*resume)(struct early_suspend *h);
88711 +#ifdef CONFIG_ANDROID_HAS_EARLYSUSPEND
88712 +void register_early_suspend(struct early_suspend *handler);
88713 +void unregister_early_suspend(struct early_suspend *handler);
88715 +#define register_early_suspend(handler) do { } while (0)
88716 +#define unregister_early_suspend(handler) do { } while (0)
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
88736 +#ifndef _LINUX_GLAMOFB_H
88737 +#define _LINUX_GLAMOFB_H
88739 +#include <linux/spi/glamo.h>
88741 +struct glamofb_val {
88742 + unsigned int defval;
88743 + unsigned int min;
88744 + unsigned int max;
88747 +struct glamo_core;
88749 +struct glamofb_platform_data {
88750 + int width, height;
88752 + int left_margin, right_margin;
88753 + int upper_margin, lower_margin;
88754 + int hsync_len, vsync_len;
88757 + struct glamofb_val xres;
88758 + struct glamofb_val yres;
88759 + struct glamofb_val bpp;
88761 + struct glamo_spi_info *spi_info;
88762 + struct glamo_spigpio_info *spigpio_info;
88763 + struct glamo_core *glamo;
88765 + struct platform_device *mmc_dev;
88767 + /* glamo mmc platform specific info */
88768 + int (*glamo_can_set_mci_power)(void);
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);
88776 +int glamofb_cmd_mode(struct glamofb_handle *gfb, int on);
88777 +int glamofb_cmd_write(struct glamofb_handle *gfb, u_int16_t val);
88779 +#ifdef CONFIG_MFD_GLAMO
88780 +void glamo_lcm_reset(int level);
88782 +#define glamo_lcm_reset(...) do {} while (0)
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
88790 +#ifndef __GLAMO_GPIO_H
88791 +#define __GLAMO_GPIO_H
88793 +struct glamo_core;
88795 +#define GLAMO_GPIO_BANKA 0x0000
88796 +#define GLAMO_GPIO_BANKB 0x1000
88797 +#define GLAMO_GPIO_BANKC 0x2000
88798 +#define GLAMO_GPIO_BANKD 0x3000
88800 +#define GLAMO_GPIONO(bank, pin) ((bank & 0xf000) | ((pin & 0xf) << 8))
88802 +#define GLAMO_GPIO_F_IN 0x0010
88803 +#define GLAMO_GPIO_F_OUT 0x0020
88804 +#define GLAMO_GPIO_F_FUNC 0x0030
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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))
88880 +void glamo_gpio_setpin(struct glamo_core *glamo, unsigned int pin,
88881 + unsigned int value);
88883 +int glamo_gpio_getpin(struct glamo_core *glamo, unsigned int pin);
88885 +void glamo_gpio_cfgpin(struct glamo_core *glamo, unsigned int pinfunc);
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
88893 +#ifndef __GTA01_BATTERY_H__
88894 +#define __GTA01_BATTERY_H__
88896 +struct gta01_bat_platform_data {
88897 + int (*get_charging_status)(void);
88898 + int (*get_voltage)(void);
88899 + int (*get_current)(void);
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
88907 +#ifndef __GTA02HDQ_H__
88908 +#define __GTA02HDQ_H__
88910 +/* platform data */
88912 +struct gta02_hdq_platform_data {
88914 + * give an opportunity to use us as parent for
88915 + * devices that depend on us
88917 + void (*attach_child_devices)(struct device *parent_device);
88920 +int gta02hdq_read(int address);
88921 +int gta02hdq_write(int address, u8 data);
88922 +int gta02hdq_initialized(void);
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
88929 +#ifndef __LINUX_HDQ_H__
88930 +#define __LINUX_HDQ_H__
88932 +#include <linux/device.h>
88934 +#define HDQ_SAMPLE_PERIOD_US 10
88936 +/* platform data */
88938 +struct hdq_platform_data {
88940 + * give an opportunity to use us as parent for
88941 + * devices that depend on us
88943 + void (*attach_child_devices)(struct device *parent_device);
88945 + void (*gpio_dir_out)(void);
88946 + void (*gpio_dir_in)(void);
88947 + void (*gpio_set)(int);
88948 + int (*gpio_get)(void);
88950 + int (*enable_fiq)(void);
88951 + void (*disable_fiq)(void);
88952 + void (*kick_fiq)(void);
88956 +int hdq_read(int address);
88957 +int hdq_write(int address, u8 data);
88958 +int hdq_initialized(void);
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
88965 #define I2C_DRIVERID_CS5345 96 /* cs5345 audio processor */
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
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 */
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
88984 +#ifndef __JBT6K74_H__
88985 +#define __JBT6K74_H__
88987 +#include <linux/spi/spi.h>
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);
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 *);
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
89012 #ifndef LINUX_KEXEC_H
89013 #define LINUX_KEXEC_H
89015 -#ifdef CONFIG_KEXEC
89016 #include <linux/types.h>
89017 #include <linux/list.h>
89018 #include <linux/linkage.h>
89020 #include <linux/elf.h>
89021 #include <asm/kexec.h>
89023 +#ifdef CONFIG_KEXEC
89025 /* Verify architecture specific macros are defined */
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
89032 +#ifndef __LINUX_L1K002_H_
89033 +#define __LINUX_L1K002_H_
89035 +struct l1k002_platform_data {
89036 + void (*pwr_onoff)(int level);
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
89044 +#ifndef _LINUX_LIS302DL_H
89045 +#define _LINUX_LIS302DL_H
89047 +#include <linux/types.h>
89048 +#include <linux/spi/spi.h>
89049 +#include <linux/input.h>
89050 +#include <linux/workqueue.h>
89052 +struct lis302dl_info;
89054 +struct lis302dl_platform_data {
89056 + unsigned long pin_chip_select;
89057 + unsigned long pin_clk;
89058 + unsigned long pin_mosi;
89059 + unsigned long pin_miso;
89062 + void (*lis302dl_suspend_io)(struct lis302dl_info *, int resuming);
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;
89074 + unsigned int threshold; /* mg */
89075 + unsigned int duration; /* ms */
89078 + struct spi_device *spi;
89079 + u_int8_t regs[0x40];
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,
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,
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,
89129 +enum lis302dl_reg_ctrl3 {
89130 + LIS302DL_CTRL3_PP_OD = 0x40,
89131 + LIS302DL_CTRL3_IHL = 0x80,
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,
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,
89157 +enum lis302dl_reg_ffwuths {
89158 + LIS302DL_FFWUTHS_DCRM = 0x80,
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,
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,
89181 +#define LIS302DL_WHO_AM_I_MAGIC 0x3b
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 */
89194 +#endif /* _LINUX_LIS302DL_H */
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
89200 +#ifndef _LINUX_LP5521_H_
89201 +#define _LINUX_LP5521_H_
89203 +#define LP5521_REG_ENABLE 0x00
89204 +#define LP5521_REG_OP_MODE 0x01
89206 +#define LP5521_REG_R_PWM 0x02
89207 +#define LP5521_REG_G_PWM 0x03
89208 +#define LP5521_REG_B_PWM 0x04
89210 +#define LP5521_REG_R_CUR 0x05
89211 +#define LP5521_REG_G_CUR 0x06
89212 +#define LP5521_REG_B_CUR 0x07
89214 +#define LP5521_REG_CONFIG 0x08
89216 +#define LP5521_REG_R_PC 0x09
89217 +#define LP5521_REG_G_PC 0x0a
89218 +#define LP5521_REG_B_PC 0x0b
89220 +#define LP5521_REG_STATUS 0x0c
89221 +#define LP5521_REG_RESET 0x0d
89222 +#define LP5521_REG_GPO 0x0e
89226 + LP5521_CONNECTED,
89237 + LP5521_MODE_DISABLE,
89238 + LP5521_MODE_LOAD,
89240 + LP5521_MODE_DIRECT,
89245 + LP5521_CPM_BY_PASS,
89256 +#define LP5521_FEAT_TRIG 0x00000001
89257 +#define LP5521_FEAT_GPO 0x00000002
89260 +struct lp5521_platform_data {
89261 + int channels[LP5521_NUM_CH];
89262 + /* chip enable */
89263 + void (*ext_enable)(int level);
89267 + struct device *dev;
89268 + struct i2c_client *client;
89269 + struct mutex lock;
89272 + struct lp5521_platform_data *pdata;
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
89280 + * adc.h -- Driver for NXP PCF50606 ADC
89282 + * (C) 2006-2008 by Openmoko, Inc.
89283 + * All rights reserved.
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.
89291 +#ifndef __LINUX_MFD_PCF50606_ADC_H
89292 +#define __LINUX_MFD_PCF50606_ADC_H
89294 +#include <linux/mfd/pcf50633/core.h>
89295 +#include <linux/platform_device.h>
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
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
89311 +#define PCF50606_ADCC1_TSCINT 0x80
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
89322 +#define PCF50606_ADCC2_ADCMUX_MASK (0xf << 1)
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)
89341 +#define PCF50606_ADCS2_ADCRDY 0x80
89344 +pcf50606_adc_async_read(struct pcf50606 *pcf, int mux,
89345 + void (*callback)(struct pcf50606 *, void *, int),
89346 + void *callback_param);
89348 +pcf50606_adc_sync_read(struct pcf50606 *pcf, int mux);
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
89356 + * core.h -- Core driver for NXP PCF50606
89358 + * (C) 2006-2008 by Openmoko, Inc.
89359 + * All rights reserved.
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.
89367 +#ifndef __LINUX_MFD_PCF50606_CORE_H
89368 +#define __LINUX_MFD_PCF50606_CORE_H
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>
89378 +#define PCF50606_NUM_REGULATORS 8
89380 +struct pcf50606_platform_data {
89381 + struct regulator_init_data reg_init_data[PCF50606_NUM_REGULATORS];
89383 + char **batteries;
89384 + int num_batteries;
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 *);
89395 +struct pcf50606_subdev_pdata {
89396 + struct pcf50606 *pcf;
89399 +struct pcf50606_irq {
89400 + void (*handler)(int, void *);
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);
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);
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);
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);
89422 +/* Interrupt registers */
89424 +#define PCF50606_REG_INT1 0x02
89425 +#define PCF50606_REG_INT2 0x03
89426 +#define PCF50606_REG_INT3 0x04
89428 +#define PCF50606_REG_INT1M 0x05
89429 +#define PCF50606_REG_INT2M 0x06
89430 +#define PCF50606_REG_INT3M 0x07
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,
89459 + /* Always last */
89460 + PCF50606_NUM_IRQ,
89464 + struct device *dev;
89465 + struct i2c_client *i2c_client;
89467 + struct pcf50606_platform_data *pdata;
89469 + struct pcf50606_irq irq_handler[PCF50606_NUM_IRQ];
89470 + struct work_struct irq_work;
89471 + struct mutex lock;
89475 + u8 suspend_irq_masks[3];
89476 + u8 resume_reason[3];
89477 + int is_suspended;
89479 + int onkey1s_held;
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];
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 */
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 */
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 */
89521 +#define PCF50606_REG_OOCC1 0x08
89522 +#define PCF50606_OOCC1_GOSTDBY 0x01
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
89530 + * gpo.h -- GPO driver for NXP PCF50606
89532 + * (C) 2006-2008 by Openmoko, Inc.
89533 + * All rights reserved.
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.
89541 +#ifndef __LINUX_MFD_PCF50606_GPO_H
89542 +#define __LINUX_MFD_PCF50606_GPO_H
89544 +#include <linux/mfd/pcf50633/core.h>
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
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
89559 +#define PCF50606_GPOCFG_GPOSEL_MASK 0x07
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);
89566 +void pcf50606_gpo_invert_set(struct pcf50606 *, int gpo, int invert);
89567 +int pcf50606_gpo_invert_get(struct pcf50606 *pcf, int gpo);
89569 +#endif /* __LINUX_MFD_PCF50606_GPIO_H */
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
89576 + * mbc.h -- Driver for NXP PCF50606 Main Battery Charger
89578 + * (C) 2006-2008 by Openmoko, Inc.
89579 + * All rights reserved.
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.
89587 +#ifndef __LINUX_MFD_PCF50606_MBC_H
89588 +#define __LINUX_MFD_PCF50606_MBC_H
89590 +#include <linux/mfd/pcf50606/core.h>
89591 +#include <linux/platform_device.h>
89593 +#define PCF50606_REG_OOCS 0x01
89596 +#define PCF50606_OOCS_CHGOK 0x20
89598 +#define PCF50606_REG_MBCC1 0x29
89599 +#define PCF50606_REG_MBCC2 0x2a
89600 +#define PCF50606_REG_MBCC3 0x2b
89601 +#define PCF50606_REG_MBCS1 0x2c
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
89617 +#define PCF50606_MBCC1_CHGMOD_SHIFT 2
89619 +/* Charger status */
89620 +#define PCF50606_MBC_CHARGER_ONLINE 0x01
89621 +#define PCF50606_MBC_CHARGER_ACTIVE 0x02
89623 +void pcf50606_charge_fast(struct pcf50606 *pcf, int on);
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
89631 +#ifndef __LINUX_MFD_PCF50606_PMIC_H
89632 +#define __LINUX_MFD_PCF50606_PMIC_H
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
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 */
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,
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,
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,
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,
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
89711 + int charging_restart_interval;
89713 + int chg_ref_current_ma;
89716 void (*probe_done)(struct pcf50633 *);
89717 void (*mbc_event_callback)(struct pcf50633 *, int);
89718 @@ -206,7 +210,8 @@
89721 /* misc. registers */
89722 -#define PCF50633_REG_OOCSHDWN 0x0c
89723 +#define PCF50633_REG_OOCSHDWN 0x0c
89724 +#define PCF50633_OOCSHDWN_GOSTDBY 0x01
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);
89734 int pcf50633_mbc_get_status(struct pcf50633 *);
89735 -void pcf50633_mbc_set_status(struct pcf50633 *, int what, int status);
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 @@
89746 +extern void mmc_flush_scheduled_work(void);
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
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
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 @@
89770 struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags);
89772 +void shmem_set_file(struct vm_area_struct *, struct file *);
89773 int shmem_zero_setup(struct vm_area_struct *);
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
89780 +struct neo1973_vib_platform_data {
89781 + int (* enable_fiq)(void);
89782 + void (*disable_fiq)(void);
89783 + void (*kick_fiq)(void);
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
89789 +#ifndef _LINUX_PCPA7200_H
89790 +#define _LINUX_PCPA7200_H
89808 +struct pcap7200_platform_data {
89809 + enum op_mode mode;
89810 + void (*reset)(void);
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
89818 +#ifndef _LINUX_PCF50606_H
89819 +#define _LINUX_PCF50606_H
89821 +#include <linux/pcf506xx.h>
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
89837 +struct pcf50606_data;
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;
89845 +pcf50606_go_standby(void);
89848 +pcf50606_gpo0_set(struct pcf50606_data *pcf, int on);
89851 +pcf50606_gpo0_get(struct pcf50606_data *pcf);
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);
89861 +pcf50606_onoff_get(struct pcf50606_data *pcf,
89862 + enum pcf50606_regulator_id reg);
89865 +pcf50606_onoff_set(struct pcf50606_data *pcf,
89866 + enum pcf50606_regulator_id reg, int on);
89869 +pcf50606_charge_fast(struct pcf50606_data *pcf, int on);
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
89885 +struct pcf50606_platform_data {
89887 + unsigned int used_features;
89888 + unsigned int onkey_seconds_required;
89890 + /* voltage regulator related */
89891 + struct pmu_voltage_rail rails[__NUM_PCF50606_REGULATORS];
89892 + unsigned int used_regulators;
89894 + /* charger related */
89895 + unsigned int r_fix_batt;
89896 + unsigned int r_fix_batt_par;
89897 + unsigned int r_sense_milli;
89899 + /* backlight related */
89900 + unsigned int init_brightness;
89903 + u_int8_t mbcc3; /* charger voltage / current */
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
89913 +#ifndef _LINUX_PCF50633_H
89914 +#define _LINUX_PCF50633_H
89916 +#include <linux/pcf506xx.h>
89917 +#include <linux/regulator/machine.h>
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
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 */
89942 + PCF50633_INT1_ALARM = 0x40, /* RTC alarm time is reached */
89943 + PCF50633_INT1_SECOND = 0x80, /* RTC periodic second interrupt */
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 */
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 */
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,
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,
89990 +struct pcf50633_data;
89991 +extern struct pcf50633_data *pcf50633_global;
89994 +pcf50633_go_standby(void);
89996 +enum pcf50633_gpio {
89997 + PCF50633_GPIO1 = 1,
89998 + PCF50633_GPIO2 = 2,
89999 + PCF50633_GPIO3 = 3,
90000 + PCF50633_GPO = 4,
90004 +pcf50633_gpio_set(struct pcf50633_data *pcf, enum pcf50633_gpio gpio, int on);
90007 +pcf50633_gpio_get(struct pcf50633_data *pcf, enum pcf50633_gpio gpio);
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);
90018 +pcf50633_onoff_get(struct pcf50633_data *pcf,
90019 + enum pcf50633_regulator_id reg);
90022 +pcf50633_onoff_set(struct pcf50633_data *pcf,
90023 + enum pcf50633_regulator_id reg, int on);
90026 +pcf50633_backlight_resume(struct pcf50633_data *pcf);
90029 +pcf50633_battvolt(struct pcf50633_data *pcf);
90032 +pcf50633_report_resumers(struct pcf50633_data *pcf, char *buf);
90035 +pcf50633_notify_usb_current_limit_change(struct pcf50633_data *pcf,
90036 + unsigned int ma);
90038 +pcf50633_wait_for_ready(struct pcf50633_data *pcf, int timeout_ms,
90041 +/* 0 = initialized and resumed and ready to roll, !=0 = either not
90042 + * initialized or not resumed yet
90045 +pcf50633_ready(struct pcf50633_data *pcf);
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
90056 +struct pcf50633_platform_data {
90058 + unsigned int used_features;
90059 + unsigned int onkey_seconds_sig_init;
90060 + unsigned int onkey_seconds_shutdown;
90062 + /* callback to attach platform children (to enforce suspend / resume
90064 + void (*attach_child_devices)(struct device *parent_device);
90066 + /* voltage regulator related */
90067 + struct pmu_voltage_rail rails[__NUM_PCF50633_REGULATORS];
90068 + unsigned int used_regulators;
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;
90076 + unsigned char resumers[5];
90079 + u_int8_t mbcc3; /* charger voltage / current */
90083 + /* post-resume backlight bringup */
90084 + int defer_resume_backlight;
90085 + u8 resume_backlight_ramp_speed;
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
90093 +#ifndef _LINUX_PCF506XX_H
90094 +#define _LINUX_PCF506XX_H
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 {
90101 + unsigned int flags;
90103 + unsigned int init;
90104 + unsigned int max;
90112 +#ifdef CONFIG_SENSORS_PCF50633
90113 + PMU_EVT_USB_INSERT,
90114 + PMU_EVT_USB_REMOVE,
90116 + PMU_EVT_CHARGER_ACTIVE,
90117 + PMU_EVT_CHARGER_IDLE,
90118 + PMU_EVT_CHARGER_CHANGE,
90122 +typedef int (*pmu_cb)(struct device *dev, unsigned int feature,
90123 + enum pmu_event event);
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
90131 +#ifndef __RESUME_DEPENDENCY_H__
90132 +#define __RESUME_DEPENDENCY_H__
90134 +/* Resume dependency framework
90136 + * (C) 2008 Openmoko, Inc.
90137 + * Author: Andy Green <andy@openmoko.com>
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.
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.
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
90155 +#include <linux/list.h>
90157 +struct resume_dependency {
90158 + struct list_head list;
90160 + void (*callback)(void *); /* called with context as arg */
90162 + int called_flag; /* set to 1 after called, use for multi dep */
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
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);
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
90181 +#define register_resume_dependency(_head, _dep) { \
90182 + struct list_head *_pos, *_q; \
90183 + struct resume_dependency *_d; \
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"); \
90194 + list_add(&(_dep)->list, &(_head)->list); \
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.
90202 +#define callback_all_resume_dependencies(_head) { \
90203 + struct list_head *_pos, *_q; \
90204 + struct resume_dependency *_dep; \
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); \
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
90226 +#define activate_all_resume_dependencies(_head) { \
90227 + struct list_head *_pos, *_q; \
90228 + struct resume_dependency *_dep; \
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; \
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
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
90249 +enum pcf50633_rtc_event {
90250 + PCF50633_RTC_EVENT_ALARM,
90251 + PCF50633_RTC_EVENT_SECOND,
90254 +extern void pcf50633_rtc_handle_event(struct pcf50633_data *pcf,
90255 + enum pcf50633_rtc_event evt);
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
90262 +#ifndef __GLAMO_SPI_H
90263 +#define __GLAMO_SPI_H
90265 +#include <linux/glamo-gpio.h>
90267 +struct spi_board_info;
90268 +struct glamofb_handle;
90269 +struct glamo_core;
90271 +struct glamo_spi_info {
90272 + unsigned long board_size;
90273 + struct spi_board_info *board_info;
90274 + struct glamofb_handle *glamofb_handle;
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;
90284 + struct glamo_core *glamo;
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
90294 u8 flags; /* extra spi->mode support */
90296 + /* Support for synchronous non blocking transfers */
90297 + int non_blocking_transfer;
90299 struct spi_master *master;
90301 /* setup_transfer() changes clock and/or wordsize to match settings
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);
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);
90319 + * Synchronous non blocking transfer function. Should guarantee
90320 + * data availability when it returns
90322 + int (*transfer_sync)(struct spi_device *spi,
90323 + struct spi_message *mesg);
90325 /* called on release() to free memory provided by spi_master */
90326 void (*cleanup)(struct spi_device *spi);
90328 @@ -573,6 +580,29 @@
90329 return spi->master->transfer(spi, message);
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)
90338 + * Data is guaranteed to be written or read when this function returns.
90340 + * Note : This may not be supported by all spi masters.
90344 +spi_non_blocking_transfer(struct spi_device *spi, struct spi_message *message)
90346 + if (unlikely(!spi->master->transfer_sync)) {
90347 + dev_err(&spi->master->dev,
90348 + "non-blocking transfers not supported\n");
90352 + return spi->master->transfer_sync(spi, message);
90355 /*---------------------------------------------------------------------------*/
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 @@
90366 + * global indication we are somewhere between start of suspend and end of
90367 + * resume, nonzero is true
90369 +extern int global_inside_suspend;
90371 /* mm/page_alloc.c */
90372 extern void mark_free_pages(struct zone *zone);
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
90380 #define MIN_NR_CONSOLES 1 /* must be at least 1 */
90381 +#if (CONFIG_NR_TTY_DEVICES < 4)
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)
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 */
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
90394 /* Note: the ioctl VT_GETSTATE does not work for
90395 consoles 16 and higher (since it returns a short) */
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
90401 +/* include/linux/wakelock.h
90403 + * Copyright (C) 2007-2008 Google, Inc.
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.
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.
90416 +#ifndef _LINUX_WAKELOCK_H
90417 +#define _LINUX_WAKELOCK_H
90419 +#include <linux/list.h>
90420 +#include <linux/ktime.h>
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.
90430 + WAKE_LOCK_SUSPEND, /* Prevent suspend */
90431 + WAKE_LOCK_IDLE, /* Prevent low power idle */
90432 + WAKE_LOCK_TYPE_COUNT
90435 +struct wake_lock {
90436 +#ifdef CONFIG_ANDROID_HAS_WAKELOCK
90437 + struct list_head link;
90439 + const char *name;
90440 + unsigned long expires;
90441 +#ifdef CONFIG_ANDROID_WAKELOCK_STAT
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;
90455 +#ifdef CONFIG_ANDROID_HAS_WAKELOCK
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);
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.
90467 +int wake_lock_active(struct wake_lock *lock);
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.
90474 +long has_wake_lock(int type);
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) {}
90485 +static inline int wake_lock_active(struct wake_lock *lock) { return 0; }
90486 +static inline long has_wake_lock(int type) { return 0; }
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.
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 }
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);
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);
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,
90543 +int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec);
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.
90556 + bool "Enable Android's Shared Memory Subsystem"
90558 + depends on SHMEM || TINY_SHMEM
90560 + The ashmem subsystem is a new shared memory allocator, similar to
90561 + POSIX SHM but with different behavior and sporting a simpler
90564 config VM_EVENT_COUNTERS
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 @@
90572 spin_unlock(&desc->lock);
90574 +EXPORT_SYMBOL(handle_level_irq);
90577 * handle_fasteoi_irq - irq handler for transparent controllers
90578 @@ -593,6 +594,7 @@
90580 spin_unlock_irqrestore(&desc->lock, flags);
90582 +EXPORT_SYMBOL(__set_irq_handler);
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 @@
90591 #endif /* CONFIG_PM_SLEEP */
90593 +int global_inside_suspend;
90594 +EXPORT_SYMBOL(global_inside_suspend);
90596 #ifdef CONFIG_SUSPEND
90598 #ifdef CONFIG_PM_TEST_SUSPEND
90599 @@ -321,6 +324,8 @@
90603 + global_inside_suspend = 1;
90605 if (suspend_ops->begin) {
90606 error = suspend_ops->begin(state);
90608 @@ -362,6 +367,8 @@
90610 if (suspend_ops->end)
90611 suspend_ops->end();
90612 + global_inside_suspend = 0;
90617 @@ -388,6 +395,9 @@
90620 static const char * const pm_states[PM_SUSPEND_MAX] = {
90621 +#ifdef CONFIG_ANDROID_EARLYSUSPEND
90622 + [PM_SUSPEND_ON] = "on",
90624 [PM_SUSPEND_STANDBY] = "standby",
90625 [PM_SUSPEND_MEM] = "mem",
90627 @@ -424,6 +434,8 @@
90630 printk(KERN_INFO "PM: Syncing filesystems ... ");
90631 + global_inside_suspend = 1;
90636 @@ -505,7 +517,11 @@
90637 const char *buf, size_t n)
90639 #ifdef CONFIG_SUSPEND
90640 +#ifdef CONFIG_ANDROID_EARLYSUSPEND
90641 + suspend_state_t state = PM_SUSPEND_ON;
90643 suspend_state_t state = PM_SUSPEND_STANDBY;
90645 const char * const *s;
90648 @@ -527,8 +543,15 @@
90651 if (state < PM_SUSPEND_MAX && *s)
90652 +#ifdef CONFIG_ANDROID_EARLYSUSPEND
90653 + if (state == PM_SUSPEND_ON || valid_state(state)) {
90655 + request_suspend_state(state);
90658 error = enter_state(state);
90663 return error ? error : n;
90664 @@ -561,6 +584,12 @@
90665 power_attr(pm_trace);
90666 #endif /* CONFIG_PM_TRACE */
90668 +#ifdef CONFIG_ANDROID_USER_WAKELOCK
90669 +power_attr(wake_lock);
90670 +power_attr(wake_full_lock);
90671 +power_attr(wake_unlock);
90674 static struct attribute * g[] = {
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,
90681 +#ifdef CONFIG_ANDROID_USER_WAKELOCK
90682 + &wake_lock_attr.attr,
90683 + &wake_unlock_attr.attr,
90684 + &wake_full_lock_attr.attr,
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 @@
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;
90704 +#ifdef CONFIG_ANDROID_USER_WAKELOCK
90705 +ssize_t wake_lock_show(struct kobject *kobj, struct kobj_attribute *attr,
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);
90712 +#define wake_full_lock_show wake_lock_show
90714 +ssize_t wake_unlock_show(struct kobject *kobj, struct kobj_attribute *attr,
90716 +ssize_t wake_unlock_store(struct kobject *kobj, struct kobj_attribute *attr,
90717 + const char *buf, size_t n);
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);
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
90729 #include <linux/module.h>
90730 #include <linux/syscalls.h>
90731 #include <linux/freezer.h>
90732 +#include <linux/wakelock.h>
90735 * Timeout for stopping processes
90737 struct timeval start, end;
90738 u64 elapsed_csecs64;
90739 unsigned int elapsed_csecs;
90740 + unsigned int wakeup = 0;
90742 do_gettimeofday(&start);
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)) {
90752 if (time_after(jiffies, end_time))
90755 @@ -77,11 +83,17 @@
90756 * and caller must call thaw_processes() if something fails),
90757 * but it cleans up leftover PF_FREEZE requests.
90760 - printk(KERN_ERR "Freezing of tasks failed after %d.%02d seconds "
90763 + printk(KERN_ERR "Freezing of %s aborted\n",
90764 + sig_only ? "user space " : "tasks ");
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);
90773 read_lock(&tasklist_lock);
90774 do_each_thread(g, 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
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>
90786 #include <asm/uaccess.h>
90787 +#include <asm/plat-s3c24xx/neo1973.h>
90790 * Architectures can override it:
90791 @@ -67,13 +70,21 @@
90792 int oops_in_progress;
90793 EXPORT_SYMBOL(oops_in_progress);
90795 +void (*printk_emergency_debug_spew_init)(void) = NULL;
90796 +EXPORT_SYMBOL(printk_emergency_debug_spew_init);
90798 +void (*printk_emergency_debug_spew_send_string)(const char *) = NULL;
90799 +EXPORT_SYMBOL(printk_emergency_debug_spew_send_string);
90802 * console_sem protects the console_drivers list, and also
90803 * provides serialisation for access to the entire console
90806 static DECLARE_MUTEX(console_sem);
90807 +#ifndef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90808 static DECLARE_MUTEX(secondary_console_sem);
90810 struct console *console_drivers;
90811 EXPORT_SYMBOL_GPL(console_drivers);
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);
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
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
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;
90837 + if (global_inside_suspend == 1) {
90838 + (printk_emergency_debug_spew_init)();
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);
90847 + global_inside_suspend++; /* only once */
90849 + (printk_emergency_debug_spew_send_string)(printk_buf);
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);
90864 void resume_console(void)
90866 if (!console_suspend_enabled)
90868 +#ifdef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90869 + down(&console_sem);
90871 console_suspended = 0;
90872 release_console_sem();
90874 @@ -912,11 +960,17 @@
90875 void acquire_console_sem(void)
90877 BUG_ON(in_interrupt());
90878 +#ifndef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90879 if (console_suspended) {
90880 down(&secondary_console_sem);
90884 down(&console_sem);
90885 +#ifdef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90886 + if (console_suspended)
90889 console_locked = 1;
90890 console_may_schedule = 1;
90892 @@ -926,6 +980,12 @@
90894 if (down_trylock(&console_sem))
90896 +#ifdef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90897 + if (console_suspended) {
90898 + up(&console_sem);
90902 console_locked = 1;
90903 console_may_schedule = 0;
90905 @@ -979,7 +1039,11 @@
90906 unsigned wake_klogd = 0;
90908 if (console_suspended) {
90909 +#ifdef CONFIG_ANDROID_CONSOLE_EARLYSUSPEND
90910 + up(&console_sem);
90912 up(&secondary_console_sem);
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.
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);
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 @@
90933 Say N if you are unsure.
90935 +config FIND_IRQ_BLOCKERS
90936 + bool "IRQ Blocker statistics"
90939 + Enables tracking of IRQ dead-time because something has
90940 + disabled interrupts
90942 config DYNAMIC_PRINTK_DEBUG
90943 bool "Enable dynamic printk() call support"
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 @@
90951 L: linux-fsdevel@vger.kernel.org
90953 +FIC/OPENMOKO NEO1973 GSM PHONE
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
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/
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
90975 +# make 6MB recovery image from two moredrivers type kernels
90976 +# placed at start and at +4MBytes
90978 +if [ -z "$1" ] ; then
90979 + echo "Usage: $0 uImage-moredrivers-..."
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
90988 +cat $1 >> recovery-$1
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
90994 +/* drivers/android/ashmem.c
90996 +** Android / Anonymous Shared Memory Subsystem, ashmem
90998 +** Copyright (C) 2008 Google, Inc.
91000 +** Robert Love <rlove@google.com>
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.
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.
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>
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()
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 */
91041 + * ashmem_range - represents an interval of unpinned (evictable) pages
91042 + * Lifecycle: From unpin to pin
91043 + * Locking: Protected by `ashmem_mutex'
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 */
91054 +/* LRU list of unpinned pages, protected by ashmem_mutex */
91055 +static LIST_HEAD(ashmem_lru_list);
91057 +/* Count of pages on our LRU list, protected by ashmem_mutex */
91058 +static unsigned long lru_count;
91061 + * ashmem_mutex - protects the list of and each individual ashmem_area
91063 + * Lock Ordering: ashmex_mutex -> i_mutex -> i_alloc_sem
91065 +static DEFINE_MUTEX(ashmem_mutex);
91067 +static struct kmem_cache *ashmem_area_cachep __read_mostly;
91068 +static struct kmem_cache *ashmem_range_cachep __read_mostly;
91070 +#define range_size(range) \
91071 + ((range)->pgend - (range)->pgstart + 1)
91073 +#define range_on_lru(range) \
91074 + ((range)->purged == ASHMEM_NOT_PURGED)
91076 +#define page_range_subsumes_range(range, start, end) \
91077 + (((range)->pgstart >= (start)) && ((range)->pgend <= (end)))
91079 +#define page_range_subsumed_by_range(range, start, end) \
91080 + (((range)->pgstart <= (start)) && ((range)->pgend >= (end)))
91082 +#define page_in_range(range, page) \
91083 + (((range)->pgstart <= (page)) && ((range)->pgend >= (page)))
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))
91089 +#define range_before_page(range, page) \
91090 + ((range)->pgend < (page))
91092 +#define PROT_MASK (PROT_EXEC | PROT_READ | PROT_WRITE)
91094 +static inline void lru_add(struct ashmem_range *range)
91096 + list_add_tail(&range->lru, &ashmem_lru_list);
91097 + lru_count += range_size(range);
91100 +static inline void lru_del(struct ashmem_range *range)
91102 + list_del(&range->lru);
91103 + lru_count -= range_size(range);
91107 + * range_alloc - allocate and initialize a new ashmem_range structure
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
91115 + * Caller must hold ashmem_mutex.
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)
91121 + struct ashmem_range *range;
91123 + range = kmem_cache_zalloc(ashmem_range_cachep, GFP_KERNEL);
91124 + if (unlikely(!range))
91127 + range->asma = asma;
91128 + range->pgstart = start;
91129 + range->pgend = end;
91130 + range->purged = purged;
91132 + list_add_tail(&range->unpinned, &prev_range->unpinned);
91134 + if (range_on_lru(range))
91140 +static void range_del(struct ashmem_range *range)
91142 + list_del(&range->unpinned);
91143 + if (range_on_lru(range))
91145 + kmem_cache_free(ashmem_range_cachep, range);
91149 + * range_shrink - shrinks a range
91151 + * Caller must hold ashmem_mutex.
91153 +static inline void range_shrink(struct ashmem_range *range,
91154 + size_t start, size_t end)
91156 + size_t pre = range_size(range);
91158 + range->pgstart = start;
91159 + range->pgend = end;
91161 + if (range_on_lru(range))
91162 + lru_count -= pre - range_size(range);
91165 +static int ashmem_open(struct inode *inode, struct file *file)
91167 + struct ashmem_area *asma;
91170 + ret = nonseekable_open(inode, file);
91171 + if (unlikely(ret))
91174 + asma = kmem_cache_zalloc(ashmem_area_cachep, GFP_KERNEL);
91175 + if (unlikely(!asma))
91178 + INIT_LIST_HEAD(&asma->unpinned_list);
91179 + asma->prot_mask = PROT_MASK;
91180 + file->private_data = asma;
91185 +static int ashmem_release(struct inode *ignored, struct file *file)
91187 + struct ashmem_area *asma = file->private_data;
91188 + struct ashmem_range *range, *next;
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);
91196 + fput(asma->file);
91197 + kmem_cache_free(ashmem_area_cachep, asma);
91202 +static int ashmem_mmap(struct file *file, struct vm_area_struct *vma)
91204 + struct ashmem_area *asma = file->private_data;
91207 + mutex_lock(&ashmem_mutex);
91209 + /* user needs to SET_SIZE before mapping */
91210 + if (unlikely(!asma->size)) {
91215 + /* requested protection bits must match our allowed protection mask */
91216 + if (unlikely((vma->vm_flags & ~asma->prot_mask) & PROT_MASK)) {
91221 + if (!asma->file) {
91222 + char *name = ASHMEM_NAME_DEF;
91223 + struct file *vmfile;
91225 + if (asma->name[0] != '\0')
91226 + name = asma->name;
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);
91234 + asma->file = vmfile;
91236 + get_file(asma->file);
91238 + shmem_set_file(vma, asma->file);
91239 + vma->vm_flags |= VM_CAN_NONLINEAR;
91242 + mutex_unlock(&ashmem_mutex);
91247 + * ashmem_shrink - our cache shrinker, called from mm/vmscan.c :: shrink_slab
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.
91252 + * 'gfp_mask' is the mask of the allocation that got us into this mess.
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).
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'
91261 +static int ashmem_shrink(int nr_to_scan, gfp_t gfp_mask)
91263 + struct ashmem_range *range, *next;
91265 + /* We might recurse into filesystem code, so bail out if necessary */
91266 + if (nr_to_scan && !(gfp_mask & __GFP_FS))
91269 + return lru_count;
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;
91277 + vmtruncate_range(inode, start, end);
91278 + range->purged = ASHMEM_WAS_PURGED;
91281 + nr_to_scan -= range_size(range);
91282 + if (nr_to_scan <= 0)
91285 + mutex_unlock(&ashmem_mutex);
91287 + return lru_count;
91290 +static struct shrinker ashmem_shrinker = {
91291 + .shrink = ashmem_shrink,
91292 + .seeks = DEFAULT_SEEKS * 4,
91295 +static int set_prot_mask(struct ashmem_area *asma, unsigned long prot)
91299 + mutex_lock(&ashmem_mutex);
91301 + /* the user can only remove, not add, protection bits */
91302 + if (unlikely((asma->prot_mask & prot) != prot)) {
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;
91311 + asma->prot_mask = prot;
91314 + mutex_unlock(&ashmem_mutex);
91318 +static int set_name(struct ashmem_area *asma, void __user *name)
91322 + mutex_lock(&ashmem_mutex);
91324 + /* cannot change an existing mapping's name */
91325 + if (unlikely(asma->file)) {
91330 + if (unlikely(copy_from_user(asma->name, name, ASHMEM_NAME_LEN)))
91332 + asma->name[ASHMEM_NAME_LEN-1] = '\0';
91335 + mutex_unlock(&ashmem_mutex);
91340 +static int get_name(struct ashmem_area *asma, void __user *name)
91344 + mutex_lock(&ashmem_mutex);
91345 + if (asma->name[0] != '\0') {
91349 + * Copying only `len', instead of ASHMEM_NAME_LEN, bytes
91350 + * prevents us from revealing one user's stack to another.
91352 + len = strlen(asma->name) + 1;
91353 + if (unlikely(copy_to_user(name, asma->name, len)))
91356 + if (unlikely(copy_to_user(name, ASHMEM_NAME_DEF,
91357 + sizeof(ASHMEM_NAME_DEF))))
91360 + mutex_unlock(&ashmem_mutex);
91366 + * ashmem_pin - pin the given ashmem region, returning whether it was
91367 + * previously purged (ASHMEM_WAS_PURGED) or not (ASHMEM_NOT_PURGED).
91369 + * Caller must hold ashmem_mutex.
91371 +static int ashmem_pin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
91373 + struct ashmem_range *range, *next;
91374 + int ret = ASHMEM_NOT_PURGED;
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))
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.
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.
91396 + if (page_range_in_range(range, pgstart, pgend)) {
91397 + ret |= range->purged;
91399 + /* Case #1: Easy. Just nuke the whole thing. */
91400 + if (page_range_subsumes_range(range, pgstart, pgend)) {
91401 + range_del(range);
91405 + /* Case #2: We overlap from the start, so adjust it */
91406 + if (range->pgstart >= pgstart) {
91407 + range_shrink(range, pgend + 1, range->pgend);
91411 + /* Case #3: We overlap from the rear, so adjust it */
91412 + if (range->pgend <= pgend) {
91413 + range_shrink(range, range->pgstart, pgstart-1);
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.
91422 + range_alloc(asma, range, range->purged,
91423 + pgend + 1, range->pgend);
91424 + range_shrink(range, range->pgstart, pgstart - 1);
91433 + * ashmem_unpin - unpin the given range of pages. Returns zero on success.
91435 + * Caller must hold ashmem_mutex.
91437 +static int ashmem_unpin(struct ashmem_area *asma, size_t pgstart, size_t pgend)
91439 + struct ashmem_range *range, *next;
91440 + unsigned int purged = ASHMEM_NOT_PURGED;
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))
91449 + * The user can ask us to unpin pages that are already entirely
91450 + * or partially pinned. We handle those two cases here.
91452 + if (page_range_subsumed_by_range(range, pgstart, pgend))
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);
91463 + return range_alloc(asma, range, purged, pgstart, pgend);
91467 + * ashmem_get_pin_status - Returns ASHMEM_IS_UNPINNED if _any_ pages in the
91468 + * given interval are unpinned and ASHMEM_IS_PINNED otherwise.
91470 + * Caller must hold ashmem_mutex.
91472 +static int ashmem_get_pin_status(struct ashmem_area *asma, size_t pgstart,
91475 + struct ashmem_range *range;
91476 + int ret = ASHMEM_IS_PINNED;
91478 + list_for_each_entry(range, &asma->unpinned_list, unpinned) {
91479 + if (range_before_page(range, pgstart))
91481 + if (page_range_in_range(range, pgstart, pgend)) {
91482 + ret = ASHMEM_IS_UNPINNED;
91490 +static int ashmem_pin_unpin(struct ashmem_area *asma, unsigned long cmd,
91493 + struct ashmem_pin pin;
91494 + size_t pgstart, pgend;
91495 + int ret = -EINVAL;
91497 + if (unlikely(!asma->file))
91500 + if (unlikely(copy_from_user(&pin, p, sizeof(pin))))
91503 + /* per custom, you can pass zero for len to mean "everything onward" */
91505 + pin.len = asma->size - pin.offset;
91507 + if (unlikely((pin.offset | pin.len) & ~PAGE_MASK))
91510 + if (unlikely(((__u32) -1) - pin.offset < pin.len))
91513 + if (unlikely(asma->size < pin.offset + pin.len))
91516 + pgstart = pin.offset / PAGE_SIZE;
91517 + pgend = pgstart + (pin.len / PAGE_SIZE) - 1;
91519 + mutex_lock(&ashmem_mutex);
91523 + ret = ashmem_pin(asma, pgstart, pgend);
91525 + case ASHMEM_UNPIN:
91526 + ret = ashmem_unpin(asma, pgstart, pgend);
91528 + case ASHMEM_GET_PIN_STATUS:
91529 + ret = ashmem_get_pin_status(asma, pgstart, pgend);
91533 + mutex_unlock(&ashmem_mutex);
91538 +static long ashmem_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
91540 + struct ashmem_area *asma = file->private_data;
91541 + long ret = -ENOTTY;
91544 + case ASHMEM_SET_NAME:
91545 + ret = set_name(asma, (void __user *) arg);
91547 + case ASHMEM_GET_NAME:
91548 + ret = get_name(asma, (void __user *) arg);
91550 + case ASHMEM_SET_SIZE:
91552 + if (!asma->file && !(arg & ~PAGE_MASK)) {
91554 + asma->size = (size_t) arg;
91557 + case ASHMEM_GET_SIZE:
91558 + ret = asma->size;
91560 + case ASHMEM_SET_PROT_MASK:
91561 + ret = set_prot_mask(asma, arg);
91563 + case ASHMEM_GET_PROT_MASK:
91564 + ret = asma->prot_mask;
91567 + case ASHMEM_UNPIN:
91568 + case ASHMEM_GET_PIN_STATUS:
91569 + ret = ashmem_pin_unpin(asma, cmd, (void __user *) arg);
91571 + case ASHMEM_PURGE_ALL_CACHES:
91573 + if (capable(CAP_SYS_ADMIN)) {
91574 + ret = ashmem_shrink(0, GFP_KERNEL);
91575 + ashmem_shrink(ret, GFP_KERNEL);
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,
91592 +static struct miscdevice ashmem_misc = {
91593 + .minor = MISC_DYNAMIC_MINOR,
91594 + .name = "ashmem",
91595 + .fops = &ashmem_fops,
91598 +static int __init ashmem_init(void)
91602 + ashmem_area_cachep = kmem_cache_create("ashmem_area_cache",
91603 + sizeof(struct ashmem_area),
91605 + if (unlikely(!ashmem_area_cachep)) {
91606 + printk(KERN_ERR "ashmem: failed to create slab cache\n");
91610 + ashmem_range_cachep = kmem_cache_create("ashmem_range_cache",
91611 + sizeof(struct ashmem_range),
91613 + if (unlikely(!ashmem_range_cachep)) {
91614 + printk(KERN_ERR "ashmem: failed to create slab cache\n");
91618 + ret = misc_register(&ashmem_misc);
91619 + if (unlikely(ret)) {
91620 + printk(KERN_ERR "ashmem: failed to register misc device!\n");
91624 + register_shrinker(&ashmem_shrinker);
91626 + printk(KERN_INFO "ashmem: initialized\n");
91631 +static void __exit ashmem_exit(void)
91635 + unregister_shrinker(&ashmem_shrinker);
91637 + ret = misc_deregister(&ashmem_misc);
91638 + if (unlikely(ret))
91639 + printk(KERN_ERR "ashmem: failed to unregister misc device!\n");
91641 + kmem_cache_destroy(ashmem_range_cachep);
91642 + kmem_cache_destroy(ashmem_area_cachep);
91644 + printk(KERN_INFO "ashmem: unloaded\n");
91647 +module_init(ashmem_init);
91648 +module_exit(ashmem_exit);
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
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
91668 + * tiny-shmem.c: simple shmemfs and tmpfs using ramfs code
91670 + * Matt Mackall <mpm@selenic.com> January, 2004
91671 + * derived from mm/shmem.c and fs/ramfs/inode.c
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.
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>
91689 +static struct file_system_type tmpfs_fs_type = {
91691 + .get_sb = ramfs_get_sb,
91692 + .kill_sb = kill_litter_super,
91695 +static struct vfsmount *shm_mnt;
91697 +static int __init init_tmpfs(void)
91699 + BUG_ON(register_filesystem(&tmpfs_fs_type) != 0);
91701 + shm_mnt = kern_mount(&tmpfs_fs_type);
91702 + BUG_ON(IS_ERR(shm_mnt));
91706 +module_init(init_tmpfs)
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
91714 +struct file *shmem_file_setup(char *name, loff_t size, unsigned long flags)
91717 + struct file *file;
91718 + struct inode *inode;
91719 + struct dentry *dentry, *root;
91720 + struct qstr this;
91722 + if (IS_ERR(shm_mnt))
91723 + return (void *)shm_mnt;
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);
91735 + file = get_empty_filp();
91740 + inode = ramfs_get_inode(root->d_sb, S_IFREG | S_IRWXUGO, 0);
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);
91750 +#ifndef CONFIG_MMU
91751 + error = ramfs_nommu_expand_for_mapping(inode, size);
91762 + return ERR_PTR(error);
91764 +EXPORT_SYMBOL_GPL(shmem_file_setup);
91766 +void shmem_set_file(struct vm_area_struct *vma, struct file *file)
91768 + if (vma->vm_file)
91769 + fput(vma->vm_file);
91770 + vma->vm_file = file;
91771 + vma->vm_ops = &generic_file_vm_ops;
91774 +void shmem_set_file(struct vm_area_struct *vma, struct file *file)
91776 + if (vma->vm_file)
91777 + fput(vma->vm_file);
91778 + vma->vm_file = file;
91779 + vma->vm_ops = &generic_file_vm_ops;
91783 + * shmem_zero_setup - setup a shared anonymous mapping
91784 + * @vma: the vma to be mmapped is prepared by do_mmap_pgoff
91786 +int shmem_zero_setup(struct vm_area_struct *vma)
91788 + struct file *file;
91789 + loff_t size = vma->vm_end - vma->vm_start;
91791 + file = shmem_file_setup("dev/zero", size, vma->vm_flags);
91792 + if (IS_ERR(file))
91793 + return PTR_ERR(file);
91795 + shmem_set_file(vma, file);
91800 +int shmem_unuse(swp_entry_t entry, struct page *page)
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)
91812 + return ramfs_nommu_get_unmapped_area(file, addr, len, pgoff, flags);
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
91821 +# automatic kernel updater and reboot - Andy Green <andy@openmoko.com>
91823 +GTA_DEVICE_IP=192.168.0.202
91825 +# you should set up key-based auth on dropbear if you want
91826 +# to play this game.
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/*
91834 +scp uImage.bin root@$GTA_DEVICE_IP:/boot
91835 +ssh root@$GTA_DEVICE_IP "mount /dev/mmcblk0p1 / -oremount,ro ; reboot -if &"
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
91841 if [ -z "${MKIMAGE}" ]; then
91843 echo '"mkimage" command not found - U-Boot images will not be built' >&2
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
91853 u16 *cache = codec->reg_cache;
91854 if (reg >= WM8731_CACHEREGNUM)
91857 + printk(KERN_INFO "%s: reg %d, val %04x\n", __func__, reg, value);
91858 cache[reg] = value;
91865 + printk(KERN_INFO "%s: reg %d val %04x\n", __func__, reg, value);
91868 * D15..D9 WM8731 register offset
91869 * D8...D0 register data
91870 @@ -521,7 +525,11 @@
91871 if (codec->reg_cache == NULL)
91874 - wm8731_reset(codec);
91875 + ret = wm8731_reset(codec);
91877 + printk(KERN_ERR "wm8731: failed to send reset\n");
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
91888 #include "wm8753.h"
91890 -#define WM8753_VERSION "0.16"
91892 static int caps_charge = 2000;
91893 module_param(caps_charge, int, 0);
91894 MODULE_PARM_DESC(caps_charge, "WM8753 cap charge time (msecs)");
91896 static void wm8753_set_dai_mode(struct snd_soc_codec *codec,
91897 unsigned int mode);
91899 -/* codec private data */
91900 -struct wm8753_priv {
91901 - unsigned int sysclk;
91902 - unsigned int pcmclk;
91906 * wm8753 register cache
91907 * We can't read the WM8753 register space when we
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)];
91921 * read wm8753 register cache
91923 @@ -1451,7 +1451,15 @@
91927 -struct snd_soc_dai wm8753_dai[2];
91928 +struct snd_soc_dai wm8753_dai[2] = {
91937 EXPORT_SYMBOL_GPL(wm8753_dai);
91939 static void wm8753_set_dai_mode(struct snd_soc_codec *codec, unsigned int mode)
91940 @@ -1459,30 +1467,35 @@
91942 int playback_active, capture_active, codec_active, pop_wait;
91943 void *private_data;
91944 + struct list_head list;
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;
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;
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)
91981 + /* No point in writing hardware default values back */
91982 + if (cache[i] == wm8753_reg[i])
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 @@
91992 +static struct snd_soc_codec *wm8753_codec;
91994 +static int wm8753_probe(struct platform_device *pdev)
91996 + struct snd_soc_device *socdev = platform_get_drvdata(pdev);
91997 + struct snd_soc_codec *codec;
92000 + if (!wm8753_codec) {
92001 + dev_err(&pdev->dev, "WM8753 codec not yet registered\n");
92005 + socdev->codec = wm8753_codec;
92006 + codec = wm8753_codec;
92008 + wm8753_set_dai_mode(codec, 0);
92010 + /* register pcms */
92011 + ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
92013 + printk(KERN_ERR "wm8753: failed to create pcms\n");
92017 + wm8753_add_controls(codec);
92018 + wm8753_add_widgets(codec);
92019 + ret = snd_soc_init_card(socdev);
92021 + printk(KERN_ERR "wm8753: failed to register card\n");
92028 + snd_soc_free_pcms(socdev);
92029 + snd_soc_dapm_free(socdev);
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.
92040 -static int wm8753_init(struct snd_soc_device *socdev)
92041 +static int run_delayed_work(struct delayed_work *dwork)
92043 - struct snd_soc_codec *codec = socdev->codec;
92044 - int reg, ret = 0;
92047 + /* cancel any work waiting to be queued. */
92048 + ret = cancel_delayed_work(dwork);
92050 + /* if there was any work waiting then we run it now and
92051 + * wait for it's completion */
92053 + schedule_delayed_work(dwork, 0);
92054 + flush_scheduled_work();
92059 +/* power down chip */
92060 +static int wm8753_remove(struct platform_device *pdev)
92062 + struct snd_soc_device *socdev = platform_get_drvdata(pdev);
92064 + snd_soc_free_pcms(socdev);
92065 + snd_soc_dapm_free(socdev);
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,
92076 +EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
92078 +static int wm8753_register(struct wm8753_priv *wm8753)
92081 + struct snd_soc_codec *codec = &wm8753->codec;
92084 + if (wm8753_codec) {
92085 + dev_err(codec->dev, "Multiple WM8753 devices not supported\n");
92090 + mutex_init(&codec->mutex);
92091 + INIT_LIST_HEAD(&codec->dapm_widgets);
92092 + INIT_LIST_HEAD(&codec->dapm_paths);
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);
92105 - if (codec->reg_cache == NULL)
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;
92113 - wm8753_reset(codec);
92114 + memcpy(codec->reg_cache, wm8753_reg, sizeof(codec->reg_cache));
92115 + INIT_DELAYED_WORK(&codec->delayed_work, wm8753_work);
92117 - /* register pcms */
92118 - ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
92119 + ret = wm8753_reset(codec);
92121 - printk(KERN_ERR "wm8753: failed to create pcms\n");
92123 + dev_err(codec->dev, "Failed to issue reset\n");
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));
92134 + /* OpenMoko specific bodge for
92135 + * http://bugzilla.openmoko.org/cgi-bin/bugzilla/show_bug.cgi?id=1172
92137 + wm8753_write(codec, WM8753_ADCTL2, 0x0000);
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);
92145 - wm8753_add_controls(codec);
92146 - wm8753_add_widgets(codec);
92147 - ret = snd_soc_init_card(socdev);
92149 - printk(KERN_ERR "wm8753: failed to register card\n");
92151 + wm8753_codec = codec;
92153 + for (i = 0; i < ARRAY_SIZE(wm8753_dai); i++)
92154 + wm8753_dai[i].dev = codec->dev;
92156 + ret = snd_soc_register_codec(codec);
92158 + dev_err(codec->dev, "Failed to register codec: %d\n", ret);
92163 + ret = snd_soc_register_dais(&wm8753_dai[0], ARRAY_SIZE(wm8753_dai));
92165 + dev_err(codec->dev, "Failed to register DAIs: %d\n", ret);
92170 - snd_soc_free_pcms(socdev);
92171 - snd_soc_dapm_free(socdev);
92173 - kfree(codec->reg_cache);
92177 + run_delayed_work(&codec->delayed_work);
92178 + snd_soc_unregister_codec(codec);
92184 -/* If the i2c layer weren't so broken, we could pass this kind of data
92186 -static struct snd_soc_device *wm8753_socdev;
92187 +static void wm8753_unregister(struct wm8753_priv *wm8753)
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);
92194 + wm8753_codec = NULL;
92197 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
92200 - * WM8753 2 wire address is determined by GPIO5
92201 - * state during powerup.
92206 static int wm8753_i2c_probe(struct i2c_client *i2c,
92207 const struct i2c_device_id *id)
92209 - struct snd_soc_device *socdev = wm8753_socdev;
92210 - struct snd_soc_codec *codec = socdev->codec;
92212 + struct snd_soc_codec *codec;
92213 + struct wm8753_priv *wm8753;
92215 - i2c_set_clientdata(i2c, codec);
92216 + wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
92217 + if (wm8753 == NULL)
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);
92225 - ret = wm8753_init(socdev);
92227 - pr_err("failed to initialise WM8753\n");
92228 + codec->dev = &i2c->dev;
92231 + return wm8753_register(wm8753);
92234 static int wm8753_i2c_remove(struct i2c_client *client)
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);
92243 @@ -1666,86 +1784,16 @@
92245 static struct i2c_driver wm8753_i2c_driver = {
92247 - .name = "WM8753 I2C Codec",
92248 + .name = "wm8753",
92249 .owner = THIS_MODULE,
92251 .probe = wm8753_i2c_probe,
92252 .remove = wm8753_i2c_remove,
92253 .id_table = wm8753_i2c_id,
92256 -static int wm8753_add_i2c_device(struct platform_device *pdev,
92257 - const struct wm8753_setup_data *setup)
92259 - struct i2c_board_info info;
92260 - struct i2c_adapter *adapter;
92261 - struct i2c_client *client;
92264 - ret = i2c_add_driver(&wm8753_i2c_driver);
92266 - dev_err(&pdev->dev, "can't add i2c driver\n");
92270 - memset(&info, 0, sizeof(struct i2c_board_info));
92271 - info.addr = setup->i2c_address;
92272 - strlcpy(info.type, "wm8753", I2C_NAME_SIZE);
92274 - adapter = i2c_get_adapter(setup->i2c_bus);
92276 - dev_err(&pdev->dev, "can't get i2c adapter %d\n",
92281 - client = i2c_new_device(adapter, &info);
92282 - i2c_put_adapter(adapter);
92284 - dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
92285 - (unsigned int)info.addr);
92292 - i2c_del_driver(&wm8753_i2c_driver);
92297 #if defined(CONFIG_SPI_MASTER)
92298 -static int __devinit wm8753_spi_probe(struct spi_device *spi)
92300 - struct snd_soc_device *socdev = wm8753_socdev;
92301 - struct snd_soc_codec *codec = socdev->codec;
92304 - codec->control_data = spi;
92306 - ret = wm8753_init(socdev);
92308 - dev_err(&spi->dev, "failed to initialise WM8753\n");
92313 -static int __devexit wm8753_spi_remove(struct spi_device *spi)
92318 -static struct spi_driver wm8753_spi_driver = {
92320 - .name = "wm8753",
92321 - .bus = &spi_bus_type,
92322 - .owner = THIS_MODULE,
92324 - .probe = wm8753_spi_probe,
92325 - .remove = __devexit_p(wm8753_spi_remove),
92328 static int wm8753_spi_write(struct spi_device *spi, const char *data, int len)
92330 struct spi_transfer t;
92331 @@ -1769,120 +1817,69 @@
92338 -static int wm8753_probe(struct platform_device *pdev)
92339 +static int __devinit wm8753_spi_probe(struct spi_device *spi)
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;
92347 - pr_info("WM8753 Audio Codec %s", WM8753_VERSION);
92349 - setup = socdev->codec_data;
92350 - codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
92351 - if (codec == NULL)
92354 wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
92355 - if (wm8753 == NULL) {
92357 + if (wm8753 == NULL)
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;
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);
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);
92384 - printk(KERN_ERR "can't add spi driver");
92387 + spi->dev.driver_data = wm8753;
92390 - kfree(codec->private_data);
92394 + return wm8753_register(wm8753);
92398 - * This function forces any delayed work to be queued and run.
92400 -static int run_delayed_work(struct delayed_work *dwork)
92401 +static int __devexit wm8753_spi_remove(struct spi_device *spi)
92405 - /* cancel any work waiting to be queued. */
92406 - ret = cancel_delayed_work(dwork);
92408 - /* if there was any work waiting then we run it now and
92409 - * wait for it's completion */
92411 - schedule_delayed_work(dwork, 0);
92412 - flush_scheduled_work();
92415 + struct wm8753_priv *wm8753 = spi->dev.driver_data;
92416 + wm8753_unregister(wm8753);
92420 -/* power down chip */
92421 -static int wm8753_remove(struct platform_device *pdev)
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 = {
92427 + .name = "wm8753",
92428 + .bus = &spi_bus_type,
92429 + .owner = THIS_MODULE,
92431 + .probe = wm8753_spi_probe,
92432 + .remove = __devexit_p(wm8753_spi_remove),
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)
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);
92449 + pr_err("Failed to register WM8753 I2C driver: %d\n", ret);
92451 #if defined(CONFIG_SPI_MASTER)
92452 - spi_unregister_driver(&wm8753_spi_driver);
92453 + ret = spi_register_driver(&wm8753_spi_driver);
92455 + pr_err("Failed to register WM8753 SPI driver: %d\n", ret);
92457 - kfree(codec->private_data);
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,
92469 -EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
92471 -static int __init wm8753_modinit(void)
92473 - return snd_soc_register_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
92475 module_init(wm8753_modinit);
92477 static void __exit wm8753_exit(void)
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);
92483 +#if defined(CONFIG_SPI_MASTER)
92484 + spi_unregister_driver(&wm8753_spi_driver);
92487 module_exit(wm8753_exit);
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
92493 #define WM8753_BIASCTL 0x3d
92494 #define WM8753_ADCTL2 0x3f
92496 -struct wm8753_setup_data {
92499 - unsigned short i2c_address;
92502 #define WM8753_PLL1 0
92503 #define WM8753_PLL2 1
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
92509 +/* sound/soc/s3c24xx/jive_wm8750.c
92511 + * Copyright 2007,2008 Simtec Electronics
92513 + * Based on sound/soc/pxa/spitz.c
92514 + * Copyright 2005 Wolfson Microelectronics PLC.
92515 + * Copyright 2005 Openedhand Ltd.
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.
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>
92529 +#include <sound/core.h>
92530 +#include <sound/pcm.h>
92531 +#include <sound/soc.h>
92532 +#include <sound/soc-dapm.h>
92534 +#include <asm/mach-types.h>
92536 +#include "s3c24xx-pcm.h"
92537 +#include "s3c2412-i2s.h"
92539 +#include "../codecs/wm8750.h"
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" },
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),
92556 +static int jive_startup(struct snd_pcm_substream *substream)
92558 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
92559 + struct snd_soc_codec *codec = rtd->socdev->codec;
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");
92565 + snd_soc_dapm_sync(codec);
92570 +static int jive_hw_params(struct snd_pcm_substream *substream,
92571 + struct snd_pcm_hw_params *params)
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;
92580 + switch (params_rate(params)) {
92594 + s3c_i2sv2_calc_rate(&div, NULL, params_rate(params),
92595 + s3c2412_get_iisclk());
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);
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);
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);
92617 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_RCLK, div.fs_div);
92621 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C2412_DIV_PRESCALER,
92622 + div.clk_div - 1);
92629 +static struct snd_soc_ops jive_ops = {
92630 + .startup = jive_startup,
92631 + .hw_params = jive_hw_params,
92634 +static int jive_wm8750_init(struct snd_soc_codec *codec)
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");
92646 + /* Add jive specific widgets */
92647 + err = snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets,
92648 + ARRAY_SIZE(wm8750_dapm_widgets));
92650 + printk(KERN_ERR "%s: failed to add widgets (%d)\n",
92655 + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
92656 + snd_soc_dapm_sync(codec);
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,
92670 +/* jive audio machine driver */
92671 +static struct snd_soc_machine snd_soc_machine_jive = {
92673 + .dai_link = &jive_dai,
92677 +/* jive audio private data */
92678 +static struct wm8750_setup_data jive_wm8750_setup = {
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,
92689 +static struct platform_device *jive_snd_device;
92691 +static int __init jive_init(void)
92695 + if (!machine_is_jive())
92698 + printk("JIVE WM8750 Audio support\n");
92700 + jive_snd_device = platform_device_alloc("soc-audio", -1);
92701 + if (!jive_snd_device)
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);
92709 + platform_device_put(jive_snd_device);
92714 +static void __exit jive_exit(void)
92716 + platform_device_unregister(jive_snd_device);
92719 +module_init(jive_init);
92720 +module_exit(jive_exit);
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
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
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
92737 config SND_S3C24XX_SOC_I2S
92740 +config SND_S3C_I2SV2_SOC
92743 config SND_S3C2412_SOC_I2S
92745 + select SND_S3C_I2SV2_SOC
92747 +config SND_S3C64XX_SOC_I2S
92749 + select SND_S3C_I2SV2_SOC
92751 config SND_S3C2443_SOC_AC97
92754 Say Y if you want to add support for SoC audio on smdk2440
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
92764 + Sat Y if you want to add support for SoC audio on the Jive.
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
92772 + Say Y if you want to add support for SoC audio on neo1973 gta02
92773 + with the WM8753 codec
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
92781 + Say Y if you want support for SoC audio on Openmoko 3D7K
92782 + with the WM8753 codec.
92784 config SND_S3C24XX_SOC_SMDK2443_WM9710
92785 tristate "SoC AC97 Audio support for SMDK2443 - WM9710"
92786 depends on SND_S3C24XX_SOC && MACH_SMDK2443
92788 depends on SND_S3C24XX_SOC
92789 select SND_S3C24XX_SOC_I2S
92790 select SND_SOC_UDA134X
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
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
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
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
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
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
92840 + * neo1973_gta02_wm8753.c -- SoC audio for Neo1973
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
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.
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>
92864 +#include <asm/mach-types.h>
92866 +#include <plat/regs-iis.h>
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"
92878 +static struct snd_soc_card neo1973_gta02;
92880 +static int neo1973_gta02_hifi_hw_params(struct snd_pcm_substream *substream,
92881 + struct snd_pcm_hw_params *params)
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;
92888 + unsigned long iis_clkrate;
92890 + iis_clkrate = s3c24xx_i2s_get_clockrate();
92892 + switch (params_rate(params)) {
92895 + pll_out = 12288000;
92898 + bclk = WM8753_BCLK_DIV_4;
92899 + pll_out = 12288000;
92902 + bclk = WM8753_BCLK_DIV_2;
92903 + pll_out = 12288000;
92906 + bclk = WM8753_BCLK_DIV_16;
92907 + pll_out = 11289600;
92910 + bclk = WM8753_BCLK_DIV_8;
92911 + pll_out = 11289600;
92914 + bclk = WM8753_BCLK_DIV_4;
92915 + pll_out = 11289600;
92918 + bclk = WM8753_BCLK_DIV_2;
92919 + pll_out = 11289600;
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);
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);
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);
92943 + /* set MCLK division for sample rate */
92944 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
92945 + S3C2410_IISMOD_32FS);
92949 + /* set codec BCLK division for sample rate */
92950 + ret = snd_soc_dai_set_clkdiv(codec_dai,
92951 + WM8753_BCLKDIV, bclk);
92955 + /* set prescaler division for sample rate */
92956 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
92957 + S3C24XX_PRESCALE(4, 4));
92961 + /* codec PLL input is PCLK/4 */
92962 + ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
92963 + iis_clkrate / 4, pll_out);
92970 +static int neo1973_gta02_hifi_hw_free(struct snd_pcm_substream *substream)
92972 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
92973 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
92975 + /* disable the PLL */
92976 + return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
92980 + * Neo1973 WM8753 HiFi DAI opserations.
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,
92987 +static int neo1973_gta02_voice_hw_params(
92988 + struct snd_pcm_substream *substream,
92989 + struct snd_pcm_hw_params *params)
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;
92995 + unsigned long iis_clkrate;
92997 + iis_clkrate = s3c24xx_i2s_get_clockrate();
92999 + if (params_rate(params) != 8000)
93001 + if (params_channels(params) != 1)
93004 + pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
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);
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);
93019 + /* set codec PCM division for sample rate */
93020 + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV,
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);
93034 +static int neo1973_gta02_voice_hw_free(struct snd_pcm_substream *substream)
93036 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
93037 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
93039 + /* disable the PLL */
93040 + return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
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,
93048 +#define LM4853_AMP 1
93049 +#define LM4853_SPK 2
93051 +static u8 lm4853_state;
93053 +/* This has no effect, it exists only to maintain compatibility with
93054 + * existing ALSA state files.
93056 +static int lm4853_set_state(struct snd_kcontrol *kcontrol,
93057 + struct snd_ctl_elem_value *ucontrol)
93059 + int val = ucontrol->value.integer.value[0];
93062 + lm4853_state |= LM4853_AMP;
93064 + lm4853_state &= ~LM4853_AMP;
93069 +static int lm4853_get_state(struct snd_kcontrol *kcontrol,
93070 + struct snd_ctl_elem_value *ucontrol)
93072 + ucontrol->value.integer.value[0] = lm4853_state & LM4853_AMP;
93077 +static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
93078 + struct snd_ctl_elem_value *ucontrol)
93080 + int val = ucontrol->value.integer.value[0];
93083 + lm4853_state |= LM4853_SPK;
93084 + s3c2410_gpio_setpin(GTA02_GPIO_HP_IN, 0);
93086 + lm4853_state &= ~LM4853_SPK;
93087 + s3c2410_gpio_setpin(GTA02_GPIO_HP_IN, 1);
93093 +static int lm4853_get_spk(struct snd_kcontrol *kcontrol,
93094 + struct snd_ctl_elem_value *ucontrol)
93096 + ucontrol->value.integer.value[0] = (lm4853_state & LM4853_SPK) >> 1;
93101 +static int lm4853_event(struct snd_soc_dapm_widget *w,
93102 + struct snd_kcontrol *k,
93105 + if (SND_SOC_DAPM_EVENT_ON(event))
93106 + s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT, 0);
93108 + if (SND_SOC_DAPM_EVENT_OFF(event))
93109 + s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT, 1);
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),
93124 +/* example machine audio_mapnections */
93125 +static const struct snd_soc_dapm_route audio_map[] = {
93127 + /* Connections to the lm4853 amp */
93128 + {"Stereo Out", NULL, "LOUT1"},
93129 + {"Stereo Out", NULL, "ROUT1"},
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"},
93137 + /* Connections to Headset */
93138 + {"MIC1", NULL, "Mic Bias"},
93139 + {"Mic Bias", NULL, "Headset Mic"},
93142 + {"MIC2", NULL, "Mic Bias"},
93143 + {"MIC2N", NULL, "Mic Bias"},
93144 + {"Mic Bias", NULL, "Handset Mic"},
93146 + /* Call Speaker */
93147 + {"Handset Spk", NULL, "LOUT2"},
93148 + {"Handset Spk", NULL, "ROUT2"},
93150 + /* Connect the ALC pins */
93151 + {"ACIN", NULL, "ACOP"},
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"),
93162 + /* This has no effect, it exists only to maintain compatibility with
93163 + * existing ALSA state files.
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,
93174 + * This is an example machine initialisation for a wm8753 connected to a
93177 +static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
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");
93187 + /* Add neo1973 gta02 specific widgets */
93188 + snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
93189 + ARRAY_SIZE(wm8753_dapm_widgets));
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],
93200 + /* set up neo1973 gta02 specific audio path audio_map */
93201 + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
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");
93211 + snd_soc_dapm_sync(codec);
93219 +static struct snd_soc_dai bt_dai = {
93220 + .name = "Bluetooth",
93223 + .channels_min = 1,
93224 + .channels_max = 1,
93225 + .rates = SNDRV_PCM_RATE_8000,
93226 + .formats = SNDRV_PCM_FMTBIT_S16_LE,},
93228 + .channels_min = 1,
93229 + .channels_max = 1,
93230 + .rates = SNDRV_PCM_RATE_8000,
93231 + .formats = SNDRV_PCM_FMTBIT_S16_LE,},
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,
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,
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),
93259 +static struct snd_soc_device neo1973_gta02_snd_devdata = {
93260 + .card = &neo1973_gta02,
93261 + .codec_dev = &soc_codec_dev_wm8753,
93264 +static struct platform_device *neo1973_gta02_snd_device;
93266 +static int __init neo1973_gta02_init(void)
93270 + if (!machine_is_neo1973_gta02()) {
93272 + "Only GTA02 is supported by this ASoC driver\n");
93276 + /* register bluetooth DAI here */
93277 + ret = snd_soc_register_dai(&bt_dai);
93281 + neo1973_gta02_snd_device = platform_device_alloc("soc-audio", -1);
93282 + if (!neo1973_gta02_snd_device)
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);
93291 + platform_device_put(neo1973_gta02_snd_device);
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);
93299 + /* Amp off by default */
93300 + s3c2410_gpio_setpin(GTA02_GPIO_AMP_SHUT, 1);
93302 + /* Speaker off by default */
93303 + s3c2410_gpio_setpin(GTA02_GPIO_HP_IN, 1);
93307 +module_init(neo1973_gta02_init);
93309 +static void __exit neo1973_gta02_exit(void)
93311 + snd_soc_unregister_dai(&bt_dai);
93312 + platform_device_unregister(neo1973_gta02_snd_device);
93314 +module_exit(neo1973_gta02_exit);
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>
93332 -#include <asm/plat-s3c24xx/regs-iis.h>
93333 +#include <plat/regs-iis.h>
93335 #include "../codecs/wm8753.h"
93336 #include "lm4857.h"
93337 @@ -585,15 +585,9 @@
93338 .num_links = ARRAY_SIZE(neo1973_dai),
93341 -static struct wm8753_setup_data neo1973_wm8753_setup = {
93343 - .i2c_address = 0x1a,
93346 static struct snd_soc_device neo1973_snd_devdata = {
93348 .codec_dev = &soc_codec_dev_wm8753,
93349 - .codec_data = &neo1973_wm8753_setup,
93352 static int lm4857_i2c_probe(struct i2c_client *client,
93353 @@ -652,13 +646,13 @@
93356 static const struct i2c_device_id lm4857_i2c_id[] = {
93357 - { "neo1973_lm4857", 0 },
93362 static struct i2c_driver lm4857_i2c_driver = {
93364 - .name = "LM4857 I2C Amp",
93365 + .name = "lm4857",
93366 .owner = THIS_MODULE,
93368 .suspend = lm4857_suspend,
93369 @@ -675,7 +669,7 @@
93373 - DBG("Entered %s\n", __func__);
93374 + printk(KERN_DEBUG "Entered %s\n", __func__);
93376 if (!machine_is_neo1973_gta01()) {
93378 @@ -683,6 +677,11 @@
93382 + /* register bluetooth DAI here */
93383 + ret = snd_soc_register_dai(&bt_dai);
93387 neo1973_snd_device = platform_device_alloc("soc-audio", -1);
93388 if (!neo1973_snd_device)
93390 @@ -708,6 +707,7 @@
93392 DBG("Entered %s\n", __func__);
93394 + snd_soc_unregister_dai(&bt_dai);
93395 i2c_del_driver(&lm4857_i2c_driver);
93396 platform_device_unregister(neo1973_snd_device);
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
93403 + * om_3d7k_wm8753.c -- SoC audio for 3D7K
93405 + * Based on neo1973_gta02_wm8753
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>
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.
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>
93431 +#include <asm/mach-types.h>
93432 +#include <asm/hardware/scoop.h>
93434 +#include <plat/regs-s3c2412-iis.h>
93436 +#include "../codecs/wm8753.h"
93437 +#include "s3c24xx-pcm.h"
93438 +#include "s3c64xx-i2s.h"
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
93452 +static struct snd_soc_card om_3d7k;
93454 +static int om_3d7k_hifi_hw_params(struct snd_pcm_substream *substream,
93455 + struct snd_pcm_hw_params *params)
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;
93462 + unsigned long iis_clkrate;
93464 + iis_clkrate = s3c64xx_i2s_get_clockrate(cpu_dai);
93466 + switch (params_rate(params)) {
93469 + pll_out = 12288000;
93472 + bclk = WM8753_BCLK_DIV_4;
93473 + pll_out = 12288000;
93476 + bclk = WM8753_BCLK_DIV_2;
93477 + pll_out = 12288000;
93480 + bclk = WM8753_BCLK_DIV_16;
93481 + pll_out = 11289600;
93484 + bclk = WM8753_BCLK_DIV_8;
93485 + pll_out = 11289600;
93488 + bclk = WM8753_BCLK_DIV_4;
93489 + pll_out = 11289600;
93492 + bclk = WM8753_BCLK_DIV_2;
93493 + pll_out = 11289600;
93497 + ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_MUX, 0,
93498 + SND_SOC_CLOCK_OUT);
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);
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);
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);
93523 + /* do not think we need to set this if the cpu is not the bitclk
93525 + /* set MCLK division for sample rate */
93526 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK,
93527 + S3C2410_IISMOD_32FS);
93532 + /* set codec BCLK division for sample rate */
93533 + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_BCLKDIV, bclk);
93537 + /* set prescaler division for sample rate */
93538 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C64XX_DIV_PRESCALER, 2-1);
93542 + /* codec PLL input is ACLK/2 */
93543 + ret = snd_soc_dai_set_pll(codec_dai, WM8753_PLL1,
93544 + iis_clkrate / 2, pll_out);
93551 + printk(KERN_ERR "%s: failed %d\n", __func__, ret);
93555 +static int om_3d7k_hifi_hw_free(struct snd_pcm_substream *substream)
93557 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
93558 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
93560 + /* disable the PLL */
93561 + return snd_soc_dai_set_pll(codec_dai, WM8753_PLL1, 0, 0);
93565 + * 3D7K WM8753 HiFi DAI opserations.
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,
93572 +static int om_3d7k_voice_hw_params(struct snd_pcm_substream *substream,
93573 + struct snd_pcm_hw_params *params)
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;
93579 + unsigned long iis_clkrate;
93581 + iis_clkrate = s3c64xx_i2s_get_clockrate(rtd->dai->cpu_dai);
93583 + if (params_rate(params) != 8000)
93585 + if (params_channels(params) != 1)
93588 + pcmdiv = WM8753_PCM_DIV_6; /* 2.048 MHz */
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));
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);
93604 + /* set codec PCM division for sample rate */
93605 + ret = snd_soc_dai_set_clkdiv(codec_dai, WM8753_PCMDIV, pcmdiv);
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);
93618 +static int om_3d7k_voice_hw_free(struct snd_pcm_substream *substream)
93620 + struct snd_soc_pcm_runtime *rtd = substream->private_data;
93621 + struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
93623 + /* disable the PLL */
93624 + return snd_soc_dai_set_pll(codec_dai, WM8753_PLL2, 0, 0);
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,
93632 +static int om_3d7k_set_stereo_out(struct snd_kcontrol *kcontrol,
93633 + struct snd_ctl_elem_value *ucontrol)
93635 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93636 + int val = ucontrol->value.integer.value[0];
93638 + snd_soc_dapm_set_endpoint(codec, "Stereo Out", val);
93639 + snd_soc_dapm_sync(codec);
93644 +static int om_3d7k_get_stereo_out(struct snd_kcontrol *kcontrol,
93645 + struct snd_ctl_elem_value *ucontrol)
93647 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93649 + ucontrol->value.integer.value[0] =
93650 + snd_soc_dapm_get_endpoint(codec, "Stereo Out");
93656 +static int om_3d7k_set_gsm_out(struct snd_kcontrol *kcontrol,
93657 + struct snd_ctl_elem_value *ucontrol)
93659 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93660 + int val = ucontrol->value.integer.value[0];
93662 + snd_soc_dapm_set_endpoint(codec, "GSM Line Out", val);
93663 + snd_soc_dapm_sync(codec);
93668 +static int om_3d7k_get_gsm_out(struct snd_kcontrol *kcontrol,
93669 + struct snd_ctl_elem_value *ucontrol)
93671 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93673 + ucontrol->value.integer.value[0] =
93674 + snd_soc_dapm_get_endpoint(codec, "GSM Line Out");
93679 +static int om_3d7k_set_gsm_in(struct snd_kcontrol *kcontrol,
93680 + struct snd_ctl_elem_value *ucontrol)
93682 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93683 + int val = ucontrol->value.integer.value[0];
93685 + snd_soc_dapm_set_endpoint(codec, "GSM Line In", val);
93686 + snd_soc_dapm_sync(codec);
93691 +static int om_3d7k_get_gsm_in(struct snd_kcontrol *kcontrol,
93692 + struct snd_ctl_elem_value *ucontrol)
93694 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93696 + ucontrol->value.integer.value[0] =
93697 + snd_soc_dapm_get_endpoint(codec, "GSM Line In");
93702 +static int om_3d7k_set_headset_mic(struct snd_kcontrol *kcontrol,
93703 + struct snd_ctl_elem_value *ucontrol)
93705 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93706 + int val = ucontrol->value.integer.value[0];
93708 + snd_soc_dapm_set_endpoint(codec, "Headset Mic", val);
93709 + snd_soc_dapm_sync(codec);
93714 +static int om_3d7k_get_headset_mic(struct snd_kcontrol *kcontrol,
93715 + struct snd_ctl_elem_value *ucontrol)
93717 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93719 + ucontrol->value.integer.value[0] =
93720 + snd_soc_dapm_get_endpoint(codec, "Headset Mic");
93725 +static int om_3d7k_set_handset_mic(struct snd_kcontrol *kcontrol,
93726 + struct snd_ctl_elem_value *ucontrol)
93728 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93729 + int val = ucontrol->value.integer.value[0];
93731 + snd_soc_dapm_set_endpoint(codec, "Handset Mic", val);
93733 + snd_soc_dapm_sync(codec);
93738 +static int om_3d7k_get_handset_mic(struct snd_kcontrol *kcontrol,
93739 + struct snd_ctl_elem_value *ucontrol)
93741 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93743 + ucontrol->value.integer.value[0] =
93744 + snd_soc_dapm_get_endpoint(codec, "Handset Mic");
93749 +static int om_3d7k_set_handset_spk(struct snd_kcontrol *kcontrol,
93750 + struct snd_ctl_elem_value *ucontrol)
93752 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93753 + int val = ucontrol->value.integer.value[0];
93755 + snd_soc_dapm_set_endpoint(codec, "Handset Spk", val);
93757 + snd_soc_dapm_sync(codec);
93762 +static int om_3d7k_get_handset_spk(struct snd_kcontrol *kcontrol,
93763 + struct snd_ctl_elem_value *ucontrol)
93765 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93767 + ucontrol->value.integer.value[0] =
93768 + snd_soc_dapm_get_endpoint(codec, "Handset Spk");
93773 +static int om_3d7k_set_headset_spk(struct snd_kcontrol *kcontrol,
93774 + struct snd_ctl_elem_value *ucontrol)
93776 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93777 + int val = ucontrol->value.integer.value[0];
93779 + snd_soc_dapm_set_endpoint(codec, "Headset Spk", val);
93781 + snd_soc_dapm_sync(codec);
93786 +static int om_3d7k_get_headset_spk(struct snd_kcontrol *kcontrol,
93787 + struct snd_ctl_elem_value *ucontrol)
93789 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
93791 + ucontrol->value.integer.value[0] =
93792 + snd_soc_dapm_get_endpoint(codec, "Headset Spk");
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),
93808 +/* example machine audio_mapnections */
93809 +static const struct snd_soc_dapm_route audio_map[] = {
93811 + {"Stereo Out", NULL, "LOUT2"},
93812 + {"Stereo Out", NULL, "ROUT2"},
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"},
93820 + /* Connections to Headset */
93821 + {"MIC1", NULL, "Mic Bias"},
93822 + {"Mic Bias", NULL, "Headset Mic"},
93825 + {"MIC2", NULL, "Mic Bias"},
93826 + {"MIC2N", NULL, "Mic Bias"},
93827 + {"Mic Bias", NULL, "Handset Mic"},
93829 + /* Call Speaker */
93830 + {"Handset Spk", NULL, "OUT3"},
93831 + {"Handset Spk", NULL, "LOUT1"},
93833 + {"Headset Spk", NULL, "ROUT1"},
93834 + {"Headset Spk", NULL, "LOUT1"},
93836 + /* Connect the ALC pins */
93837 + {"ACIN", NULL, "ACOP"},
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),
93865 + * This is an example machine initialisation for a wm8753 connected to a
93868 +static int om_3d7k_wm8753_init(struct snd_soc_codec *codec)
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);
93878 + /* Add neo1973 gta02 specific widgets */
93879 + snd_soc_dapm_new_controls(codec, wm8753_dapm_widgets,
93880 + ARRAY_SIZE(wm8753_dapm_widgets));
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],
93891 + /* set up neo1973 gta02 specific audio path audio_mapnects */
93892 + snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
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);
93903 + snd_soc_dapm_sync(codec);
93911 +static struct snd_soc_dai bt_dai =
93912 +{ .name = "Bluetooth",
93915 + .channels_min = 1,
93916 + .channels_max = 1,
93917 + .rates = SNDRV_PCM_RATE_8000,
93918 + .formats = SNDRV_PCM_FMTBIT_S16_LE,
93921 + .channels_min = 1,
93922 + .channels_max = 1,
93923 + .rates = SNDRV_PCM_RATE_8000,
93924 + .formats = SNDRV_PCM_FMTBIT_S16_LE,
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,
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,
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),
93953 +static struct snd_soc_device om_3d7k_snd_devdata = {
93954 + .card = &om_3d7k,
93955 + .codec_dev = &soc_codec_dev_wm8753,
93958 +static struct platform_device *om_3d7k_snd_device;
93960 +static int __init om_3d7k_init(void)
93964 + if (!machine_is_om_3d7k()) {
93965 + printk(KERN_INFO "Only 3D7K supported by ASoC driver\n");
93969 + /* register bluetooth DAI here */
93970 + ret = snd_soc_register_dai(&bt_dai);
93974 + om_3d7k_snd_device = platform_device_alloc("soc-audio", 1);
93975 + if (!om_3d7k_snd_device)
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);
93983 + platform_device_put(om_3d7k_snd_device);
93990 +static void __exit om_3d7k_exit(void)
93992 + platform_device_unregister(om_3d7k_snd_device);
93995 +module_init(om_3d7k_init);
93996 +module_exit(om_3d7k_exit);
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
94006 #include <linux/delay.h>
94007 #include <linux/clk.h>
94008 #include <linux/kernel.h>
94009 +#include <linux/io.h>
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>
94017 -#include <linux/io.h>
94018 -#include <asm/dma.h>
94020 -#include <asm/plat-s3c24xx/regs-s3c2412-iis.h>
94021 +#include <plat/regs-s3c2412-iis.h>
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>
94029 #include "s3c24xx-pcm.h"
94030 #include "s3c2412-i2s.h"
94032 #define S3C2412_I2S_DEBUG 0
94033 -#define S3C2412_I2S_DEBUG_CON 0
94035 #if S3C2412_I2S_DEBUG
94036 #define DBG(x...) printk(KERN_INFO x)
94037 @@ -73,431 +70,7 @@
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;
94048 - u32 suspend_iismod;
94049 - u32 suspend_iiscon;
94050 - u32 suspend_iispsr;
94053 -static struct s3c2412_i2s_info s3c2412_i2s;
94055 -#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
94057 -#if S3C2412_I2S_DEBUG_CON
94058 -static void dbg_showcon(const char *fn, u32 con)
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));
94067 - printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n",
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));
94079 -static inline void dbg_showcon(const char *fn, u32 con)
94084 -/* Turn on or off the transmission path. */
94085 -static void s3c2412_snd_txctrl(int on)
94087 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
94088 - void __iomem *regs = i2s->regs;
94089 - u32 fic, con, mod;
94091 - DBG("%s(%d)\n", __func__, on);
94093 - fic = readl(regs + S3C2412_IISFIC);
94094 - con = readl(regs + S3C2412_IISCON);
94095 - mod = readl(regs + S3C2412_IISMOD);
94097 - DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
94100 - con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
94101 - con &= ~S3C2412_IISCON_TXDMA_PAUSE;
94102 - con &= ~S3C2412_IISCON_TXCH_PAUSE;
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 */
94110 - case S3C2412_IISMOD_MODE_RXONLY:
94111 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94112 - mod |= S3C2412_IISMOD_MODE_TXRX;
94116 - dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n");
94119 - writel(con, regs + S3C2412_IISCON);
94120 - writel(mod, regs + S3C2412_IISMOD);
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.
94127 - con |= S3C2412_IISCON_TXDMA_PAUSE;
94128 - con |= S3C2412_IISCON_TXCH_PAUSE;
94129 - con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
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;
94137 - case S3C2412_IISMOD_MODE_TXONLY:
94138 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94139 - con &= ~S3C2412_IISCON_IIS_ACTIVE;
94143 - dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n");
94146 - writel(mod, regs + S3C2412_IISMOD);
94147 - writel(con, regs + S3C2412_IISCON);
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);
94155 -static void s3c2412_snd_rxctrl(int on)
94157 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
94158 - void __iomem *regs = i2s->regs;
94159 - u32 fic, con, mod;
94161 - DBG("%s(%d)\n", __func__, on);
94163 - fic = readl(regs + S3C2412_IISFIC);
94164 - con = readl(regs + S3C2412_IISCON);
94165 - mod = readl(regs + S3C2412_IISMOD);
94167 - DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
94170 - con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
94171 - con &= ~S3C2412_IISCON_RXDMA_PAUSE;
94172 - con &= ~S3C2412_IISCON_RXCH_PAUSE;
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 */
94180 - case S3C2412_IISMOD_MODE_TXONLY:
94181 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94182 - mod |= S3C2412_IISMOD_MODE_TXRX;
94186 - dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
94189 - writel(mod, regs + S3C2412_IISMOD);
94190 - writel(con, regs + S3C2412_IISCON);
94192 - /* See txctrl notes on FIFOs. */
94194 - con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
94195 - con |= S3C2412_IISCON_RXDMA_PAUSE;
94196 - con |= S3C2412_IISCON_RXCH_PAUSE;
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;
94204 - case S3C2412_IISMOD_MODE_TXRX:
94205 - mod &= ~S3C2412_IISMOD_MODE_MASK;
94206 - mod |= S3C2412_IISMOD_MODE_TXONLY;
94210 - dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
94213 - writel(con, regs + S3C2412_IISCON);
94214 - writel(mod, regs + S3C2412_IISMOD);
94217 - fic = readl(regs + S3C2412_IISFIC);
94218 - DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
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.
94226 -static int s3c2412_snd_lrsync(void)
94229 - unsigned long timeout = jiffies + msecs_to_jiffies(5);
94231 - DBG("Entered %s\n", __func__);
94234 - iiscon = readl(s3c2412_i2s.regs + S3C2412_IISCON);
94235 - if (iiscon & S3C2412_IISCON_LRINDEX)
94238 - if (timeout < jiffies) {
94239 - printk(KERN_ERR "%s: timeout\n", __func__);
94240 - return -ETIMEDOUT;
94248 - * Check whether CPU is the master or slave
94250 -static inline int s3c2412_snd_is_clkmaster(void)
94252 - u32 iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
94254 - DBG("Entered %s\n", __func__);
94256 - iismod &= S3C2412_IISMOD_MASTER_MASK;
94257 - return !(iismod == S3C2412_IISMOD_SLAVE);
94261 - * Set S3C2412 I2S DAI format
94263 -static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
94264 - unsigned int fmt)
94269 - DBG("Entered %s\n", __func__);
94271 - iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
94272 - DBG("hw_params r: IISMOD: %x \n", iismod);
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;
94279 - case SND_SOC_DAIFMT_CBS_CFS:
94280 - iismod &= ~S3C2412_IISMOD_MASTER_MASK;
94281 - iismod |= S3C2412_IISMOD_MASTER_INTERNAL;
94284 - DBG("unknwon master/slave format\n");
94288 - iismod &= ~S3C2412_IISMOD_SDF_MASK;
94290 - switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
94291 - case SND_SOC_DAIFMT_RIGHT_J:
94292 - iismod |= S3C2412_IISMOD_SDF_MSB;
94294 - case SND_SOC_DAIFMT_LEFT_J:
94295 - iismod |= S3C2412_IISMOD_SDF_LSB;
94297 - case SND_SOC_DAIFMT_I2S:
94298 - iismod |= S3C2412_IISMOD_SDF_IIS;
94301 - DBG("Unknown data format\n");
94305 - writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD);
94306 - DBG("hw_params w: IISMOD: %x \n", iismod);
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)
94314 - struct snd_soc_pcm_runtime *rtd = substream->private_data;
94317 - DBG("Entered %s\n", __func__);
94319 - if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
94320 - rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_out;
94322 - rtd->dai->cpu_dai->dma_data = &s3c2412_i2s_pcm_stereo_in;
94324 - /* Working copies of register */
94325 - iismod = readl(s3c2412_i2s.regs + S3C2412_IISMOD);
94326 - DBG("%s: r: IISMOD: %x\n", __func__, iismod);
94328 - switch (params_format(params)) {
94329 - case SNDRV_PCM_FORMAT_S8:
94330 - iismod |= S3C2412_IISMOD_8BIT;
94332 - case SNDRV_PCM_FORMAT_S16_LE:
94333 - iismod &= ~S3C2412_IISMOD_8BIT;
94337 - writel(iismod, s3c2412_i2s.regs + S3C2412_IISMOD);
94338 - DBG("%s: w: IISMOD: %x\n", __func__, iismod);
94342 -static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
94343 - struct snd_soc_dai *dai)
94345 - int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
94346 - unsigned long irqs;
94349 - DBG("Entered %s\n", __func__);
94352 - case SNDRV_PCM_TRIGGER_START:
94353 - /* On start, ensure that the FIFOs are cleared and reset. */
94355 - writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH,
94356 - s3c2412_i2s.regs + S3C2412_IISFIC);
94358 - /* clear again, just in case */
94359 - writel(0x0, s3c2412_i2s.regs + S3C2412_IISFIC);
94361 - case SNDRV_PCM_TRIGGER_RESUME:
94362 - case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
94363 - if (!s3c2412_snd_is_clkmaster()) {
94364 - ret = s3c2412_snd_lrsync();
94369 - local_irq_save(irqs);
94372 - s3c2412_snd_rxctrl(1);
94374 - s3c2412_snd_txctrl(1);
94376 - local_irq_restore(irqs);
94379 - case SNDRV_PCM_TRIGGER_STOP:
94380 - case SNDRV_PCM_TRIGGER_SUSPEND:
94381 - case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
94382 - local_irq_save(irqs);
94385 - s3c2412_snd_rxctrl(0);
94387 - s3c2412_snd_txctrl(0);
94389 - local_irq_restore(irqs);
94400 -/* default table of all avaialable root fs divisors */
94401 -static unsigned int s3c2412_iis_fs[] = { 256, 512, 384, 768, 0 };
94403 -int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info,
94404 - unsigned int *fstab,
94405 - unsigned int rate, struct clk *clk)
94407 - unsigned long clkrate = clk_get_rate(clk);
94408 - unsigned int div;
94409 - unsigned int fsclk;
94410 - unsigned int actual;
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;
94420 - if (fstab == NULL)
94421 - fstab = s3c2412_iis_fs;
94423 - for (fs = 0;; fs++) {
94424 - fsdiv = s3c2412_iis_fs[fs];
94429 - fsclk = clkrate / fsdiv;
94430 - div = fsclk / rate;
94432 - if ((fsclk % rate) > (rate / 2))
94438 - actual = clkrate / (fsdiv * div);
94439 - deviation = actual - rate;
94441 - printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n",
94442 - fsdiv, div, actual, deviation);
94444 - deviation = abs(deviation);
94446 - if (deviation < best_deviation) {
94449 - best_rate = actual;
94450 - best_deviation = deviation;
94453 - if (deviation == 0)
94457 - printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n",
94458 - best_fs, best_div, best_rate);
94460 - info->fs_div = best_fs;
94461 - info->clk_div = best_div;
94465 -EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate);
94466 +static struct s3c_i2sv2_info s3c2412_i2s;
94469 * Set S3C2412 Clock source
94470 @@ -512,10 +85,12 @@
94473 case S3C2412_CLKSRC_PCLK:
94474 + s3c2412_i2s.master = 1;
94475 iismod &= ~S3C2412_IISMOD_MASTER_MASK;
94476 iismod |= S3C2412_IISMOD_MASTER_INTERNAL;
94478 case S3C2412_CLKSRC_I2SCLK:
94479 + s3c2412_i2s.master = 0;
94480 iismod &= ~S3C2412_IISMOD_MASTER_MASK;
94481 iismod |= S3C2412_IISMOD_MASTER_EXTERNAL;
94483 @@ -527,74 +102,6 @@
94488 - * Set S3C2412 Clock dividers
94490 -static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
94491 - int div_id, int div)
94493 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
94496 - DBG("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div);
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);
94504 - DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
94507 - case S3C2412_DIV_RCLK:
94509 - /* convert value to bit field */
94513 - div = S3C2412_IISMOD_RCLK_256FS;
94517 - div = S3C2412_IISMOD_RCLK_384FS;
94521 - div = S3C2412_IISMOD_RCLK_512FS;
94525 - div = S3C2412_IISMOD_RCLK_768FS;
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));
94539 - case S3C2412_DIV_PRESCALER:
94541 - writel((div << 8) | S3C2412_IISPSR_PSREN,
94542 - i2s->regs + S3C2412_IISPSR);
94544 - writel(0x0, i2s->regs + S3C2412_IISPSR);
94546 - DBG("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR));
94556 struct clk *s3c2412_get_iisclk(void)
94558 @@ -606,20 +113,16 @@
94559 static int s3c2412_i2s_probe(struct platform_device *pdev,
94560 struct snd_soc_dai *dai)
94564 DBG("Entered %s\n", __func__);
94566 - s3c2412_i2s.dev = &pdev->dev;
94567 + ret = s3c_i2sv2_probe(pdev, dai, &s3c2412_i2s, S3C2410_PA_IIS);
94571 - s3c2412_i2s.regs = ioremap(S3C2410_PA_IIS, 0x100);
94572 - if (s3c2412_i2s.regs == NULL)
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);
94581 + s3c2412_i2s.dma_capture = &s3c2412_i2s_pcm_stereo_in;
94582 + s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
94584 s3c2412_i2s.iis_cclk = clk_get(&pdev->dev, "i2sclk");
94585 if (s3c2412_i2s.iis_cclk == NULL) {
94586 @@ -628,12 +131,12 @@
94590 - clk_set_parent(s3c2412_i2s.iis_cclk, clk_get(NULL, "mpll"));
94591 + /* Set MPLL as the source for IIS CLK */
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);
94597 - s3c2412_i2s.iis_clk = s3c2412_i2s.iis_pclk;
94598 + s3c2412_i2s.iis_cclk = s3c2412_i2s.iis_pclk;
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);
94606 - s3c2412_snd_txctrl(0);
94607 - s3c2412_snd_rxctrl(0);
94613 -static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
94615 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
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);
94623 - /* some basic suspend checks */
94625 - iismod = readl(i2s->regs + S3C2412_IISMOD);
94627 - if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
94628 - pr_warning("%s: RXDMA active?\n", __func__);
94630 - if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
94631 - pr_warning("%s: TXDMA active?\n", __func__);
94633 - if (iismod & S3C2412_IISCON_IIS_ACTIVE)
94634 - pr_warning("%s: IIS active\n", __func__);
94640 -static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
94642 - struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
94644 - pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
94645 - dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
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);
94652 - writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
94653 - i2s->regs + S3C2412_IISFIC);
94656 - writel(0x0, i2s->regs + S3C2412_IISFIC);
94663 -#define s3c2412_i2s_suspend NULL
94664 -#define s3c2412_i2s_resume NULL
94665 -#endif /* CONFIG_PM */
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)
94672 struct snd_soc_dai s3c2412_i2s_dai = {
94673 - .name = "s3c2412-i2s",
94675 - .probe = s3c2412_i2s_probe,
94676 - .suspend = s3c2412_i2s_suspend,
94677 - .resume = s3c2412_i2s_resume,
94678 + .name = "s3c2412-i2s",
94680 + .probe = s3c2412_i2s_probe,
94684 @@ -727,10 +170,6 @@
94685 .formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,
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,
94695 @@ -738,7 +177,7 @@
94697 static int __init s3c2412_i2s_init(void)
94699 - return snd_soc_register_dai(&s3c2412_i2s_dai);
94700 + return s3c_i2sv2_register_dai(&s3c2412_i2s_dai);
94702 module_init(s3c2412_i2s_init);
94704 @@ -748,7 +187,6 @@
94706 module_exit(s3c2412_i2s_exit);
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
94716 #ifndef __SND_SOC_S3C24XX_S3C2412_I2S_H
94717 #define __SND_SOC_S3C24XX_S3C2412_I2S_H __FILE__
94719 -#define S3C2412_DIV_BCLK (1)
94720 -#define S3C2412_DIV_RCLK (2)
94721 -#define S3C2412_DIV_PRESCALER (3)
94722 +#include "s3c-i2s-v2.h"
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
94728 #define S3C2412_CLKSRC_PCLK (0)
94729 #define S3C2412_CLKSRC_I2SCLK (1)
94732 extern struct snd_soc_dai s3c2412_i2s_dai;
94734 -struct s3c2412_rate_calc {
94735 - unsigned int clk_div; /* for prescaler */
94736 - unsigned int fs_div; /* for root frame clock */
94739 -extern int s3c2412_iis_calc_rate(struct s3c2412_rate_calc *info,
94740 - unsigned int *fstab,
94741 - unsigned int rate, struct clk *clk);
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
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>
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
94760 * (c) 2006 Wolfson Microelectronics PLC.
94761 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
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>
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>
94777 -#include <asm/plat-s3c24xx/regs-iis.h>
94778 +#include <plat/regs-iis.h>
94780 #include "s3c24xx-pcm.h"
94781 #include "s3c24xx-i2s.h"
94782 @@ -175,7 +175,7 @@
94783 static int s3c24xx_snd_lrsync(void)
94786 - int timeout = 50; /* 5ms */
94787 + int timeout = 5; /* 500us, 125 should be enough at 8kHz */
94789 DBG("Entered %s\n", __func__);
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();
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.
94807 + s3c24xx_snd_lrsync();
94809 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
94810 s3c24xx_snd_rxctrl(1);
94811 @@ -315,7 +318,6 @@
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
94823 * (c) 2006 Wolfson Microelectronics PLC.
94824 * Graeme Gregory graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
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>
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>
94838 #include "s3c24xx-pcm.h"
94840 @@ -82,11 +82,19 @@
94842 struct s3c24xx_runtime_data *prtd = substream->runtime->private_data;
94843 dma_addr_t pos = prtd->dma_pos;
94844 + unsigned int limit;
94847 DBG("Entered %s\n", __func__);
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;
94853 + limit = prtd->dma_limit;
94855 + DBG("%s: loaded %d, limit %d\n", __func__, prtd->dma_loaded, limit);
94857 + while (prtd->dma_loaded < limit) {
94858 unsigned long len = prtd->dma_period;
94860 DBG("dma_loaded: %d\n", prtd->dma_loaded);
94861 @@ -130,7 +138,7 @@
94862 snd_pcm_period_elapsed(substream);
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);
94870 @@ -168,9 +176,14 @@
94871 prtd->params->client, NULL);
94874 - DBG(KERN_ERR "failed to get dma channel\n");
94875 + DBG(KERN_ERR "failed to get dma channel: %d\n", ret);
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);
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);
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);
94900 - s3c2410_dma_config(prtd->params->channel,
94901 - prtd->params->dma_size,
94902 - S3C2410_DCON_HANDSHAKE |
94903 - S3C2410_DCON_SYNC_PCLK);
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);
94912 + s3c2410_dma_config(prtd->params->channel,
94913 + prtd->params->dma_size);
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
94921 #include <sound/s3c24xx_uda134x.h>
94922 #include <sound/uda134x.h>
94924 -#include <asm/plat-s3c24xx/regs-iis.h>
94925 +#include <plat/regs-iis.h>
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
94933 +/* sound/soc/s3c24xx/s3c64xx-i2s.c
94935 + * ALSA SoC Audio Layer - S3C64XX I2S driver
94937 + * Copyright 2008 Openmoko, Inc.
94938 + * Copyright 2008 Simtec Electronics
94939 + * Ben Dooks <ben@simtec.co.uk>
94940 + * http://armlinux.simtec.co.uk/
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.
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>
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>
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>
94968 +#include <mach/map.h>
94969 +#include <mach/dma.h>
94971 +#include "s3c24xx-pcm.h"
94972 +#include "s3c64xx-i2s.h"
94974 +static struct s3c2410_dma_client s3c64xx_dma_client_out = {
94975 + .name = "I2S PCM Stereo out"
94978 +static struct s3c2410_dma_client s3c64xx_dma_client_in = {
94979 + .name = "I2S PCM Stereo in"
94982 +static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_out[2] = {
94984 + .channel = DMACH_I2S0_OUT,
94985 + .client = &s3c64xx_dma_client_out,
94986 + .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISTXD,
94990 + .channel = DMACH_I2S1_OUT,
94991 + .client = &s3c64xx_dma_client_out,
94992 + .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISTXD,
94997 +static struct s3c24xx_pcm_dma_params s3c64xx_i2s_pcm_stereo_in[2] = {
94999 + .channel = DMACH_I2S0_IN,
95000 + .client = &s3c64xx_dma_client_in,
95001 + .dma_addr = S3C64XX_PA_IIS0 + S3C2412_IISRXD,
95005 + .channel = DMACH_I2S1_IN,
95006 + .client = &s3c64xx_dma_client_in,
95007 + .dma_addr = S3C64XX_PA_IIS1 + S3C2412_IISRXD,
95012 +static struct s3c_i2sv2_info s3c64xx_i2s[2];
95014 +static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
95016 + return cpu_dai->private_data;
95019 +static int s3c64xx_i2s_set_sysclk(struct snd_soc_dai *cpu_dai,
95020 + int clk_id, unsigned int freq, int dir)
95022 + struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
95023 + u32 iismod = readl(i2s->regs + S3C2412_IISMOD);
95025 + switch (clk_id) {
95026 + case S3C64XX_CLKSRC_PCLK:
95027 + iismod &= ~S3C64XX_IISMOD_IMS_SYSMUX;
95030 + case S3C64XX_CLKSRC_MUX:
95031 + iismod |= S3C64XX_IISMOD_IMS_SYSMUX;
95038 + writel(iismod, i2s->regs + S3C2412_IISMOD);
95043 +unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *dai)
95045 + struct s3c_i2sv2_info *i2s = to_info(dai);
95047 + return clk_get_rate(i2s->iis_cclk);
95049 +EXPORT_SYMBOL_GPL(s3c64xx_i2s_get_clockrate);
95051 +static int s3c64xx_i2s_probe(struct platform_device *pdev,
95052 + struct snd_soc_dai *dai)
95054 + struct device *dev = &pdev->dev;
95055 + struct s3c_i2sv2_info *i2s;
95058 + dev_dbg(dev, "%s: probing dai %d\n", __func__, pdev->id);
95060 + if (pdev->id < 0 || pdev->id > ARRAY_SIZE(s3c64xx_i2s)) {
95061 + dev_err(dev, "id %d out of range\n", pdev->id);
95065 + i2s = &s3c64xx_i2s[pdev->id];
95067 + ret = s3c_i2sv2_probe(pdev, dai, i2s,
95068 + pdev->id ? S3C64XX_PA_IIS1 : S3C64XX_PA_IIS0);
95072 + i2s->dma_capture = &s3c64xx_i2s_pcm_stereo_in[pdev->id];
95073 + i2s->dma_playback = &s3c64xx_i2s_pcm_stereo_out[pdev->id];
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);
95082 + /* configure GPIO for i2s port */
95083 + switch (pdev->id) {
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);
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);
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)
95108 +#define S3C64XX_I2S_FMTS \
95109 + (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE)
95111 +struct snd_soc_dai s3c64xx_i2s_dai = {
95112 + .name = "s3c64xx-i2s",
95114 + .probe = s3c64xx_i2s_probe,
95116 + .channels_min = 2,
95117 + .channels_max = 2,
95118 + .rates = S3C64XX_I2S_RATES,
95119 + .formats = S3C64XX_I2S_FMTS,
95122 + .channels_min = 2,
95123 + .channels_max = 2,
95124 + .rates = S3C64XX_I2S_RATES,
95125 + .formats = S3C64XX_I2S_FMTS,
95128 + .set_sysclk = s3c64xx_i2s_set_sysclk,
95131 +EXPORT_SYMBOL_GPL(s3c64xx_i2s_dai);
95133 +static int __init s3c64xx_i2s_init(void)
95135 + return s3c_i2sv2_register_dai(&s3c64xx_i2s_dai);
95137 +module_init(s3c64xx_i2s_init);
95139 +static void __exit s3c64xx_i2s_exit(void)
95141 + snd_soc_unregister_dai(&s3c64xx_i2s_dai);
95143 +module_exit(s3c64xx_i2s_exit);
95145 +/* Module information */
95146 +MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
95147 +MODULE_DESCRIPTION("S3C64XX I2S SoC Interface");
95148 +MODULE_LICENSE("GPL");
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
95156 +/* sound/soc/s3c24xx/s3c64xx-i2s.h
95158 + * ALSA SoC Audio Layer - S3C64XX I2S driver
95160 + * Copyright 2008 Openmoko, Inc.
95161 + * Copyright 2008 Simtec Electronics
95162 + * Ben Dooks <ben@simtec.co.uk>
95163 + * http://armlinux.simtec.co.uk/
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.
95170 +#ifndef __SND_SOC_S3C24XX_S3C64XX_I2S_H
95171 +#define __SND_SOC_S3C24XX_S3C64XX_I2S_H __FILE__
95173 +#include "s3c-i2s-v2.h"
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
95179 +#define S3C64XX_CLKSRC_PCLK (0)
95180 +#define S3C64XX_CLKSRC_MUX (1)
95182 +extern struct snd_soc_dai s3c64xx_i2s_dai;
95184 +extern unsigned long s3c64xx_i2s_get_clockrate(struct snd_soc_dai *cpu_dai);
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
95191 +/* sound/soc/s3c24xx/s3c-i2c-v2.c
95193 + * ALSA Soc Audio Layer - I2S core for newer Samsung SoCs.
95195 + * Copyright (c) 2006 Wolfson Microelectronics PLC.
95196 + * Graeme Gregory graeme.gregory@wolfsonmicro.com
95197 + * linux@wolfsonmicro.com
95199 + * Copyright (c) 2008, 2007, 2004-2005 Simtec Electronics
95200 + * http://armlinux.simtec.co.uk/
95201 + * Ben Dooks <ben@simtec.co.uk>
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.
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>
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>
95223 +#include <plat/regs-s3c2412-iis.h>
95225 +#include <plat/audio.h>
95226 +#include <mach/dma.h>
95228 +#include "s3c-i2s-v2.h"
95230 +#define S3C2412_I2S_DEBUG_CON 0
95231 +#define S3C2412_I2S_DEBUG 0
95233 +#if S3C2412_I2S_DEBUG
95234 +#define DBG(x...) printk(KERN_INFO x)
95236 +#define DBG(x...) do { } while (0)
95239 +static inline struct s3c_i2sv2_info *to_info(struct snd_soc_dai *cpu_dai)
95241 + return cpu_dai->private_data;
95244 +#define bit_set(v, b) (((v) & (b)) ? 1 : 0)
95246 +#if S3C2412_I2S_DEBUG_CON
95247 +static void dbg_showcon(const char *fn, u32 con)
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));
95256 + printk(KERN_DEBUG "%s: PAUSE: TXDMA=%d, RXDMA=%d, TXCH=%d, RXCH=%d\n",
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));
95268 +static inline void dbg_showcon(const char *fn, u32 con)
95274 +/* Turn on or off the transmission path. */
95275 +void s3c2412_snd_txctrl(struct s3c_i2sv2_info *i2s, int on)
95277 + void __iomem *regs = i2s->regs;
95278 + u32 fic, con, mod;
95280 + DBG("%s(%d)\n", __func__, on);
95282 + fic = readl(regs + S3C2412_IISFIC);
95283 + con = readl(regs + S3C2412_IISCON);
95284 + mod = readl(regs + S3C2412_IISMOD);
95286 + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
95289 + con |= S3C2412_IISCON_TXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
95290 + con &= ~S3C2412_IISCON_TXDMA_PAUSE;
95291 + con &= ~S3C2412_IISCON_TXCH_PAUSE;
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 */
95299 + case S3C2412_IISMOD_MODE_RXONLY:
95300 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95301 + mod |= S3C2412_IISMOD_MODE_TXRX;
95305 + dev_err(i2s->dev, "TXEN: Invalid MODE in IISMOD\n");
95308 + writel(con, regs + S3C2412_IISCON);
95309 + writel(mod, regs + S3C2412_IISMOD);
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.
95316 + con |= S3C2412_IISCON_TXDMA_PAUSE;
95317 + con |= S3C2412_IISCON_TXCH_PAUSE;
95318 + con &= ~S3C2412_IISCON_TXDMA_ACTIVE;
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;
95326 + case S3C2412_IISMOD_MODE_TXONLY:
95327 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95328 + con &= ~S3C2412_IISCON_IIS_ACTIVE;
95332 + dev_err(i2s->dev, "TXDIS: Invalid MODE in IISMOD\n");
95335 + writel(mod, regs + S3C2412_IISMOD);
95336 + writel(con, regs + S3C2412_IISCON);
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);
95343 +EXPORT_SYMBOL_GPL(s3c2412_snd_txctrl);
95345 +void s3c2412_snd_rxctrl(struct s3c_i2sv2_info *i2s, int on)
95347 + void __iomem *regs = i2s->regs;
95348 + u32 fic, con, mod;
95350 + DBG("%s(%d)\n", __func__, on);
95352 + fic = readl(regs + S3C2412_IISFIC);
95353 + con = readl(regs + S3C2412_IISCON);
95354 + mod = readl(regs + S3C2412_IISMOD);
95356 + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
95359 + con |= S3C2412_IISCON_RXDMA_ACTIVE | S3C2412_IISCON_IIS_ACTIVE;
95360 + con &= ~S3C2412_IISCON_RXDMA_PAUSE;
95361 + con &= ~S3C2412_IISCON_RXCH_PAUSE;
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 */
95369 + case S3C2412_IISMOD_MODE_TXONLY:
95370 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95371 + mod |= S3C2412_IISMOD_MODE_TXRX;
95375 + dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
95378 + writel(mod, regs + S3C2412_IISMOD);
95379 + writel(con, regs + S3C2412_IISCON);
95381 + /* See txctrl notes on FIFOs. */
95383 + con &= ~S3C2412_IISCON_RXDMA_ACTIVE;
95384 + con |= S3C2412_IISCON_RXDMA_PAUSE;
95385 + con |= S3C2412_IISCON_RXCH_PAUSE;
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;
95393 + case S3C2412_IISMOD_MODE_TXRX:
95394 + mod &= ~S3C2412_IISMOD_MODE_MASK;
95395 + mod |= S3C2412_IISMOD_MODE_TXONLY;
95399 + dev_err(i2s->dev, "RXEN: Invalid MODE in IISMOD\n");
95402 + writel(con, regs + S3C2412_IISCON);
95403 + writel(mod, regs + S3C2412_IISMOD);
95406 + fic = readl(regs + S3C2412_IISFIC);
95407 + DBG("%s: IIS: CON=%x MOD=%x FIC=%x\n", __func__, con, mod, fic);
95409 +EXPORT_SYMBOL_GPL(s3c2412_snd_rxctrl);
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.
95415 +static int s3c2412_snd_lrsync(struct s3c_i2sv2_info *i2s)
95418 + unsigned long timeout = jiffies + msecs_to_jiffies(5);
95420 + DBG("Entered %s\n", __func__);
95423 + iiscon = readl(i2s->regs + S3C2412_IISCON);
95424 + if (iiscon & S3C2412_IISCON_LRINDEX)
95427 + if (timeout < jiffies) {
95428 + printk(KERN_ERR "%s: timeout\n", __func__);
95429 + return -ETIMEDOUT;
95437 + * Set S3C2412 I2S DAI format
95439 +static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
95440 + unsigned int fmt)
95442 + struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
95445 + DBG("Entered %s\n", __func__);
95447 + iismod = readl(i2s->regs + S3C2412_IISMOD);
95448 + DBG("hw_params r: IISMOD: %x \n", iismod);
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
95456 +#if defined(CONFIG_PLAT_S3C64XX)
95457 +/* From Rev1.1 datasheet, we have two master and two slave modes:
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
95464 +#define IISMOD_MASTER_MASK (1 << 11)
95465 +#define IISMOD_SLAVE (1 << 11)
95466 +#define IISMOD_MASTER (0x0)
95469 + switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
95470 + case SND_SOC_DAIFMT_CBM_CFM:
95472 + iismod &= ~IISMOD_MASTER_MASK;
95473 + iismod |= IISMOD_SLAVE;
95475 + case SND_SOC_DAIFMT_CBS_CFS:
95477 + iismod &= ~IISMOD_MASTER_MASK;
95478 + iismod |= IISMOD_MASTER;
95481 + DBG("unknwon master/slave format\n");
95485 + iismod &= ~S3C2412_IISMOD_SDF_MASK;
95487 + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
95488 + case SND_SOC_DAIFMT_RIGHT_J:
95489 + iismod |= S3C2412_IISMOD_SDF_MSB;
95491 + case SND_SOC_DAIFMT_LEFT_J:
95492 + iismod |= S3C2412_IISMOD_SDF_LSB;
95494 + case SND_SOC_DAIFMT_I2S:
95495 + iismod |= S3C2412_IISMOD_SDF_IIS;
95498 + DBG("Unknown data format\n");
95502 + writel(iismod, i2s->regs + S3C2412_IISMOD);
95503 + DBG("hw_params w: IISMOD: %x \n", iismod);
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)
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);
95516 + DBG("Entered %s\n", __func__);
95518 + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
95519 + dai->cpu_dai->dma_data = i2s->dma_playback;
95521 + dai->cpu_dai->dma_data = i2s->dma_capture;
95523 + /* Working copies of register */
95524 + iismod = readl(i2s->regs + S3C2412_IISMOD);
95525 + DBG("%s: r: IISMOD: %x\n", __func__, iismod);
95527 + switch (params_format(params)) {
95528 + case SNDRV_PCM_FORMAT_S8:
95529 + iismod |= S3C2412_IISMOD_8BIT;
95531 + case SNDRV_PCM_FORMAT_S16_LE:
95532 + iismod &= ~S3C2412_IISMOD_8BIT;
95536 + writel(iismod, i2s->regs + S3C2412_IISMOD);
95537 + DBG("%s: w: IISMOD: %x\n", __func__, iismod);
95541 +static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
95542 + struct snd_soc_dai *dai)
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;
95550 + DBG("Entered %s\n", __func__);
95553 + case SNDRV_PCM_TRIGGER_START:
95554 + /* On start, ensure that the FIFOs are cleared and reset. */
95556 + writel(capture ? S3C2412_IISFIC_RXFLUSH : S3C2412_IISFIC_TXFLUSH,
95557 + i2s->regs + S3C2412_IISFIC);
95559 + /* clear again, just in case */
95560 + writel(0x0, i2s->regs + S3C2412_IISFIC);
95562 + case SNDRV_PCM_TRIGGER_RESUME:
95563 + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
95564 + if (!i2s->master) {
95565 + ret = s3c2412_snd_lrsync(i2s);
95570 + local_irq_save(irqs);
95573 + s3c2412_snd_rxctrl(i2s, 1);
95575 + s3c2412_snd_txctrl(i2s, 1);
95577 + local_irq_restore(irqs);
95580 + case SNDRV_PCM_TRIGGER_STOP:
95581 + case SNDRV_PCM_TRIGGER_SUSPEND:
95582 + case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
95583 + local_irq_save(irqs);
95586 + s3c2412_snd_rxctrl(i2s, 0);
95588 + s3c2412_snd_txctrl(i2s, 0);
95590 + local_irq_restore(irqs);
95602 + * Set S3C2412 Clock dividers
95604 +static int s3c2412_i2s_set_clkdiv(struct snd_soc_dai *cpu_dai,
95605 + int div_id, int div)
95607 + struct s3c_i2sv2_info *i2s = to_info(cpu_dai);
95610 + DBG("%s(%p, %d, %d)\n", __func__, cpu_dai, div_id, div);
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);
95618 + DBG("%s: MOD=%08x\n", __func__, readl(i2s->regs + S3C2412_IISMOD));
95621 + case S3C_I2SV2_DIV_RCLK:
95623 + /* convert value to bit field */
95627 + div = S3C2412_IISMOD_RCLK_256FS;
95631 + div = S3C2412_IISMOD_RCLK_384FS;
95635 + div = S3C2412_IISMOD_RCLK_512FS;
95639 + div = S3C2412_IISMOD_RCLK_768FS;
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));
95653 + case S3C_I2SV2_DIV_PRESCALER:
95655 + writel((div << 8) | S3C2412_IISPSR_PSREN,
95656 + i2s->regs + S3C2412_IISPSR);
95658 + writel(0x0, i2s->regs + S3C2412_IISPSR);
95660 + DBG("%s: PSR=%08x\n", __func__, readl(i2s->regs + S3C2412_IISPSR));
95670 +/* default table of all avaialable root fs divisors */
95671 +static unsigned int iis_fs_tab[] = { 256, 512, 384, 768 };
95673 +int s3c2412_iis_calc_rate(struct s3c_i2sv2_rate_calc *info,
95674 + unsigned int *fstab,
95675 + unsigned int rate, struct clk *clk)
95677 + unsigned long clkrate = clk_get_rate(clk);
95678 + unsigned int div;
95679 + unsigned int fsclk;
95680 + unsigned int actual;
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;
95689 + if (fstab == NULL)
95690 + fstab = iis_fs_tab;
95692 + for (fs = 0; fs < ARRAY_SIZE(iis_fs_tab); fs++) {
95693 + fsdiv = iis_fs_tab[fs];
95695 + fsclk = clkrate / fsdiv;
95696 + div = fsclk / rate;
95698 + if ((fsclk % rate) > (rate / 2))
95704 + actual = clkrate / (fsdiv * div);
95705 + deviation = actual - rate;
95707 + printk(KERN_DEBUG "%dfs: div %d => result %d, deviation %d\n",
95708 + fsdiv, div, actual, deviation);
95710 + deviation = abs(deviation);
95712 + if (deviation < best_deviation) {
95715 + best_rate = actual;
95716 + best_deviation = deviation;
95719 + if (deviation == 0)
95723 + printk(KERN_DEBUG "best: fs=%d, div=%d, rate=%d\n",
95724 + best_fs, best_div, best_rate);
95726 + info->fs_div = best_fs;
95727 + info->clk_div = best_div;
95731 +EXPORT_SYMBOL_GPL(s3c2412_iis_calc_rate);
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)
95738 + struct device *dev = &pdev->dev;
95742 + /* record our i2s structure for later use in the callbacks */
95743 + dai->private_data = i2s;
95745 + i2s->regs = ioremap(base, 0x100);
95746 + if (i2s->regs == NULL) {
95747 + dev_err(dev, "cannot ioremap registers\n");
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);
95758 + clk_enable(i2s->iis_pclk);
95760 + s3c2412_snd_txctrl(i2s, 0);
95761 + s3c2412_snd_rxctrl(i2s, 0);
95766 +EXPORT_SYMBOL_GPL(s3c_i2sv2_probe);
95769 +static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
95771 + struct s3c_i2sv2_info *i2s = to_info(dai);
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);
95779 + /* some basic suspend checks */
95781 + iismod = readl(i2s->regs + S3C2412_IISMOD);
95783 + if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
95784 + pr_warning("%s: RXDMA active?\n", __func__);
95786 + if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
95787 + pr_warning("%s: TXDMA active?\n", __func__);
95789 + if (iismod & S3C2412_IISCON_IIS_ACTIVE)
95790 + pr_warning("%s: IIS active\n", __func__);
95796 +static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
95798 + struct s3c_i2sv2_info *i2s = to_info(dai);
95800 + pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
95801 + dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
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);
95808 + writel(S3C2412_IISFIC_RXFLUSH | S3C2412_IISFIC_TXFLUSH,
95809 + i2s->regs + S3C2412_IISFIC);
95812 + writel(0x0, i2s->regs + S3C2412_IISFIC);
95818 +#define s3c2412_i2s_suspend NULL
95819 +#define s3c2412_i2s_resume NULL
95822 +int s3c_i2sv2_register_dai(struct snd_soc_dai *dai)
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;
95829 + dai->suspend = s3c2412_i2s_suspend;
95830 + dai->resume = s3c2412_i2s_resume;
95832 + return snd_soc_register_dai(dai);
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
95840 +/* sound/soc/s3c24xx/s3c-i2s-v2.h
95842 + * ALSA Soc Audio Layer - S3C_I2SV2 I2S driver
95844 + * Copyright (c) 2007 Simtec Electronics
95845 + * http://armlinux.simtec.co.uk/
95846 + * Ben Dooks <ben@simtec.co.uk>
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.
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.
95860 +#ifndef __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H
95861 +#define __SND_SOC_S3C24XX_S3C_I2SV2_I2S_H __FILE__
95863 +#define S3C_I2SV2_DIV_BCLK (1)
95864 +#define S3C_I2SV2_DIV_RCLK (2)
95865 +#define S3C_I2SV2_DIV_PRESCALER (3)
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.
95878 + * This is the private codec state for the hardware associated with an
95879 + * I2S channel such as the register mappings and clock sources.
95881 +struct s3c_i2sv2_info {
95882 + struct device *dev;
95883 + void __iomem *regs;
95885 + struct clk *iis_pclk;
95886 + struct clk *iis_cclk;
95887 + struct clk *iis_clk;
95889 + unsigned char master;
95891 + struct s3c24xx_pcm_dma_params *dma_playback;
95892 + struct s3c24xx_pcm_dma_params *dma_capture;
95894 + u32 suspend_iismod;
95895 + u32 suspend_iiscon;
95896 + u32 suspend_iispsr;
95899 +struct s3c_i2sv2_rate_calc {
95900 + unsigned int clk_div; /* for prescaler */
95901 + unsigned int fs_div; /* for root frame clock */
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);
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.
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);
95921 + * s3c_i2sv2_register_dai - register dai with soc core
95922 + * @dai: The snd_soc_dai structure to register
95924 + * Fill in any missing fields and then register the given dai with the
95927 +extern int s3c_i2sv2_register_dai(struct snd_soc_dai *dai);
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
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>
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>
95950 +#include <asm/mach-types.h>
95952 +#include "../codecs/wm8731.h"
95953 +#include "s3c64xx-i2s.h"
95955 +static struct platform_device *socdev;
95959 +static void wm_shutdown(struct snd_pcm_substream *substream)
95961 + printk(KERN_INFO "%s: substream %p\n", __func__, substream);
95964 +static int wm_hw_params(struct snd_pcm_substream *substream,
95965 + struct snd_pcm_hw_params *params)
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;
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);
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;
95980 + ret = snd_soc_dai_set_fmt(codec_dai, fmt);
95984 + /* set cpu DAI configuration */
95985 + ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
95989 + if (fmt == (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM)) {
95990 + unsigned long iis_clkrate;
95992 + ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_MUX, 0,
95993 + SND_SOC_CLOCK_OUT);
95995 + printk(KERN_ERR "%s: cpu set_sysclk err\n", __func__);
95999 + /* set prescaler division for sample rate */
96000 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C64XX_DIV_PRESCALER, 1);
96002 + printk(KERN_ERR "%s: codec clkdiv err\n", __func__);
96006 + iis_clkrate = s3c64xx_i2s_get_clockrate(cpu_dai) / 2;
96007 + printk(KERN_INFO "%s: clockrate %ld\n", __func__, iis_clkrate);
96009 + iis_clkrate = 12000000; //tmphack//
96011 + /* set the codec system clock for DAC and ADC */
96012 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
96014 + SND_SOC_CLOCK_IN);
96016 + printk(KERN_ERR "%s: codec sysclk err\n", __func__);
96028 +static int wm_startup(struct snd_pcm_substream *substream)
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;
96035 + ret = snd_soc_dai_set_sysclk(cpu_dai, S3C64XX_CLKSRC_MUX, 0,
96036 + SND_SOC_CLOCK_OUT);
96038 + printk(KERN_ERR "%s: cpu set_sysclk err\n", __func__);
96042 + ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C64XX_DIV_PRESCALER, 1);
96044 + printk(KERN_ERR "%s: cpu set_clkdiv err\n", __func__);
96048 + ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
96049 + 12000000, SND_SOC_CLOCK_IN);
96051 + printk(KERN_ERR "%s: codec sysclk err\n", __func__);
96058 +static struct snd_soc_ops wm_ops = {
96059 + .startup = wm_startup,
96060 + .hw_params = wm_hw_params,
96061 + .shutdown = wm_shutdown,
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"),
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"},
96075 + {"Line Out", NULL, "LOUT" },
96076 + {"Line Out", NULL, "ROUT" },
96078 + {"LLINEIN", NULL, "Line In" },
96079 + {"RLINEIN", NULL, "Line In" },
96082 +static int wm_init(struct snd_soc_codec *codec)
96084 + printk(KERN_DEBUG "%s: codec %p\n", __func__, codec);
96086 + snd_soc_dapm_new_controls(codec, widgets, ARRAY_SIZE(widgets));
96087 + snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
96089 + snd_soc_dapm_sync(codec);
96094 +#include "s3c24xx-pcm.h"
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,
96105 +static struct snd_soc_card wm_card = {
96106 + .name = "SMDK6410-WM8731",
96107 + .dai_link = &wm_dai_link,
96108 + .platform = &s3c24xx_soc_platform,
96112 +struct wm8731_setup_data wm_setup = {
96114 + .i2c_address = 0x1a,
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,
96123 +static int __init smdk6410_wm8731_init(void)
96127 + printk(KERN_INFO "%s: welcome\n", __func__);
96129 + if (!machine_is_smdk6410()) {
96130 + printk(KERN_INFO "%s: for SMDK6410s\n", __func__);
96134 + socdev = platform_device_alloc("soc-audio", 0);
96136 + printk(KERN_ERR "%s: no device\n", __func__);
96140 + platform_set_drvdata(socdev, &wm_snd_devdata);
96142 + wm_snd_devdata.dev = &socdev->dev;
96144 + ret = platform_device_add(socdev);
96146 + printk(KERN_ERR "%s: failed to add\n", __func__);
96150 + printk(KERN_INFO "%s: succesfull\n", __func__);
96154 + platform_device_put(socdev);
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 @@
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 @@
96177 snprintf(path->long_name, name_len, "%s %s",
96178 w->name, w->kcontrols[i].name);
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.
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);
96197 path->long_name[name_len - 1] = '\0';
96199 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
96200 @@ -876,7 +894,7 @@
96203 static int snd_soc_dapm_set_pin(struct snd_soc_codec *codec,
96204 - char *pin, int status)
96205 + const char *pin, int status)
96207 struct snd_soc_dapm_widget *w;
96209 @@ -1396,6 +1414,76 @@
96210 EXPORT_SYMBOL_GPL(snd_soc_dapm_put_value_enum_double);
96213 + * snd_soc_dapm_info_pin_switch - Info for a pin switch
96215 + * @kcontrol: mixer control
96216 + * @uinfo: control element information
96218 + * Callback to provide information about a pin switch control.
96220 +int snd_soc_dapm_info_pin_switch(struct snd_kcontrol *kcontrol,
96221 + struct snd_ctl_elem_info *uinfo)
96223 + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
96224 + uinfo->count = 1;
96225 + uinfo->value.integer.min = 0;
96226 + uinfo->value.integer.max = 1;
96230 +EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
96233 + * snd_soc_dapm_get_pin_switch - Get information for a pin switch
96235 + * @kcontrol: mixer control
96236 + * @ucontrol: Value
96238 +int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
96239 + struct snd_ctl_elem_value *ucontrol)
96241 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
96242 + const char *pin = (const char *)kcontrol->private_value;
96244 + mutex_lock(&codec->mutex);
96246 + ucontrol->value.integer.value[0] =
96247 + snd_soc_dapm_get_pin_status(codec, pin);
96249 + mutex_unlock(&codec->mutex);
96253 +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
96256 + * snd_soc_dapm_put_pin_switch - Set information for a pin switch
96258 + * @kcontrol: mixer control
96259 + * @ucontrol: Value
96261 +int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
96262 + struct snd_ctl_elem_value *ucontrol)
96264 + struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
96265 + const char *pin = (const char *)kcontrol->private_value;
96267 + mutex_lock(&codec->mutex);
96269 + if (ucontrol->value.integer.value[0])
96270 + snd_soc_dapm_enable_pin(codec, pin);
96272 + snd_soc_dapm_disable_pin(codec, pin);
96274 + snd_soc_dapm_sync(codec);
96276 + mutex_unlock(&codec->mutex);
96280 +EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
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.
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)
96293 return snd_soc_dapm_set_pin(codec, pin, 1);
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.
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)
96302 return snd_soc_dapm_set_pin(codec, pin, 0);
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.
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)
96311 return snd_soc_dapm_set_pin(codec, pin, 0);
96313 @@ -1599,7 +1687,7 @@
96315 * Returns 1 for connected otherwise 0.
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)
96320 struct snd_soc_dapm_widget *w;
96322 @@ -1613,6 +1701,56 @@
96323 EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_status);
96326 + * snd_soc_dapm_get_endpoint - get audio endpoint status
96327 + * @codec: audio codec
96328 + * @endpoint: audio signal endpoint (or start point)
96330 + * Get audio endpoint status - connected or disconnected.
96334 +int snd_soc_dapm_get_endpoint(struct snd_soc_codec *codec,
96337 + struct snd_soc_dapm_widget *w;
96339 + list_for_each_entry(w, &codec->dapm_widgets, list) {
96340 + if (!strcmp(w->name, endpoint)) {
96341 + return w->connected;
96347 +EXPORT_SYMBOL_GPL(snd_soc_dapm_get_endpoint);
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
96355 + * Set audio endpoint status - connected or disconnected.
96357 + * Returns 0 for success else error.
96359 +int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
96360 + char *endpoint, int status)
96362 + struct snd_soc_dapm_widget *w;
96364 + list_for_each_entry(w, &codec->dapm_widgets, list) {
96365 + if (!strcmp(w->name, endpoint)) {
96366 + w->connected = status;
96373 +EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
96376 * snd_soc_dapm_free - free dapm resources
96377 * @socdev: SoC device