Date:2011-08-22 10:19:14 (2 years 11 months ago)
Author:Xiangfu Liu
Commit:2d22f1f788faaa4cfd7cf7e6a577d2e1e6094ccc
Message:ben nanonote: forward patches to linux-3.1

Files: target/linux/xburst/patches-3.1/0001-JZ4740-cache-quirks.patch (1 diff)
target/linux/xburst/patches-3.1/0002-Add-n516-board-support.patch (1 diff)
target/linux/xburst/patches-3.1/0003-Add-n526-board-support.patch (1 diff)
target/linux/xburst/patches-3.1/0004-MIPS-JZ4740-Add-id800wt-board.patch (1 diff)
target/linux/xburst/patches-3.1/0005-Add-N516-sound-SoC-board-driver.patch (1 diff)
target/linux/xburst/patches-3.1/0006-Add-N526-sound-SoC-board-driver.patch (1 diff)
target/linux/xburst/patches-3.1/0007-qi_lb60-Don-t-use-3-wire-spi-mode-for-the-display-fo.patch (1 diff)
target/linux/xburst/patches-3.1/0008-i2c-Add-i2c-driver-for-JZ47XX-SoCs.patch (1 diff)
target/linux/xburst/patches-3.1/0009-MIPS-JZ4740-Fix-i2c-driver-name.patch (1 diff)
target/linux/xburst/patches-3.1/0010-MFD-jz4740-adc-Add-support-for-the-touchscreen-part-.patch (1 diff)
target/linux/xburst/patches-3.1/0011-input-Add-touchscreen-driver-for-the-JZ4740-SoC.patch (1 diff)
target/linux/xburst/patches-3.1/0012-Add-ili8960-lcd-driver.patch (1 diff)
target/linux/xburst/patches-3.1/0013-Add-jz4740-udc-driver.patch (1 diff)
target/linux/xburst/patches-3.1/0014-Framebuffer-notifier-Call-notifier-callbacks-prior-t.patch (1 diff)
target/linux/xburst/patches-3.1/0015-500-modifier-keys.patch.patch (1 diff)
target/linux/xburst/patches-3.1/0016-Add-n516-lpc-driver.patch (1 diff)
target/linux/xburst/patches-3.1/0017-Add-n526-lpc-driver.patch (1 diff)
target/linux/xburst/patches-3.1/0018-850-ks7010-support.patch.patch (1 diff)
target/linux/xburst/patches-3.1/0019-Add-openwrt-logo.patch (1 diff)
target/linux/xburst/patches-3.1/0020-901-ubi-Read-only-the-vid-header-instead-of-the-whol.patch (1 diff)
target/linux/xburst/patches-3.1/0021-902-NAND-Optimize-NAND_ECC_HW_OOB_FIRST-read.patch.patch (1 diff)
target/linux/xburst/patches-3.1/0022-903-NAND-Add-support-for-subpage-reads-for-NAND_ECC_.patch (1 diff)
target/linux/xburst/patches-3.1/0023-904-NAND-Optimize-reading-the-eec-data-for-the-JZ474.patch (1 diff)
target/linux/xburst/patches-3.1/0024-qi_lb60-modify-patition-size.patch (1 diff)

Change Details

target/linux/xburst/patches-3.1/0001-JZ4740-cache-quirks.patch
1From 1ac9b15b7af3b9ac1749167f6830181c2d8311b7 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sat, 24 Apr 2010 17:34:29 +0200
4Subject: [PATCH 01/24] JZ4740 cache quirks
5
6---
7 arch/mips/include/asm/r4kcache.h | 231 ++++++++++++++++++++++++++++++++++++++
8 1 files changed, 231 insertions(+), 0 deletions(-)
9
10diff --git a/arch/mips/include/asm/r4kcache.h b/arch/mips/include/asm/r4kcache.h
11index 54ea47d..868a198 100644
12--- a/arch/mips/include/asm/r4kcache.h
13@@ -17,6 +17,58 @@
14 #include <asm/cpu-features.h>
15 #include <asm/mipsmtregs.h>
16
17+#ifdef CONFIG_JZRISC
18+
19+#define K0_TO_K1() \
20+do { \
21+ unsigned long __k0_addr; \
22+ \
23+ __asm__ __volatile__( \
24+ "la %0, 1f\n\t" \
25+ "or %0, %0, %1\n\t" \
26+ "jr %0\n\t" \
27+ "nop\n\t" \
28+ "1: nop\n" \
29+ : "=&r"(__k0_addr) \
30+ : "r" (0x20000000) ); \
31+} while(0)
32+
33+#define K1_TO_K0() \
34+do { \
35+ unsigned long __k0_addr; \
36+ __asm__ __volatile__( \
37+ "nop;nop;nop;nop;nop;nop;nop\n\t" \
38+ "la %0, 1f\n\t" \
39+ "jr %0\n\t" \
40+ "nop\n\t" \
41+ "1: nop\n" \
42+ : "=&r" (__k0_addr)); \
43+} while (0)
44+
45+#define INVALIDATE_BTB() \
46+do { \
47+ unsigned long tmp; \
48+ __asm__ __volatile__( \
49+ ".set mips32\n\t" \
50+ "mfc0 %0, $16, 7\n\t" \
51+ "nop\n\t" \
52+ "ori %0, 2\n\t" \
53+ "mtc0 %0, $16, 7\n\t" \
54+ "nop\n\t" \
55+ : "=&r" (tmp)); \
56+} while (0)
57+
58+#define SYNC_WB() __asm__ __volatile__ ("sync")
59+
60+#else /* CONFIG_JZRISC */
61+
62+#define K0_TO_K1() do { } while (0)
63+#define K1_TO_K0() do { } while (0)
64+#define INVALIDATE_BTB() do { } while (0)
65+#define SYNC_WB() do { } while (0)
66+
67+#endif /* CONFIG_JZRISC */
68+
69 /*
70  * This macro return a properly sign-extended address suitable as base address
71  * for indexed cache operations. Two issues here:
72@@ -144,6 +196,7 @@ static inline void flush_icache_line_indexed(unsigned long addr)
73 {
74     __iflush_prologue
75     cache_op(Index_Invalidate_I, addr);
76+ INVALIDATE_BTB();
77     __iflush_epilogue
78 }
79
80@@ -151,6 +204,7 @@ static inline void flush_dcache_line_indexed(unsigned long addr)
81 {
82     __dflush_prologue
83     cache_op(Index_Writeback_Inv_D, addr);
84+ SYNC_WB();
85     __dflush_epilogue
86 }
87
88@@ -163,6 +217,7 @@ static inline void flush_icache_line(unsigned long addr)
89 {
90     __iflush_prologue
91     cache_op(Hit_Invalidate_I, addr);
92+ INVALIDATE_BTB();
93     __iflush_epilogue
94 }
95
96@@ -170,6 +225,7 @@ static inline void flush_dcache_line(unsigned long addr)
97 {
98     __dflush_prologue
99     cache_op(Hit_Writeback_Inv_D, addr);
100+ SYNC_WB();
101     __dflush_epilogue
102 }
103
104@@ -177,6 +233,7 @@ static inline void invalidate_dcache_line(unsigned long addr)
105 {
106     __dflush_prologue
107     cache_op(Hit_Invalidate_D, addr);
108+ SYNC_WB();
109     __dflush_epilogue
110 }
111
112@@ -209,6 +266,7 @@ static inline void flush_scache_line(unsigned long addr)
113 static inline void protected_flush_icache_line(unsigned long addr)
114 {
115     protected_cache_op(Hit_Invalidate_I, addr);
116+ INVALIDATE_BTB();
117 }
118
119 /*
120@@ -220,6 +278,7 @@ static inline void protected_flush_icache_line(unsigned long addr)
121 static inline void protected_writeback_dcache_line(unsigned long addr)
122 {
123     protected_cache_op(Hit_Writeback_Inv_D, addr);
124+ SYNC_WB();
125 }
126
127 static inline void protected_writeback_scache_line(unsigned long addr)
128@@ -396,8 +455,10 @@ static inline void blast_##pfx##cache##lsize##_page_indexed(unsigned long page)
129 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 16)
130 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 16)
131 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 16)
132+#ifndef CONFIG_JZRISC
133 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 32)
134 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 32)
135+#endif
136 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 32)
137 __BUILD_BLAST_CACHE(d, dcache, Index_Writeback_Inv_D, Hit_Writeback_Inv_D, 64)
138 __BUILD_BLAST_CACHE(i, icache, Index_Invalidate_I, Hit_Invalidate_I, 64)
139@@ -405,12 +466,122 @@ __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 64)
140 __BUILD_BLAST_CACHE(s, scache, Index_Writeback_Inv_SD, Hit_Writeback_Inv_SD, 128)
141
142 __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 16)
143+#ifndef CONFIG_JZRISC
144 __BUILD_BLAST_CACHE(inv_d, dcache, Index_Writeback_Inv_D, Hit_Invalidate_D, 32)
145+#endif
146 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 16)
147 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 32)
148 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 64)
149 __BUILD_BLAST_CACHE(inv_s, scache, Index_Writeback_Inv_SD, Hit_Invalidate_SD, 128)
150
151+#ifdef CONFIG_JZRISC
152+
153+static inline void blast_dcache32(void)
154+{
155+ unsigned long start = INDEX_BASE;
156+ unsigned long end = start + current_cpu_data.dcache.waysize;
157+ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
158+ unsigned long ws_end = current_cpu_data.dcache.ways <<
159+ current_cpu_data.dcache.waybit;
160+ unsigned long ws, addr;
161+
162+ for (ws = 0; ws < ws_end; ws += ws_inc)
163+ for (addr = start; addr < end; addr += 0x400)
164+ cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
165+
166+ SYNC_WB();
167+}
168+
169+static inline void blast_dcache32_page(unsigned long page)
170+{
171+ unsigned long start = page;
172+ unsigned long end = page + PAGE_SIZE;
173+
174+ do {
175+ cache32_unroll32(start,Hit_Writeback_Inv_D);
176+ start += 0x400;
177+ } while (start < end);
178+
179+ SYNC_WB();
180+}
181+
182+static inline void blast_dcache32_page_indexed(unsigned long page)
183+{
184+ unsigned long indexmask = current_cpu_data.dcache.waysize - 1;
185+ unsigned long start = INDEX_BASE + (page & indexmask);
186+ unsigned long end = start + PAGE_SIZE;
187+ unsigned long ws_inc = 1UL << current_cpu_data.dcache.waybit;
188+ unsigned long ws_end = current_cpu_data.dcache.ways <<
189+ current_cpu_data.dcache.waybit;
190+ unsigned long ws, addr;
191+
192+ for (ws = 0; ws < ws_end; ws += ws_inc)
193+ for (addr = start; addr < end; addr += 0x400)
194+ cache32_unroll32(addr|ws,Index_Writeback_Inv_D);
195+
196+ SYNC_WB();
197+}
198+
199+static inline void blast_icache32(void)
200+{
201+ unsigned long start = INDEX_BASE;
202+ unsigned long end = start + current_cpu_data.icache.waysize;
203+ unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
204+ unsigned long ws_end = current_cpu_data.icache.ways <<
205+ current_cpu_data.icache.waybit;
206+ unsigned long ws, addr;
207+
208+ K0_TO_K1();
209+
210+ for (ws = 0; ws < ws_end; ws += ws_inc)
211+ for (addr = start; addr < end; addr += 0x400)
212+ cache32_unroll32(addr|ws,Index_Invalidate_I);
213+
214+ INVALIDATE_BTB();
215+
216+ K1_TO_K0();
217+}
218+
219+static inline void blast_icache32_page(unsigned long page)
220+{
221+ unsigned long start = page;
222+ unsigned long end = page + PAGE_SIZE;
223+
224+ K0_TO_K1();
225+
226+ do {
227+ cache32_unroll32(start,Hit_Invalidate_I);
228+ start += 0x400;
229+ } while (start < end);
230+
231+ INVALIDATE_BTB();
232+
233+ K1_TO_K0();
234+}
235+
236+static inline void blast_icache32_page_indexed(unsigned long page)
237+{
238+ unsigned long indexmask = current_cpu_data.icache.waysize - 1;
239+ unsigned long start = INDEX_BASE + (page & indexmask);
240+ unsigned long end = start + PAGE_SIZE;
241+ unsigned long ws_inc = 1UL << current_cpu_data.icache.waybit;
242+ unsigned long ws_end = current_cpu_data.icache.ways <<
243+ current_cpu_data.icache.waybit;
244+ unsigned long ws, addr;
245+
246+ K0_TO_K1();
247+
248+ for (ws = 0; ws < ws_end; ws += ws_inc)
249+ for (addr = start; addr < end; addr += 0x400)
250+ cache32_unroll32(addr|ws,Index_Invalidate_I);
251+
252+ INVALIDATE_BTB();
253+
254+ K1_TO_K0();
255+}
256+
257+#endif /* CONFIG_JZRISC */
258+
259 /* build blast_xxx_range, protected_blast_xxx_range */
260 #define __BUILD_BLAST_CACHE_RANGE(pfx, desc, hitop, prot) \
261 static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
262@@ -432,13 +603,73 @@ static inline void prot##blast_##pfx##cache##_range(unsigned long start, \
263     __##pfx##flush_epilogue \
264 }
265
266+#ifndef CONFIG_JZRISC
267 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, protected_)
268+#endif
269 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, protected_)
270+#ifndef CONFIG_JZRISC
271 __BUILD_BLAST_CACHE_RANGE(i, icache, Hit_Invalidate_I, protected_)
272 __BUILD_BLAST_CACHE_RANGE(d, dcache, Hit_Writeback_Inv_D, )
273+#endif
274 __BUILD_BLAST_CACHE_RANGE(s, scache, Hit_Writeback_Inv_SD, )
275 /* blast_inv_dcache_range */
276 __BUILD_BLAST_CACHE_RANGE(inv_d, dcache, Hit_Invalidate_D, )
277 __BUILD_BLAST_CACHE_RANGE(inv_s, scache, Hit_Invalidate_SD, )
278
279+#ifdef CONFIG_JZRISC
280+
281+static inline void protected_blast_dcache_range(unsigned long start,
282+ unsigned long end)
283+{
284+ unsigned long lsize = cpu_dcache_line_size();
285+ unsigned long addr = start & ~(lsize - 1);
286+ unsigned long aend = (end - 1) & ~(lsize - 1);
287+
288+ while (1) {
289+ protected_cache_op(Hit_Writeback_Inv_D, addr);
290+ if (addr == aend)
291+ break;
292+ addr += lsize;
293+ }
294+ SYNC_WB();
295+}
296+
297+static inline void protected_blast_icache_range(unsigned long start,
298+ unsigned long end)
299+{
300+ unsigned long lsize = cpu_icache_line_size();
301+ unsigned long addr = start & ~(lsize - 1);
302+ unsigned long aend = (end - 1) & ~(lsize - 1);
303+
304+ K0_TO_K1();
305+
306+ while (1) {
307+ protected_cache_op(Hit_Invalidate_I, addr);
308+ if (addr == aend)
309+ break;
310+ addr += lsize;
311+ }
312+ INVALIDATE_BTB();
313+
314+ K1_TO_K0();
315+}
316+
317+static inline void blast_dcache_range(unsigned long start,
318+ unsigned long end)
319+{
320+ unsigned long lsize = cpu_dcache_line_size();
321+ unsigned long addr = start & ~(lsize - 1);
322+ unsigned long aend = (end - 1) & ~(lsize - 1);
323+
324+ while (1) {
325+ cache_op(Hit_Writeback_Inv_D, addr);
326+ if (addr == aend)
327+ break;
328+ addr += lsize;
329+ }
330+ SYNC_WB();
331+}
332+
333+#endif /* CONFIG_JZRISC */
334+
335 #endif /* _ASM_R4KCACHE_H */
336--
3371.7.4.1
338
target/linux/xburst/patches-3.1/0002-Add-n516-board-support.patch
1From f234576c4988ceecc5270491629ff474f3c761ae Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sat, 24 Apr 2010 17:25:01 +0200
4Subject: [PATCH 02/24] Add n516 board support
5
6---
7 arch/mips/include/asm/mach-jz4740/board-n516.h | 39 +++
8 arch/mips/jz4740/Kconfig | 4 +
9 arch/mips/jz4740/Makefile | 1 +
10 arch/mips/jz4740/board-n516-display.c | 394 ++++++++++++++++++++++++
11 arch/mips/jz4740/board-n516.c | 182 +++++++++++
12 5 files changed, 620 insertions(+), 0 deletions(-)
13 create mode 100644 arch/mips/include/asm/mach-jz4740/board-n516.h
14 create mode 100644 arch/mips/jz4740/board-n516-display.c
15 create mode 100644 arch/mips/jz4740/board-n516.c
16
17diff --git a/arch/mips/include/asm/mach-jz4740/board-n516.h b/arch/mips/include/asm/mach-jz4740/board-n516.h
18new file mode 100644
19index 0000000..090707e
20--- /dev/null
21@@ -0,0 +1,39 @@
22+/*
23+ * linux/include/asm-mips/mach-jz4740/board-n516.h
24+ *
25+ * JZ4730-based N516 board definition.
26+ *
27+ * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
28+ *
29+ * This program is free software; you can redistribute it and/or modify
30+ * it under the terms of the GNU General Public License as published by
31+ * the Free Software Foundation; either version 2 of the License, or
32+ * (at your option) any later version.
33+ */
34+
35+#ifndef __ASM_JZ4740_N516_H__
36+#define __ASM_JZ4740_N516_H__
37+
38+#include <asm/mach-jz4740/gpio.h>
39+
40+/*
41+ * GPIO
42+ */
43+#define GPIO_SD_VCC_EN_N JZ_GPIO_PORTD(17)
44+#define GPIO_SD_CD_N JZ_GPIO_PORTD(7)
45+#define GPIO_SD_WP JZ_GPIO_PORTD(15)
46+#define GPIO_USB_DETECT JZ_GPIO_PORTD(19)
47+#define GPIO_CHARG_STAT_N JZ_GPIO_PORTD(16)
48+#define GPIO_LED_ENABLE JZ_GPIO_PORTD(28)
49+#define GPIO_LPC_INT JZ_GPIO_PORTD(14)
50+#define GPIO_HPHONE_DETECT JZ_GPIO_PORTD(20)
51+#define GPIO_SPEAKER_ENABLE JZ_GPIO_PORTD(21)
52+
53+/* Display */
54+#define GPIO_DISPLAY_RST_L JZ_GPIO_PORTB(18)
55+#define GPIO_DISPLAY_RDY JZ_GPIO_PORTB(17)
56+#define GPIO_DISPLAY_STBY JZ_GPIO_PORTC(22)
57+#define GPIO_DISPLAY_ERR JZ_GPIO_PORTC(23)
58+#define GPIO_DISPLAY_OFF_N JZ_GPIO_PORTD(1)
59+
60+#endif /* __ASM_JZ4740_N516_H__ */
61diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
62index 3e7141f..85bfbf3 100644
63--- a/arch/mips/jz4740/Kconfig
64@@ -6,6 +6,10 @@ choice
65 config JZ4740_QI_LB60
66     bool "Qi Hardware Ben NanoNote"
67
68+config JZ4740_N516
69+ bool "Hanvon n516 eBook reader"
70+ select SOC_JZ4740
71+
72 endchoice
73
74 config HAVE_PWM
75diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
76index a9dff33..727270a 100644
77--- a/arch/mips/jz4740/Makefile
78@@ -12,6 +12,7 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
79 # board specific support
80
81 obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
82+obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o
83
84 # PM support
85
86diff --git a/arch/mips/jz4740/board-n516-display.c b/arch/mips/jz4740/board-n516-display.c
87new file mode 100644
88index 0000000..0e77a82
89--- /dev/null
90@@ -0,0 +1,394 @@
91+/*
92+ * board-n516-display.c -- Platform device for N516 display
93+ *
94+ * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
95+ *
96+ * This file is subject to the terms and conditions of the GNU General Public
97+ * License. See the file COPYING in the main directory of this archive for
98+ * more details.
99+ */
100+
101+#include <linux/module.h>
102+#include <linux/kernel.h>
103+#include <linux/errno.h>
104+#include <linux/string.h>
105+#include <linux/delay.h>
106+#include <linux/interrupt.h>
107+#include <linux/fb.h>
108+#include <linux/init.h>
109+#include <linux/platform_device.h>
110+#include <linux/irq.h>
111+#include <linux/gpio.h>
112+
113+#include <asm/mach-jz4740/jz4740_fb.h>
114+
115+#include <asm/mach-jz4740/platform.h>
116+#include <asm/mach-jz4740/board-n516.h>
117+
118+#include <video/metronomefb.h>
119+#include <linux/console.h>
120+
121+static struct fb_videomode n516_fb_modes[] = {
122+ [0] = {
123+ .name = "Metronome 800x600",
124+ .refresh = 50,
125+ .xres = 400,
126+ .yres = 624,
127+ .hsync_len = 31,
128+ .vsync_len = 23,
129+ .right_margin = 31,
130+ .left_margin = 5,
131+ .upper_margin = 1,
132+ .lower_margin = 2,
133+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
134+ },
135+};
136+
137+static struct jz4740_fb_platform_data n516_fb_pdata = {
138+ .num_modes = ARRAY_SIZE(n516_fb_modes),
139+ .modes = n516_fb_modes,
140+ .bpp = 16,
141+ .lcd_type = JZ_LCD_TYPE_GENERIC_16_BIT,
142+};
143+
144+struct n516_board_info {
145+ uint8_t *metromem;
146+ size_t wfm_size;
147+ struct fb_info *host_fbinfo; /* the host LCD controller's fbi */
148+ unsigned int fw;
149+ unsigned int fh;
150+};
151+
152+static struct platform_device *n516_device;
153+static struct n516_board_info n516_board_info;
154+
155+static int metronome_gpios[] = {
156+ GPIO_DISPLAY_STBY,
157+ GPIO_DISPLAY_RST_L,
158+ GPIO_DISPLAY_RDY,
159+ GPIO_DISPLAY_ERR,
160+/* GPIO_DISPLAY_OFF_N,*/
161+};
162+
163+static const char *metronome_gpio_names[] = {
164+ "Metronome STDBY",
165+ "Metronome RST",
166+ "Metronome RDY",
167+ "Metronome ERR",
168+/* "Metronone OFF",*/
169+};
170+
171+static int n516_enable_hostfb(bool enable)
172+{
173+ int ret;
174+ int blank = enable ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
175+
176+ acquire_console_sem();
177+ ret = fb_blank(n516_board_info.host_fbinfo, blank);
178+ release_console_sem();
179+
180+ return ret;
181+}
182+
183+static int n516_init_metronome_gpios(struct metronomefb_par *par)
184+{
185+ int i;
186+ int ret;
187+
188+ for (i = 0; i < ARRAY_SIZE(metronome_gpios); ++i) {
189+ ret = gpio_request(metronome_gpios[i], metronome_gpio_names[i]);
190+ if (ret)
191+ goto err;
192+ }
193+
194+ gpio_direction_output(GPIO_DISPLAY_OFF_N, 0);
195+ gpio_direction_output(GPIO_DISPLAY_RST_L, 0);
196+ gpio_direction_output(GPIO_DISPLAY_STBY, 0);
197+ gpio_direction_input(GPIO_DISPLAY_RDY);
198+ gpio_direction_input(GPIO_DISPLAY_ERR);
199+
200+ return 0;
201+err:
202+ for (--i; i >= 0; --i)
203+ gpio_free(metronome_gpios[i]);
204+
205+ return ret;
206+}
207+
208+static int n516_share_video_mem(struct fb_info *info)
209+{
210+ int ret;
211+
212+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
213+ dev_dbg(&n516_device->dev, "%s, info->var.xres = %u, info->var.yres = %u\n", __func__, info->var.xres, info->var.yres);
214+ /* rough check if this is our desired fb and not something else */
215+ if ((info->var.xres != n516_fb_pdata.modes[0].xres)
216+ || (info->var.yres != n516_fb_pdata.modes[0].yres))
217+ return 0;
218+
219+ /* we've now been notified that we have our new fb */
220+ n516_board_info.metromem = info->screen_base;
221+ n516_board_info.host_fbinfo = info;
222+
223+ n516_enable_hostfb(false);
224+ /* try to refcount host drv since we are the consumer after this */
225+ if (!try_module_get(info->fbops->owner))
226+ return -ENODEV;
227+
228+ /* this _add binds metronomefb to n516. metronomefb refcounts n516 */
229+ ret = platform_device_add(n516_device);
230+
231+ if (ret) {
232+ platform_device_put(n516_device);
233+ return ret;
234+ }
235+
236+ /* request our platform independent driver */
237+ request_module("metronomefb");
238+
239+ return 0;
240+}
241+
242+static int n516_unshare_video_mem(struct fb_info *info)
243+{
244+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
245+
246+ if (info != n516_board_info.host_fbinfo)
247+ return 0;
248+
249+ module_put(n516_board_info.host_fbinfo->fbops->owner);
250+ return 0;
251+}
252+
253+static int n516_fb_notifier_callback(struct notifier_block *self,
254+ unsigned long event, void *data)
255+{
256+ struct fb_event *evdata = data;
257+ struct fb_info *info = evdata->info;
258+
259+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
260+
261+ if (event == FB_EVENT_FB_REGISTERED)
262+ return n516_share_video_mem(info);
263+ else if (event == FB_EVENT_FB_UNREGISTERED)
264+ return n516_unshare_video_mem(info);
265+
266+ return 0;
267+}
268+
269+static struct notifier_block n516_fb_notif = {
270+ .notifier_call = n516_fb_notifier_callback,
271+};
272+
273+/* this gets called as part of our init. these steps must be done now so
274+ * that we can use set_pxa_fb_info */
275+static void __init n516_presetup_fb(void)
276+{
277+ int padding_size;
278+ int totalsize;
279+
280+ /* the frame buffer is divided as follows:
281+ command | CRC | padding
282+ 16kb waveform data | CRC | padding
283+ image data | CRC
284+ */
285+
286+ n516_board_info.fw = 800;
287+ n516_board_info.fh = 624;
288+
289+ /* waveform must be 16k + 2 for checksum */
290+ n516_board_info.wfm_size = roundup(16*1024 + 2, n516_board_info.fw);
291+
292+ padding_size = PAGE_SIZE + (4 * n516_board_info.fw);
293+
294+ /* total is 1 cmd , 1 wfm, padding and image */
295+ totalsize = n516_board_info.fw + n516_board_info.wfm_size;
296+ totalsize += padding_size + (n516_board_info.fw*n516_board_info.fh);
297+
298+ /* save this off because we're manipulating fw after this and
299+ * we'll need it when we're ready to setup the framebuffer */
300+
301+ /* the reason we do this adjustment is because we want to acquire
302+ * more framebuffer memory without imposing custom awareness on the
303+ * underlying driver */
304+ n516_fb_pdata.modes[0].yres = DIV_ROUND_UP(totalsize, n516_board_info.fw);
305+
306+ jz4740_framebuffer_device.dev.platform_data = &n516_fb_pdata;
307+ platform_device_register(&jz4740_framebuffer_device);
308+}
309+
310+/* this gets called by metronomefb as part of its init, in our case, we
311+ * have already completed initial framebuffer init in presetup_fb so we
312+ * can just setup the fb access pointers */
313+static int n516_setup_fb(struct metronomefb_par *par)
314+{
315+ /* metromem was set up by the notifier in share_video_mem so now
316+ * we can use its value to calculate the other entries */
317+ par->metromem_cmd = (struct metromem_cmd *) n516_board_info.metromem;
318+ par->metromem_wfm = n516_board_info.metromem + n516_board_info.fw;
319+ par->metromem_img = par->metromem_wfm + n516_board_info.wfm_size;
320+ par->metromem_img_csum = (u16 *) (par->metromem_img + (n516_board_info.fw * n516_board_info.fh));
321+ par->metromem_dma = n516_board_info.host_fbinfo->fix.smem_start;
322+
323+ return 0;
324+}
325+
326+static int n516_get_panel_type(void)
327+{
328+ return 5;
329+}
330+
331+static irqreturn_t n516_handle_irq(int irq, void *dev_id)
332+{
333+ struct metronomefb_par *par = dev_id;
334+
335+ dev_dbg(&par->pdev->dev, "Metronome IRQ! RDY=%d\n", gpio_get_value(GPIO_DISPLAY_RDY));
336+ wake_up_all(&par->waitq);
337+
338+ return IRQ_HANDLED;
339+}
340+
341+static void n516_power_ctl(struct metronomefb_par *par, int cmd)
342+{
343+ switch (cmd) {
344+ case METRONOME_POWER_OFF:
345+ gpio_set_value(GPIO_DISPLAY_OFF_N, 1);
346+ n516_enable_hostfb(false);
347+ break;
348+ case METRONOME_POWER_ON:
349+ gpio_set_value(GPIO_DISPLAY_OFF_N, 0);
350+ n516_enable_hostfb(true);
351+ break;
352+ }
353+}
354+
355+static int n516_get_rdy(struct metronomefb_par *par)
356+{
357+ return gpio_get_value(GPIO_DISPLAY_RDY);
358+}
359+
360+static int n516_get_err(struct metronomefb_par *par)
361+{
362+ return gpio_get_value(GPIO_DISPLAY_ERR);
363+}
364+
365+static int n516_setup_irq(struct fb_info *info)
366+{
367+ int ret;
368+
369+ dev_dbg(&n516_device->dev, "ENTER %s\n", __func__);
370+
371+ ret = request_irq(gpio_to_irq(GPIO_DISPLAY_RDY), n516_handle_irq,
372+ IRQF_TRIGGER_RISING,
373+ "n516", info->par);
374+ if (ret)
375+ dev_err(&n516_device->dev, "request_irq failed: %d\n", ret);
376+
377+ return ret;
378+}
379+
380+static void n516_set_rst(struct metronomefb_par *par, int state)
381+{
382+ dev_dbg(&n516_device->dev, "ENTER %s, RDY=%d\n", __func__, gpio_get_value(GPIO_DISPLAY_RDY));
383+ if (state)
384+ gpio_set_value(GPIO_DISPLAY_RST_L, 1);
385+ else
386+ gpio_set_value(GPIO_DISPLAY_RST_L, 0);
387+}
388+
389+static void n516_set_stdby(struct metronomefb_par *par, int state)
390+{
391+ dev_dbg(&n516_device->dev, "ENTER %s, RDY=%d\n", __func__, gpio_get_value(GPIO_DISPLAY_RDY));
392+ if (state)
393+ gpio_set_value(GPIO_DISPLAY_STBY, 1);
394+ else
395+ gpio_set_value(GPIO_DISPLAY_STBY, 0);
396+}
397+
398+static int n516_wait_event(struct metronomefb_par *par)
399+{
400+ unsigned long timeout = jiffies + HZ / 20;
401+
402+ dev_dbg(&n516_device->dev, "ENTER1 %s, RDY=%d\n",
403+ __func__, gpio_get_value(GPIO_DISPLAY_RDY));
404+ while (n516_get_rdy(par) && time_before(jiffies, timeout))
405+ schedule();
406+
407+ dev_dbg(&n516_device->dev, "ENTER2 %s, RDY=%d\n",
408+ __func__, gpio_get_value(GPIO_DISPLAY_RDY));
409+ return wait_event_timeout(par->waitq,
410+ n516_get_rdy(par), HZ * 2) ? 0 : -EIO;
411+}
412+
413+static int n516_wait_event_intr(struct metronomefb_par *par)
414+{
415+ unsigned long timeout = jiffies + HZ/20;
416+
417+ dev_dbg(&n516_device->dev, "ENTER1 %s, RDY=%d\n",
418+ __func__, gpio_get_value(GPIO_DISPLAY_RDY));
419+ while (n516_get_rdy(par) && time_before(jiffies, timeout))
420+ schedule();
421+
422+ dev_dbg(&n516_device->dev, "ENTER2 %s, RDY=%d\n",
423+ __func__, gpio_get_value(GPIO_DISPLAY_RDY));
424+ return wait_event_interruptible_timeout(par->waitq,
425+ n516_get_rdy(par), HZ * 2) ? 0 : -EIO;
426+}
427+
428+static void n516_cleanup(struct metronomefb_par *par)
429+{
430+ int i;
431+
432+ free_irq(gpio_to_irq(GPIO_DISPLAY_RDY), par);
433+ for (i = 0; i < ARRAY_SIZE(metronome_gpios); ++i)
434+ gpio_free(metronome_gpios[i]);
435+}
436+
437+static struct metronome_board n516_board __initdata = {
438+ .owner = THIS_MODULE,
439+ .power_ctl = n516_power_ctl,
440+ .setup_irq = n516_setup_irq,
441+ .setup_io = n516_init_metronome_gpios,
442+ .setup_fb = n516_setup_fb,
443+ .set_rst = n516_set_rst,
444+ .get_err = n516_get_err,
445+ .get_rdy = n516_get_rdy,
446+ .set_stdby = n516_set_stdby,
447+ .met_wait_event = n516_wait_event,
448+ .met_wait_event_intr = n516_wait_event_intr,
449+ .get_panel_type = n516_get_panel_type,
450+ .cleanup = n516_cleanup,
451+};
452+
453+static int __init n516_init(void)
454+{
455+ int ret;
456+
457+ /* Keep the metronome off, until its driver is loaded */
458+ ret = gpio_request(GPIO_DISPLAY_OFF_N, "Display off");
459+ if (ret)
460+ return ret;
461+
462+ gpio_direction_output(GPIO_DISPLAY_OFF_N, 1);
463+
464+ /* before anything else, we request notification for any fb
465+ * creation events */
466+ fb_register_client(&n516_fb_notif);
467+
468+ n516_device = platform_device_alloc("metronomefb", -1);
469+ if (!n516_device)
470+ return -ENOMEM;
471+
472+ /* the n516_board that will be seen by metronomefb is a copy */
473+ platform_device_add_data(n516_device, &n516_board,
474+ sizeof(n516_board));
475+
476+ n516_presetup_fb();
477+
478+ return 0;
479+}
480+module_init(n516_init);
481+
482+MODULE_DESCRIPTION("board driver for n516 display");
483+MODULE_AUTHOR("Yauhen Kharuzhy");
484+MODULE_LICENSE("GPL");
485diff --git a/arch/mips/jz4740/board-n516.c b/arch/mips/jz4740/board-n516.c
486new file mode 100644
487index 0000000..678885c
488--- /dev/null
489@@ -0,0 +1,182 @@
490+/*
491+ * linux/arch/mips/jz4740/board-516.c
492+ *
493+ * JZ4740 n516 board setup routines.
494+ *
495+ * Copyright (c) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
496+ *
497+ * This program is free software; you can redistribute it and/or modify
498+ * it under the terms of the GNU General Public License as published by
499+ * the Free Software Foundation; either version 2 of the License, or
500+ * (at your option) any later version.
501+ */
502+
503+#include <linux/init.h>
504+#include <linux/sched.h>
505+#include <linux/ioport.h>
506+#include <linux/mm.h>
507+#include <linux/console.h>
508+#include <linux/delay.h>
509+#include <linux/i2c.h>
510+#include <linux/platform_device.h>
511+#include <linux/mtd/mtd.h>
512+#include <linux/leds.h>
513+
514+#include <linux/power_supply.h>
515+#include <linux/power/gpio-charger.h>
516+
517+#include <linux/i2c.h>
518+
519+#include <asm/mach-jz4740/jz4740_mmc.h>
520+#include <asm/mach-jz4740/jz4740_nand.h>
521+
522+#include <asm/mach-jz4740/board-n516.h>
523+#include <asm/mach-jz4740/platform.h>
524+
525+#include "clock.h"
526+
527+static long n516_panic_blink(int state)
528+{
529+ gpio_set_value(GPIO_LED_ENABLE, state ? 1 : 0);
530+ return 0;
531+}
532+
533+static void __init board_gpio_setup(void)
534+{
535+/* jz_gpio_enable_pullup(JZ_GPIO_PORTD(23));
536+ jz_gpio_enable_pullup(JZ_GPIO_PORTD(24));*/
537+}
538+
539+static const struct i2c_board_info n516_i2c_board_info[] = {
540+ {
541+ .type = "LPC524",
542+ .addr = 0x54,
543+ },
544+ {
545+ .type = "lm75a",
546+ .addr = 0x48,
547+ }
548+};
549+
550+static struct jz4740_mmc_platform_data n516_mmc_pdata = {
551+ .gpio_card_detect = GPIO_SD_CD_N,
552+ .card_detect_active_low = 1,
553+ .gpio_read_only = -1,
554+ .gpio_power = GPIO_SD_VCC_EN_N,
555+ .power_active_low = 1,
556+};
557+
558+static struct gpio_led n516_leds[] = {
559+ {
560+ .name = "n516:blue:power",
561+ .gpio = GPIO_LED_ENABLE,
562+ .default_state = LEDS_GPIO_DEFSTATE_ON,
563+ .default_trigger = "nand-disk",
564+ }
565+};
566+
567+static struct gpio_led_platform_data n516_leds_pdata = {
568+ .leds = n516_leds,
569+ .num_leds = ARRAY_SIZE(n516_leds),
570+};
571+
572+static struct platform_device n516_leds_device = {
573+ .name = "leds-gpio",
574+ .id = -1,
575+ .dev = {
576+ .platform_data = &n516_leds_pdata,
577+ },
578+};
579+
580+static struct mtd_partition n516_partitions[] = {
581+ { .name = "NAND BOOT partition",
582+ .offset = 0 * 0x100000,
583+ .size = 4 * 0x100000,
584+ },
585+ { .name = "NAND KERNEL partition",
586+ .offset = 4 * 0x100000,
587+ .size = 4 * 0x100000,
588+ },
589+ { .name = "NAND ROOTFS partition",
590+ .offset = 8 * 0x100000,
591+ .size = 504 * 0x100000,
592+ },
593+};
594+
595+static struct nand_ecclayout n516_ecclayout = {
596+ .eccbytes = 36,
597+ .eccpos = {
598+ 6, 7, 8, 9, 10, 11, 12, 13, 14,
599+ 15, 16, 17, 18, 19, 20, 21, 22, 23,
600+ 24, 25, 26, 27, 28, 29, 30, 31, 32,
601+ 33, 34, 35, 36, 37, 38, 39, 40, 41,
602+ },
603+ .oobfree = {
604+ {
605+ .offset = 2,
606+ .length = 4
607+ },
608+ {
609+ .offset = 42,
610+ .length = 22,
611+ }
612+ }
613+};
614+
615+static struct jz_nand_platform_data n516_nand_pdata = {
616+ .ecc_layout = &n516_ecclayout,
617+ .partitions = n516_partitions,
618+ .num_partitions = ARRAY_SIZE(n516_partitions),
619+ .busy_gpio = 94,
620+};
621+
622+static char *n516_batteries[] = {
623+ "n516_battery",
624+};
625+
626+static struct gpio_charger_platform_data n516_charger_pdata = {
627+ .name = "usb",
628+ .type = POWER_SUPPLY_TYPE_USB,
629+ .gpio = GPIO_USB_DETECT,
630+ .gpio_active_low = 1,
631+ .batteries = n516_batteries,
632+ .num_batteries = ARRAY_SIZE(n516_batteries),
633+};
634+
635+static struct platform_device n516_charger_device = {
636+ .name = "gpio-charger",
637+ .dev = {
638+ .platform_data = &n516_charger_pdata,
639+ },
640+};
641+
642+static struct platform_device *n516_devices[] __initdata = {
643+ &jz4740_nand_device,
644+ &n516_leds_device,
645+ &jz4740_mmc_device,
646+ &jz4740_i2s_device,
647+ &jz4740_codec_device,
648+ &jz4740_rtc_device,
649+ &jz4740_udc_device,
650+ &jz4740_i2c_device,
651+ &n516_charger_device,
652+};
653+
654+struct jz4740_clock_board_data jz4740_clock_bdata = {
655+ .ext_rate = 12000000,
656+ .rtc_rate = 32768,
657+};
658+
659+static int n516_setup_platform(void)
660+{
661+ jz4740_serial_device_register();
662+ board_gpio_setup();
663+
664+ panic_blink = n516_panic_blink;
665+ i2c_register_board_info(0, n516_i2c_board_info, ARRAY_SIZE(n516_i2c_board_info));
666+ jz4740_mmc_device.dev.platform_data = &n516_mmc_pdata;
667+ jz4740_nand_device.dev.platform_data = &n516_nand_pdata;
668+
669+ return platform_add_devices(n516_devices, ARRAY_SIZE(n516_devices));
670+}
671+arch_initcall(n516_setup_platform);
672--
6731.7.4.1
674
target/linux/xburst/patches-3.1/0003-Add-n526-board-support.patch
1From 0014ec2fd9e50a38ef45ee01c663b6e902c68da1 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sat, 24 Apr 2010 17:25:23 +0200
4Subject: [PATCH 03/24] Add n526 board support
5
6---
7 arch/mips/jz4740/Kconfig | 4 +
8 arch/mips/jz4740/Makefile | 1 +
9 arch/mips/jz4740/board-n526.c | 320 +++++++++++++++++++++++++++++++++++++++++
10 3 files changed, 325 insertions(+), 0 deletions(-)
11 create mode 100644 arch/mips/jz4740/board-n526.c
12
13diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
14index 85bfbf3..2f366d7 100644
15--- a/arch/mips/jz4740/Kconfig
16@@ -10,6 +10,10 @@ config JZ4740_N516
17     bool "Hanvon n516 eBook reader"
18     select SOC_JZ4740
19
20+config JZ4740_N526
21+ bool "Hanvon n526 eBook reader"
22+ select SOC_JZ4740
23+
24 endchoice
25
26 config HAVE_PWM
27diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
28index 727270a..e8f2904 100644
29--- a/arch/mips/jz4740/Makefile
30@@ -13,6 +13,7 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
31
32 obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
33 obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o
34+obj-$(CONFIG_JZ4740_N526) += board-n526.o
35
36 # PM support
37
38diff --git a/arch/mips/jz4740/board-n526.c b/arch/mips/jz4740/board-n526.c
39new file mode 100644
40index 0000000..494c4cb
41--- /dev/null
42@@ -0,0 +1,320 @@
43+/*
44+ * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
45+ * N526 eBook reader support
46+ *
47+ * This program is free software; you can redistribute it and/or modify it
48+ * under the terms of the GNU General Public License as published by the
49+ * Free Software Foundation; either version 2 of the License, or (at your
50+ * option) any later version.
51+ *
52+ * You should have received a copy of the GNU General Public License along
53+ * with this program; if not, write to the Free Software Foundation, Inc.,
54+ * 675 Mass Ave, Cambridge, MA 02139, USA.
55+ *
56+ */
57+
58+#include <linux/kernel.h>
59+#include <linux/init.h>
60+#include <linux/gpio.h>
61+
62+#include <linux/mutex.h>
63+#include <linux/wait.h>
64+#include <video/broadsheetfb.h>
65+#include <linux/delay.h>
66+#include <linux/interrupt.h>
67+
68+#include <linux/input.h>
69+#include <linux/gpio_keys.h>
70+
71+#include <linux/leds.h>
72+
73+#include <linux/i2c.h>
74+
75+#include "clock.h"
76+
77+#include <asm/mach-jz4740/jz4740_mmc.h>
78+#include <asm/mach-jz4740/jz4740_nand.h>
79+#include <asm/mach-jz4740/jz4740_fb.h>
80+
81+#include <asm/mach-jz4740/platform.h>
82+
83+/* NAND */
84+static struct nand_ecclayout n526_ecclayout = {
85+ .eccbytes = 36,
86+ .eccpos = {
87+ 6, 7, 8, 9, 10, 11, 12, 13,
88+ 14, 15, 16, 17, 18, 19, 20, 21,
89+ 22, 23, 24, 25, 26, 27, 28, 29,
90+ 30, 31, 32, 33, 34, 35, 36, 37,
91+ 38, 39, 40, 41},
92+ .oobfree = {
93+ {
94+ .offset = 2,
95+ .length = 4,
96+ },
97+ {
98+ .offset = 42,
99+ .length = 22,
100+ },
101+ }
102+};
103+
104+static struct mtd_partition n526_partitions[] = {
105+ { .name = "NAND BOOT partition",
106+ .offset = 0 * 0x100000,
107+ .size = 4 * 0x100000,
108+ },
109+ { .name = "NAND KERNEL partition",
110+ .offset = 4 * 0x100000,
111+ .size = 4 * 0x100000,
112+ },
113+ { .name = "NAND ROOTFS partition",
114+ .offset = 16 * 0x100000,
115+ .size = 498 * 0x100000,
116+ },
117+};
118+
119+static struct jz_nand_platform_data n526_nand_pdata = {
120+ .ecc_layout = &n526_ecclayout,
121+ .partitions = n526_partitions,
122+ .num_partitions = ARRAY_SIZE(n526_partitions),
123+ .busy_gpio = JZ_GPIO_PORTC(30),
124+};
125+
126+static struct jz4740_mmc_platform_data n526_mmc_pdata = {
127+ .gpio_card_detect = JZ_GPIO_PORTD(7),
128+ .card_detect_active_low = 1,
129+ .gpio_read_only = -1,
130+ .gpio_power = JZ_GPIO_PORTD(17),
131+ .power_active_low = 1,
132+};
133+
134+static struct gpio_led n526_leds[] = {
135+ {
136+ .name = "n526:blue:power",
137+ .gpio = JZ_GPIO_PORTD(28),
138+ .default_state = LEDS_GPIO_DEFSTATE_ON,
139+ }
140+};
141+
142+static struct gpio_led_platform_data n526_leds_pdata = {
143+ .leds = n526_leds,
144+ .num_leds = ARRAY_SIZE(n526_leds),
145+};
146+
147+static struct platform_device n526_leds_device = {
148+ .name = "leds-gpio",
149+ .id = -1,
150+ .dev = {
151+ .platform_data = &n526_leds_pdata,
152+ },
153+};
154+
155+static void __init board_gpio_setup(void)
156+{
157+ /* We only need to enable/disable pullup here for pins used in generic
158+ * drivers. Everything else is done by the drivers themselfs. */
159+ jz_gpio_disable_pullup(JZ_GPIO_PORTD(17));
160+ jz_gpio_enable_pullup(JZ_GPIO_PORTD(7));
161+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(19));
162+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(20));
163+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(21));
164+ jz_gpio_disable_pullup(JZ_GPIO_PORTC(23));
165+}
166+
167+
168+static const int n526_eink_ctrl_gpios[] = {
169+ 0,
170+ JZ_GPIO_PORTC(23),
171+ JZ_GPIO_PORTC(19),
172+ JZ_GPIO_PORTC(20),
173+};
174+
175+static void n526_eink_set_ctl(struct broadsheetfb_par * par, unsigned char ctrl, u8
176+value)
177+{
178+ gpio_set_value(n526_eink_ctrl_gpios[ctrl], value);
179+}
180+
181+
182+static int n526_eink_wait(struct broadsheetfb_par *par)
183+{
184+ wait_event(par->waitq, gpio_get_value(JZ_GPIO_PORTB(17)));
185+
186+ return 0;
187+}
188+
189+static u16 n526_eink_get_hdb(struct broadsheetfb_par *par)
190+{
191+ u16 value = 0;
192+ jz_gpio_port_direction_input(JZ_GPIO_PORTC(0), 0xffff);
193+ gpio_set_value(JZ_GPIO_PORTC(21), 0);
194+ mdelay(100);
195+
196+ value = jz_gpio_port_get_value(JZ_GPIO_PORTC(0), 0xffff);
197+
198+ gpio_set_value(JZ_GPIO_PORTC(21), 1);
199+ jz_gpio_port_direction_output(JZ_GPIO_PORTC(0), 0xffff);
200+ return value;
201+}
202+
203+static void n526_eink_set_hdb(struct broadsheetfb_par *par, u16 value)
204+{
205+ jz_gpio_port_set_value(JZ_GPIO_PORTC(0), value, 0xffff);
206+}
207+
208+static int n526_eink_init(struct broadsheetfb_par *par)
209+{
210+ int i;
211+
212+ gpio_request(JZ_GPIO_PORTD(1), "display reset");
213+ gpio_direction_output(JZ_GPIO_PORTD(1), 1);
214+ mdelay(10);
215+ gpio_set_value(JZ_GPIO_PORTD(1), 0);
216+
217+ gpio_request(JZ_GPIO_PORTB(18), "eink enable");
218+ gpio_direction_output(JZ_GPIO_PORTB(18), 0);
219+
220+ gpio_request(JZ_GPIO_PORTB(29), "foobar");
221+ gpio_direction_output(JZ_GPIO_PORTB(29), 1);
222+
223+ for(i = 1; i < ARRAY_SIZE(n526_eink_ctrl_gpios); ++i) {
224+ gpio_request(n526_eink_ctrl_gpios[i], "eink display ctrl");
225+ gpio_direction_output(n526_eink_ctrl_gpios[i], 0);
226+ }
227+
228+ gpio_request(JZ_GPIO_PORTC(22), "foobar");
229+ gpio_direction_input(JZ_GPIO_PORTC(22));
230+ gpio_request(JZ_GPIO_PORTC(21), "eink nRD");
231+ gpio_direction_output(JZ_GPIO_PORTC(21), 1);
232+
233+ for(i = 0; i < 16; ++i) {
234+ gpio_request(JZ_GPIO_PORTC(i), "eink display data");
235+ }
236+ jz_gpio_port_direction_output(JZ_GPIO_PORTC(0), 0xffff);
237+
238+ gpio_set_value(JZ_GPIO_PORTB(18), 1);
239+
240+ return 0;
241+}
242+
243+static irqreturn_t n526_eink_busy_irq(int irq, void *devid)
244+{
245+ struct broadsheetfb_par *par = devid;
246+ wake_up(&par->waitq);
247+
248+ return IRQ_HANDLED;
249+}
250+
251+static int n526_eink_setup_irq(struct fb_info *info)
252+{
253+ int ret;
254+ struct broadsheetfb_par *par = info->par;
255+
256+ gpio_request(JZ_GPIO_PORTB(17), "eink busy");
257+ gpio_direction_input(JZ_GPIO_PORTB(17));
258+
259+ ret = request_irq(gpio_to_irq(JZ_GPIO_PORTB(17)), n526_eink_busy_irq,
260+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
261+ "eink busyline", par);
262+ if (ret)
263+ printk("n526 display: Failed to request busyline irq: %d\n", ret);
264+ return 0;
265+}
266+
267+static void n526_eink_cleanup(struct broadsheetfb_par *par)
268+{
269+}
270+
271+static struct broadsheet_board broadsheet_pdata = {
272+ .owner = THIS_MODULE,
273+ .init = n526_eink_init,
274+ .wait_for_rdy = n526_eink_wait,
275+ .set_ctl = n526_eink_set_ctl,
276+ .set_hdb = n526_eink_set_hdb,
277+ .get_hdb = n526_eink_get_hdb,
278+ .cleanup = n526_eink_cleanup,
279+ .setup_irq = n526_eink_setup_irq,
280+};
281+
282+static struct platform_device n526_broadsheet_device = {
283+ .name = "broadsheetfb",
284+ .id = -1,
285+ .dev = {
286+ .platform_data = &broadsheet_pdata,
287+ },
288+};
289+
290+/* Buttons */
291+static struct gpio_keys_button n526_gpio_keys_buttons[] = {
292+ [0] = {
293+ .code = KEY_ENTER,
294+ .gpio = 0,
295+ .active_low = 1,
296+ .desc = "Power",
297+ },
298+};
299+
300+static struct gpio_keys_platform_data n526_gpio_keys_data = {
301+ .nbuttons = ARRAY_SIZE(n526_gpio_keys_buttons),
302+ .buttons = n526_gpio_keys_buttons,
303+};
304+
305+static struct platform_device n526_gpio_keys_device = {
306+ .name = "gpio-keys",
307+ .id = -1,
308+ .dev = {
309+ .platform_data = &n526_gpio_keys_data,
310+ }
311+};
312+
313+static struct i2c_board_info n526_i2c_board_info = {
314+ .type = "n526-lpc",
315+ .addr = 0x54,
316+};
317+
318+static struct platform_device *n526_platform_devices[] __initdata = {
319+ &jz4740_usb_ohci_device,
320+ &jz4740_udc_device,
321+ &jz4740_mmc_device,
322+ &jz4740_nand_device,
323+ &jz4740_i2s_device,
324+ &jz4740_codec_device,
325+ &jz4740_pcm_device,
326+ &jz4740_rtc_device,
327+ &jz4740_i2c_device,
328+ &n526_leds_device,
329+ &n526_broadsheet_device,
330+ &n526_gpio_keys_device,
331+};
332+
333+static int __init n526_init_platform_devices(void)
334+{
335+ jz4740_nand_device.dev.platform_data = &n526_nand_pdata;
336+ jz4740_mmc_device.dev.platform_data = &n526_mmc_pdata;
337+
338+ jz4740_serial_device_register();
339+
340+ n526_i2c_board_info.irq = gpio_to_irq(JZ_GPIO_PORTD(14)),
341+ i2c_register_board_info(0, &n526_i2c_board_info, 1);
342+
343+ return platform_add_devices(n526_platform_devices,
344+ ARRAY_SIZE(n526_platform_devices));
345+
346+}
347+
348+struct jz4740_clock_board_data jz4740_clock_bdata = {
349+ .ext_rate = 12000000,
350+ .rtc_rate = 32768,
351+};
352+
353+static int __init n526_board_setup(void)
354+{
355+ board_gpio_setup();
356+
357+ if (n526_init_platform_devices())
358+ panic("Failed to initalize platform devices\n");
359+
360+ return 0;
361+}
362+arch_initcall(n526_board_setup);
363--
3641.7.4.1
365
target/linux/xburst/patches-3.1/0004-MIPS-JZ4740-Add-id800wt-board.patch
1From 563306ff1f5274e2ee2536c7dd3243de8537e568 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sun, 5 Sep 2010 20:34:08 +0200
4Subject: [PATCH 04/24] MIPS: JZ4740: Add id800wt board
5
6---
7 arch/mips/jz4740/Kconfig | 4 +
8 arch/mips/jz4740/Makefile | 1 +
9 arch/mips/jz4740/board-id800wt.c | 158 ++++++++++++++++++++++++++++++++++++++
10 3 files changed, 163 insertions(+), 0 deletions(-)
11 create mode 100644 arch/mips/jz4740/board-id800wt.c
12
13diff --git a/arch/mips/jz4740/Kconfig b/arch/mips/jz4740/Kconfig
14index 2f366d7..680a2bd 100644
15--- a/arch/mips/jz4740/Kconfig
16@@ -14,6 +14,10 @@ config JZ4740_N526
17     bool "Hanvon n526 eBook reader"
18     select SOC_JZ4740
19
20+config JZ4740_ID800WT
21+ bool "Sungale id800wt picture frame"
22+ select SOC_JZ4740
23+
24 endchoice
25
26 config HAVE_PWM
27diff --git a/arch/mips/jz4740/Makefile b/arch/mips/jz4740/Makefile
28index e8f2904..72eb2ad 100644
29--- a/arch/mips/jz4740/Makefile
30@@ -14,6 +14,7 @@ obj-$(CONFIG_DEBUG_FS) += clock-debugfs.o
31 obj-$(CONFIG_JZ4740_QI_LB60) += board-qi_lb60.o
32 obj-$(CONFIG_JZ4740_N516) += board-n516.o board-n516-display.o
33 obj-$(CONFIG_JZ4740_N526) += board-n526.o
34+obj-$(CONFIG_JZ4740_ID800WT) += board-id800wt.o
35
36 # PM support
37
38diff --git a/arch/mips/jz4740/board-id800wt.c b/arch/mips/jz4740/board-id800wt.c
39new file mode 100644
40index 0000000..93fc996
41--- /dev/null
42@@ -0,0 +1,158 @@
43+/*
44+ * Copyright (C) 2010 Lars-Peter Clausen <lars@metafoo.de>
45+ *
46+ * This program is free software; you can redistribute it and/or modify
47+ * it under the terms of the GNU General Public License version 2 or later
48+ * as published by the Free Software Foundation.
49+ */
50+
51+#include <linux/kernel.h>
52+#include <linux/init.h>
53+#include <linux/gpio.h>
54+
55+#include <asm/mach-jz4740/platform.h>
56+
57+#include <linux/input.h>
58+#include <linux/power_supply.h>
59+#include <linux/pwm_backlight.h>
60+
61+#include "clock.h"
62+
63+#include <asm/mach-jz4740/jz4740_fb.h>
64+#include <asm/mach-jz4740/jz4740_nand.h>
65+
66+/* NAND */
67+static struct nand_ecclayout id800wt_ecclayout = {
68+ .oobfree = {
69+ {
70+ .offset = 2,
71+ .length = 4,
72+ },
73+ {
74+ .offset = 42,
75+ .length = 22,
76+ },
77+ }
78+};
79+
80+static struct mtd_partition id800wt_partitions[] = {
81+ { .name = "NAND BOOT partition",
82+ .offset = 0 * 0x100000,
83+ .size = 2 * 0x100000,
84+ },
85+ { .name = "NAND KERNEL partition",
86+ .offset = 2 * 0x100000,
87+ .size = 4 * 0x100000,
88+ },
89+ { .name = "NAND ROOTFS partition",
90+ .offset = 6 * 0x100000,
91+ .size = 498 * 0x100000,
92+ },
93+};
94+
95+static struct jz_nand_platform_data id800wt_nand_pdata = {
96+ .ecc_layout = &id800wt_ecclayout,
97+ .partitions = id800wt_partitions,
98+ .num_partitions = ARRAY_SIZE(id800wt_partitions),
99+ .busy_gpio = JZ_GPIO_PORTC(30),
100+};
101+
102+/* Display */
103+static struct fb_videomode id800wt_video_modes[] = {
104+ {
105+ .name = "800x600",
106+ .xres = 800,
107+ .yres = 600,
108+ .refresh = 40,
109+ .left_margin = 0,
110+ .right_margin = 255,
111+ .upper_margin = 0,
112+ .lower_margin = 35,
113+ .hsync_len = 1,
114+ .vsync_len = 1,
115+ .sync = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
116+ .vmode = FB_VMODE_NONINTERLACED,
117+ },
118+};
119+
120+static struct jz4740_fb_platform_data id800wt_fb_pdata = {
121+ .width = 60,
122+ .height = 45,
123+ .num_modes = ARRAY_SIZE(id800wt_video_modes),
124+ .modes = id800wt_video_modes,
125+ .bpp = 16,
126+ .lcd_type = JZ_LCD_TYPE_SPECIAL_TFT_1,
127+ .pixclk_falling_edge = 1,
128+ .special_tft_config = {
129+ .spl = JZ4740_FB_SPECIAL_TFT_CONFIG(1051, 1053),
130+ .cls = JZ4740_FB_SPECIAL_TFT_CONFIG(631, 744),
131+ .ps = JZ4740_FB_SPECIAL_TFT_CONFIG(0, 45),
132+ .rev = JZ4740_FB_SPECIAL_TFT_CONFIG(0, 0),
133+ },
134+};
135+
136+/* Backlight */
137+static int id800wt_backlight_invert(struct device *dev, int brightness)
138+{
139+ return 255 - brightness;
140+}
141+
142+static struct platform_pwm_backlight_data id800wt_backlight_data = {
143+ .pwm_id = 7,
144+ .max_brightness = 255,
145+ .dft_brightness = 255,
146+ .pwm_period_ns = 8000000,
147+ .notify = id800wt_backlight_invert,
148+};
149+
150+static struct platform_device id800wt_backlight_device = {
151+ .name = "pwm-backlight",
152+ .id = -1,
153+ .dev = {
154+ .platform_data = &id800wt_backlight_data,
155+ .parent = &jz4740_framebuffer_device.dev,
156+ },
157+};
158+
159+static struct platform_device *jz_platform_devices[] __initdata = {
160+ &jz4740_usb_ohci_device,
161+ &jz4740_udc_device,
162+ &jz4740_nand_device,
163+ &jz4740_framebuffer_device,
164+ &jz4740_i2s_device,
165+ &jz4740_codec_device,
166+ &jz4740_pcm_device,
167+ &jz4740_rtc_device,
168+ &jz4740_adc_device,
169+ &id800wt_backlight_device,
170+};
171+
172+static int __init id800wt_init_platform_devices(void)
173+{
174+ jz4740_framebuffer_device.dev.platform_data = &id800wt_fb_pdata;
175+ jz4740_nand_device.dev.platform_data = &id800wt_nand_pdata;
176+
177+ jz4740_serial_device_register();
178+
179+ jz_gpio_enable_pullup(JZ_GPIO_LCD_PS);
180+ jz_gpio_enable_pullup(JZ_GPIO_LCD_REV);
181+
182+ return platform_add_devices(jz_platform_devices,
183+ ARRAY_SIZE(jz_platform_devices));
184+}
185+
186+struct jz4740_clock_board_data jz4740_clock_bdata = {
187+ .ext_rate = 12000000,
188+ .rtc_rate = 32768,
189+};
190+
191+static int __init id800wt_board_setup(void)
192+{
193+ printk("Sungale pictureframe id800wt setup\n");
194+
195+ if (id800wt_init_platform_devices())
196+ panic("Failed to initalize platform devices\n");
197+
198+ return 0;
199+}
200+arch_initcall(id800wt_board_setup);
201--
2021.7.4.1
203
target/linux/xburst/patches-3.1/0005-Add-N516-sound-SoC-board-driver.patch
1From bb71013753bf82d9fa500e711923482fd375933d Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sun, 1 Aug 2010 21:34:54 +0200
4Subject: [PATCH 05/24] Add N516 sound SoC board driver
5
6---
7 sound/soc/jz4740/Kconfig | 8 ++
8 sound/soc/jz4740/Makefile | 2 +
9 sound/soc/jz4740/n516.c | 303 +++++++++++++++++++++++++++++++++++++++++++++
10 3 files changed, 313 insertions(+), 0 deletions(-)
11 create mode 100644 sound/soc/jz4740/n516.c
12
13diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
14index 5351cba..08530ca 100644
15--- a/sound/soc/jz4740/Kconfig
16@@ -21,3 +21,11 @@ config SND_JZ4740_SOC_QI_LB60
17     help
18       Say Y if you want to add support for ASoC audio on the Qi LB60 board
19       a.k.a Qi Ben NanoNote.
20+
21+config SND_JZ4740_SOC_N516
22+ tristate "SoC Audio support for Hanvon N516 eBook reader"
23+ depends on SND_JZ4740_SOC && JZ4740_N516
24+ select SND_JZ4740_SOC_I2S
25+ select SND_SOC_JZCODEC
26+ help
27+ Say Y if you want to enable support for SoC audio on the Hanvon N516.
28diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
29index be873c1..b64d912 100644
30--- a/sound/soc/jz4740/Makefile
31@@ -9,5 +9,7 @@ obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
32
33 # Jz4740 Machine Support
34 snd-soc-qi-lb60-objs := qi_lb60.o
35+snd-soc-n516-objs := n516.o
36
37 obj-$(CONFIG_SND_JZ4740_SOC_QI_LB60) += snd-soc-qi-lb60.o
38+obj-$(CONFIG_SND_JZ4740_SOC_N516) += snd-soc-n516.o
39diff --git a/sound/soc/jz4740/n516.c b/sound/soc/jz4740/n516.c
40new file mode 100644
41index 0000000..9cb51c2
42--- /dev/null
43@@ -0,0 +1,303 @@
44+/*
45+ * Copyright (C) 2009, Yauhen Kharuzhy <jekhor@gmail.com>
46+ * OpenInkpot project
47+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
48+ *
49+ * This program is free software; you can redistribute it and/or modify
50+ * it under the terms of the GNU General Public License version 2 as
51+ * published by the Free Software Foundation.
52+ *
53+ * You should have received a copy of the GNU General Public License along
54+ * with this program; if not, write to the Free Software Foundation, Inc.,
55+ * 675 Mass Ave, Cambridge, MA 02139, USA.
56+ *
57+ */
58+
59+#include <linux/module.h>
60+#include <linux/interrupt.h>
61+#include <linux/platform_device.h>
62+#include <sound/core.h>
63+#include <sound/pcm.h>
64+#include <sound/soc.h>
65+#include <sound/soc-dapm.h>
66+#include <sound/jack.h>
67+#include <linux/gpio.h>
68+#include <linux/workqueue.h>
69+
70+#include "../codecs/jzcodec.h"
71+#include "jz4740-pcm.h"
72+#include "jz4740-i2s.h"
73+
74+#include <asm/mach-jz4740/board-n516.h>
75+
76+enum {
77+ N516_SPEAKER_AUTO = 0,
78+ N516_SPEAKER_OFF = 1,
79+ N516_SPEAKER_ON = 2,
80+};
81+
82+static int n516_speaker_mode;
83+static struct snd_soc_codec *n516_codec;
84+static struct work_struct n516_headphone_work;
85+
86+static void n516_ext_control(void)
87+{
88+ if (!n516_codec)
89+ return;
90+
91+ switch (n516_speaker_mode) {
92+ case N516_SPEAKER_ON:
93+ snd_soc_dapm_enable_pin(n516_codec, "Speaker");
94+ break;
95+ case N516_SPEAKER_OFF:
96+ snd_soc_dapm_disable_pin(n516_codec, "Speaker");
97+ break;
98+ case N516_SPEAKER_AUTO:
99+ if (snd_soc_dapm_get_pin_status(n516_codec, "Headphone"))
100+ snd_soc_dapm_disable_pin(n516_codec, "Speaker");
101+ else
102+ snd_soc_dapm_enable_pin(n516_codec, "Speaker");
103+ break;
104+ default:
105+ break;
106+ }
107+
108+ /* signal a DAPM event */
109+ snd_soc_dapm_sync(n516_codec);
110+}
111+
112+static int n516_speaker_event(struct snd_soc_dapm_widget *widget,
113+ struct snd_kcontrol *ctrl, int event)
114+{
115+ int on = !SND_SOC_DAPM_EVENT_OFF(event);
116+
117+ gpio_set_value(GPIO_SPEAKER_ENABLE, on);
118+
119+ return 0;
120+}
121+
122+static void n516_headphone_event_work(struct work_struct *work)
123+{
124+ n516_ext_control();
125+}
126+
127+static int n516_headphone_event(struct snd_soc_dapm_widget *widget,
128+ struct snd_kcontrol *ctrl, int event)
129+{
130+ /* We can't call soc_dapm_sync from a event handler */
131+ if (event & (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD))
132+ schedule_work(&n516_headphone_work);
133+ return 0;
134+}
135+
136+static const struct snd_soc_dapm_widget n516_widgets[] = {
137+ SND_SOC_DAPM_SPK("Speaker", n516_speaker_event),
138+ SND_SOC_DAPM_HP("Headphone", n516_headphone_event),
139+ SND_SOC_DAPM_MIC("Mic", NULL),
140+};
141+
142+static const struct snd_soc_dapm_route n516_routes[] = {
143+ {"Mic", NULL, "MIC"},
144+ {"Speaker", NULL, "LOUT"},
145+ {"Speaker", NULL, "ROUT"},
146+ {"Headphone", NULL, "LOUT"},
147+ {"Headphone", NULL, "ROUT"},
148+};
149+
150+static const char *n516_speaker_modes[] = {"Auto", "Off", "On"};
151+static const struct soc_enum n516_speaker_mode_enum =
152+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(n516_speaker_modes), n516_speaker_modes);
153+
154+static int n516_get_speaker_mode(struct snd_kcontrol *kcontrol,
155+ struct snd_ctl_elem_value *ucontrol)
156+{
157+ ucontrol->value.integer.value[0] = n516_speaker_mode;
158+ return 0;
159+}
160+
161+static int n516_set_speaker_mode(struct snd_kcontrol *kcontrol,
162+ struct snd_ctl_elem_value *ucontrol)
163+{
164+ if (n516_speaker_mode == ucontrol->value.integer.value[0])
165+ return 0;
166+
167+ n516_speaker_mode = ucontrol->value.integer.value[0];
168+ n516_ext_control();
169+ return 1;
170+}
171+
172+static const struct snd_kcontrol_new n516_controls[] = {
173+ SOC_ENUM_EXT("Speaker Function", n516_speaker_mode_enum,
174+ n516_get_speaker_mode, n516_set_speaker_mode),
175+};
176+
177+#define N516_DAIFMT (SND_SOC_DAIFMT_I2S | \
178+ SND_SOC_DAIFMT_NB_NF | \
179+ SND_SOC_DAIFMT_CBM_CFM)
180+
181+static int n516_codec_init(struct snd_soc_codec *codec)
182+{
183+ int ret;
184+ struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai;
185+ struct snd_soc_dai *codec_dai = codec->socdev->card->dai_link->codec_dai;
186+
187+ n516_codec = codec;
188+
189+ snd_soc_dapm_nc_pin(codec, "LIN");
190+ snd_soc_dapm_nc_pin(codec, "RIN");
191+
192+ ret = snd_soc_dai_set_fmt(codec_dai, N516_DAIFMT);
193+ if (ret < 0) {
194+ dev_err(codec->dev, "Failed to set codec dai format: %d\n", ret);
195+ return ret;
196+ }
197+
198+ ret = snd_soc_dai_set_fmt(cpu_dai, N516_DAIFMT);
199+ if (ret < 0) {
200+ dev_err(codec->dev, "Failed to set cpu dai format: %d\n", ret);
201+ return ret;
202+ }
203+
204+ ret = snd_soc_dai_set_sysclk(codec_dai, JZCODEC_SYSCLK, 111,
205+ SND_SOC_CLOCK_IN);
206+ if (ret < 0) {
207+ dev_err(codec->dev, "Failed to set codec dai sysclk: %d\n", ret);
208+ return ret;
209+ }
210+
211+ ret = snd_soc_add_controls(codec, n516_controls,
212+ ARRAY_SIZE(n516_controls));
213+ if (ret) {
214+ dev_err(codec->dev, "Failed to add controls: %d\n", ret);
215+ return ret;
216+ }
217+
218+
219+ ret = snd_soc_dapm_new_controls(codec, n516_widgets,
220+ ARRAY_SIZE(n516_widgets));
221+ if (ret) {
222+ dev_err(codec->dev, "Failed to add dapm controls: %d\n", ret);
223+ return ret;
224+ }
225+
226+ ret = snd_soc_dapm_add_routes(codec, n516_routes, ARRAY_SIZE(n516_routes));
227+ if (ret) {
228+ dev_err(codec->dev, "Failed to add dapm routes: %d\n", ret);
229+ return ret;
230+ }
231+
232+ snd_soc_dapm_sync(codec);
233+
234+ return 0;
235+}
236+
237+static struct snd_soc_dai_link n516_dai = {
238+ .name = "jz-codec",
239+ .stream_name = "JZCODEC",
240+ .cpu_dai = &jz4740_i2s_dai,
241+ .codec_dai = &jz_codec_dai,
242+ .init = n516_codec_init,
243+};
244+
245+static struct snd_soc_card n516_card = {
246+ .name = "N516",
247+ .dai_link = &n516_dai,
248+ .num_links = 1,
249+ .platform = &jz4740_soc_platform,
250+};
251+
252+static struct snd_soc_device n516_snd_devdata = {
253+ .card = &n516_card,
254+ .codec_dev = &soc_codec_dev_jzcodec,
255+};
256+
257+static struct platform_device *n516_snd_device;
258+
259+static struct snd_soc_jack n516_hp_jack;
260+
261+static struct snd_soc_jack_pin n516_hp_pin = {
262+ .pin = "Headphone",
263+ .mask = SND_JACK_HEADPHONE,
264+};
265+
266+static struct snd_soc_jack_gpio n516_hp_gpio = {
267+ .gpio = GPIO_HPHONE_DETECT,
268+ .name = "Headphone detect",
269+ .report = SND_JACK_HEADPHONE,
270+ .debounce_time = 100,
271+};
272+
273+static int __init n516_add_headphone_jack(void)
274+{
275+ int ret;
276+
277+ ret = snd_soc_jack_new(&n516_card, "Headphone jack",
278+ SND_JACK_HEADPHONE, &n516_hp_jack);
279+ if (ret)
280+ return ret;
281+
282+ ret = snd_soc_jack_add_pins(&n516_hp_jack, 1, &n516_hp_pin);
283+ if (ret)
284+ return ret;
285+
286+ ret = snd_soc_jack_add_gpios(&n516_hp_jack, 1, &n516_hp_gpio);
287+
288+ return ret;
289+}
290+
291+static int __init n516_init(void)
292+{
293+ int ret;
294+
295+ n516_snd_device = platform_device_alloc("soc-audio", -1);
296+
297+ if (!n516_snd_device)
298+ return -ENOMEM;
299+
300+ ret = gpio_request(GPIO_SPEAKER_ENABLE, "Speaker enable");
301+ if (ret) {
302+ pr_err("n516 snd: Failed to request SPEAKER_ENABLE GPIO(%d): %d\n",
303+ GPIO_SPEAKER_ENABLE, ret);
304+ goto err_device_put;
305+ }
306+
307+ gpio_direction_output(GPIO_SPEAKER_ENABLE, 0);
308+ INIT_WORK(&n516_headphone_work, n516_headphone_event_work);
309+
310+ platform_set_drvdata(n516_snd_device, &n516_snd_devdata);
311+ n516_snd_devdata.dev = &n516_snd_device->dev;
312+ ret = platform_device_add(n516_snd_device);
313+ if (ret) {
314+ pr_err("n516 snd: Failed to add snd soc device: %d\n", ret);
315+ goto err_unset_pdata;
316+ }
317+
318+ ret = n516_add_headphone_jack();
319+ /* We can live without it, so just print a warning */
320+ if (ret)
321+ pr_warning("n516 snd: Failed to initalise headphone jack: %d\n", ret);
322+
323+ return 0;
324+
325+err_unset_pdata:
326+ platform_set_drvdata(n516_snd_device, NULL);
327+/*err_gpio_free_speaker:*/
328+ gpio_free(GPIO_SPEAKER_ENABLE);
329+err_device_put:
330+ platform_device_put(n516_snd_device);
331+
332+ return ret;
333+}
334+module_init(n516_init);
335+
336+static void __exit n516_exit(void)
337+{
338+ snd_soc_jack_free_gpios(&n516_hp_jack, 1, &n516_hp_gpio);
339+ gpio_free(GPIO_SPEAKER_ENABLE);
340+ platform_device_unregister(n516_snd_device);
341+}
342+module_exit(n516_exit);
343+
344+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
345+MODULE_DESCRIPTION("ALSA SoC N516 Audio support");
346+MODULE_LICENSE("GPL v2");
347--
3481.7.4.1
349
target/linux/xburst/patches-3.1/0006-Add-N526-sound-SoC-board-driver.patch
1From b5b7ee6e57e4ddd2db85e8a15508fc70c2cc41f8 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sat, 24 Apr 2010 12:38:41 +0200
4Subject: [PATCH 06/24] Add N526 sound SoC board driver
5
6---
7 sound/soc/jz4740/Kconfig | 8 ++
8 sound/soc/jz4740/Makefile | 2 +
9 sound/soc/jz4740/n526.c | 169 +++++++++++++++++++++++++++++++++++++++++++++
10 3 files changed, 179 insertions(+), 0 deletions(-)
11 create mode 100644 sound/soc/jz4740/n526.c
12
13diff --git a/sound/soc/jz4740/Kconfig b/sound/soc/jz4740/Kconfig
14index 08530ca..c222dcb 100644
15--- a/sound/soc/jz4740/Kconfig
16@@ -29,3 +29,11 @@ config SND_JZ4740_SOC_N516
17     select SND_SOC_JZCODEC
18     help
19       Say Y if you want to enable support for SoC audio on the Hanvon N516.
20+
21+config SND_JZ4740_SOC_N526
22+ tristate "SoC Audio support for Hanvon N526 eBook reader"
23+ depends on SND_JZ4740_SOC && JZ4740_N526
24+ select SND_JZ4740_SOC_I2S
25+ select SND_SOC_JZCODEC
26+ help
27+ Say Y if you want to enable support for SoC audio on the Hanvon N526.
28diff --git a/sound/soc/jz4740/Makefile b/sound/soc/jz4740/Makefile
29index b64d912..e7952d3 100644
30--- a/sound/soc/jz4740/Makefile
31@@ -10,6 +10,8 @@ obj-$(CONFIG_SND_JZ4740_SOC_I2S) += snd-soc-jz4740-i2s.o
32 # Jz4740 Machine Support
33 snd-soc-qi-lb60-objs := qi_lb60.o
34 snd-soc-n516-objs := n516.o
35+snd-soc-n526-objs := n526.o
36
37 obj-$(CONFIG_SND_JZ4740_SOC_QI_LB60) += snd-soc-qi-lb60.o
38 obj-$(CONFIG_SND_JZ4740_SOC_N516) += snd-soc-n516.o
39+obj-$(CONFIG_SND_JZ4740_SOC_N526) += snd-soc-n526.o
40diff --git a/sound/soc/jz4740/n526.c b/sound/soc/jz4740/n526.c
41new file mode 100644
42index 0000000..2283904
43--- /dev/null
44@@ -0,0 +1,169 @@
45+/*
46+ * Copyright (C) 2009, Lars-Peter Clausen <lars@metafoo.de>
47+ *
48+ * This program is free software; you can redistribute it and/or modify
49+ * it under the terms of the GNU General Public License version 2 as
50+ * published by the Free Software Foundation.
51+ *
52+ * You should have received a copy of the GNU General Public License along
53+ * with this program; if not, write to the Free Software Foundation, Inc.,
54+ * 675 Mass Ave, Cambridge, MA 02139, USA.
55+ *
56+ */
57+
58+#include <linux/module.h>
59+#include <linux/moduleparam.h>
60+#include <linux/timer.h>
61+#include <linux/interrupt.h>
62+#include <linux/platform_device.h>
63+#include <sound/core.h>
64+#include <sound/pcm.h>
65+#include <sound/soc.h>
66+#include <sound/soc-dapm.h>
67+#include <linux/gpio.h>
68+
69+#include "../codecs/jzcodec.h"
70+#include "jz4740-pcm.h"
71+#include "jz4740-i2s.h"
72+
73+#define N526_AMP_EN_GPIO JZ_GPIO_PORTD(4)
74+
75+static int n526_spk_event(struct snd_soc_dapm_widget *widget,
76+ struct snd_kcontrol *ctrl, int event)
77+{
78+ gpio_set_value(N526_AMP_EN_GPIO, !SND_SOC_DAPM_EVENT_OFF(event));
79+ return 0;
80+}
81+
82+static const struct snd_soc_dapm_widget n526_widgets[] = {
83+ SND_SOC_DAPM_SPK("Speaker", n526_spk_event),
84+ SND_SOC_DAPM_HP("Headphone", NULL),
85+ SND_SOC_DAPM_MIC("Mic", NULL),
86+};
87+
88+static const struct snd_soc_dapm_route n526_routes[] = {
89+ {"Mic", NULL, "MIC"},
90+ {"Speaker", NULL, "LOUT"},
91+ {"Speaker", NULL, "ROUT"},
92+ {"Headphone", NULL, "LOUT"},
93+ {"Headphone", NULL, "ROUT"},
94+};
95+
96+static const struct snd_kcontrol_new n526_controls[] = {
97+ SOC_DAPM_PIN_SWITCH("Speaker"),
98+};
99+
100+#define N526_DAIFMT (SND_SOC_DAIFMT_I2S | \
101+ SND_SOC_DAIFMT_NB_NF | \
102+ SND_SOC_DAIFMT_CBM_CFM)
103+
104+static int n526_codec_init(struct snd_soc_codec *codec)
105+{
106+ int ret;
107+ struct snd_soc_dai *cpu_dai = codec->socdev->card->dai_link->cpu_dai;
108+ struct snd_soc_dai *codec_dai = codec->socdev->card->dai_link->codec_dai;
109+
110+ snd_soc_dapm_nc_pin(codec, "LIN");
111+ snd_soc_dapm_nc_pin(codec, "RIN");
112+
113+ ret = snd_soc_dai_set_fmt(codec_dai, N526_DAIFMT);
114+ if (ret < 0) {
115+ dev_err(codec->dev, "Failed to set codec dai format: %d\n", ret);
116+ return ret;
117+ }
118+
119+ ret = snd_soc_dai_set_fmt(cpu_dai, N526_DAIFMT);
120+ if (ret < 0) {
121+ dev_err(codec->dev, "Failed to set cpu dai format: %d\n", ret);
122+ return ret;
123+ }
124+
125+ ret = snd_soc_dai_set_sysclk(codec_dai, JZCODEC_SYSCLK, 111,
126+ SND_SOC_CLOCK_IN);
127+ if (ret < 0) {
128+ dev_err(codec->dev, "Failed to set codec dai sysclk: %d\n", ret);
129+ return ret;
130+ }
131+
132+ snd_soc_dapm_new_controls(codec, n526_widgets, ARRAY_SIZE(n526_widgets));
133+
134+ snd_soc_add_controls(codec, n526_controls,
135+ ARRAY_SIZE(n526_controls));
136+
137+ snd_soc_dapm_add_routes(codec, n526_routes, ARRAY_SIZE(n526_routes));
138+
139+ snd_soc_dapm_sync(codec);
140+
141+ return 0;
142+}
143+
144+static struct snd_soc_dai_link n526_dai = {
145+ .name = "jz-codec",
146+ .stream_name = "JZCODEC",
147+ .cpu_dai = &jz4740_i2s_dai,
148+ .codec_dai = &jz_codec_dai,
149+ .init = n526_codec_init,
150+};
151+
152+static struct snd_soc_card n526 = {
153+ .name = "N526",
154+ .dai_link = &n526_dai,
155+ .num_links = 1,
156+ .platform = &jz4740_soc_platform,
157+};
158+
159+static struct snd_soc_device n526_snd_devdata = {
160+ .card = &n526,
161+ .codec_dev = &soc_codec_dev_jzcodec,
162+};
163+
164+static struct platform_device *n526_snd_device;
165+
166+static int __init n526_init(void)
167+{
168+ int ret;
169+
170+ n526_snd_device = platform_device_alloc("soc-audio", -1);
171+
172+ if (!n526_snd_device)
173+ return -ENOMEM;
174+
175+ ret = gpio_request(N526_AMP_EN_GPIO, "AMP");
176+ if (ret) {
177+ pr_err("n526 snd: Failed to request AMP GPIO(%d): %d\n",
178+ N526_AMP_EN_GPIO, ret);
179+ goto err_device_put;
180+ }
181+
182+ gpio_direction_output(JZ_GPIO_PORTD(4), 0);
183+
184+ platform_set_drvdata(n526_snd_device, &n526_snd_devdata);
185+ n526_snd_devdata.dev = &n526_snd_device->dev;
186+ ret = platform_device_add(n526_snd_device);
187+ if (ret) {
188+ pr_err("n526 snd: Failed to add snd soc device: %d\n", ret);
189+ goto err_unset_pdata;
190+ }
191+
192+ return 0;
193+
194+err_unset_pdata:
195+ platform_set_drvdata(n526_snd_device, NULL);
196+ gpio_free(N526_AMP_EN_GPIO);
197+err_device_put:
198+ platform_device_put(n526_snd_device);
199+
200+ return ret;
201+}
202+module_init(n526_init);
203+
204+static void __exit n526_exit(void)
205+{
206+ gpio_free(N526_AMP_EN_GPIO);
207+ platform_device_unregister(n526_snd_device);
208+}
209+module_exit(n526_exit);
210+
211+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
212+MODULE_DESCRIPTION("ALSA SoC N526 audio support");
213+MODULE_LICENSE("GPL v2");
214--
2151.7.4.1
216
target/linux/xburst/patches-3.1/0007-qi_lb60-Don-t-use-3-wire-spi-mode-for-the-display-fo.patch
1From 13516fbd5d40c5762f963125b92c7940e7e4cec4 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Wed, 13 Oct 2010 01:17:24 +0200
4Subject: [PATCH 07/24] qi_lb60: Don't use 3-wire spi mode for the display for now
5
6The spi_gpio driver does not support 3-wire mode.
7---
8 arch/mips/jz4740/board-qi_lb60.c | 1 -
9 1 files changed, 0 insertions(+), 1 deletions(-)
10
11diff --git a/arch/mips/jz4740/board-qi_lb60.c b/arch/mips/jz4740/board-qi_lb60.c
12index c3b04be..b622941 100644
13--- a/arch/mips/jz4740/board-qi_lb60.c
14@@ -310,7 +310,6 @@ static struct spi_board_info qi_lb60_spi_board_info[] = {
15         .chip_select = 0,
16         .bus_num = 1,
17         .max_speed_hz = 30 * 1000,
18- .mode = SPI_3WIRE,
19     },
20 };
21
22--
231.7.4.1
24
target/linux/xburst/patches-3.1/0008-i2c-Add-i2c-driver-for-JZ47XX-SoCs.patch
1From 8a61ab191d9194d166b2de96f7722dcc94ed9b42 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sun, 5 Sep 2010 03:19:10 +0200
4Subject: [PATCH 08/24] i2c: Add i2c driver for JZ47XX SoCs
5
6This patch adds a driver for the i2c controller found in Ingenic JZ47XX based
7SoCs.
8
9Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
10---
11 drivers/i2c/busses/Kconfig | 10 +
12 drivers/i2c/busses/Makefile | 1 +
13 drivers/i2c/busses/i2c-jz47xx.c | 424 +++++++++++++++++++++++++++++++++++++++
14 3 files changed, 435 insertions(+), 0 deletions(-)
15 create mode 100644 drivers/i2c/busses/i2c-jz47xx.c
16
17diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
18index 646068e..5b76fcf 100644
19--- a/drivers/i2c/busses/Kconfig
20@@ -434,6 +434,16 @@ config I2C_IXP2000
21       This driver is deprecated and will be dropped soon. Use i2c-gpio
22       instead.
23
24+config I2C_JZ47XX
25+ tristate "JZ4740 I2C Interface"
26+ depends on ARCH_JZ4740
27+ help
28+ Say Y here if you want support for the I2C controller found on Ingenic
29+ JZ47XX based SoCs.
30+
31+ This driver can also be built as a module. If so, the module will be
32+ called i2c-jz47xx.
33+
34 config I2C_MPC
35     tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
36     depends on PPC
37diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
38index e6cf294..07be071 100644
39--- a/drivers/i2c/busses/Makefile
40@@ -41,6 +41,7 @@ obj-$(CONFIG_I2C_IMX) += i2c-imx.o
41 obj-$(CONFIG_I2C_INTEL_MID) += i2c-intel-mid.o
42 obj-$(CONFIG_I2C_IOP3XX) += i2c-iop3xx.o
43 obj-$(CONFIG_I2C_IXP2000) += i2c-ixp2000.o
44+obj-$(CONFIG_I2C_JZ47XX) += i2c-jz47xx.o
45 obj-$(CONFIG_I2C_MPC) += i2c-mpc.o
46 obj-$(CONFIG_I2C_MV64XXX) += i2c-mv64xxx.o
47 obj-$(CONFIG_I2C_MXS) += i2c-mxs.o
48diff --git a/drivers/i2c/busses/i2c-jz47xx.c b/drivers/i2c/busses/i2c-jz47xx.c
49new file mode 100644
50index 0000000..492d350
51--- /dev/null
52@@ -0,0 +1,424 @@
53+
54+#include <linux/init.h>
55+#include <linux/kernel.h>
56+#include <linux/module.h>
57+#include <linux/err.h>
58+#include <linux/clk.h>
59+#include <linux/platform_device.h>
60+#include <linux/i2c.h>
61+#include <linux/slab.h>
62+#include <linux/interrupt.h>
63+
64+#include <linux/gpio.h>
65+#include <linux/delay.h>
66+
67+#define JZ47XX_REG_I2C_DATA 0x00
68+#define JZ47XX_REG_I2C_CTRL 0x04
69+#define JZ47XX_REG_I2C_STATUS 0x08
70+#define JZ47XX_REG_I2C_CLOCK 0x0C
71+
72+#define JZ47XX_I2C_STATUS_FIFO_FULL BIT(4)
73+#define JZ47XX_I2C_STATUS_BUSY BIT(3)
74+#define JZ47XX_I2C_STATUS_TEND BIT(2)
75+#define JZ47XX_I2C_STATUS_DATA_VALID BIT(1)
76+#define JZ47XX_I2C_STATUS_NACK BIT(0)
77+
78+#define JZ47XX_I2C_CTRL_IRQ_ENABLE BIT(4)
79+#define JZ47XX_I2C_CTRL_START BIT(3)
80+#define JZ47XX_I2C_CTRL_STOP BIT(2)
81+#define JZ47XX_I2C_CTRL_NACK BIT(1)
82+#define JZ47XX_I2C_CTRL_ENABLE BIT(0)
83+
84+struct jz47xx_i2c {
85+ struct resource *mem;
86+ void __iomem *base;
87+ int irq;
88+ struct clk *clk;
89+
90+ struct i2c_adapter adapter;
91+
92+ wait_queue_head_t wait_queue;
93+};
94+
95+static inline struct jz47xx_i2c *adapter_to_jz47xx_i2c(struct i2c_adapter *adap)
96+{
97+ return container_of(adap, struct jz47xx_i2c, adapter);
98+}
99+
100+static inline void jz47xx_i2c_set_ctrl(struct jz47xx_i2c *jz47xx_i2c,
101+ uint8_t mask, uint8_t value)
102+{
103+ uint8_t ctrl;
104+ ctrl = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_CTRL);
105+ ctrl &= ~mask;
106+ ctrl |= value;
107+ printk("ctrl: %x\n", ctrl);
108+ writeb(ctrl, jz47xx_i2c->base + JZ47XX_REG_I2C_CTRL);
109+}
110+
111+static irqreturn_t jz47xx_i2c_irq_handler(int irq, void *devid)
112+{
113+ struct jz47xx_i2c *jz47xx_i2c = devid;
114+
115+ printk("IRQ\n");
116+
117+ wake_up(&jz47xx_i2c->wait_queue);
118+
119+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_IRQ_ENABLE, 0);
120+
121+ return IRQ_HANDLED;
122+}
123+
124+static inline void jz47xx_i2c_set_data_valid(struct jz47xx_i2c *jz47xx_i2c,
125+ bool valid)
126+{
127+ uint8_t val;
128+ val = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS);
129+ if (valid)
130+ val |= JZ47XX_I2C_STATUS_DATA_VALID;
131+ else
132+ val &= ~JZ47XX_I2C_STATUS_DATA_VALID;
133+ writeb(val, jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS);
134+}
135+
136+static int jz47xx_i2c_test_event(struct jz47xx_i2c *jz47xx_i2c, uint8_t mask, uint8_t value)
137+{
138+ uint8_t status;
139+
140+ mask |= JZ47XX_I2C_STATUS_NACK;
141+ value |= JZ47XX_I2C_STATUS_NACK;
142+
143+ status = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS);
144+ printk("status: %x %x %x %x\n", status, mask, value, (status & mask) ^
145+ value);
146+ if (((status & mask) ^ value) == mask) {
147+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_IRQ_ENABLE,
148+ JZ47XX_I2C_CTRL_IRQ_ENABLE);
149+ return 0;
150+ }
151+ return 1;
152+}
153+
154+static int jz47xx_i2c_wait_event_or_nack(struct jz47xx_i2c *jz47xx_i2c, uint8_t
155+mask, uint8_t value)
156+{
157+ int ret;
158+
159+ ret = wait_event_interruptible_timeout(jz47xx_i2c->wait_queue,
160+ jz47xx_i2c_test_event(jz47xx_i2c, mask, value), 30 * HZ);
161+
162+/* while (!jz47xx_i2c_test_event(jz47xx_i2c, mask, value));
163+
164+ ret = 1;*/
165+
166+ printk("wait event or nack: %d %x\n", ret, readb(jz47xx_i2c->base +
167+ JZ47XX_REG_I2C_STATUS));
168+
169+ if (ret == 0)
170+ ret = -ETIMEDOUT;
171+ else if(ret > 0) {
172+ if (readb(jz47xx_i2c->base + JZ47XX_REG_I2C_STATUS) & JZ47XX_I2C_STATUS_NACK)
173+ ret = -EIO;
174+ else
175+ ret = 0;
176+ }
177+
178+ return ret;
179+}
180+
181+static int jz47xx_i2c_wait_event(struct jz47xx_i2c *jz47xx_i2c, uint8_t event)
182+{
183+ int ret;
184+
185+ ret = wait_event_interruptible_timeout(jz47xx_i2c->wait_queue,
186+ jz47xx_i2c_test_event(jz47xx_i2c, event, event), 30 * HZ);
187+
188+ if (ret == 0)
189+ ret = -ETIMEDOUT;
190+ else if(ret > 0)
191+ ret = 0;
192+
193+ return ret;
194+}
195+
196+
197+static int jz47xx_i2c_write_msg(struct jz47xx_i2c *jz47xx_i2c,
198+ struct i2c_msg *msg)
199+{
200+ int ret;
201+ int i;
202+
203+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
204+ for (i = 0; i < msg->len; ++i) {
205+ writeb(msg->buf[i], jz47xx_i2c->base + JZ47XX_REG_I2C_DATA);
206+ jz47xx_i2c_set_data_valid(jz47xx_i2c, true);
207+ ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c,
208+ JZ47XX_I2C_STATUS_DATA_VALID, 0);
209+ if (ret)
210+ break;
211+ }
212+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_STOP,
213+ JZ47XX_I2C_CTRL_STOP);
214+
215+ if (!ret)
216+ ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c, JZ47XX_I2C_STATUS_TEND,
217+ JZ47XX_I2C_STATUS_TEND);
218+
219+ return ret;
220+}
221+
222+static int jz47xx_i2c_read_msg(struct jz47xx_i2c *jz47xx_i2c,
223+ struct i2c_msg *msg)
224+{
225+ int i;
226+ int ret;
227+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
228+
229+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_NACK,
230+ msg->len == 1 ? JZ47XX_I2C_CTRL_NACK : 0);
231+
232+ for (i = 0; i < msg->len; ++i) {
233+ ret = jz47xx_i2c_wait_event(jz47xx_i2c, JZ47XX_I2C_STATUS_DATA_VALID);
234+ if (ret) {
235+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_NACK,
236+ JZ47XX_I2C_CTRL_NACK);
237+ break;
238+ }
239+
240+ if (i == msg->len - 2) {
241+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_NACK,
242+ JZ47XX_I2C_CTRL_NACK);
243+ }
244+
245+ msg->buf[i] = readb(jz47xx_i2c->base + JZ47XX_REG_I2C_DATA);
246+ printk("read: %x\n", msg->buf[i]);
247+ jz47xx_i2c_set_data_valid(jz47xx_i2c, false);
248+ }
249+
250+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_STOP,
251+ JZ47XX_I2C_CTRL_STOP);
252+
253+ return ret;
254+}
255+
256+static int jz47xx_i2c_xfer_msg(struct jz47xx_i2c *jz47xx_i2c,
257+ struct i2c_msg *msg)
258+{
259+ uint8_t addr;
260+ int ret;
261+
262+ addr = msg->addr << 1;
263+ if (msg->flags & I2C_M_RD)
264+ addr |= 1;
265+
266+ jz47xx_i2c_set_ctrl(jz47xx_i2c, JZ47XX_I2C_CTRL_START,
267+ JZ47XX_I2C_CTRL_START);
268+ writeb(addr, jz47xx_i2c->base + JZ47XX_REG_I2C_DATA);
269+ jz47xx_i2c_set_data_valid(jz47xx_i2c, true);
270+
271+ if (msg->flags & I2C_M_RD) {
272+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
273+ ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c,
274+ JZ47XX_I2C_STATUS_TEND, JZ47XX_I2C_STATUS_TEND);
275+ if (!ret)
276+ ret = jz47xx_i2c_read_msg(jz47xx_i2c, msg);
277+ } else {
278+ printk("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
279+ ret = jz47xx_i2c_wait_event_or_nack(jz47xx_i2c,
280+ JZ47XX_I2C_STATUS_DATA_VALID, 0);
281+ if (!ret)
282+ ret = jz47xx_i2c_write_msg(jz47xx_i2c, msg);
283+ }
284+
285+ return ret;
286+}
287+
288+static int jz47xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int
289+num)
290+{
291+ struct jz47xx_i2c *jz47xx_i2c = adapter_to_jz47xx_i2c(adap);
292+ int ret = 0;
293+ int i;
294+ int mask = JZ47XX_I2C_CTRL_ENABLE;
295+
296+ printk("xfer: %d %x\n", num, readb(jz47xx_i2c->base +
297+ JZ47XX_REG_I2C_STATUS));
298+
299+ clk_enable(jz47xx_i2c->clk);
300+ jz47xx_i2c_set_ctrl(jz47xx_i2c, mask, mask);
301+
302+ for (i = 0; i < num; ++i) {
303+ ret = jz47xx_i2c_xfer_msg(jz47xx_i2c, &msgs[i]);
304+ if (ret)
305+ break;
306+ }
307+
308+ jz47xx_i2c_set_ctrl(jz47xx_i2c, mask, 0);
309+ clk_disable(jz47xx_i2c->clk);
310+
311+ printk("xfer ret: %d\n", ret);
312+
313+ return ret;
314+}
315+
316+static u32 jz47xx_i2c_functionality(struct i2c_adapter *adap)
317+{
318+ return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
319+}
320+
321+static const struct i2c_algorithm jz47xx_i2c_algorithm = {
322+ .master_xfer = jz47xx_i2c_xfer,
323+ .functionality = jz47xx_i2c_functionality,
324+};
325+
326+const static struct jz_gpio_bulk_request jz47xx_i2c_pins[] = {
327+ JZ_GPIO_BULK_PIN(I2C_SDA),
328+ JZ_GPIO_BULK_PIN(I2C_SCK),
329+};
330+
331+static int __devinit jz47xx_i2c_probe(struct platform_device *pdev)
332+{
333+ struct jz47xx_i2c *jz47xx_i2c;
334+ struct resource *mem;
335+ void __iomem *base;
336+ struct clk *clk;
337+ int irq;
338+ int ret;
339+
340+ irq = platform_get_irq(pdev, 0);
341+ if (!irq) {
342+ dev_err(&pdev->dev, "Failed to get IRQ: %d\n", irq);
343+ return irq;
344+ }
345+
346+ mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
347+ if (!mem) {
348+ dev_err(&pdev->dev, "Failed to get iomem region\n");
349+ return -ENXIO;
350+ }
351+
352+ mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
353+ if (!mem) {
354+ dev_err(&pdev->dev, "Failed to request iomem region\n");
355+ return -EBUSY;
356+ }
357+
358+ base = ioremap(mem->start, resource_size(mem));
359+ if (!base) {
360+ dev_err(&pdev->dev, "Failed to ioremap iomem\n");
361+ ret = -EBUSY;
362+ goto err_release_mem_region;
363+ }
364+
365+ clk = clk_get(&pdev->dev, "i2c");
366+ if (IS_ERR(clk)) {
367+ ret = PTR_ERR(clk);
368+ goto err_iounmap;
369+ }
370+
371+ jz47xx_i2c = kzalloc(sizeof(*jz47xx_i2c), GFP_KERNEL);
372+ if (!jz47xx_i2c) {
373+ ret = -ENOMEM;
374+ goto err_clk_put;
375+ }
376+
377+ jz47xx_i2c->adapter.owner = THIS_MODULE;
378+ jz47xx_i2c->adapter.algo = &jz47xx_i2c_algorithm;
379+ jz47xx_i2c->adapter.dev.parent = &pdev->dev;
380+ jz47xx_i2c->adapter.nr = pdev->id < 0 ?: 0;
381+ strcpy(jz47xx_i2c->adapter.name, pdev->name);
382+
383+ jz47xx_i2c->mem = mem;
384+ jz47xx_i2c->base = base;
385+ jz47xx_i2c->clk = clk;
386+ jz47xx_i2c->irq = irq;
387+
388+ init_waitqueue_head(&jz47xx_i2c->wait_queue);
389+
390+ ret = request_irq(irq, jz47xx_i2c_irq_handler, 0, pdev->name, jz47xx_i2c);
391+ if (ret) {
392+ dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
393+ goto err_free;
394+ }
395+
396+ ret = jz_gpio_bulk_request(jz47xx_i2c_pins, ARRAY_SIZE(jz47xx_i2c_pins));
397+ if (ret) {
398+ dev_err(&pdev->dev, "Failed to request i2c pins: %d\n", ret);
399+ goto err_free_irq;
400+ }
401+
402+ writew(0x10, jz47xx_i2c->base + JZ47XX_REG_I2C_CLOCK);
403+
404+ ret = i2c_add_numbered_adapter(&jz47xx_i2c->adapter);
405+ if (ret) {
406+ dev_err(&pdev->dev, "Failed to add i2c adapter: %d\n", ret);
407+ goto err_free_gpios;
408+ }
409+
410+ platform_set_drvdata(pdev, jz47xx_i2c);
411+
412+ printk("JZ4740 I2C\n");
413+
414+ return 0;
415+
416+err_free_gpios:
417+ jz_gpio_bulk_free(jz47xx_i2c_pins, ARRAY_SIZE(jz47xx_i2c_pins));
418+err_free_irq:
419+ free_irq(irq, jz47xx_i2c);
420+err_free:
421+ kfree(jz47xx_i2c);
422+err_clk_put:
423+ clk_put(clk);
424+err_iounmap:
425+ iounmap(base);
426+err_release_mem_region:
427+ release_mem_region(mem->start, resource_size(mem));
428+ return ret;
429+}
430+
431+static int __devexit jz47xx_i2c_remove(struct platform_device *pdev)
432+{
433+ struct jz47xx_i2c *jz47xx_i2c = platform_get_drvdata(pdev);
434+
435+ platform_set_drvdata(pdev, NULL);
436+ i2c_del_adapter(&jz47xx_i2c->adapter);
437+
438+ jz_gpio_bulk_free(jz47xx_i2c_pins, ARRAY_SIZE(jz47xx_i2c_pins));
439+
440+ free_irq(jz47xx_i2c->irq, jz47xx_i2c);
441+ clk_put(jz47xx_i2c->clk);
442+
443+ iounmap(jz47xx_i2c->base);
444+ release_mem_region(jz47xx_i2c->mem->start, resource_size(jz47xx_i2c->mem));
445+
446+ kfree(jz47xx_i2c);
447+
448+ return 0;
449+}
450+
451+static struct platform_driver jz47xx_i2c_driver = {
452+ .probe = jz47xx_i2c_probe,
453+ .remove = jz47xx_i2c_remove,
454+ .driver = {
455+ .name = "jz47xx-i2c",
456+ .owner = THIS_MODULE,
457+ },
458+};
459+
460+static int __init jz47xx_i2c_init(void)
461+{
462+ return platform_driver_register(&jz47xx_i2c_driver);
463+}
464+module_init(jz47xx_i2c_init);
465+
466+static void jz47xx_i2c_exit(void)
467+{
468+ platform_driver_unregister(&jz47xx_i2c_driver);
469+}
470+module_exit(jz47xx_i2c_exit);
471+
472+MODULE_LICENSE("GPL");
473+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
474+MODULE_DESCRIPTION("I2C adapter driver for JZ47XX SoCs");
475+MODULE_ALIAS("platform:jz47xx-i2c");
476+
477--
4781.7.4.1
479
target/linux/xburst/patches-3.1/0009-MIPS-JZ4740-Fix-i2c-driver-name.patch
1From 44613d48dc365fccbed7d34148d2306d0621ee6e Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sun, 5 Sep 2010 03:21:51 +0200
4Subject: [PATCH 09/24] MIPS: JZ4740: Fix i2c driver name.
5
6The i2c driver is generic to all JZ47XX based SoCs not only the JZ4740. Reflect
7this in the driver name.
8
9Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
10---
11 arch/mips/jz4740/platform.c | 2 +-
12 1 files changed, 1 insertions(+), 1 deletions(-)
13
14diff --git a/arch/mips/jz4740/platform.c b/arch/mips/jz4740/platform.c
15index 10929e2..cc6de5b 100644
16--- a/arch/mips/jz4740/platform.c
17@@ -142,7 +142,7 @@ static struct resource jz4740_i2c_resources[] = {
18 };
19
20 struct platform_device jz4740_i2c_device = {
21- .name = "jz4740-i2c",
22+ .name = "jz47xx-i2c",
23     .id = 0,
24     .num_resources = ARRAY_SIZE(jz4740_i2c_resources),
25     .resource = jz4740_i2c_resources,
26--
271.7.4.1
28
target/linux/xburst/patches-3.1/0010-MFD-jz4740-adc-Add-support-for-the-touchscreen-part-.patch
1From 2d6a2fa32588ffae0fca3847ef05edc9f35bc5c8 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sun, 5 Sep 2010 20:36:59 +0200
4Subject: [PATCH 10/24] MFD: jz4740-adc: Add support for the touchscreen part of the adc unit
5
6---
7 drivers/mfd/jz4740-adc.c | 27 ++++++++++++++++++++++++---
8 include/linux/jz4740-adc.h | 2 +-
9 2 files changed, 25 insertions(+), 4 deletions(-)
10
11diff --git a/drivers/mfd/jz4740-adc.c b/drivers/mfd/jz4740-adc.c
12index 21131c7..f49a4a5 100644
13--- a/drivers/mfd/jz4740-adc.c
14@@ -46,9 +46,9 @@
15 enum {
16     JZ_ADC_IRQ_ADCIN = 0,
17     JZ_ADC_IRQ_BATTERY,
18- JZ_ADC_IRQ_TOUCH,
19- JZ_ADC_IRQ_PENUP,
20- JZ_ADC_IRQ_PENDOWN,
21+ JZ_ADC_IRQ_TS_DATA_READY,
22+ JZ_ADC_IRQ_TS_PENUP,
23+ JZ_ADC_IRQ_TS_PENDOWN,
24 };
25
26 struct jz4740_adc {
27@@ -180,6 +180,27 @@ static struct resource jz4740_battery_resources[] = {
28     },
29 };
30
31+static struct resource jz4740_ts_resources[] = {
32+ {
33+ .start = JZ_ADC_IRQ_TS_DATA_READY,
34+ .flags = IORESOURCE_IRQ,
35+ },
36+ {
37+ .start = JZ_ADC_IRQ_TS_PENUP,
38+ .flags = IORESOURCE_IRQ,
39+ },
40+ {
41+ .start = JZ_ADC_IRQ_TS_PENDOWN,
42+ .flags = IORESOURCE_IRQ,
43+ },
44+ {
45+ .start = JZ_REG_ADC_TOUCHSCREEN_BASE,
46+ .end = JZ_REG_ADC_TOUCHSCREEN_BASE + 0xb,
47+ .flags = IORESOURCE_MEM,
48+ },
49+};
50+
51+
52 const struct mfd_cell jz4740_adc_cells[] = {
53     {
54         .id = 0,
55diff --git a/include/linux/jz4740-adc.h b/include/linux/jz4740-adc.h
56index 9053f95..3f15f66 100644
57--- a/include/linux/jz4740-adc.h
58@@ -25,7 +25,7 @@ int jz4740_adc_set_config(struct device *dev, uint32_t mask, uint32_t val);
59 #define JZ_ADC_CONFIG_BAT_MB BIT(4)
60
61 #define JZ_ADC_CONFIG_DNUM(dnum) ((dnum) << 16)
62-#define JZ_ADC_CONFIG_XYZ_OFFSET(dnum) ((xyz) << 13)
63+#define JZ_ADC_CONFIG_XYZ_OFFSET(xyz) ((xyz) << 13)
64 #define JZ_ADC_CONFIG_SAMPLE_NUM(x) ((x) << 10)
65 #define JZ_ADC_CONFIG_CLKDIV(div) ((div) << 5)
66
67--
681.7.4.1
69
target/linux/xburst/patches-3.1/0011-input-Add-touchscreen-driver-for-the-JZ4740-SoC.patch
1From 7c266d35f74f23b8e40f3e54d8c7a64c28d1e084 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sun, 5 Sep 2010 20:45:08 +0200
4Subject: [PATCH 11/24] input: Add touchscreen driver for the JZ4740 SoC
5
6This patch adds a touchscreen driver for the Ingenic JZ4740 SoC.
7The touchscreen controller is part of the ADC unit and thus this driver is a mfd
8cell from the jz4740-adc driver.
9
10Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
11---
12 drivers/input/touchscreen/Kconfig | 12 ++
13 drivers/input/touchscreen/Makefile | 1 +
14 drivers/input/touchscreen/jz4740-ts.c | 330 +++++++++++++++++++++++++++++++++
15 3 files changed, 343 insertions(+), 0 deletions(-)
16 create mode 100644 drivers/input/touchscreen/jz4740-ts.c
17
18diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig
19index cabd9e5..10836e5 100644
20--- a/drivers/input/touchscreen/Kconfig
21@@ -726,4 +726,16 @@ config TOUCHSCREEN_TPS6507X
22       To compile this driver as a module, choose M here: the
23       module will be called tps6507x_ts.
24
25+config TOUCHSCREEN_JZ4740
26+ tristate "JZ4740 touchscreen support"
27+ depends on MFD_JZ4740_ADC
28+ help
29+ Say Y here if you want support for the touchscreen controller found on
30+ Ingenic JZ4740 SoCs.
31+
32+ If unsure, say N.
33+
34+ To compile this driver as a module, choose M here: the
35+ module will be called jz4740-ts.
36+
37 endif
38diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile
39index 282d6f7..d8cc316 100644
40--- a/drivers/input/touchscreen/Makefile
41@@ -27,6 +27,7 @@ obj-$(CONFIG_TOUCHSCREEN_FUJITSU) += fujitsu_ts.o
42 obj-$(CONFIG_TOUCHSCREEN_INEXIO) += inexio.o
43 obj-$(CONFIG_TOUCHSCREEN_INTEL_MID) += intel-mid-touch.o
44 obj-$(CONFIG_TOUCHSCREEN_LPC32XX) += lpc32xx_ts.o
45+obj-$(CONFIG_TOUCHSCREEN_JZ4740) += jz4740-ts.o
46 obj-$(CONFIG_TOUCHSCREEN_MAX11801) += max11801_ts.o
47 obj-$(CONFIG_TOUCHSCREEN_MC13783) += mc13783_ts.o
48 obj-$(CONFIG_TOUCHSCREEN_MCS5000) += mcs5000_ts.o
49diff --git a/drivers/input/touchscreen/jz4740-ts.c b/drivers/input/touchscreen/jz4740-ts.c
50new file mode 100644
51index 0000000..dd5de34
52--- /dev/null
53@@ -0,0 +1,330 @@
54+/*
55+ * Touchscreen driver for Ingenic JZ SoCs.
56+ *
57+ * Copyright (C) 2010, Lars-Peter Clausen <lars@metafoo.de>
58+ *
59+ * This program is free software; you can redistribute it and/or modify
60+ * it under the terms of the GNU General Public License version 2 as
61+ * published by the Free Software Foundation.
62+ *
63+ */
64+
65+#include <linux/interrupt.h>
66+#include <linux/kernel.h>
67+#include <linux/module.h>
68+#include <linux/platform_device.h>
69+#include <linux/slab.h>
70+
71+#include <linux/delay.h>
72+#include <linux/mfd/core.h>
73+#include <linux/input.h>
74+#include <linux/bitops.h>
75+#include <linux/jz4740-adc.h>
76+
77+struct jz4740_ts {
78+ struct platform_device *pdev;
79+
80+ struct resource *mem;
81+ void __iomem *base;
82+
83+ int irq_penup;
84+ int irq_pendown;
85+ int irq_data_ready;
86+
87+ struct mfd_cell *cell;
88+ struct input_dev *input;
89+
90+ bool is_open;
91+};
92+
93+static irqreturn_t jz4740_ts_data_ready_irq_handler(int irq, void *devid)
94+{
95+ struct jz4740_ts *jz4740_ts = devid;
96+ uint32_t data;
97+ unsigned long x, y, z1, z2, pressure;
98+
99+ data = readl(jz4740_ts->base + 0x08);
100+ x = data & 0xfff;
101+ y = (data >> 16) & 0xfff;
102+
103+ data = readl(jz4740_ts->base + 0x08);
104+ z1 = data & 0xfff;
105+ z2 = (data >> 16) & 0xfff;
106+ if (z1 == 0) {
107+ pressure = 4095UL;
108+ } else if (z1 > z2) {
109+ pressure = 0;
110+ } else {
111+ if (data & 0x8000)
112+ pressure = (((480UL * x * z2) / z1) - 480UL * x) / 4096UL;
113+ else
114+ pressure = (((272UL * y * z2) / z1) - 272UL * y) / 4096UL;
115+ if (pressure >= 4096UL)
116+ pressure = 4095UL;
117+ pressure = 4095UL - pressure;
118+ }
119+
120+ input_report_abs(jz4740_ts->input, ABS_X, y);
121+ input_report_abs(jz4740_ts->input, ABS_Y, 4095 - x);
122+ input_report_abs(jz4740_ts->input, ABS_PRESSURE, pressure);
123+ input_report_key(jz4740_ts->input, BTN_TOUCH, 1);
124+ input_sync(jz4740_ts->input);
125+
126+ return IRQ_HANDLED;
127+}
128+
129+static irqreturn_t jz4740_ts_pen_irq_handler(int irq, void *devid)
130+{
131+ struct jz4740_ts *jz4740_ts = devid;
132+ int is_pressed;
133+
134+ if (irq == jz4740_ts->irq_penup) {
135+ enable_irq(jz4740_ts->irq_pendown);
136+ is_pressed = 0;
137+ } else {
138+ enable_irq(jz4740_ts->irq_penup);
139+ is_pressed = 1;
140+ }
141+ disable_irq_nosync(irq);
142+
143+ printk("pen irq: %d\n", irq);
144+ input_report_key(jz4740_ts->input, BTN_TOUCH, is_pressed);
145+ if (is_pressed == 0)
146+ input_report_abs(jz4740_ts->input, ABS_PRESSURE, 0);
147+ input_sync(jz4740_ts->input);
148+
149+ return IRQ_HANDLED;
150+}
151+
152+static int jz4740_ts_open(struct input_dev *input)
153+{
154+ struct jz4740_ts *jz4740_ts = input_get_drvdata(input);
155+
156+ jz4740_ts->is_open = true;
157+ jz4740_ts->cell->enable(jz4740_ts->pdev);
158+
159+ return 0;
160+}
161+
162+static void jz4740_ts_close(struct input_dev *input)
163+{
164+ struct jz4740_ts *jz4740_ts = input_get_drvdata(input);
165+
166+ jz4740_ts->cell->disable(jz4740_ts->pdev);
167+ jz4740_ts->is_open = false;
168+}
169+
170+static int __devinit jz4740_ts_probe(struct platform_device *pdev)
171+{
172+ int ret = 0;
173+ struct jz4740_ts *jz4740_ts;
174+ struct input_dev *input;
175+
176+ jz4740_ts = kzalloc(sizeof(*jz4740_ts), GFP_KERNEL);
177+ if (!jz4740_ts) {
178+ dev_err(&pdev->dev, "Failed to allocate driver structure\n");
179+ return -ENOMEM;
180+ }
181+
182+ jz4740_ts->pdev = pdev;
183+ jz4740_ts->cell = pdev->dev.platform_data;
184+
185+ jz4740_ts->irq_data_ready = platform_get_irq(pdev, 0);
186+ if (jz4740_ts->irq_data_ready < 0) {
187+ ret = jz4740_ts->irq_data_ready;
188+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
189+ goto err_free;
190+ }
191+
192+ jz4740_ts->irq_penup = platform_get_irq(pdev, 1);
193+ if (jz4740_ts->irq_penup < 0) {
194+ ret = jz4740_ts->irq_penup;
195+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
196+ goto err_free;
197+ }
198+
199+ jz4740_ts->irq_pendown = platform_get_irq(pdev, 2);
200+ if (jz4740_ts->irq_pendown < 0) {
201+ ret = jz4740_ts->irq_pendown;
202+ dev_err(&pdev->dev, "Failed to get platform irq: %d\n", ret);
203+ goto err_free;
204+ }
205+
206+ jz4740_ts->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
207+ if (!jz4740_ts->mem) {
208+ ret = -ENOENT;
209+ dev_err(&pdev->dev, "Failed to get platform mmio resource\n");
210+ goto err_free;
211+ }
212+
213+ jz4740_ts->mem = request_mem_region(jz4740_ts->mem->start,
214+ resource_size(jz4740_ts->mem), pdev->name);
215+ if (!jz4740_ts->mem) {
216+ ret = -EBUSY;
217+ dev_err(&pdev->dev, "Failed to request mmio memory region\n");
218+ goto err_free;
219+ }
220+
221+ jz4740_ts->base = ioremap_nocache(jz4740_ts->mem->start,
222+ resource_size(jz4740_ts->mem));
223+ if (!jz4740_ts->base) {
224+ ret = -EBUSY;
225+ dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
226+ goto err_release_mem_region;
227+ }
228+
229+ input = input_allocate_device();
230+ if (!input) {
231+ dev_err(&pdev->dev, "Failed to allocate input device\n");
232+ ret = -ENOMEM;
233+ goto err_iounmap;
234+ }
235+
236+ input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
237+ __set_bit(BTN_TOUCH, input->keybit);
238+
239+ input_set_abs_params(input, ABS_X, 150, 3920, 0, 0);
240+ input_set_abs_params(input, ABS_Y, 270, 3700, 0, 0);
241+ input_set_abs_params(input, ABS_PRESSURE, 0, 4096, 0, 0);
242+
243+ input->name = pdev->name;
244+ input->phys = "jz4740";
245+ input->id.bustype = BUS_HOST;
246+ input->dev.parent = &pdev->dev;
247+
248+ input->open = jz4740_ts_open;
249+ input->close = jz4740_ts_close;
250+
251+ input_set_drvdata(input, jz4740_ts);
252+
253+ ret = input_register_device(input);
254+ if (ret) {
255+ dev_err(&pdev->dev, "Failed to register input device: %d\n", ret);
256+ input_free_device(input);
257+ goto err_iounmap;
258+ }
259+ jz4740_ts->input = input;
260+
261+ ret = request_irq(jz4740_ts->irq_data_ready, jz4740_ts_data_ready_irq_handler, 0, pdev->name,
262+ jz4740_ts);
263+ if (ret) {
264+ dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
265+ goto err_input_unregister_device;
266+ }
267+ ret = request_irq(jz4740_ts->irq_penup, jz4740_ts_pen_irq_handler, 0, pdev->name,
268+ jz4740_ts);
269+ if (ret) {
270+ dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
271+ goto err_free_irq_data_ready;
272+ }
273+ disable_irq(jz4740_ts->irq_penup);
274+ ret = request_irq(jz4740_ts->irq_pendown, jz4740_ts_pen_irq_handler, 0, pdev->name,
275+ jz4740_ts);
276+ if (ret) {
277+ dev_err(&pdev->dev, "Failed to request irq %d\n", ret);
278+ goto err_free_irq_penup;
279+ }
280+ platform_set_drvdata(pdev, jz4740_ts);
281+
282+ jz4740_adc_set_config(pdev->dev.parent,
283+ JZ_ADC_CONFIG_EX_IN | JZ_ADC_CONFIG_XYZ_OFFSET(2) | JZ_ADC_CONFIG_DNUM(7),
284+ JZ_ADC_CONFIG_EX_IN | JZ_ADC_CONFIG_XYZ_MASK | JZ_ADC_CONFIG_DNUM_MASK);
285+
286+
287+ writel(0x15e, jz4740_ts->base);
288+ writel(0x32, jz4740_ts->base + 0x04);
289+
290+ return 0;
291+
292+err_free_irq_penup:
293+ free_irq(jz4740_ts->irq_penup, jz4740_ts);
294+err_free_irq_data_ready:
295+ free_irq(jz4740_ts->irq_data_ready, jz4740_ts);
296+err_input_unregister_device:
297+ input_unregister_device(jz4740_ts->input);
298+err_iounmap:
299+ platform_set_drvdata(pdev, NULL);
300+ iounmap(jz4740_ts->base);
301+err_release_mem_region:
302+ release_mem_region(jz4740_ts->mem->start, resource_size(jz4740_ts->mem));
303+err_free:
304+ kfree(jz4740_ts);
305+ return ret;
306+}
307+
308+static int __devexit jz4740_ts_remove(struct platform_device *pdev)
309+{
310+ struct jz4740_ts *jz4740_ts = platform_get_drvdata(pdev);
311+
312+
313+ free_irq(jz4740_ts->irq_pendown, jz4740_ts);
314+ free_irq(jz4740_ts->irq_penup, jz4740_ts);
315+ free_irq(jz4740_ts->irq_data_ready, jz4740_ts);
316+
317+ input_unregister_device(jz4740_ts->input);
318+
319+ iounmap(jz4740_ts->base);
320+ release_mem_region(jz4740_ts->mem->start, resource_size(jz4740_ts->mem));
321+
322+ kfree(jz4740_ts);
323+
324+ return 0;
325+}
326+
327+#ifdef CONFIG_PM
328+static int jz4740_ts_suspend(struct device *dev)
329+{
330+ struct jz4740_ts *jz4740_ts = dev_get_drvdata(dev);
331+
332+ if (jz4740_ts->is_open);
333+ jz4740_ts->cell->disable(jz4740_ts->pdev);
334+
335+ return 0;
336+}
337+
338+static int jz4740_ts_resume(struct device *dev)
339+{
340+ struct jz4740_ts *jz4740_ts = dev_get_drvdata(dev);
341+
342+ if (jz4740_ts->is_open);
343+ jz4740_ts->cell->enable(jz4740_ts->pdev);
344+
345+ return 0;
346+}
347+
348+static const struct dev_pm_ops jz4740_ts_pm_ops = {
349+ .suspend = jz4740_ts_suspend,
350+ .resume = jz4740_ts_resume,
351+};
352+
353+#define JZ4740_TS_PM_OPS (&jz4740_ts_pm_ops)
354+#else
355+#define JZ4740_TS_PM_OPS NULL
356+#endif
357+
358+static struct platform_driver jz4740_ts_driver = {
359+ .probe = jz4740_ts_probe,
360+ .remove = __devexit_p(jz4740_ts_remove),
361+ .driver = {
362+ .name = "jz4740-ts",
363+ .owner = THIS_MODULE,
364+ .pm = JZ4740_TS_PM_OPS,
365+ },
366+};
367+
368+static int __init jz4740_ts_init(void)
369+{
370+ return platform_driver_register(&jz4740_ts_driver);
371+}
372+module_init(jz4740_ts_init);
373+
374+static void __exit jz4740_ts_exit(void)
375+{
376+ platform_driver_unregister(&jz4740_ts_driver);
377+}
378+module_exit(jz4740_ts_exit);
379+
380+MODULE_ALIAS("platform:jz4740-ts");
381+MODULE_LICENSE("GPL");
382+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
383+MODULE_DESCRIPTION("JZ4740 SoC battery driver");
384--
3851.7.4.1
386
target/linux/xburst/patches-3.1/0012-Add-ili8960-lcd-driver.patch
1From 19cb6a83b7564e675d58526210f8e143938234bf Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sun, 1 Aug 2010 21:19:40 +0200
4Subject: [PATCH 12/24] Add ili8960 lcd driver
5
6---
7 drivers/video/backlight/Kconfig | 7 +
8 drivers/video/backlight/Makefile | 1 +
9 drivers/video/backlight/ili8960.c | 263 +++++++++++++++++++++++++++++++++++++
10 3 files changed, 271 insertions(+), 0 deletions(-)
11 create mode 100644 drivers/video/backlight/ili8960.c
12
13diff --git a/drivers/video/backlight/Kconfig b/drivers/video/backlight/Kconfig
14index 278aeaa..f617883 100644
15--- a/drivers/video/backlight/Kconfig
16@@ -59,6 +59,13 @@ config LCD_LTV350QV
17
18       The LTV350QV panel is present on all ATSTK1000 boards.
19
20+config LCD_ILI8960
21+ tristate "Ilitek ili8960 LCD driver"
22+ depends on LCD_CLASS_DEVICE && SPI
23+ default n
24+ help
25+ Driver for the Ilitek ili8960 LCD controller chip.
26+
27 config LCD_ILI9320
28     tristate
29     help
30diff --git a/drivers/video/backlight/Makefile b/drivers/video/backlight/Makefile
31index fdd1fc4..01ec378 100644
32--- a/drivers/video/backlight/Makefile
33@@ -6,6 +6,7 @@ obj-$(CONFIG_LCD_HP700) += jornada720_lcd.o
34 obj-$(CONFIG_LCD_L4F00242T03) += l4f00242t03.o
35 obj-$(CONFIG_LCD_LMS283GF05) += lms283gf05.o
36 obj-$(CONFIG_LCD_LTV350QV) += ltv350qv.o
37+obj-$(CONFIG_LCD_ILI8960) += ili8960.o
38 obj-$(CONFIG_LCD_ILI9320) += ili9320.o
39 obj-$(CONFIG_LCD_PLATFORM) += platform_lcd.o
40 obj-$(CONFIG_LCD_VGG2432A4) += vgg2432a4.o
41diff --git a/drivers/video/backlight/ili8960.c b/drivers/video/backlight/ili8960.c
42new file mode 100644
43index 0000000..1438e92
44--- /dev/null
45@@ -0,0 +1,263 @@
46+/*
47+ * Copyright (C) 2009-2010, Lars-Peter Clausen <lars@metafoo.de>
48+ * Driver for Ilitek ili8960 LCD
49+ *
50+ * This program is free software; you can redistribute it and/or modify it
51+ * under the terms of the GNU General Public License as published by the
52+ * Free Software Foundation; either version 2 of the License, or (at your
53+ * option) any later version.
54+ *
55+ * You should have received a copy of the GNU General Public License along
56+ * with this program; if not, write to the Free Software Foundation, Inc.,
57+ * 675 Mass Ave, Cambridge, MA 02139, USA.
58+ *
59+ */
60+
61+#include <linux/module.h>
62+#include <linux/spi/spi.h>
63+#include <linux/lcd.h>
64+#include <linux/backlight.h>
65+#include <linux/delay.h>
66+
67+struct ili8960 {
68+ struct spi_device *spi;
69+ struct lcd_device *lcd;
70+ struct backlight_device *bl;
71+ bool enabled;
72+ unsigned int brightness;
73+};
74+
75+#define ILI8960_REG_BRIGHTNESS 0x03
76+#define ILI8960_REG_POWER 0x05
77+#define ILI8960_REG_CONTRAST 0x0d
78+
79+static int ili8960_write_reg(struct spi_device *spi, uint8_t reg,
80+ uint8_t data)
81+{
82+ uint8_t buf[2];
83+ buf[0] = ((reg & 0x40) << 1) | (reg & 0x3f);
84+ buf[1] = data;
85+
86+ return spi_write(spi, buf, sizeof(buf));
87+}
88+
89+static int ili8960_programm_power(struct spi_device *spi, bool enabled)
90+{
91+ int ret;
92+
93+ if (enabled)
94+ mdelay(20);
95+
96+ ret = ili8960_write_reg(spi, ILI8960_REG_POWER, enabled ? 0xc7 : 0xc6);
97+
98+ if (!enabled)
99+ mdelay(20);
100+
101+ return ret;
102+}
103+
104+static int ili8960_set_power(struct lcd_device *lcd, int power)
105+{
106+ struct ili8960 *ili8960 = lcd_get_data(lcd);
107+
108+ switch (power) {
109+ case FB_BLANK_UNBLANK:
110+ ili8960->enabled = true;
111+ break;
112+ default:
113+ ili8960->enabled = false;
114+ break;
115+ }
116+
117+ return ili8960_programm_power(ili8960->spi, ili8960->enabled);
118+}
119+
120+static int ili8960_get_power(struct lcd_device *lcd)
121+{
122+ struct ili8960 *ili8960 = lcd_get_data(lcd);
123+ return ili8960->enabled ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
124+}
125+
126+static int ili8960_set_contrast(struct lcd_device *lcd, int contrast)
127+{
128+ struct ili8960 *ili8960 = lcd_get_data(lcd);
129+
130+ return ili8960_write_reg(ili8960->spi, ILI8960_REG_CONTRAST, contrast);
131+}
132+
133+static int ili8960_set_mode(struct lcd_device *lcd, struct fb_videomode *mode)
134+{
135+ if (mode->xres != 320 && mode->yres != 240)
136+ return -EINVAL;
137+
138+ return 0;
139+}
140+
141+static int ili8960_set_brightness(struct ili8960 *ili8960, int brightness)
142+{
143+ int ret;
144+
145+ ret = ili8960_write_reg(ili8960->spi, ILI8960_REG_BRIGHTNESS, brightness);
146+
147+ if (ret == 0)
148+ ili8960->brightness = brightness;
149+
150+ return ret;
151+}
152+
153+static ssize_t ili8960_show_brightness(struct device *dev,
154+ struct device_attribute *attr, char *buf)
155+{
156+ struct lcd_device *ld = to_lcd_device(dev);
157+ struct ili8960 *ili8960 = lcd_get_data(ld);
158+
159+ return sprintf(buf, "%u\n", ili8960->brightness);
160+}
161+
162+static ssize_t ili8960_store_brightness(struct device *dev,
163+ struct device_attribute *attr, const char *buf, size_t count)
164+{
165+ struct lcd_device *ld = to_lcd_device(dev);
166+ struct ili8960 *ili8960 = lcd_get_data(ld);
167+ unsigned long brightness;
168+ int ret;
169+
170+ ret = strict_strtoul(buf, 0, &brightness);
171+ if (ret)
172+ return ret;
173+
174+ if (brightness > 255)
175+ return -EINVAL;
176+
177+ ili8960_set_brightness(ili8960, brightness);
178+
179+ return count;
180+}
181+
182+
183+static DEVICE_ATTR(brightness, 0644, ili8960_show_brightness,
184+ ili8960_store_brightness);
185+
186+static struct lcd_ops ili8960_lcd_ops = {
187+ .set_power = ili8960_set_power,
188+ .get_power = ili8960_get_power,
189+ .set_contrast = ili8960_set_contrast,
190+ .set_mode = ili8960_set_mode,
191+};
192+
193+static int __devinit ili8960_probe(struct spi_device *spi)
194+{
195+ int ret;
196+ struct ili8960 *ili8960;
197+
198+ ili8960 = kmalloc(sizeof(*ili8960), GFP_KERNEL);
199+ if (!ili8960)
200+ return -ENOMEM;
201+
202+ spi->bits_per_word = 8;
203+ spi->mode = SPI_MODE_3;
204+
205+ ret = spi_setup(spi);
206+ if (ret) {
207+ dev_err(&spi->dev, "Failed to setup spi\n");
208+ goto err_free_ili8960;
209+ }
210+
211+ ili8960->spi = spi;
212+
213+ ili8960->lcd = lcd_device_register("ili8960-lcd", &spi->dev, ili8960,
214+ &ili8960_lcd_ops);
215+
216+ if (IS_ERR(ili8960->lcd)) {
217+ ret = PTR_ERR(ili8960->lcd);
218+ dev_err(&spi->dev, "Failed to register lcd device: %d\n", ret);
219+ goto err_free_ili8960;
220+ }
221+
222+ ili8960->lcd->props.max_contrast = 255;
223+
224+ ret = device_create_file(&ili8960->lcd->dev, &dev_attr_brightness);
225+ if (ret)
226+ goto err_unregister_lcd;
227+
228+ ili8960_programm_power(ili8960->spi, true);
229+ ili8960->enabled = true;
230+
231+ spi_set_drvdata(spi, ili8960);
232+
233+ ili8960_write_reg(spi, 0x13, 0x01);
234+
235+ return 0;
236+err_unregister_lcd:
237+ lcd_device_unregister(ili8960->lcd);
238+err_free_ili8960:
239+ kfree(ili8960);
240+ return ret;
241+}
242+
243+static int __devexit ili8960_remove(struct spi_device *spi)
244+{
245+ struct ili8960 *ili8960 = spi_get_drvdata(spi);
246+
247+ device_remove_file(&ili8960->lcd->dev, &dev_attr_brightness);
248+ lcd_device_unregister(ili8960->lcd);
249+
250+ spi_set_drvdata(spi, NULL);
251+ kfree(ili8960);
252+ return 0;
253+}
254+
255+#ifdef CONFIG_PM
256+
257+static int ili8960_suspend(struct spi_device *spi, pm_message_t state)
258+{
259+ struct ili8960 *ili8960 = spi_get_drvdata(spi);
260+
261+ if (ili8960->enabled)
262+ ili8960_programm_power(ili8960->spi, false);
263+
264+ return 0;
265+}
266+
267+static int ili8960_resume(struct spi_device *spi)
268+{
269+ struct ili8960 *ili8960 = spi_get_drvdata(spi);
270+
271+ if (ili8960->enabled)
272+ ili8960_programm_power(ili8960->spi, true);
273+
274+ return 0;
275+}
276+
277+#else
278+#define ili8960_suspend NULL
279+#define ili8960_resume NULL
280+#endif
281+
282+static struct spi_driver ili8960_driver = {
283+ .driver = {
284+ .name = "ili8960",
285+ .owner = THIS_MODULE,
286+ },
287+ .probe = ili8960_probe,
288+ .remove = __devexit_p(ili8960_remove),
289+ .suspend = ili8960_suspend,
290+ .resume = ili8960_resume,
291+};
292+
293+static int __init ili8960_init(void)
294+{
295+ return spi_register_driver(&ili8960_driver);
296+}
297+module_init(ili8960_init);
298+
299+static void __exit ili8960_exit(void)
300+{
301+ spi_unregister_driver(&ili8960_driver);
302+}
303+module_exit(ili8960_exit)
304+
305+MODULE_AUTHOR("Lars-Peter Clausen");
306+MODULE_LICENSE("GPL");
307+MODULE_DESCRIPTION("LCD driver for Ilitek ili8960");
308+MODULE_ALIAS("spi:ili8960");
309--
3101.7.4.1
311
target/linux/xburst/patches-3.1/0013-Add-jz4740-udc-driver.patch
1From e4a0de3dcd42844cbaa2510508fda678d6c4962f Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sat, 24 Apr 2010 12:18:46 +0200
4Subject: [PATCH 13/24] Add jz4740 udc driver
5
6---
7 drivers/usb/gadget/Kconfig | 13 +
8 drivers/usb/gadget/Makefile | 1 +
9 drivers/usb/gadget/gadget_chips.h | 8 +
10 drivers/usb/gadget/jz4740_udc.c | 2378 +++++++++++++++++++++++++++++++++++++
11 drivers/usb/gadget/jz4740_udc.h | 101 ++
12 5 files changed, 2501 insertions(+), 0 deletions(-)
13 create mode 100644 drivers/usb/gadget/jz4740_udc.c
14 create mode 100644 drivers/usb/gadget/jz4740_udc.h
15
16diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
17index 5a084b9..9607fdf 100644
18--- a/drivers/usb/gadget/Kconfig
19@@ -118,6 +118,19 @@ choice
20 #
21 # Integrated controllers
22 #
23+config USB_GADGET_JZ4740
24+ boolean "JZ4740 UDC"
25+ depends on MACH_JZ4740
26+ select USB_GADGET_SELECTED
27+ select USB_GADGET_DUALSPEED
28+ help
29+ Select this to support the Ingenic JZ4740 processor
30+ high speed USB device controller.
31+
32+config USB_JZ4740
33+ tristate
34+ depends on USB_GADGET_JZ4740
35+ default USB_GADGET
36
37 config USB_AT91
38     tristate "Atmel AT91 USB Device Port"
39diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile
40index 9ba725a..0a1b119 100644
41--- a/drivers/usb/gadget/Makefile
42@@ -31,6 +31,7 @@ obj-$(CONFIG_USB_PXA_U2O) += mv_udc.o
43 mv_udc-y := mv_udc_core.o mv_udc_phy.o
44 obj-$(CONFIG_USB_CI13XXX_MSM) += ci13xxx_msm.o
45 obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o
46+obj-$(CONFIG_USB_JZ4740) += jz4740_udc.o
47
48 #
49 # USB gadget drivers
50diff --git a/drivers/usb/gadget/gadget_chips.h b/drivers/usb/gadget/gadget_chips.h
51index f3a83cd..cc30b50 100644
52--- a/drivers/usb/gadget/gadget_chips.h
53@@ -15,6 +15,12 @@
54 #ifndef __GADGET_CHIPS_H
55 #define __GADGET_CHIPS_H
56
57+#ifdef CONFIG_USB_GADGET_JZ4740
58+#define gadget_is_jz4740(g) !strcmp("ingenic_hsusb", (g)->name)
59+#else
60+#define gadget_is_jz4740(g) 0
61+#endif
62+
63 /*
64  * NOTICE: the entries below are alphabetical and should be kept
65  * that way.
66@@ -115,6 +121,8 @@ static inline int usb_gadget_controller_number(struct usb_gadget *gadget)
67         return 0x30;
68     else if (gadget_is_net2272(gadget))
69         return 0x31;
70+ else if (gadget_is_jz4740(gadget))
71+ return 0x32;
72
73     return -ENOENT;
74 }
75diff --git a/drivers/usb/gadget/jz4740_udc.c b/drivers/usb/gadget/jz4740_udc.c
76new file mode 100644
77index 0000000..68e511a
78--- /dev/null
79@@ -0,0 +1,2378 @@
80+/*
81+ * linux/drivers/usb/gadget/jz4740_udc.c
82+ *
83+ * Ingenic JZ4740 on-chip high speed USB device controller
84+ *
85+ * Copyright (C) 2006 - 2008 Ingenic Semiconductor Inc.
86+ * Author: <jlwei@ingenic.cn>
87+ *
88+ * This program is free software; you can redistribute it and/or modify
89+ * it under the terms of the GNU General Public License as published by
90+ * the Free Software Foundation; either version 2 of the License, or
91+ * (at your option) any later version.
92+ */
93+
94+/*
95+ * This device has ep0, two bulk-in/interrupt-in endpoints, and one bulk-out endpoint.
96+ *
97+ * - Endpoint numbering is fixed: ep0, ep1in-int, ep2in-bulk, ep1out-bulk.
98+ * - DMA works with bulk-in (channel 1) and bulk-out (channel 2) endpoints.
99+ */
100+
101+#include <linux/kernel.h>
102+#include <linux/module.h>
103+#include <linux/platform_device.h>
104+#include <linux/delay.h>
105+#include <linux/ioport.h>
106+#include <linux/slab.h>
107+#include <linux/errno.h>
108+#include <linux/init.h>
109+#include <linux/list.h>
110+#include <linux/interrupt.h>
111+#include <linux/proc_fs.h>
112+#include <linux/usb.h>
113+#include <linux/usb/gadget.h>
114+#include <linux/clk.h>
115+
116+#include <asm/byteorder.h>
117+#include <asm/io.h>
118+#include <asm/irq.h>
119+#include <asm/system.h>
120+#include <asm/mach-jz4740/clock.h>
121+
122+#include "jz4740_udc.h"
123+
124+#define JZ_REG_UDC_FADDR 0x00 /* Function Address 8-bit */
125+#define JZ_REG_UDC_POWER 0x01 /* Power Management 8-bit */
126+#define JZ_REG_UDC_INTRIN 0x02 /* Interrupt IN 16-bit */
127+#define JZ_REG_UDC_INTROUT 0x04 /* Interrupt OUT 16-bit */
128+#define JZ_REG_UDC_INTRINE 0x06 /* Intr IN enable 16-bit */
129+#define JZ_REG_UDC_INTROUTE 0x08 /* Intr OUT enable 16-bit */
130+#define JZ_REG_UDC_INTRUSB 0x0a /* Interrupt USB 8-bit */
131+#define JZ_REG_UDC_INTRUSBE 0x0b /* Interrupt USB Enable 8-bit */
132+#define JZ_REG_UDC_FRAME 0x0c /* Frame number 16-bit */
133+#define JZ_REG_UDC_INDEX 0x0e /* Index register 8-bit */
134+#define JZ_REG_UDC_TESTMODE 0x0f /* USB test mode 8-bit */
135+
136+#define JZ_REG_UDC_CSR0 0x12 /* EP0 CSR 8-bit */
137+#define JZ_REG_UDC_INMAXP 0x10 /* EP1-2 IN Max Pkt Size 16-bit */
138+#define JZ_REG_UDC_INCSR 0x12 /* EP1-2 IN CSR LSB 8/16bit */
139+#define JZ_REG_UDC_INCSRH 0x13 /* EP1-2 IN CSR MSB 8-bit */
140+#define JZ_REG_UDC_OUTMAXP 0x14 /* EP1 OUT Max Pkt Size 16-bit */
141+#define JZ_REG_UDC_OUTCSR 0x16 /* EP1 OUT CSR LSB 8/16bit */
142+#define JZ_REG_UDC_OUTCSRH 0x17 /* EP1 OUT CSR MSB 8-bit */
143+#define JZ_REG_UDC_OUTCOUNT 0x18 /* bytes in EP0/1 OUT FIFO 16-bit */
144+
145+#define JZ_REG_UDC_EP_FIFO(x) (4 * (x) + 0x20)
146+
147+#define JZ_REG_UDC_EPINFO 0x78 /* Endpoint information */
148+#define JZ_REG_UDC_RAMINFO 0x79 /* RAM information */
149+
150+#define JZ_REG_UDC_INTR 0x200 /* DMA pending interrupts */
151+#define JZ_REG_UDC_CNTL1 0x204 /* DMA channel 1 control */
152+#define JZ_REG_UDC_ADDR1 0x208 /* DMA channel 1 AHB memory addr */
153+#define JZ_REG_UDC_COUNT1 0x20c /* DMA channel 1 byte count */
154+#define JZ_REG_UDC_CNTL2 0x214 /* DMA channel 2 control */
155+#define JZ_REG_UDC_ADDR2 0x218 /* DMA channel 2 AHB memory addr */
156+#define JZ_REG_UDC_COUNT2 0x21c /* DMA channel 2 byte count */
157+
158+/* Power register bit masks */
159+#define USB_POWER_SUSPENDM 0x01
160+#define USB_POWER_RESUME 0x04
161+#define USB_POWER_HSMODE 0x10
162+#define USB_POWER_HSENAB 0x20
163+#define USB_POWER_SOFTCONN 0x40
164+
165+/* Interrupt register bit masks */
166+#define USB_INTR_SUSPEND 0x01
167+#define USB_INTR_RESUME 0x02
168+#define USB_INTR_RESET 0x04
169+
170+#define USB_INTR_EP0 0x0001
171+#define USB_INTR_INEP1 0x0002
172+#define USB_INTR_INEP2 0x0004
173+#define USB_INTR_OUTEP1 0x0002
174+
175+/* CSR0 bit masks */
176+#define USB_CSR0_OUTPKTRDY 0x01
177+#define USB_CSR0_INPKTRDY 0x02
178+#define USB_CSR0_SENTSTALL 0x04
179+#define USB_CSR0_DATAEND 0x08
180+#define USB_CSR0_SETUPEND 0x10
181+#define USB_CSR0_SENDSTALL 0x20
182+#define USB_CSR0_SVDOUTPKTRDY 0x40
183+#define USB_CSR0_SVDSETUPEND 0x80
184+
185+/* Endpoint CSR register bits */
186+#define USB_INCSRH_AUTOSET 0x80
187+#define USB_INCSRH_ISO 0x40
188+#define USB_INCSRH_MODE 0x20
189+#define USB_INCSRH_DMAREQENAB 0x10
190+#define USB_INCSRH_DMAREQMODE 0x04
191+#define USB_INCSR_CDT 0x40
192+#define USB_INCSR_SENTSTALL 0x20
193+#define USB_INCSR_SENDSTALL 0x10
194+#define USB_INCSR_FF 0x08
195+#define USB_INCSR_UNDERRUN 0x04
196+#define USB_INCSR_FFNOTEMPT 0x02
197+#define USB_INCSR_INPKTRDY 0x01
198+#define USB_OUTCSRH_AUTOCLR 0x80
199+#define USB_OUTCSRH_ISO 0x40
200+#define USB_OUTCSRH_DMAREQENAB 0x20
201+#define USB_OUTCSRH_DNYT 0x10
202+#define USB_OUTCSRH_DMAREQMODE 0x08
203+#define USB_OUTCSR_CDT 0x80
204+#define USB_OUTCSR_SENTSTALL 0x40
205+#define USB_OUTCSR_SENDSTALL 0x20
206+#define USB_OUTCSR_FF 0x10
207+#define USB_OUTCSR_DATAERR 0x08
208+#define USB_OUTCSR_OVERRUN 0x04
209+#define USB_OUTCSR_FFFULL 0x02
210+#define USB_OUTCSR_OUTPKTRDY 0x01
211+
212+/* DMA control bits */
213+#define USB_CNTL_ENA 0x01
214+#define USB_CNTL_DIR_IN 0x02
215+#define USB_CNTL_MODE_1 0x04
216+#define USB_CNTL_INTR_EN 0x08
217+#define USB_CNTL_EP(n) ((n) << 4)
218+#define USB_CNTL_BURST_0 (0 << 9)
219+#define USB_CNTL_BURST_4 (1 << 9)
220+#define USB_CNTL_BURST_8 (2 << 9)
221+#define USB_CNTL_BURST_16 (3 << 9)
222+
223+
224+#ifndef DEBUG
225+# define DEBUG(fmt,args...) do {} while(0)
226+#endif
227+#ifndef DEBUG_EP0
228+# define NO_STATES
229+# define DEBUG_EP0(fmt,args...) do {} while(0)
230+#endif
231+#ifndef DEBUG_SETUP
232+# define DEBUG_SETUP(fmt,args...) do {} while(0)
233+#endif
234+
235+static unsigned int use_dma = 0; /* 1: use DMA, 0: use PIO */
236+
237+module_param(use_dma, int, 0);
238+MODULE_PARM_DESC(use_dma, "DMA mode enable flag");
239+
240+static struct jz4740_udc jz4740_udc_controller;
241+
242+/*
243+ * Local declarations.
244+ */
245+static void jz4740_ep0_kick(struct jz4740_udc *dev, struct jz4740_ep *ep);
246+static void jz4740_handle_ep0(struct jz4740_udc *dev, uint32_t intr);
247+
248+static void done(struct jz4740_ep *ep, struct jz4740_request *req,
249+ int status);
250+static void pio_irq_enable(struct jz4740_ep *ep);
251+static void pio_irq_disable(struct jz4740_ep *ep);
252+static void stop_activity(struct jz4740_udc *dev,
253+ struct usb_gadget_driver *driver);
254+static void nuke(struct jz4740_ep *ep, int status);
255+static void flush(struct jz4740_ep *ep);
256+static void udc_set_address(struct jz4740_udc *dev, unsigned char address);
257+
258+/*-------------------------------------------------------------------------*/
259+
260+/* inline functions of register read/write/set/clear */
261+
262+static inline uint8_t usb_readb(struct jz4740_udc *udc, size_t reg)
263+{
264+ return readb(udc->base + reg);
265+}
266+
267+static inline uint16_t usb_readw(struct jz4740_udc *udc, size_t reg)
268+{
269+ return readw(udc->base + reg);
270+}
271+
272+static inline uint32_t usb_readl(struct jz4740_udc *udc, size_t reg)
273+{
274+ return readl(udc->base + reg);
275+}
276+
277+static inline void usb_writeb(struct jz4740_udc *udc, size_t reg, uint8_t val)
278+{
279+ writeb(val, udc->base + reg);
280+}
281+
282+static inline void usb_writew(struct jz4740_udc *udc, size_t reg, uint16_t val)
283+{
284+ writew(val, udc->base + reg);
285+}
286+
287+static inline void usb_writel(struct jz4740_udc *udc, size_t reg, uint32_t val)
288+{
289+ writel(val, udc->base + reg);
290+}
291+
292+static inline void usb_setb(struct jz4740_udc *udc, size_t reg, uint8_t mask)
293+{
294+ usb_writeb(udc, reg, usb_readb(udc, reg) | mask);
295+}
296+
297+static inline void usb_setw(struct jz4740_udc *udc, size_t reg, uint8_t mask)
298+{
299+ usb_writew(udc, reg, usb_readw(udc, reg) | mask);
300+}
301+
302+static inline void usb_clearb(struct jz4740_udc *udc, size_t reg, uint8_t mask)
303+{
304+ usb_writeb(udc, reg, usb_readb(udc, reg) & ~mask);
305+}
306+
307+static inline void usb_clearw(struct jz4740_udc *udc, size_t reg, uint16_t mask)
308+{
309+ usb_writew(udc, reg, usb_readw(udc, reg) & ~mask);
310+}
311+
312+/*-------------------------------------------------------------------------*/
313+
314+static inline void jz_udc_set_index(struct jz4740_udc *udc, uint8_t index)
315+{
316+ usb_writeb(udc, JZ_REG_UDC_INDEX, index);
317+}
318+
319+static inline void jz_udc_select_ep(struct jz4740_ep *ep)
320+{
321+ jz_udc_set_index(ep->dev, ep_index(ep));
322+}
323+
324+static inline int write_packet(struct jz4740_ep *ep,
325+ struct jz4740_request *req, unsigned int count)
326+{
327+ uint8_t *buf;
328+ unsigned int length, nlong, nbyte;
329+ void __iomem *fifo = ep->dev->base + ep->fifo;
330+
331+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
332+
333+ buf = req->req.buf + req->req.actual;
334+ prefetch(buf);
335+
336+ length = req->req.length - req->req.actual;
337+ if (length > count)
338+ length = count;
339+ req->req.actual += length;
340+
341+ DEBUG("Write %d (count %d), fifo %x\n", length, count, ep->fifo);
342+
343+ nlong = length >> 2;
344+ nbyte = length & 0x3;
345+ while (nlong--) {
346+ writel(*((uint32_t *)buf), fifo);
347+ buf += 4;
348+ }
349+ while (nbyte--)
350+ writeb(*buf++, fifo);
351+
352+ return length;
353+}
354+
355+static int read_packet(struct jz4740_ep *ep,
356+ struct jz4740_request *req, unsigned int count)
357+{
358+ uint8_t *buf;
359+ unsigned int length, nlong, nbyte;
360+ void __iomem *fifo = ep->dev->base + ep->fifo;
361+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
362+
363+ buf = req->req.buf + req->req.actual;
364+ prefetchw(buf);
365+
366+ length = req->req.length - req->req.actual;
367+ if (length > count)
368+ length = count;
369+ req->req.actual += length;
370+
371+ DEBUG("Read %d, fifo %x\n", length, ep->fifo);
372+ nlong = length >> 2;
373+ nbyte = length & 0x3;
374+ while (nlong--) {
375+ *((uint32_t *)buf) = readl(fifo);
376+ buf += 4;
377+ }
378+ while (nbyte--)
379+ *buf++ = readb(fifo);
380+
381+ return length;
382+}
383+
384+/*-------------------------------------------------------------------------*/
385+
386+/*
387+ * udc_disable - disable USB device controller
388+ */
389+static void udc_disable(struct jz4740_udc *dev)
390+{
391+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
392+
393+ udc_set_address(dev, 0);
394+
395+ /* Disable interrupts */
396+ usb_writew(dev, JZ_REG_UDC_INTRINE, 0);
397+ usb_writew(dev, JZ_REG_UDC_INTROUTE, 0);
398+ usb_writeb(dev, JZ_REG_UDC_INTRUSBE, 0);
399+
400+ /* Disable DMA */
401+ usb_writel(dev, JZ_REG_UDC_CNTL1, 0);
402+ usb_writel(dev, JZ_REG_UDC_CNTL2, 0);
403+
404+ /* Disconnect from usb */
405+ usb_clearb(dev, JZ_REG_UDC_POWER, USB_POWER_SOFTCONN);
406+
407+ /* Disable the USB PHY */
408+ clk_disable(dev->clk);
409+
410+ dev->ep0state = WAIT_FOR_SETUP;
411+ dev->gadget.speed = USB_SPEED_UNKNOWN;
412+
413+ return;
414+}
415+
416+/*
417+ * udc_reinit - initialize software state
418+ */
419+static void udc_reinit(struct jz4740_udc *dev)
420+{
421+ int i;
422+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
423+
424+ /* device/ep0 records init */
425+ INIT_LIST_HEAD(&dev->gadget.ep_list);
426+ INIT_LIST_HEAD(&dev->gadget.ep0->ep_list);
427+ dev->ep0state = WAIT_FOR_SETUP;
428+
429+ for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
430+ struct jz4740_ep *ep = &dev->ep[i];
431+
432+ if (i != 0)
433+ list_add_tail(&ep->ep.ep_list, &dev->gadget.ep_list);
434+
435+ INIT_LIST_HEAD(&ep->queue);
436+ ep->desc = 0;
437+ ep->stopped = 0;
438+ }
439+}
440+
441+/* until it's enabled, this UDC should be completely invisible
442+ * to any USB host.
443+ */
444+static void udc_enable(struct jz4740_udc *dev)
445+{
446+ int i;
447+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
448+
449+ /* UDC state is incorrect - Added by River */
450+ if (dev->state != UDC_STATE_ENABLE) {
451+ return;
452+ }
453+
454+ dev->gadget.speed = USB_SPEED_UNKNOWN;
455+
456+ /* Flush FIFO for each */
457+ for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
458+ struct jz4740_ep *ep = &dev->ep[i];
459+
460+ jz_udc_set_index(dev, ep_index(ep));
461+ flush(ep);
462+ }
463+
464+ /* Set this bit to allow the UDC entering low-power mode when
465+ * there are no actions on the USB bus.
466+ * UDC still works during this bit was set.
467+ */
468+ jz4740_clock_udc_enable_auto_suspend();
469+
470+ /* Enable the USB PHY */
471+ clk_enable(dev->clk);
472+
473+ /* Disable interrupts */
474+/* usb_writew(dev, JZ_REG_UDC_INTRINE, 0);
475+ usb_writew(dev, JZ_REG_UDC_INTROUTE, 0);
476+ usb_writeb(dev, JZ_REG_UDC_INTRUSBE, 0);*/
477+
478+ /* Enable interrupts */
479+ usb_setw(dev, JZ_REG_UDC_INTRINE, USB_INTR_EP0);
480+ usb_setb(dev, JZ_REG_UDC_INTRUSBE, USB_INTR_RESET);
481+ /* Don't enable rest of the interrupts */
482+ /* usb_setw(dev, JZ_REG_UDC_INTRINE, USB_INTR_INEP1 | USB_INTR_INEP2);
483+ usb_setw(dev, JZ_REG_UDC_INTROUTE, USB_INTR_OUTEP1); */
484+
485+ /* Enable SUSPEND */
486+ /* usb_setb(dev, JZ_REG_UDC_POWER, USB_POWER_SUSPENDM); */
487+
488+ /* Enable HS Mode */
489+ usb_setb(dev, JZ_REG_UDC_POWER, USB_POWER_HSENAB);
490+
491+ /* Let host detect UDC:
492+ * Software must write a 1 to the PMR:USB_POWER_SOFTCONN bit to turn this
493+ * transistor on and pull the USBDP pin HIGH.
494+ */
495+ usb_setb(dev, JZ_REG_UDC_POWER, USB_POWER_SOFTCONN);
496+
497+ return;
498+}
499+
500+/*-------------------------------------------------------------------------*/
501+
502+/* keeping it simple:
503+ * - one bus driver, initted first;
504+ * - one function driver, initted second
505+ */
506+
507+/*
508+ * Register entry point for the peripheral controller driver.
509+ */
510+
511+int usb_gadget_probe_driver(struct usb_gadget_driver *driver,
512+ int (*bind)(struct usb_gadget *))
513+{
514+ struct jz4740_udc *dev = &jz4740_udc_controller;
515+ int retval;
516+
517+ if (!driver || !bind)
518+ return -EINVAL;
519+
520+ if (!dev)
521+ return -ENODEV;
522+
523+ if (dev->driver)
524+ return -EBUSY;
525+
526+ /* hook up the driver */
527+ dev->driver = driver;
528+ dev->gadget.dev.driver = &driver->driver;
529+
530+ retval = bind(&dev->gadget);
531+ if (retval) {
532+ DEBUG("%s: bind to driver %s --> error %d\n", dev->gadget.name,
533+ driver->driver.name, retval);
534+ dev->driver = 0;
535+ return retval;
536+ }
537+
538+ /* then enable host detection and ep0; and we're ready
539+ * for set_configuration as well as eventual disconnect.
540+ */
541+ udc_enable(dev);
542+
543+ DEBUG("%s: registered gadget driver '%s'\n", dev->gadget.name,
544+ driver->driver.name);
545+
546+ return 0;
547+}
548+EXPORT_SYMBOL(usb_gadget_probe_driver);
549+
550+static void stop_activity(struct jz4740_udc *dev,
551+ struct usb_gadget_driver *driver)
552+{
553+ int i;
554+
555+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
556+
557+ /* don't disconnect drivers more than once */
558+ if (dev->gadget.speed == USB_SPEED_UNKNOWN)
559+ driver = 0;
560+ dev->gadget.speed = USB_SPEED_UNKNOWN;
561+
562+ /* prevent new request submissions, kill any outstanding requests */
563+ for (i = 0; i < UDC_MAX_ENDPOINTS; i++) {
564+ struct jz4740_ep *ep = &dev->ep[i];
565+
566+ ep->stopped = 1;
567+
568+ jz_udc_set_index(dev, ep_index(ep));
569+ nuke(ep, -ESHUTDOWN);
570+ }
571+
572+ /* report disconnect; the driver is already quiesced */
573+ if (driver) {
574+ spin_unlock(&dev->lock);
575+ driver->disconnect(&dev->gadget);
576+ spin_lock(&dev->lock);
577+ }
578+
579+ /* re-init driver-visible data structures */
580+ udc_reinit(dev);
581+}
582+
583+
584+/*
585+ * Unregister entry point for the peripheral controller driver.
586+ */
587+int usb_gadget_unregister_driver(struct usb_gadget_driver *driver)
588+{
589+ struct jz4740_udc *dev = &jz4740_udc_controller;
590+ unsigned long flags;
591+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
592+
593+ if (!dev)
594+ return -ENODEV;
595+ if (!driver || driver != dev->driver)
596+ return -EINVAL;
597+ if (!driver->unbind)
598+ return -EBUSY;
599+
600+ spin_lock_irqsave(&dev->lock, flags);
601+ dev->driver = 0;
602+ stop_activity(dev, driver);
603+ spin_unlock_irqrestore(&dev->lock, flags);
604+
605+ driver->unbind(&dev->gadget);
606+
607+ udc_disable(dev);
608+
609+ DEBUG("unregistered driver '%s'\n", driver->driver.name);
610+
611+ return 0;
612+}
613+
614+EXPORT_SYMBOL(usb_gadget_unregister_driver);
615+
616+/*-------------------------------------------------------------------------*/
617+
618+/*
619+ * Starting DMA using mode 1
620+ */
621+static void kick_dma(struct jz4740_ep *ep, struct jz4740_request *req)
622+{
623+ struct jz4740_udc *dev = ep->dev;
624+ uint32_t count = req->req.length;
625+ uint32_t physaddr = virt_to_phys((void *)req->req.buf);
626+
627+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
628+
629+ jz_udc_select_ep(ep);
630+
631+ if (ep_is_in(ep)) { /* Bulk-IN transfer using DMA channel 1 */
632+ ep->reg_addr = JZ_REG_UDC_ADDR1;
633+
634+ dma_cache_wback_inv((unsigned long)req->req.buf, count);
635+
636+ pio_irq_enable(ep);
637+
638+ usb_writeb(dev, JZ_REG_UDC_INCSRH,
639+ USB_INCSRH_DMAREQENAB | USB_INCSRH_AUTOSET | USB_INCSRH_DMAREQMODE);
640+
641+ usb_writel(dev, JZ_REG_UDC_ADDR1, physaddr);
642+ usb_writel(dev, JZ_REG_UDC_COUNT1, count);
643+ usb_writel(dev, JZ_REG_UDC_CNTL1, USB_CNTL_ENA | USB_CNTL_DIR_IN | USB_CNTL_MODE_1 |
644+ USB_CNTL_INTR_EN | USB_CNTL_BURST_16 | USB_CNTL_EP(ep_index(ep)));
645+ }
646+ else { /* Bulk-OUT transfer using DMA channel 2 */
647+ ep->reg_addr = JZ_REG_UDC_ADDR2;
648+
649+ dma_cache_wback_inv((unsigned long)req->req.buf, count);
650+
651+ pio_irq_enable(ep);
652+
653+ usb_setb(dev, JZ_REG_UDC_OUTCSRH,
654+ USB_OUTCSRH_DMAREQENAB | USB_OUTCSRH_AUTOCLR | USB_OUTCSRH_DMAREQMODE);
655+
656+ usb_writel(dev, JZ_REG_UDC_ADDR2, physaddr);
657+ usb_writel(dev, JZ_REG_UDC_COUNT2, count);
658+ usb_writel(dev, JZ_REG_UDC_CNTL2, USB_CNTL_ENA | USB_CNTL_MODE_1 |
659+ USB_CNTL_INTR_EN | USB_CNTL_BURST_16 | USB_CNTL_EP(ep_index(ep)));
660+ }
661+}
662+
663+/*-------------------------------------------------------------------------*/
664+
665+/** Write request to FIFO (max write == maxp size)
666+ * Return: 0 = still running, 1 = completed, negative = errno
667+ * NOTE: INDEX register must be set for EP
668+ */
669+static int write_fifo(struct jz4740_ep *ep, struct jz4740_request *req)
670+{
671+ struct jz4740_udc *dev = ep->dev;
672+ uint32_t max, csr;
673+ uint32_t physaddr = virt_to_phys((void *)req->req.buf);
674+
675+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
676+ max = le16_to_cpu(ep->desc->wMaxPacketSize);
677+
678+ if (use_dma) {
679+ uint32_t dma_count;
680+
681+ /* DMA interrupt generated due to the last packet loaded into the FIFO */
682+
683+ dma_count = usb_readl(dev, ep->reg_addr) - physaddr;
684+ req->req.actual += dma_count;
685+
686+ if (dma_count % max) {
687+ /* If the last packet is less than MAXP, set INPKTRDY manually */
688+ usb_setb(dev, ep->csr, USB_INCSR_INPKTRDY);
689+ }
690+
691+ done(ep, req, 0);
692+ if (list_empty(&ep->queue)) {
693+ pio_irq_disable(ep);
694+ return 1;
695+ }
696+ else {
697+ /* advance the request queue */
698+ req = list_entry(ep->queue.next, struct jz4740_request, queue);
699+ kick_dma(ep, req);
700+ return 0;
701+ }
702+ }
703+
704+ /*
705+ * PIO mode handling starts here ...
706+ */
707+
708+ csr = usb_readb(dev, ep->csr);
709+
710+ if (!(csr & USB_INCSR_FFNOTEMPT)) {
711+ unsigned count;
712+ int is_last, is_short;
713+
714+ count = write_packet(ep, req, max);
715+ usb_setb(dev, ep->csr, USB_INCSR_INPKTRDY);
716+
717+ /* last packet is usually short (or a zlp) */
718+ if (unlikely(count != max))
719+ is_last = is_short = 1;
720+ else {
721+ if (likely(req->req.length != req->req.actual)
722+ || req->req.zero)
723+ is_last = 0;
724+ else
725+ is_last = 1;
726+ /* interrupt/iso maxpacket may not fill the fifo */
727+ is_short = unlikely(max < ep_maxpacket(ep));
728+ }
729+
730+ DEBUG("%s: wrote %s %d bytes%s%s %d left %p\n", __FUNCTION__,
731+ ep->ep.name, count,
732+ is_last ? "/L" : "", is_short ? "/S" : "",
733+ req->req.length - req->req.actual, req);
734+
735+ /* requests complete when all IN data is in the FIFO */
736+ if (is_last) {
737+ done(ep, req, 0);
738+ if (list_empty(&ep->queue)) {
739+ pio_irq_disable(ep);
740+ }
741+ return 1;
742+ }
743+ } else {
744+ DEBUG("Hmm.. %d ep FIFO is not empty!\n", ep_index(ep));
745+ }
746+
747+ return 0;
748+}
749+
750+/** Read to request from FIFO (max read == bytes in fifo)
751+ * Return: 0 = still running, 1 = completed, negative = errno
752+ * NOTE: INDEX register must be set for EP
753+ */
754+static int read_fifo(struct jz4740_ep *ep, struct jz4740_request *req)
755+{
756+ struct jz4740_udc *dev = ep->dev;
757+ uint32_t csr;
758+ unsigned count, is_short;
759+
760+#if 0
761+ uint32_t physaddr = virt_to_phys((void *)req->req.buf);
762+
763+ if (use_dma) {
764+ uint32_t dma_count;
765+
766+ /* DMA interrupt generated due to a packet less than MAXP loaded into the FIFO */
767+
768+ dma_count = usb_readl(dev, ep->reg_addr) - physaddr;
769+ req->req.actual += dma_count;
770+
771+ /* Disable interrupt and DMA */
772+ pio_irq_disable(ep);
773+ usb_writel(dev, JZ_REG_UDC_CNTL2, 0);
774+
775+ /* Read all bytes from this packet */
776+ count = usb_readw(dev, JZ_REG_UDC_OUTCOUNT);
777+ count = read_packet(ep, req, count);
778+
779+ if (count) {
780+ /* If the last packet is greater than zero, clear OUTPKTRDY manually */
781+ usb_clearb(dev, ep->csr, USB_OUTCSR_OUTPKTRDY);
782+ }
783+ done(ep, req, 0);
784+
785+ if (!list_empty(&ep->queue)) {
786+ /* advance the request queue */
787+ req = list_entry(ep->queue.next, struct jz4740_request, queue);
788+ kick_dma(ep, req);
789+ }
790+
791+ return 1;
792+ }
793+#endif
794+ /*
795+ * PIO mode handling starts here ...
796+ */
797+
798+ /* make sure there's a packet in the FIFO. */
799+ csr = usb_readb(dev, ep->csr);
800+ if (!(csr & USB_OUTCSR_OUTPKTRDY)) {
801+ DEBUG("%s: Packet NOT ready!\n", __FUNCTION__);
802+ return -EINVAL;
803+ }
804+
805+ /* read all bytes from this packet */
806+ count = usb_readw(dev, JZ_REG_UDC_OUTCOUNT);
807+
808+ is_short = (count < ep->ep.maxpacket);
809+
810+ count = read_packet(ep, req, count);
811+
812+ DEBUG("read %s %02x, %d bytes%s req %p %d/%d\n",
813+ ep->ep.name, csr, count,
814+ is_short ? "/S" : "", req, req->req.actual, req->req.length);
815+
816+ /* Clear OutPktRdy */
817+ usb_clearb(dev, ep->csr, USB_OUTCSR_OUTPKTRDY);
818+
819+ /* completion */
820+ if (is_short || req->req.actual == req->req.length) {
821+ done(ep, req, 0);
822+
823+ if (list_empty(&ep->queue))
824+ pio_irq_disable(ep);
825+ return 1;
826+ }
827+
828+ /* finished that packet. the next one may be waiting... */
829+ return 0;
830+}
831+
832+/*
833+ * done - retire a request; caller blocked irqs
834+ * INDEX register is preserved to keep same
835+ */
836+static void done(struct jz4740_ep *ep, struct jz4740_request *req, int status)
837+{
838+ unsigned int stopped = ep->stopped;
839+ uint32_t index;
840+
841+ DEBUG("%s, %p\n", __FUNCTION__, ep);
842+ list_del_init(&req->queue);
843+
844+ if (likely(req->req.status == -EINPROGRESS))
845+ req->req.status = status;
846+ else
847+ status = req->req.status;
848+
849+ if (status && status != -ESHUTDOWN)
850+ DEBUG("complete %s req %p stat %d len %u/%u\n",
851+ ep->ep.name, &req->req, status,
852+ req->req.actual, req->req.length);
853+
854+ /* don't modify queue heads during completion callback */
855+ ep->stopped = 1;
856+ /* Read current index (completion may modify it) */
857+ index = usb_readb(ep->dev, JZ_REG_UDC_INDEX);
858+ spin_unlock_irqrestore(&ep->dev->lock, ep->dev->lock_flags);
859+
860+ req->req.complete(&ep->ep, &req->req);
861+
862+ spin_lock_irqsave(&ep->dev->lock, ep->dev->lock_flags);
863+ /* Restore index */
864+ jz_udc_set_index(ep->dev, index);
865+ ep->stopped = stopped;
866+}
867+
868+/** Enable EP interrupt */
869+static void pio_irq_enable(struct jz4740_ep *ep)
870+{
871+ uint8_t index = ep_index(ep);
872+ struct jz4740_udc *dev = ep->dev;
873+ DEBUG("%s: EP%d %s\n", __FUNCTION__, ep_index(ep), ep_is_in(ep) ? "IN": "OUT");
874+
875+ if (ep_is_in(ep)) {
876+ switch (index) {
877+ case 1:
878+ case 2:
879+ usb_setw(dev, JZ_REG_UDC_INTRINE, BIT(index));
880+ break;
881+ default:
882+ DEBUG("Unknown endpoint: %d\n", index);
883+ break;
884+ }
885+ }
886+ else {
887+ switch (index) {
888+ case 1:
889+ usb_setw(dev, JZ_REG_UDC_INTROUTE, BIT(index));
890+ break;
891+ default:
892+ DEBUG("Unknown endpoint: %d\n", index);
893+ break;
894+ }
895+ }
896+}
897+
898+/** Disable EP interrupt */
899+static void pio_irq_disable(struct jz4740_ep *ep)
900+{
901+ uint8_t index = ep_index(ep);
902+
903+ DEBUG("%s: EP%d %s\n", __FUNCTION__, ep_index(ep), ep_is_in(ep) ? "IN": "OUT");
904+
905+ if (ep_is_in(ep)) {
906+ switch (ep_index(ep)) {
907+ case 1:
908+ case 2:
909+ usb_clearw(ep->dev, JZ_REG_UDC_INTRINE, BIT(index));
910+ break;
911+ default:
912+ DEBUG("Unknown endpoint: %d\n", index);
913+ break;
914+ }
915+ }
916+ else {
917+ switch (ep_index(ep)) {
918+ case 1:
919+ usb_clearw(ep->dev, JZ_REG_UDC_INTROUTE, BIT(index));
920+ break;
921+ default:
922+ DEBUG("Unknown endpoint: %d\n", index);
923+ break;
924+ }
925+ }
926+}
927+
928+/*
929+ * nuke - dequeue ALL requests
930+ */
931+static void nuke(struct jz4740_ep *ep, int status)
932+{
933+ struct jz4740_request *req;
934+
935+ DEBUG("%s, %p\n", __FUNCTION__, ep);
936+
937+ /* Flush FIFO */
938+ flush(ep);
939+
940+ /* called with irqs blocked */
941+ while (!list_empty(&ep->queue)) {
942+ req = list_entry(ep->queue.next, struct jz4740_request, queue);
943+ done(ep, req, status);
944+ }
945+
946+ /* Disable IRQ if EP is enabled (has descriptor) */
947+ if (ep->desc)
948+ pio_irq_disable(ep);
949+}
950+
951+/** Flush EP FIFO
952+ * NOTE: INDEX register must be set before this call
953+ */
954+static void flush(struct jz4740_ep *ep)
955+{
956+ DEBUG("%s: %s\n", __FUNCTION__, ep->ep.name);
957+
958+ switch (ep->type) {
959+ case ep_bulk_in:
960+ case ep_interrupt:
961+ usb_setb(ep->dev, ep->csr, USB_INCSR_FF);
962+ break;
963+ case ep_bulk_out:
964+ usb_setb(ep->dev, ep->csr, USB_OUTCSR_FF);
965+ break;
966+ case ep_control:
967+ break;
968+ }
969+}
970+
971+/**
972+ * jz4740_in_epn - handle IN interrupt
973+ */
974+static void jz4740_in_epn(struct jz4740_udc *dev, uint32_t ep_idx, uint32_t intr)
975+{
976+ uint32_t csr;
977+ struct jz4740_ep *ep = &dev->ep[ep_idx + 1];
978+ struct jz4740_request *req;
979+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
980+
981+ jz_udc_set_index(dev, ep_index(ep));
982+
983+ csr = usb_readb(dev, ep->csr);
984+ DEBUG("%s: %d, csr %x\n", __FUNCTION__, ep_idx, csr);
985+
986+ if (csr & USB_INCSR_SENTSTALL) {
987+ DEBUG("USB_INCSR_SENTSTALL\n");
988+ usb_clearb(dev, ep->csr, USB_INCSR_SENTSTALL);
989+ return;
990+ }
991+
992+ if (!ep->desc) {
993+ DEBUG("%s: NO EP DESC\n", __FUNCTION__);
994+ return;
995+ }
996+
997+ if (!list_empty(&ep->queue)) {
998+ req = list_first_entry(&ep->queue, struct jz4740_request, queue);
999+ write_fifo(ep, req);
1000+ }
1001+}
1002+
1003+/*
1004+ * Bulk OUT (recv)
1005+ */
1006+static void jz4740_out_epn(struct jz4740_udc *dev, uint32_t ep_idx, uint32_t intr)
1007+{
1008+ struct jz4740_ep *ep = &dev->ep[ep_idx];
1009+ struct jz4740_request *req;
1010+
1011+ DEBUG("%s: %d\n", __FUNCTION__, ep_idx);
1012+
1013+ jz_udc_select_ep(ep);
1014+ if (ep->desc) {
1015+ uint32_t csr;
1016+
1017+ if (use_dma) {
1018+ /* DMA starts here ... */
1019+ if (!list_empty(&ep->queue)) {
1020+ req = list_first_entry(&ep->queue, struct jz4740_request, queue);
1021+ read_fifo(ep, req);
1022+ }
1023+ return;
1024+ }
1025+
1026+ /*
1027+ * PIO mode starts here ...
1028+ */
1029+
1030+ while ((csr = usb_readb(dev, ep->csr)) &
1031+ (USB_OUTCSR_OUTPKTRDY | USB_OUTCSR_SENTSTALL)) {
1032+ DEBUG("%s: %x\n", __FUNCTION__, csr);
1033+
1034+ if (csr & USB_OUTCSR_SENTSTALL) {
1035+ DEBUG("%s: stall sent, flush fifo\n",
1036+ __FUNCTION__);
1037+ /* usb_set(USB_OUT_CSR1_FIFO_FLUSH, ep->csr1); */
1038+ flush(ep);
1039+ } else if (csr & USB_OUTCSR_OUTPKTRDY) {
1040+ if (list_empty(&ep->queue))
1041+ req = 0;
1042+ else
1043+ req =
1044+ list_entry(ep->queue.next,
1045+ struct jz4740_request,
1046+ queue);
1047+
1048+ if (!req) {
1049+ DEBUG("%s: NULL REQ %d\n",
1050+ __FUNCTION__, ep_idx);
1051+ break;
1052+ } else {
1053+ read_fifo(ep, req);
1054+ }
1055+ }
1056+ }
1057+ } else {
1058+ /* Throw packet away.. */
1059+ DEBUG("%s: ep %p ep_indx %d No descriptor?!?\n", __FUNCTION__, ep, ep_idx);
1060+ flush(ep);
1061+ }
1062+}
1063+
1064+/** Halt specific EP
1065+ * Return 0 if success
1066+ * NOTE: Sets INDEX register to EP !
1067+ */
1068+static int jz4740_set_halt(struct usb_ep *_ep, int value)
1069+{
1070+ struct jz4740_udc *dev;
1071+ struct jz4740_ep *ep;
1072+ unsigned long flags;
1073+
1074+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
1075+
1076+ ep = container_of(_ep, struct jz4740_ep, ep);
1077+ if (unlikely(!_ep || (!ep->desc && ep->type != ep_control))) {
1078+ DEBUG("%s, bad ep\n", __FUNCTION__);
1079+ return -EINVAL;
1080+ }
1081+
1082+ dev = ep->dev;
1083+
1084+ spin_lock_irqsave(&dev->lock, flags);
1085+
1086+ jz_udc_select_ep(ep);
1087+
1088+ DEBUG("%s, ep %d, val %d\n", __FUNCTION__, ep_index(ep), value);
1089+
1090+ if (ep_index(ep) == 0) {
1091+ /* EP0 */
1092+ usb_setb(dev, JZ_REG_UDC_CSR0, USB_CSR0_SENDSTALL);
1093+ } else if (ep_is_in(ep)) {
1094+ uint32_t csr = usb_readb(dev, ep->csr);
1095+ if (value && ((csr & USB_INCSR_FFNOTEMPT)
1096+ || !list_empty(&ep->queue))) {
1097+ /*
1098+ * Attempts to halt IN endpoints will fail (returning -EAGAIN)
1099+ * if any transfer requests are still queued, or if the controller
1100+ * FIFO still holds bytes that the host hasn’t collected.
1101+ */
1102+ spin_unlock_irqrestore(&dev->lock, flags);
1103+ DEBUG
1104+ ("Attempt to halt IN endpoint failed (returning -EAGAIN) %d %d\n",
1105+ (csr & USB_INCSR_FFNOTEMPT),
1106+ !list_empty(&ep->queue));
1107+ return -EAGAIN;
1108+ }
1109+ flush(ep);
1110+ if (value) {
1111+ usb_setb(dev, ep->csr, USB_INCSR_SENDSTALL);
1112+ } else {
1113+ usb_clearb(dev, ep->csr, USB_INCSR_SENDSTALL);
1114+ usb_setb(dev, ep->csr, USB_INCSR_CDT);
1115+ }
1116+ } else {
1117+
1118+ flush(ep);
1119+ if (value) {
1120+ usb_setb(dev, ep->csr, USB_OUTCSR_SENDSTALL);
1121+ } else {
1122+ usb_clearb(dev, ep->csr, USB_OUTCSR_SENDSTALL);
1123+ usb_setb(dev, ep->csr, USB_OUTCSR_CDT);
1124+ }
1125+ }
1126+
1127+ ep->stopped = value;
1128+
1129+ spin_unlock_irqrestore(&dev->lock, flags);
1130+
1131+ DEBUG("%s %s halted\n", _ep->name, value == 0 ? "NOT" : "IS");
1132+
1133+ return 0;
1134+}
1135+
1136+
1137+static int jz4740_ep_enable(struct usb_ep *_ep,
1138+ const struct usb_endpoint_descriptor *desc)
1139+{
1140+ struct jz4740_ep *ep;
1141+ struct jz4740_udc *dev;
1142+ unsigned long flags;
1143+ uint32_t max, csrh = 0;
1144+
1145+ DEBUG("%s: trying to enable %s\n", __FUNCTION__, _ep->name);
1146+
1147+ if (!_ep || !desc)
1148+ return -EINVAL;
1149+
1150+ ep = container_of(_ep, struct jz4740_ep, ep);
1151+ if (ep->desc || ep->type == ep_control
1152+ || desc->bDescriptorType != USB_DT_ENDPOINT
1153+ || ep->bEndpointAddress != desc->bEndpointAddress) {
1154+ DEBUG("%s, bad ep or descriptor\n", __FUNCTION__);
1155+ return -EINVAL;
1156+ }
1157+
1158+ /* xfer types must match, except that interrupt ~= bulk */
1159+ if (ep->bmAttributes != desc->bmAttributes
1160+ && ep->bmAttributes != USB_ENDPOINT_XFER_BULK
1161+ && desc->bmAttributes != USB_ENDPOINT_XFER_INT) {
1162+ DEBUG("%s, %s type mismatch\n", __FUNCTION__, _ep->name);
1163+ return -EINVAL;
1164+ }
1165+
1166+ dev = ep->dev;
1167+ if (!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN) {
1168+ DEBUG("%s, bogus device state\n", __FUNCTION__);
1169+ return -ESHUTDOWN;
1170+ }
1171+
1172+ max = le16_to_cpu(desc->wMaxPacketSize);
1173+
1174+ spin_lock_irqsave(&ep->dev->lock, flags);
1175+
1176+ /* Configure the endpoint */
1177+ jz_udc_select_ep(ep);
1178+ if (ep_is_in(ep)) {
1179+ usb_writew(dev, JZ_REG_UDC_INMAXP, max);
1180+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
1181+ case USB_ENDPOINT_XFER_BULK:
1182+ case USB_ENDPOINT_XFER_INT:
1183+ csrh &= ~USB_INCSRH_ISO;
1184+ break;
1185+ case USB_ENDPOINT_XFER_ISOC:
1186+ csrh |= USB_INCSRH_ISO;
1187+ break;
1188+ }
1189+ usb_writeb(dev, JZ_REG_UDC_INCSRH, csrh);
1190+ }
1191+ else {
1192+ usb_writew(dev, JZ_REG_UDC_OUTMAXP, max);
1193+ switch (desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) {
1194+ case USB_ENDPOINT_XFER_BULK:
1195+ csrh &= ~USB_OUTCSRH_ISO;
1196+ break;
1197+ case USB_ENDPOINT_XFER_INT:
1198+ csrh &= ~USB_OUTCSRH_ISO;
1199+ csrh |= USB_OUTCSRH_DNYT;
1200+ break;
1201+ case USB_ENDPOINT_XFER_ISOC:
1202+ csrh |= USB_OUTCSRH_ISO;
1203+ break;
1204+ }
1205+ usb_writeb(dev, JZ_REG_UDC_OUTCSRH, csrh);
1206+ }
1207+
1208+
1209+ ep->stopped = 0;
1210+ ep->desc = desc;
1211+ ep->ep.maxpacket = max;
1212+
1213+ spin_unlock_irqrestore(&ep->dev->lock, flags);
1214+
1215+ /* Reset halt state (does flush) */
1216+ jz4740_set_halt(_ep, 0);
1217+
1218+ DEBUG("%s: enabled %s\n", __FUNCTION__, _ep->name);
1219+
1220+ return 0;
1221+}
1222+
1223+/** Disable EP
1224+ * NOTE: Sets INDEX register
1225+ */
1226+static int jz4740_ep_disable(struct usb_ep *_ep)
1227+{
1228+ struct jz4740_ep *ep;
1229+ unsigned long flags;
1230+
1231+ DEBUG("%s, %p\n", __FUNCTION__, _ep);
1232+
1233+ ep = container_of(_ep, struct jz4740_ep, ep);
1234+ if (!_ep || !ep->desc) {
1235+ DEBUG("%s, %s not enabled\n", __FUNCTION__,
1236+ _ep ? ep->ep.name : NULL);
1237+ return -EINVAL;
1238+ }
1239+
1240+ spin_lock_irqsave(&ep->dev->lock, flags);
1241+
1242+ jz_udc_select_ep(ep);
1243+
1244+ /* Nuke all pending requests (does flush) */
1245+ nuke(ep, -ESHUTDOWN);
1246+
1247+ /* Disable ep IRQ */
1248+ pio_irq_disable(ep);
1249+
1250+ ep->desc = 0;
1251+ ep->stopped = 1;
1252+
1253+ spin_unlock_irqrestore(&ep->dev->lock, flags);
1254+
1255+ DEBUG("%s: disabled %s\n", __FUNCTION__, _ep->name);
1256+ return 0;
1257+}
1258+
1259+static struct usb_request *jz4740_alloc_request(struct usb_ep *ep, gfp_t gfp_flags)
1260+{
1261+ struct jz4740_request *req;
1262+
1263+ req = kzalloc(sizeof(*req), gfp_flags);
1264+ if (!req)
1265+ return NULL;
1266+
1267+ INIT_LIST_HEAD(&req->queue);
1268+
1269+ return &req->req;
1270+}
1271+
1272+static void jz4740_free_request(struct usb_ep *ep, struct usb_request *_req)
1273+{
1274+ struct jz4740_request *req;
1275+
1276+ DEBUG("%s, %p\n", __FUNCTION__, ep);
1277+
1278+ req = container_of(_req, struct jz4740_request, req);
1279+ WARN_ON(!list_empty(&req->queue));
1280+ kfree(req);
1281+}
1282+
1283+/*--------------------------------------------------------------------*/
1284+
1285+/** Queue one request
1286+ * Kickstart transfer if needed
1287+ * NOTE: Sets INDEX register
1288+ */
1289+static int jz4740_queue(struct usb_ep *_ep, struct usb_request *_req,
1290+ gfp_t gfp_flags)
1291+{
1292+ struct jz4740_request *req;
1293+ struct jz4740_ep *ep;
1294+ struct jz4740_udc *dev;
1295+
1296+ DEBUG("%s, %p\n", __FUNCTION__, _ep);
1297+
1298+ req = container_of(_req, struct jz4740_request, req);
1299+ if (unlikely
1300+ (!_req || !_req->complete || !_req->buf
1301+ || !list_empty(&req->queue))) {
1302+ DEBUG("%s, bad params\n", __FUNCTION__);
1303+ return -EINVAL;
1304+ }
1305+
1306+ ep = container_of(_ep, struct jz4740_ep, ep);
1307+ if (unlikely(!_ep || (!ep->desc && ep->type != ep_control))) {
1308+ DEBUG("%s, bad ep\n", __FUNCTION__);
1309+ return -EINVAL;
1310+ }
1311+
1312+ dev = ep->dev;
1313+ if (unlikely(!dev->driver || dev->gadget.speed == USB_SPEED_UNKNOWN)) {
1314+ DEBUG("%s, bogus device state %p\n", __FUNCTION__, dev->driver);
1315+ return -ESHUTDOWN;
1316+ }
1317+
1318+ DEBUG("%s queue req %p, len %d buf %p\n", _ep->name, _req, _req->length,
1319+ _req->buf);
1320+
1321+ spin_lock_irqsave(&dev->lock, dev->lock_flags);
1322+
1323+ _req->status = -EINPROGRESS;
1324+ _req->actual = 0;
1325+
1326+ /* kickstart this i/o queue? */
1327+ DEBUG("Add to %d Q %d %d\n", ep_index(ep), list_empty(&ep->queue),
1328+ ep->stopped);
1329+ if (list_empty(&ep->queue) && likely(!ep->stopped)) {
1330+ uint32_t csr;
1331+
1332+ if (unlikely(ep_index(ep) == 0)) {
1333+ /* EP0 */
1334+ list_add_tail(&req->queue, &ep->queue);
1335+ jz4740_ep0_kick(dev, ep);
1336+ req = 0;
1337+ } else if (use_dma) {
1338+ /* DMA */
1339+ kick_dma(ep, req);
1340+ }
1341+ /* PIO */
1342+ else if (ep_is_in(ep)) {
1343+ /* EP1 & EP2 */
1344+ jz_udc_select_ep(ep);
1345+ csr = usb_readb(dev, ep->csr);
1346+ pio_irq_enable(ep);
1347+ if (!(csr & USB_INCSR_FFNOTEMPT)) {
1348+ if (write_fifo(ep, req) == 1)
1349+ req = 0;
1350+ }
1351+ } else {
1352+ /* EP1 */
1353+ jz_udc_select_ep(ep);
1354+ csr = usb_readb(dev, ep->csr);
1355+ pio_irq_enable(ep);
1356+ if (csr & USB_OUTCSR_OUTPKTRDY) {
1357+ if (read_fifo(ep, req) == 1)
1358+ req = 0;
1359+ }
1360+ }
1361+ }
1362+
1363+ /* pio or dma irq handler advances the queue. */
1364+ if (likely(req != 0))
1365+ list_add_tail(&req->queue, &ep->queue);
1366+
1367+ spin_unlock_irqrestore(&dev->lock, dev->lock_flags);
1368+
1369+ return 0;
1370+}
1371+
1372+/* dequeue JUST ONE request */
1373+static int jz4740_dequeue(struct usb_ep *_ep, struct usb_request *_req)
1374+{
1375+ struct jz4740_ep *ep;
1376+ struct jz4740_request *req;
1377+ unsigned long flags;
1378+
1379+ DEBUG("%s, %p\n", __FUNCTION__, _ep);
1380+
1381+ ep = container_of(_ep, struct jz4740_ep, ep);
1382+ if (!_ep || ep->type == ep_control)
1383+ return -EINVAL;
1384+
1385+ spin_lock_irqsave(&ep->dev->lock, flags);
1386+
1387+ /* make sure it's actually queued on this endpoint */
1388+ list_for_each_entry(req, &ep->queue, queue) {
1389+ if (&req->req == _req)
1390+ break;
1391+ }
1392+ if (&req->req != _req) {
1393+ spin_unlock_irqrestore(&ep->dev->lock, flags);
1394+ return -EINVAL;
1395+ }
1396+ done(ep, req, -ECONNRESET);
1397+
1398+ spin_unlock_irqrestore(&ep->dev->lock, flags);
1399+ return 0;
1400+}
1401+
1402+/** Return bytes in EP FIFO
1403+ * NOTE: Sets INDEX register to EP
1404+ */
1405+static int jz4740_fifo_status(struct usb_ep *_ep)
1406+{
1407+ uint32_t csr;
1408+ int count = 0;
1409+ struct jz4740_ep *ep;
1410+ unsigned long flags;
1411+
1412+ ep = container_of(_ep, struct jz4740_ep, ep);
1413+ if (!_ep) {
1414+ DEBUG("%s, bad ep\n", __FUNCTION__);
1415+ return -ENODEV;
1416+ }
1417+
1418+ DEBUG("%s, %d\n", __FUNCTION__, ep_index(ep));
1419+
1420+ /* LPD can't report unclaimed bytes from IN fifos */
1421+ if (ep_is_in(ep))
1422+ return -EOPNOTSUPP;
1423+
1424+ spin_lock_irqsave(&ep->dev->lock, flags);
1425+ jz_udc_select_ep(ep);
1426+
1427+ csr = usb_readb(ep->dev, ep->csr);
1428+ if (ep->dev->gadget.speed != USB_SPEED_UNKNOWN ||
1429+ csr & 0x1) {
1430+ count = usb_readw(ep->dev, JZ_REG_UDC_OUTCOUNT);
1431+ }
1432+
1433+ spin_unlock_irqrestore(&ep->dev->lock, flags);
1434+
1435+ return count;
1436+}
1437+
1438+/** Flush EP FIFO
1439+ * NOTE: Sets INDEX register to EP
1440+ */
1441+static void jz4740_fifo_flush(struct usb_ep *_ep)
1442+{
1443+ struct jz4740_ep *ep;
1444+ unsigned long flags;
1445+
1446+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
1447+
1448+ ep = container_of(_ep, struct jz4740_ep, ep);
1449+ if (unlikely(!_ep || (!ep->desc && ep->type == ep_control))) {
1450+ DEBUG("%s, bad ep\n", __FUNCTION__);
1451+ return;
1452+ }
1453+
1454+ spin_lock_irqsave(&ep->dev->lock, flags);
1455+
1456+ jz_udc_select_ep(ep);
1457+ flush(ep);
1458+
1459+ spin_unlock_irqrestore(&ep->dev->lock, flags);
1460+}
1461+
1462+/****************************************************************/
1463+/* End Point 0 related functions */
1464+/****************************************************************/
1465+
1466+/* return: 0 = still running, 1 = completed, negative = errno */
1467+static int write_fifo_ep0(struct jz4740_ep *ep, struct jz4740_request *req)
1468+{
1469+ uint32_t max;
1470+ unsigned count;
1471+ int is_last;
1472+
1473+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
1474+ max = ep_maxpacket(ep);
1475+
1476+ count = write_packet(ep, req, max);
1477+
1478+ /* last packet is usually short (or a zlp) */
1479+ if (unlikely(count != max))
1480+ is_last = 1;
1481+ else {
1482+ if (likely(req->req.length != req->req.actual) || req->req.zero)
1483+ is_last = 0;
1484+ else
1485+ is_last = 1;
1486+ }
1487+
1488+ DEBUG_EP0("%s: wrote %s %d bytes%s %d left %p\n", __FUNCTION__,
1489+ ep->ep.name, count,
1490+ is_last ? "/L" : "", req->req.length - req->req.actual, req);
1491+
1492+ /* requests complete when all IN data is in the FIFO */
1493+ if (is_last) {
1494+ done(ep, req, 0);
1495+ return 1;
1496+ }
1497+
1498+ return 0;
1499+}
1500+
1501+static inline int jz4740_fifo_read(struct jz4740_ep *ep,
1502+ unsigned char *cp, int max)
1503+{
1504+ int bytes;
1505+ int count = usb_readw(ep->dev, JZ_REG_UDC_OUTCOUNT);
1506+
1507+ if (count > max)
1508+ count = max;
1509+ bytes = count;
1510+ while (count--)
1511+ *cp++ = usb_readb(ep->dev, ep->fifo);
1512+
1513+ return bytes;
1514+}
1515+
1516+static inline void jz4740_fifo_write(struct jz4740_ep *ep,
1517+ unsigned char *cp, int count)
1518+{
1519+ DEBUG("fifo_write: %d %d\n", ep_index(ep), count);
1520+ while (count--)
1521+ usb_writeb(ep->dev, ep->fifo, *cp++);
1522+}
1523+
1524+static int read_fifo_ep0(struct jz4740_ep *ep, struct jz4740_request *req)
1525+{
1526+ struct jz4740_udc *dev = ep->dev;
1527+ uint32_t csr;
1528+ uint8_t *buf;
1529+ unsigned bufferspace, count, is_short;
1530+
1531+ DEBUG_EP0("%s\n", __FUNCTION__);
1532+
1533+ csr = usb_readb(dev, JZ_REG_UDC_CSR0);
1534+ if (!(csr & USB_CSR0_OUTPKTRDY))
1535+ return 0;
1536+
1537+ buf = req->req.buf + req->req.actual;
1538+ prefetchw(buf);
1539+ bufferspace = req->req.length - req->req.actual;
1540+
1541+ /* read all bytes from this packet */
1542+ if (likely(csr & USB_CSR0_OUTPKTRDY)) {
1543+ count = usb_readw(dev, JZ_REG_UDC_OUTCOUNT);
1544+ req->req.actual += min(count, bufferspace);
1545+ } else /* zlp */
1546+ count = 0;
1547+
1548+ is_short = (count < ep->ep.maxpacket);
1549+ DEBUG_EP0("read %s %02x, %d bytes%s req %p %d/%d\n",
1550+ ep->ep.name, csr, count,
1551+ is_short ? "/S" : "", req, req->req.actual, req->req.length);
1552+
1553+ while (likely(count-- != 0)) {
1554+ uint8_t byte = (uint8_t)usb_readl(dev, ep->fifo);
1555+
1556+ if (unlikely(bufferspace == 0)) {
1557+ /* this happens when the driver's buffer
1558+ * is smaller than what the host sent.
1559+ * discard the extra data.
1560+ */
1561+ if (req->req.status != -EOVERFLOW)
1562+ DEBUG_EP0("%s overflow %d\n", ep->ep.name,
1563+ count);
1564+ req->req.status = -EOVERFLOW;
1565+ } else {
1566+ *buf++ = byte;
1567+ bufferspace--;
1568+ }
1569+ }
1570+
1571+ /* completion */
1572+ if (is_short || req->req.actual == req->req.length) {
1573+ done(ep, req, 0);
1574+ return 1;
1575+ }
1576+
1577+ /* finished that packet. the next one may be waiting... */
1578+ return 0;
1579+}
1580+
1581+/**
1582+ * udc_set_address - set the USB address for this device
1583+ * @address:
1584+ *
1585+ * Called from control endpoint function after it decodes a set address setup packet.
1586+ */
1587+static void udc_set_address(struct jz4740_udc *dev, unsigned char address)
1588+{
1589+ DEBUG_EP0("%s: %d\n", __FUNCTION__, address);
1590+
1591+ usb_writeb(dev, JZ_REG_UDC_FADDR, address);
1592+}
1593+
1594+/*
1595+ * DATA_STATE_RECV (USB_CSR0_OUTPKTRDY)
1596+ * - if error
1597+ * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL bits
1598+ * - else
1599+ * set USB_CSR0_SVDOUTPKTRDY bit
1600+ if last set USB_CSR0_DATAEND bit
1601+ */
1602+static void jz4740_ep0_out(struct jz4740_udc *dev, uint32_t csr, int kickstart)
1603+{
1604+ struct jz4740_request *req;
1605+ struct jz4740_ep *ep = &dev->ep[0];
1606+ int ret;
1607+
1608+ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
1609+
1610+ if (list_empty(&ep->queue))
1611+ req = 0;
1612+ else
1613+ req = list_entry(ep->queue.next, struct jz4740_request, queue);
1614+
1615+ if (req) {
1616+ if (req->req.length == 0) {
1617+ DEBUG_EP0("ZERO LENGTH OUT!\n");
1618+ usb_setb(dev, JZ_REG_UDC_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND));
1619+ dev->ep0state = WAIT_FOR_SETUP;
1620+ return;
1621+ } else if (kickstart) {
1622+ usb_setb(dev, JZ_REG_UDC_CSR0, (USB_CSR0_SVDOUTPKTRDY));
1623+ return;
1624+ }
1625+ ret = read_fifo_ep0(ep, req);
1626+ if (ret) {
1627+ /* Done! */
1628+ DEBUG_EP0("%s: finished, waiting for status\n",
1629+ __FUNCTION__);
1630+ usb_setb(dev, JZ_REG_UDC_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND));
1631+ dev->ep0state = WAIT_FOR_SETUP;
1632+ } else {
1633+ /* Not done yet.. */
1634+ DEBUG_EP0("%s: not finished\n", __FUNCTION__);
1635+ usb_setb(dev, JZ_REG_UDC_CSR0, USB_CSR0_SVDOUTPKTRDY);
1636+ }
1637+ } else {
1638+ DEBUG_EP0("NO REQ??!\n");
1639+ }
1640+}
1641+
1642+/*
1643+ * DATA_STATE_XMIT
1644+ */
1645+static int jz4740_ep0_in(struct jz4740_udc *dev, uint32_t csr)
1646+{
1647+ struct jz4740_request *req;
1648+ struct jz4740_ep *ep = &dev->ep[0];
1649+ int ret, need_zlp = 0;
1650+
1651+ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
1652+
1653+ if (list_empty(&ep->queue))
1654+ req = 0;
1655+ else
1656+ req = list_entry(ep->queue.next, struct jz4740_request, queue);
1657+
1658+ if (!req) {
1659+ DEBUG_EP0("%s: NULL REQ\n", __FUNCTION__);
1660+ return 0;
1661+ }
1662+
1663+ if (req->req.length == 0) {
1664+ usb_setb(dev, JZ_REG_UDC_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND));
1665+ dev->ep0state = WAIT_FOR_SETUP;
1666+ return 1;
1667+ }
1668+
1669+ if (req->req.length - req->req.actual == EP0_MAXPACKETSIZE) {
1670+ /* Next write will end with the packet size, */
1671+ /* so we need zero-length-packet */
1672+ need_zlp = 1;
1673+ }
1674+
1675+ ret = write_fifo_ep0(ep, req);
1676+
1677+ if (ret == 1 && !need_zlp) {
1678+ /* Last packet */
1679+ DEBUG_EP0("%s: finished, waiting for status\n", __FUNCTION__);
1680+
1681+ usb_setb(dev, JZ_REG_UDC_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND));
1682+ dev->ep0state = WAIT_FOR_SETUP;
1683+ } else {
1684+ DEBUG_EP0("%s: not finished\n", __FUNCTION__);
1685+ usb_setb(dev, JZ_REG_UDC_CSR0, USB_CSR0_INPKTRDY);
1686+ }
1687+
1688+ if (need_zlp) {
1689+ DEBUG_EP0("%s: Need ZLP!\n", __FUNCTION__);
1690+ usb_setb(dev, JZ_REG_UDC_CSR0, USB_CSR0_INPKTRDY);
1691+ dev->ep0state = DATA_STATE_NEED_ZLP;
1692+ }
1693+
1694+ return 1;
1695+}
1696+
1697+static int jz4740_handle_get_status(struct jz4740_udc *dev,
1698+ struct usb_ctrlrequest *ctrl)
1699+{
1700+ struct jz4740_ep *ep0 = &dev->ep[0];
1701+ struct jz4740_ep *qep;
1702+ int reqtype = (ctrl->bRequestType & USB_RECIP_MASK);
1703+ uint16_t val = 0;
1704+
1705+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
1706+
1707+ if (reqtype == USB_RECIP_INTERFACE) {
1708+ /* This is not supported.
1709+ * And according to the USB spec, this one does nothing..
1710+ * Just return 0
1711+ */
1712+ DEBUG_SETUP("GET_STATUS: USB_RECIP_INTERFACE\n");
1713+ } else if (reqtype == USB_RECIP_DEVICE) {
1714+ DEBUG_SETUP("GET_STATUS: USB_RECIP_DEVICE\n");
1715+ val |= (1 << 0); /* Self powered */
1716+ /*val |= (1<<1); *//* Remote wakeup */
1717+ } else if (reqtype == USB_RECIP_ENDPOINT) {
1718+ int ep_num = (ctrl->wIndex & ~USB_DIR_IN);
1719+
1720+ DEBUG_SETUP
1721+ ("GET_STATUS: USB_RECIP_ENDPOINT (%d), ctrl->wLength = %d\n",
1722+ ep_num, ctrl->wLength);
1723+
1724+ if (ctrl->wLength > 2 || ep_num > 3)
1725+ return -EOPNOTSUPP;
1726+
1727+ qep = &dev->ep[ep_num];
1728+ if (ep_is_in(qep) != ((ctrl->wIndex & USB_DIR_IN) ? 1 : 0)
1729+ && ep_index(qep) != 0) {
1730+ return -EOPNOTSUPP;
1731+ }
1732+
1733+ jz_udc_set_index(dev, ep_index(qep));
1734+
1735+ /* Return status on next IN token */
1736+ switch (qep->type) {
1737+ case ep_control:
1738+ val =
1739+ (usb_readb(dev, qep->csr) & USB_CSR0_SENDSTALL) ==
1740+ USB_CSR0_SENDSTALL;
1741+ break;
1742+ case ep_bulk_in:
1743+ case ep_interrupt:
1744+ val =
1745+ (usb_readb(dev, qep->csr) & USB_INCSR_SENDSTALL) ==
1746+ USB_INCSR_SENDSTALL;
1747+ break;
1748+ case ep_bulk_out:
1749+ val =
1750+ (usb_readb(dev, qep->csr) & USB_OUTCSR_SENDSTALL) ==
1751+ USB_OUTCSR_SENDSTALL;
1752+ break;
1753+ }
1754+
1755+ /* Back to EP0 index */
1756+ jz_udc_set_index(dev, 0);
1757+
1758+ DEBUG_SETUP("GET_STATUS, ep: %d (%x), val = %d\n", ep_num,
1759+ ctrl->wIndex, val);
1760+ } else {
1761+ DEBUG_SETUP("Unknown REQ TYPE: %d\n", reqtype);
1762+ return -EOPNOTSUPP;
1763+ }
1764+
1765+ /* Clear "out packet ready" */
1766+ usb_setb(dev, JZ_REG_UDC_CSR0, USB_CSR0_SVDOUTPKTRDY);
1767+ /* Put status to FIFO */
1768+ jz4740_fifo_write(ep0, (uint8_t *)&val, sizeof(val));
1769+ /* Issue "In packet ready" */
1770+ usb_setb(dev, JZ_REG_UDC_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND));
1771+
1772+ return 0;
1773+}
1774+
1775+/*
1776+ * WAIT_FOR_SETUP (OUTPKTRDY)
1777+ * - read data packet from EP0 FIFO
1778+ * - decode command
1779+ * - if error
1780+ * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL bits
1781+ * - else
1782+ * set USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND bits
1783+ */
1784+static void jz4740_ep0_setup(struct jz4740_udc *dev, uint32_t csr)
1785+{
1786+ struct jz4740_ep *ep = &dev->ep[0];
1787+ struct usb_ctrlrequest ctrl;
1788+ int i;
1789+
1790+ DEBUG_SETUP("%s: %x\n", __FUNCTION__, csr);
1791+
1792+ /* Nuke all previous transfers */
1793+ nuke(ep, -EPROTO);
1794+
1795+ /* read control req from fifo (8 bytes) */
1796+ jz4740_fifo_read(ep, (unsigned char *)&ctrl, 8);
1797+
1798+ DEBUG_SETUP("SETUP %02x.%02x v%04x i%04x l%04x\n",
1799+ ctrl.bRequestType, ctrl.bRequest,
1800+ ctrl.wValue, ctrl.wIndex, ctrl.wLength);
1801+
1802+ /* Set direction of EP0 */
1803+ if (likely(ctrl.bRequestType & USB_DIR_IN)) {
1804+ ep->bEndpointAddress |= USB_DIR_IN;
1805+ } else {
1806+ ep->bEndpointAddress &= ~USB_DIR_IN;
1807+ }
1808+
1809+ /* Handle some SETUP packets ourselves */
1810+ switch (ctrl.bRequest) {
1811+ case USB_REQ_SET_ADDRESS:
1812+ if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
1813+ break;
1814+
1815+ DEBUG_SETUP("USB_REQ_SET_ADDRESS (%d)\n", ctrl.wValue);
1816+ udc_set_address(dev, ctrl.wValue);
1817+ usb_setb(dev, JZ_REG_UDC_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND));
1818+ return;
1819+
1820+ case USB_REQ_SET_CONFIGURATION:
1821+ if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
1822+ break;
1823+
1824+ DEBUG_SETUP("USB_REQ_SET_CONFIGURATION (%d)\n", ctrl.wValue);
1825+/* usb_setb(JZ_REG_UDC_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND));*/
1826+
1827+ /* Enable RESUME and SUSPEND interrupts */
1828+ usb_setb(dev, JZ_REG_UDC_INTRUSBE, (USB_INTR_RESUME | USB_INTR_SUSPEND));
1829+ break;
1830+
1831+ case USB_REQ_SET_INTERFACE:
1832+ if (ctrl.bRequestType != (USB_TYPE_STANDARD | USB_RECIP_DEVICE))
1833+ break;
1834+
1835+ DEBUG_SETUP("USB_REQ_SET_INTERFACE (%d)\n", ctrl.wValue);
1836+/* usb_setb(JZ_REG_UDC_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND));*/
1837+ break;
1838+
1839+ case USB_REQ_GET_STATUS:
1840+ if (jz4740_handle_get_status(dev, &ctrl) == 0)
1841+ return;
1842+
1843+ case USB_REQ_CLEAR_FEATURE:
1844+ case USB_REQ_SET_FEATURE:
1845+ if (ctrl.bRequestType == USB_RECIP_ENDPOINT) {
1846+ struct jz4740_ep *qep;
1847+ int ep_num = (ctrl.wIndex & 0x0f);
1848+
1849+ /* Support only HALT feature */
1850+ if (ctrl.wValue != 0 || ctrl.wLength != 0
1851+ || ep_num > 3 || ep_num < 1)
1852+ break;
1853+
1854+ qep = &dev->ep[ep_num];
1855+ spin_unlock(&dev->lock);
1856+ if (ctrl.bRequest == USB_REQ_SET_FEATURE) {
1857+ DEBUG_SETUP("SET_FEATURE (%d)\n",
1858+ ep_num);
1859+ jz4740_set_halt(&qep->ep, 1);
1860+ } else {
1861+ DEBUG_SETUP("CLR_FEATURE (%d)\n",
1862+ ep_num);
1863+ jz4740_set_halt(&qep->ep, 0);
1864+ }
1865+ spin_lock(&dev->lock);
1866+
1867+ jz_udc_set_index(dev, 0);
1868+
1869+ /* Reply with a ZLP on next IN token */
1870+ usb_setb(dev, JZ_REG_UDC_CSR0,
1871+ (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND));
1872+ return;
1873+ }
1874+ break;
1875+
1876+ default:
1877+ break;
1878+ }
1879+
1880+ /* gadget drivers see class/vendor specific requests,
1881+ * {SET,GET}_{INTERFACE,DESCRIPTOR,CONFIGURATION},
1882+ * and more.
1883+ */
1884+ if (dev->driver) {
1885+ /* device-2-host (IN) or no data setup command, process immediately */
1886+ spin_unlock(&dev->lock);
1887+
1888+ i = dev->driver->setup(&dev->gadget, &ctrl);
1889+ spin_lock(&dev->lock);
1890+
1891+ if (unlikely(i < 0)) {
1892+ /* setup processing failed, force stall */
1893+ DEBUG_SETUP
1894+ (" --> ERROR: gadget setup FAILED (stalling), setup returned %d\n",
1895+ i);
1896+ jz_udc_set_index(dev, 0);
1897+ usb_setb(dev, JZ_REG_UDC_CSR0, (USB_CSR0_SVDOUTPKTRDY | USB_CSR0_DATAEND | USB_CSR0_SENDSTALL));
1898+
1899+ /* ep->stopped = 1; */
1900+ dev->ep0state = WAIT_FOR_SETUP;
1901+ }
1902+ else {
1903+ DEBUG_SETUP("gadget driver setup ok (%d)\n", ctrl.wLength);
1904+/* if (!ctrl.wLength) {
1905+ usb_setb(JZ_REG_UDC_CSR0, USB_CSR0_SVDOUTPKTRDY);
1906+ }*/
1907+ }
1908+ }
1909+}
1910+
1911+/*
1912+ * DATA_STATE_NEED_ZLP
1913+ */
1914+static void jz4740_ep0_in_zlp(struct jz4740_udc *dev, uint32_t csr)
1915+{
1916+ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
1917+
1918+ usb_setb(dev, JZ_REG_UDC_CSR0, (USB_CSR0_INPKTRDY | USB_CSR0_DATAEND));
1919+ dev->ep0state = WAIT_FOR_SETUP;
1920+}
1921+
1922+/*
1923+ * handle ep0 interrupt
1924+ */
1925+static void jz4740_handle_ep0(struct jz4740_udc *dev, uint32_t intr)
1926+{
1927+ struct jz4740_ep *ep = &dev->ep[0];
1928+ uint32_t csr;
1929+
1930+ DEBUG("%s:%s[%d]\n", __FILE__, __func__, __LINE__);
1931+ /* Set index 0 */
1932+ jz_udc_set_index(dev, 0);
1933+ csr = usb_readb(dev, JZ_REG_UDC_CSR0);
1934+
1935+ DEBUG_EP0("%s: csr = %x state = \n", __FUNCTION__, csr);//, state_names[dev->ep0state]);
1936+
1937+ /*
1938+ * if SENT_STALL is set
1939+ * - clear the SENT_STALL bit
1940+ */
1941+ if (csr & USB_CSR0_SENTSTALL) {
1942+ DEBUG_EP0("%s: USB_CSR0_SENTSTALL is set: %x\n", __FUNCTION__, csr);
1943+ usb_clearb(dev, JZ_REG_UDC_CSR0, USB_CSR0_SENDSTALL | USB_CSR0_SENTSTALL);
1944+ nuke(ep, -ECONNABORTED);
1945+ dev->ep0state = WAIT_FOR_SETUP;
1946+ return;
1947+ }
1948+
1949+ /*
1950+ * if a transfer is in progress && INPKTRDY and OUTPKTRDY are clear
1951+ * - fill EP0 FIFO
1952+ * - if last packet
1953+ * - set IN_PKT_RDY | DATA_END
1954+ * - else
1955+ * set IN_PKT_RDY
1956+ */
1957+ if (!(csr & (USB_CSR0_INPKTRDY | USB_CSR0_OUTPKTRDY))) {
1958+ DEBUG_EP0("%s: INPKTRDY and OUTPKTRDY are clear\n",
1959+ __FUNCTION__);
1960+
1961+ switch (dev->ep0state) {
1962+ case DATA_STATE_XMIT:
1963+ DEBUG_EP0("continue with DATA_STATE_XMIT\n");
1964+ jz4740_ep0_in(dev, csr);
1965+ return;
1966+ case DATA_STATE_NEED_ZLP:
1967+ DEBUG_EP0("continue with DATA_STATE_NEED_ZLP\n");
1968+ jz4740_ep0_in_zlp(dev, csr);
1969+ return;
1970+ default:
1971+ /* Stall? */
1972+// DEBUG_EP0("Odd state!! state = %s\n",
1973+// state_names[dev->ep0state]);
1974+ dev->ep0state = WAIT_FOR_SETUP;
1975+ /* nuke(ep, 0); */
1976+ /* usb_setb(ep->csr, USB_CSR0_SENDSTALL); */
1977+// break;
1978+ return;
1979+ }
1980+ }
1981+
1982+ /*
1983+ * if SETUPEND is set
1984+ * - abort the last transfer
1985+ * - set SERVICED_SETUP_END_BIT
1986+ */
1987+ if (csr & USB_CSR0_SETUPEND) {
1988+ DEBUG_EP0("%s: USB_CSR0_SETUPEND is set: %x\n", __FUNCTION__, csr);
1989+
1990+ usb_setb(dev, JZ_REG_UDC_CSR0, USB_CSR0_SVDSETUPEND);
1991+ nuke(ep, 0);
1992+ dev->ep0state = WAIT_FOR_SETUP;
1993+ }
1994+
1995+ /*
1996+ * if USB_CSR0_OUTPKTRDY is set
1997+ * - read data packet from EP0 FIFO
1998+ * - decode command
1999+ * - if error
2000+ * set SVDOUTPKTRDY | DATAEND | SENDSTALL bits
2001+ * - else
2002+ * set SVDOUTPKTRDY | DATAEND bits
2003+ */
2004+ if (csr & USB_CSR0_OUTPKTRDY) {
2005+
2006+ DEBUG_EP0("%s: EP0_OUT_PKT_RDY is set: %x\n", __FUNCTION__,
2007+ csr);
2008+
2009+ switch (dev->ep0state) {
2010+ case WAIT_FOR_SETUP:
2011+ DEBUG_EP0("WAIT_FOR_SETUP\n");
2012+ jz4740_ep0_setup(dev, csr);
2013+ break;
2014+
2015+ case DATA_STATE_RECV:
2016+ DEBUG_EP0("DATA_STATE_RECV\n");
2017+ jz4740_ep0_out(dev, csr, 0);
2018+ break;
2019+
2020+ default:
2021+ /* send stall? */
2022+ DEBUG_EP0("strange state!! 2. send stall? state = %d\n",
2023+ dev->ep0state);
2024+ break;
2025+ }
2026+ }
2027+}
2028+
2029+static void jz4740_ep0_kick(struct jz4740_udc *dev, struct jz4740_ep *ep)
2030+{
2031+ uint32_t csr;
2032+
2033+ jz_udc_set_index(dev, 0);
2034+
2035+ DEBUG_EP0("%s: %x\n", __FUNCTION__, csr);
2036+
2037+ /* Clear "out packet ready" */
2038+
2039+ if (ep_is_in(ep)) {
2040+ usb_setb(dev, JZ_REG_UDC_CSR0, USB_CSR0_SVDOUTPKTRDY);
2041+ csr = usb_readb(dev, JZ_REG_UDC_CSR0);
2042+ dev->ep0state = DATA_STATE_XMIT;
2043+ jz4740_ep0_in(dev, csr);
2044+ } else {
2045+ csr = usb_readb(dev, JZ_REG_UDC_CSR0);
2046+ dev->ep0state = DATA_STATE_RECV;
2047+ jz4740_ep0_out(dev, csr, 1);
2048+ }
2049+}
2050+
2051+/** Handle USB RESET interrupt
2052+ */
2053+static void jz4740_reset_irq(struct jz4740_udc *dev)
2054+{
2055+ dev->gadget.speed = (usb_readb(dev, JZ_REG_UDC_POWER) & USB_POWER_HSMODE) ?
2056+ USB_SPEED_HIGH : USB_SPEED_FULL;
2057+
2058+ DEBUG_SETUP("%s: address = %d, speed = %s\n", __FUNCTION__, 0,
2059+ (dev->gadget.speed == USB_SPEED_HIGH) ? "HIGH":"FULL" );
2060+}
2061+
2062+/*
2063+ * jz4740 usb device interrupt handler.
2064+ */
2065+static irqreturn_t jz4740_udc_irq(int irq, void *devid)
2066+{
2067+ struct jz4740_udc *jz4740_udc = devid;
2068+ uint8_t index;
2069+
2070+ uint32_t intr_usb = usb_readb(jz4740_udc, JZ_REG_UDC_INTRUSB) & 0x7; /* mask SOF */
2071+ uint32_t intr_in = usb_readw(jz4740_udc, JZ_REG_UDC_INTRIN);
2072+ uint32_t intr_out = usb_readw(jz4740_udc, JZ_REG_UDC_INTROUT);
2073+ uint32_t intr_dma = usb_readb(jz4740_udc, JZ_REG_UDC_INTR);
2074+
2075+ if (!intr_usb && !intr_in && !intr_out && !intr_dma)
2076+ return IRQ_HANDLED;
2077+
2078+
2079+ DEBUG("intr_out=%x intr_in=%x intr_usb=%x\n",
2080+ intr_out, intr_in, intr_usb);
2081+
2082+ spin_lock(&jz4740_udc->lock);
2083+ index = usb_readb(jz4740_udc, JZ_REG_UDC_INDEX);
2084+
2085+ /* Check for resume from suspend mode */
2086+ if ((intr_usb & USB_INTR_RESUME) &&
2087+ (usb_readb(jz4740_udc, JZ_REG_UDC_INTRUSBE) & USB_INTR_RESUME)) {
2088+ DEBUG("USB resume\n");
2089+ jz4740_udc->driver->resume(&jz4740_udc->gadget); /* We have suspend(), so we must have resume() too. */
2090+ }
2091+
2092+ /* Check for system interrupts */
2093+ if (intr_usb & USB_INTR_RESET) {
2094+ DEBUG("USB reset\n");
2095+ jz4740_reset_irq(jz4740_udc);
2096+ }
2097+
2098+ /* Check for endpoint 0 interrupt */
2099+ if (intr_in & USB_INTR_EP0) {
2100+ DEBUG("USB_INTR_EP0 (control)\n");
2101+ jz4740_handle_ep0(jz4740_udc, intr_in);
2102+ }
2103+
2104+ /* Check for Bulk-IN DMA interrupt */
2105+ if (intr_dma & 0x1) {
2106+ int ep_num;
2107+ struct jz4740_ep *ep;
2108+ ep_num = (usb_readl(jz4740_udc, JZ_REG_UDC_CNTL1) >> 4) & 0xf;
2109+ ep = &jz4740_udc->ep[ep_num + 1];
2110+ jz_udc_set_index(jz4740_udc, ep_num);
2111+ usb_setb(jz4740_udc, ep->csr, USB_INCSR_INPKTRDY);
2112+/* jz4740_in_epn(jz4740_udc, ep_num, intr_in);*/
2113+ }
2114+
2115+ /* Check for Bulk-OUT DMA interrupt */
2116+ if (intr_dma & 0x2) {
2117+ int ep_num;
2118+ ep_num = (usb_readl(jz4740_udc, JZ_REG_UDC_CNTL2) >> 4) & 0xf;
2119+ jz4740_out_epn(jz4740_udc, ep_num, intr_out);
2120+ }
2121+
2122+ /* Check for each configured endpoint interrupt */
2123+ if (intr_in & USB_INTR_INEP1) {
2124+ DEBUG("USB_INTR_INEP1\n");
2125+ jz4740_in_epn(jz4740_udc, 1, intr_in);
2126+ }
2127+
2128+ if (intr_in & USB_INTR_INEP2) {
2129+ DEBUG("USB_INTR_INEP2\n");
2130+ jz4740_in_epn(jz4740_udc, 2, intr_in);
2131+ }
2132+
2133+ if (intr_out & USB_INTR_OUTEP1) {
2134+ DEBUG("USB_INTR_OUTEP1\n");
2135+ jz4740_out_epn(jz4740_udc, 1, intr_out);
2136+ }
2137+
2138+ /* Check for suspend mode */
2139+ if ((intr_usb & USB_INTR_SUSPEND) &&
2140+ (usb_readb(jz4740_udc, JZ_REG_UDC_INTRUSBE) & USB_INTR_SUSPEND)) {
2141+ DEBUG("USB suspend\n");
2142+ jz4740_udc->driver->suspend(&jz4740_udc->gadget);
2143+ /* Host unloaded from us, can do something, such as flushing
2144+ the NAND block cache etc. */
2145+ }
2146+
2147+ jz_udc_set_index(jz4740_udc, index);
2148+
2149+ spin_unlock(&jz4740_udc->lock);
2150+
2151+ return IRQ_HANDLED;
2152+}
2153+
2154+
2155+
2156+/*-------------------------------------------------------------------------*/
2157+
2158+
2159+static inline struct jz4740_udc *gadget_to_udc(struct usb_gadget *gadget)
2160+{
2161+ return container_of(gadget, struct jz4740_udc, gadget);
2162+}
2163+
2164+static int jz4740_udc_get_frame(struct usb_gadget *_gadget)
2165+{
2166+ DEBUG("%s, %p\n", __FUNCTION__, _gadget);
2167+ return usb_readw(gadget_to_udc(_gadget), JZ_REG_UDC_FRAME);
2168+}
2169+
2170+static int jz4740_udc_wakeup(struct usb_gadget *_gadget)
2171+{
2172+ /* host may not have enabled remote wakeup */
2173+ /*if ((UDCCS0 & UDCCS0_DRWF) == 0)
2174+ return -EHOSTUNREACH;
2175+ udc_set_mask_UDCCR(UDCCR_RSM); */
2176+ return -ENOTSUPP;
2177+}
2178+
2179+static int jz4740_udc_pullup(struct usb_gadget *_gadget, int on)
2180+{
2181+ struct jz4740_udc *udc = gadget_to_udc(_gadget);
2182+ unsigned long flags;
2183+
2184+ local_irq_save(flags);
2185+
2186+ if (on) {
2187+ udc->state = UDC_STATE_ENABLE;
2188+ udc_enable(udc);
2189+ } else {
2190+ udc->state = UDC_STATE_DISABLE;
2191+ udc_disable(udc);
2192+ }
2193+
2194+ local_irq_restore(flags);
2195+
2196+ return 0;
2197+}
2198+
2199+
2200+static const struct usb_gadget_ops jz4740_udc_ops = {
2201+ .get_frame = jz4740_udc_get_frame,
2202+ .wakeup = jz4740_udc_wakeup,
2203+ .pullup = jz4740_udc_pullup,
2204+};
2205+
2206+static struct usb_ep_ops jz4740_ep_ops = {
2207+ .enable = jz4740_ep_enable,
2208+ .disable = jz4740_ep_disable,
2209+
2210+ .alloc_request = jz4740_alloc_request,
2211+ .free_request = jz4740_free_request,
2212+
2213+ .queue = jz4740_queue,
2214+ .dequeue = jz4740_dequeue,
2215+
2216+ .set_halt = jz4740_set_halt,
2217+ .fifo_status = jz4740_fifo_status,
2218+ .fifo_flush = jz4740_fifo_flush,
2219+};
2220+
2221+
2222+/*-------------------------------------------------------------------------*/
2223+
2224+static struct jz4740_udc jz4740_udc_controller = {
2225+ .gadget = {
2226+ .ops = &jz4740_udc_ops,
2227+ .ep0 = &jz4740_udc_controller.ep[0].ep,
2228+ .name = "jz4740-udc",
2229+ .dev = {
2230+ .init_name = "gadget",
2231+ },
2232+ },
2233+
2234+ /* control endpoint */
2235+ .ep[0] = {
2236+ .ep = {
2237+ .name = "ep0",
2238+ .ops = &jz4740_ep_ops,
2239+ .maxpacket = EP0_MAXPACKETSIZE,
2240+ },
2241+ .dev = &jz4740_udc_controller,
2242+
2243+ .bEndpointAddress = 0,
2244+ .bmAttributes = 0,
2245+
2246+ .type = ep_control,
2247+ .fifo = JZ_REG_UDC_EP_FIFO(0),
2248+ .csr = JZ_REG_UDC_CSR0,
2249+ },
2250+
2251+ /* bulk out endpoint */
2252+ .ep[1] = {
2253+ .ep = {
2254+ .name = "ep1out-bulk",
2255+ .ops = &jz4740_ep_ops,
2256+ .maxpacket = EPBULK_MAXPACKETSIZE,
2257+ },
2258+ .dev = &jz4740_udc_controller,
2259+
2260+ .bEndpointAddress = 1,
2261+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
2262+
2263+ .type = ep_bulk_out,
2264+ .fifo = JZ_REG_UDC_EP_FIFO(1),
2265+ .csr = JZ_REG_UDC_OUTCSR,
2266+ },
2267+
2268+ /* bulk in endpoint */
2269+ .ep[2] = {
2270+ .ep = {
2271+ .name = "ep1in-bulk",
2272+ .ops = &jz4740_ep_ops,
2273+ .maxpacket = EPBULK_MAXPACKETSIZE,
2274+ },
2275+ .dev = &jz4740_udc_controller,
2276+
2277+ .bEndpointAddress = 1 | USB_DIR_IN,
2278+ .bmAttributes = USB_ENDPOINT_XFER_BULK,
2279+
2280+ .type = ep_bulk_in,
2281+ .fifo = JZ_REG_UDC_EP_FIFO(1),
2282+ .csr = JZ_REG_UDC_INCSR,
2283+ },
2284+
2285+ /* interrupt in endpoint */
2286+ .ep[3] = {
2287+ .ep = {
2288+ .name = "ep2in-int",
2289+ .ops = &jz4740_ep_ops,
2290+ .maxpacket = EPINTR_MAXPACKETSIZE,
2291+ },
2292+ .dev = &jz4740_udc_controller,
2293+
2294+ .bEndpointAddress = 2 | USB_DIR_IN,
2295+ .bmAttributes = USB_ENDPOINT_XFER_INT,
2296+
2297+ .type = ep_interrupt,
2298+ .fifo = JZ_REG_UDC_EP_FIFO(2),
2299+ .csr = JZ_REG_UDC_INCSR,
2300+ },
2301+};
2302+
2303+static int __devinit jz4740_udc_probe(struct platform_device *pdev)
2304+{
2305+ struct jz4740_udc *jz4740_udc = &jz4740_udc_controller;
2306+ int ret;
2307+
2308+ spin_lock_init(&jz4740_udc->lock);
2309+
2310+ jz4740_udc->dev = &pdev->dev;
2311+ jz4740_udc->gadget.dev.parent = &pdev->dev;
2312+ jz4740_udc->gadget.dev.dma_mask = pdev->dev.dma_mask;
2313+
2314+ ret = device_register(&jz4740_udc->gadget.dev);
2315+ if (ret)
2316+ return ret;
2317+
2318+ jz4740_udc->clk = clk_get(&pdev->dev, "udc");
2319+ if (IS_ERR(jz4740_udc->clk)) {
2320+ ret = PTR_ERR(jz4740_udc->clk);
2321+ dev_err(&pdev->dev, "Failed to get udc clock: %d\n", ret);
2322+ goto err_device_unregister;
2323+ }
2324+
2325+ platform_set_drvdata(pdev, jz4740_udc);
2326+
2327+ jz4740_udc->mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
2328+
2329+ if (!jz4740_udc->mem) {
2330+ ret = -ENOENT;
2331+ dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
2332+ goto err_clk_put;
2333+ }
2334+
2335+ jz4740_udc->mem = request_mem_region(jz4740_udc->mem->start,
2336+ resource_size(jz4740_udc->mem), pdev->name);
2337+
2338+ if (!jz4740_udc->mem) {
2339+ ret = -EBUSY;
2340+ dev_err(&pdev->dev, "Failed to request mmio memory region\n");
2341+ goto err_device_unregister;
2342+ }
2343+
2344+ jz4740_udc->base = ioremap(jz4740_udc->mem->start, resource_size(jz4740_udc->mem));
2345+
2346+ if (!jz4740_udc->base) {
2347+ ret = -EBUSY;
2348+ dev_err(&pdev->dev, "Failed to ioremap mmio memory\n");
2349+ goto err_release_mem_region;
2350+ }
2351+
2352+ jz4740_udc->irq = platform_get_irq(pdev, 0);
2353+ ret = request_irq(jz4740_udc->irq, jz4740_udc_irq, 0, pdev->name,
2354+ jz4740_udc);
2355+ if (ret) {
2356+ dev_err(&pdev->dev, "Failed to request irq: %d\n", ret);
2357+ goto err_iounmap;
2358+ }
2359+
2360+ udc_disable(jz4740_udc);
2361+ udc_reinit(jz4740_udc);
2362+
2363+ return 0;
2364+
2365+err_iounmap:
2366+ iounmap(jz4740_udc->base);
2367+err_release_mem_region:
2368+ release_mem_region(jz4740_udc->mem->start, resource_size(jz4740_udc->mem));
2369+err_clk_put:
2370+ clk_put(jz4740_udc->clk);
2371+err_device_unregister:
2372+ device_unregister(&jz4740_udc->gadget.dev);
2373+ platform_set_drvdata(pdev, NULL);
2374+
2375+ return ret;
2376+}
2377+
2378+static int __devexit jz4740_udc_remove(struct platform_device *pdev)
2379+{
2380+ struct jz4740_udc *dev = platform_get_drvdata(pdev);
2381+
2382+ if (dev->driver)
2383+ return -EBUSY;
2384+
2385+ udc_disable(dev);
2386+
2387+ free_irq(dev->irq, dev);
2388+ iounmap(dev->base);
2389+ release_mem_region(dev->mem->start, resource_size(dev->mem));
2390+ clk_put(dev->clk);
2391+
2392+ platform_set_drvdata(pdev, NULL);
2393+ device_unregister(&dev->gadget.dev);
2394+
2395+ return 0;
2396+}
2397+
2398+#ifdef CONFIG_PM
2399+
2400+static int jz4740_udc_suspend(struct device *dev)
2401+{
2402+ struct jz4740_udc *jz4740_udc = dev_get_drvdata(dev);
2403+
2404+ if (jz4740_udc->state == UDC_STATE_ENABLE)
2405+ udc_disable(jz4740_udc);
2406+
2407+ return 0;
2408+}
2409+
2410+static int jz4740_udc_resume(struct device *dev)
2411+{
2412+ struct jz4740_udc *jz4740_udc = dev_get_drvdata(dev);
2413+
2414+ if (jz4740_udc->state == UDC_STATE_ENABLE)
2415+ udc_enable(jz4740_udc);
2416+
2417+ return 0;
2418+}
2419+
2420+static const struct dev_pm_ops jz4740_udc_pm_ops = {
2421+ .suspend = jz4740_udc_suspend,
2422+ .resume = jz4740_udc_resume,
2423+};
2424+
2425+#define JZ4740_UDC_PM_OPS (&jz4740_udc_pm_ops)
2426+
2427+#else
2428+#define JZ4740_UDC_PM_OPS NULL
2429+#endif
2430+
2431+static struct platform_driver udc_driver = {
2432+ .probe = jz4740_udc_probe,
2433+ .remove = __devexit_p(jz4740_udc_remove),
2434+ .driver = {
2435+ .name = "jz-udc",
2436+ .owner = THIS_MODULE,
2437+ .pm = JZ4740_UDC_PM_OPS,
2438+ },
2439+};
2440+
2441+/*-------------------------------------------------------------------------*/
2442+
2443+static int __init udc_init (void)
2444+{
2445+ return platform_driver_register(&udc_driver);
2446+}
2447+module_init(udc_init);
2448+
2449+static void __exit udc_exit (void)
2450+{
2451+ platform_driver_unregister(&udc_driver);
2452+}
2453+module_exit(udc_exit);
2454+
2455+MODULE_DESCRIPTION("JZ4740 USB Device Controller");
2456+MODULE_AUTHOR("Wei Jianli <jlwei@ingenic.cn>");
2457+MODULE_LICENSE("GPL");
2458diff --git a/drivers/usb/gadget/jz4740_udc.h b/drivers/usb/gadget/jz4740_udc.h
2459new file mode 100644
2460index 0000000..53fd1da
2461--- /dev/null
2462@@ -0,0 +1,101 @@
2463+/*
2464+ * linux/drivers/usb/gadget/jz4740_udc.h
2465+ *
2466+ * Ingenic JZ4740 on-chip high speed USB device controller
2467+ *
2468+ * Copyright (C) 2006 Ingenic Semiconductor Inc.
2469+ * Author: <jlwei@ingenic.cn>
2470+ *
2471+ * This program is free software; you can redistribute it and/or modify
2472+ * it under the terms of the GNU General Public License as published by
2473+ * the Free Software Foundation; either version 2 of the License, or
2474+ * (at your option) any later version.
2475+ */
2476+
2477+#ifndef __USB_GADGET_JZ4740_H__
2478+#define __USB_GADGET_JZ4740_H__
2479+
2480+/*-------------------------------------------------------------------------*/
2481+
2482+// Max packet size
2483+#define EP0_MAXPACKETSIZE 64
2484+#define EPBULK_MAXPACKETSIZE 512
2485+#define EPINTR_MAXPACKETSIZE 64
2486+
2487+#define UDC_MAX_ENDPOINTS 4
2488+
2489+/*-------------------------------------------------------------------------*/
2490+
2491+enum ep_type {
2492+ ep_control, ep_bulk_in, ep_bulk_out, ep_interrupt
2493+};
2494+
2495+struct jz4740_ep {
2496+ struct usb_ep ep;
2497+ struct jz4740_udc *dev;
2498+
2499+ const struct usb_endpoint_descriptor *desc;
2500+
2501+ uint8_t stopped;
2502+ uint8_t bEndpointAddress;
2503+ uint8_t bmAttributes;
2504+
2505+ enum ep_type type;
2506+ size_t fifo;
2507+ uint32_t csr;
2508+
2509+ uint32_t reg_addr;
2510+ struct list_head queue;
2511+};
2512+
2513+struct jz4740_request {
2514+ struct usb_request req;
2515+ struct list_head queue;
2516+};
2517+
2518+enum ep0state {
2519+ WAIT_FOR_SETUP, /* between STATUS ack and SETUP report */
2520+ DATA_STATE_XMIT, /* data tx stage */
2521+ DATA_STATE_NEED_ZLP, /* data tx zlp stage */
2522+ WAIT_FOR_OUT_STATUS, /* status stages */
2523+ DATA_STATE_RECV, /* data rx stage */
2524+};
2525+
2526+/* For function binding with UDC Disable - Added by River */
2527+typedef enum {
2528+ UDC_STATE_ENABLE = 0,
2529+ UDC_STATE_DISABLE,
2530+}udc_state_t;
2531+
2532+struct jz4740_udc {
2533+ struct usb_gadget gadget;
2534+ struct usb_gadget_driver *driver;
2535+ struct device *dev;
2536+ spinlock_t lock;
2537+ unsigned long lock_flags;
2538+
2539+ enum ep0state ep0state;
2540+ struct jz4740_ep ep[UDC_MAX_ENDPOINTS];
2541+
2542+ udc_state_t state;
2543+
2544+ struct resource *mem;
2545+ void __iomem *base;
2546+ int irq;
2547+
2548+ struct clk *clk;
2549+};
2550+
2551+#define ep_maxpacket(EP) ((EP)->ep.maxpacket)
2552+
2553+static inline bool ep_is_in(const struct jz4740_ep *ep)
2554+{
2555+ return (ep->bEndpointAddress & USB_DIR_IN) == USB_DIR_IN;
2556+}
2557+
2558+static inline uint8_t ep_index(const struct jz4740_ep *ep)
2559+{
2560+ return ep->bEndpointAddress & 0xf;
2561+}
2562+
2563+#endif /* __USB_GADGET_JZ4740_H__ */
2564--
25651.7.4.1
2566
target/linux/xburst/patches-3.1/0014-Framebuffer-notifier-Call-notifier-callbacks-prior-t.patch
1From adf29db8bcc9f98b88c7d0faf1b9eeb68111c491 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Sat, 24 Apr 2010 12:23:28 +0200
4Subject: [PATCH 14/24] Framebuffer notifier: Call notifier callbacks prior to blanking the screen
5
6---
7 drivers/video/fbmem.c | 8 ++++++--
8 1 files changed, 6 insertions(+), 2 deletions(-)
9
10diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c
11index 5aac00e..b1beaa7 100644
12--- a/drivers/video/fbmem.c
13@@ -1032,12 +1032,12 @@ fb_set_var(struct fb_info *info, struct fb_var_screeninfo *var)
14 int
15 fb_blank(struct fb_info *info, int blank)
16 {
17- int ret = -EINVAL;
18+ int ret = 0;
19
20      if (blank > FB_BLANK_POWERDOWN)
21          blank = FB_BLANK_POWERDOWN;
22
23- if (info->fbops->fb_blank)
24+ if (info->fbops->fb_blank && blank == FB_BLANK_UNBLANK)
25          ret = info->fbops->fb_blank(blank, info);
26
27      if (!ret) {
28@@ -1048,6 +1048,10 @@ fb_blank(struct fb_info *info, int blank)
29         fb_notifier_call_chain(FB_EVENT_BLANK, &event);
30     }
31
32+ if (info->fbops->fb_blank && blank != FB_BLANK_UNBLANK)
33+ ret = info->fbops->fb_blank(blank, info);
34+
35+
36      return ret;
37 }
38
39--
401.7.4.1
41
target/linux/xburst/patches-3.1/0015-500-modifier-keys.patch.patch
1From 859a0dcb70eb137149992304659f080a9547d8ad Mon Sep 17 00:00:00 2001
2From: Xiangfu Liu <xiangfu@macbook.(none)>
3Date: Fri, 19 Aug 2011 15:40:08 +0800
4Subject: [PATCH 15/24] 500-modifier-keys.patch
5
6---
7 drivers/tty/vt/defkeymap.c_shipped | 326 +++++++++++++++++++++++++++---------
8 drivers/tty/vt/defkeymap.map | 88 +++++++---
9 2 files changed, 305 insertions(+), 109 deletions(-)
10
11diff --git a/drivers/tty/vt/defkeymap.c_shipped b/drivers/tty/vt/defkeymap.c_shipped
12index d2208dfe..41ea840 100644
13--- a/drivers/tty/vt/defkeymap.c_shipped
14@@ -9,10 +9,10 @@ u_short plain_map[NR_KEYS] = {
15     0xf200, 0xf01b, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035, 0xf036,
16     0xf037, 0xf038, 0xf039, 0xf030, 0xf02d, 0xf03d, 0xf07f, 0xf009,
17     0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
18- 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf702, 0xfb61, 0xfb73,
19+ 0xfb6f, 0xfb70, 0xf05b, 0xf05d, 0xf201, 0xf706, 0xfb61, 0xfb73,
20     0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf03b,
21     0xf027, 0xf060, 0xf700, 0xf05c, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
22- 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf700, 0xf30c,
23+ 0xfb62, 0xfb6e, 0xfb6d, 0xf02c, 0xf02e, 0xf02f, 0xf701, 0xf30c,
24     0xf703, 0xf020, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
25     0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf209, 0xf307,
26     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
27@@ -20,56 +20,104 @@ u_short plain_map[NR_KEYS] = {
28     0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
29     0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
30     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
31- 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
32+ 0xf11a, 0xf10c, 0xf10b, 0xf10a, 0xf11c, 0xf110, 0xf311, 0xf11d,
33+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
34+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
35+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
36+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
37+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
38+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
39+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
40+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
41+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
42+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
43+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
44+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
45+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
46+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
47+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
48+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
49     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
50 };
51
52-u_short shift_map[NR_KEYS] = {
53+static u_short shift_map[NR_KEYS] = {
54     0xf200, 0xf01b, 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e,
55     0xf026, 0xf02a, 0xf028, 0xf029, 0xf05f, 0xf02b, 0xf07f, 0xf009,
56     0xfb51, 0xfb57, 0xfb45, 0xfb52, 0xfb54, 0xfb59, 0xfb55, 0xfb49,
57- 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf702, 0xfb41, 0xfb53,
58+ 0xfb4f, 0xfb50, 0xf07b, 0xf07d, 0xf201, 0xf706, 0xfb41, 0xfb53,
59     0xfb44, 0xfb46, 0xfb47, 0xfb48, 0xfb4a, 0xfb4b, 0xfb4c, 0xf03a,
60     0xf022, 0xf07e, 0xf700, 0xf07c, 0xfb5a, 0xfb58, 0xfb43, 0xfb56,
61- 0xfb42, 0xfb4e, 0xfb4d, 0xf03c, 0xf03e, 0xf03f, 0xf700, 0xf30c,
62+ 0xfb42, 0xfb4e, 0xfb4d, 0xf03b, 0xf03a, 0xf03f, 0xf701, 0xf30c,
63     0xf703, 0xf020, 0xf207, 0xf10a, 0xf10b, 0xf10c, 0xf10d, 0xf10e,
64     0xf10f, 0xf110, 0xf111, 0xf112, 0xf113, 0xf213, 0xf203, 0xf307,
65     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
66- 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf10a,
67- 0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
68- 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
69+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf03e, 0xf20b,
70+ 0xf20a, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
71+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
72     0xf20b, 0xf601, 0xf602, 0xf117, 0xf600, 0xf20a, 0xf115, 0xf116,
73- 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
74+ 0xf11a, 0xf10c, 0xf20a, 0xf20b, 0xf11c, 0xf110, 0xf311, 0xf11d,
75+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
76+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
77+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
78+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
79+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
80+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
81+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
82+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
83+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
84+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
85+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
86+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
87+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
88+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
89+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
90+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
91     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
92 };
93
94-u_short altgr_map[NR_KEYS] = {
95+static u_short altgr_map[NR_KEYS] = {
96     0xf200, 0xf200, 0xf200, 0xf040, 0xf200, 0xf024, 0xf200, 0xf200,
97- 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf200, 0xf200, 0xf200,
98- 0xfb71, 0xfb77, 0xf918, 0xfb72, 0xfb74, 0xfb79, 0xfb75, 0xfb69,
99- 0xfb6f, 0xfb70, 0xf200, 0xf07e, 0xf201, 0xf702, 0xf914, 0xfb73,
100- 0xf917, 0xf919, 0xfb67, 0xfb68, 0xfb6a, 0xfb6b, 0xfb6c, 0xf200,
101- 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xf916, 0xfb76,
102- 0xf915, 0xfb6e, 0xfb6d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
103- 0xf703, 0xf200, 0xf207, 0xf50c, 0xf50d, 0xf50e, 0xf50f, 0xf510,
104- 0xf511, 0xf512, 0xf513, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
105+ 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf05c, 0xf07e, 0xf116, 0xf200,
106+ 0xf021, 0xf040, 0xf023, 0xf024, 0xf025, 0xf05e, 0xf026, 0xf02a,
107+ 0xf028, 0xf029, 0xf200, 0xf07e, 0xf201, 0xf706, 0xf0b0, 0xf0a8,
108+ 0xf0a4, 0xf02d, 0xf05f, 0xf07b, 0xf05b, 0xf05d, 0xf07d, 0xf200,
109+ 0xf200, 0xf200, 0xf700, 0xf200, 0xf039, 0xf030, 0xf916, 0xfb76,
110+ 0xf915, 0xf03c, 0xf03e, 0xf027, 0xf022, 0xf200, 0xf701, 0xf30c,
111+ 0xf703, 0xf200, 0xf207, 0xf031, 0xf032, 0xf033, 0xf034, 0xf035,
112+ 0xf036, 0xf037, 0xf038, 0xf514, 0xf515, 0xf208, 0xf202, 0xf911,
113     0xf912, 0xf913, 0xf30b, 0xf90e, 0xf90f, 0xf910, 0xf30a, 0xf90b,
114     0xf90c, 0xf90d, 0xf90a, 0xf310, 0xf206, 0xf200, 0xf07c, 0xf516,
115     0xf517, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
116- 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
117+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
118     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
119- 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
120+ 0xf11a, 0xf10c, 0xf517, 0xf516, 0xf11c, 0xf110, 0xf311, 0xf11d,
121+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
122+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
123+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
124+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
125+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
126+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
127+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
128+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
129+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
130+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
131+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
132+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
133+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
134+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
135+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
136+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
137     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
138 };
139
140-u_short ctrl_map[NR_KEYS] = {
141+static u_short ctrl_map[NR_KEYS] = {
142     0xf200, 0xf200, 0xf200, 0xf000, 0xf01b, 0xf01c, 0xf01d, 0xf01e,
143- 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf008, 0xf200,
144+ 0xf01f, 0xf07f, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
145     0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
146- 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf702, 0xf001, 0xf013,
147+ 0xf00f, 0xf010, 0xf01b, 0xf01d, 0xf201, 0xf706, 0xf001, 0xf013,
148     0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
149     0xf007, 0xf000, 0xf700, 0xf01c, 0xf01a, 0xf018, 0xf003, 0xf016,
150- 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf700, 0xf30c,
151+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf20e, 0xf07f, 0xf701, 0xf30c,
152     0xf703, 0xf000, 0xf207, 0xf100, 0xf101, 0xf102, 0xf103, 0xf104,
153     0xf105, 0xf106, 0xf107, 0xf108, 0xf109, 0xf208, 0xf204, 0xf307,
154     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
155@@ -77,37 +125,69 @@ u_short ctrl_map[NR_KEYS] = {
156     0xf10b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
157     0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
158     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
159- 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
160+ 0xf11a, 0xf10c, 0xf10b, 0xf10a, 0xf11c, 0xf110, 0xf311, 0xf11d,
161+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
162+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
163+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
164+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
165+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
166+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
167+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
168+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
169+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
170+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
171+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
172+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
173+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
174+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
175+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
176+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
177     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
178 };
179
180-u_short shift_ctrl_map[NR_KEYS] = {
181+static u_short shift_ctrl_map[NR_KEYS] = {
182     0xf200, 0xf200, 0xf200, 0xf000, 0xf200, 0xf200, 0xf200, 0xf200,
183     0xf200, 0xf200, 0xf200, 0xf200, 0xf01f, 0xf200, 0xf200, 0xf200,
184     0xf011, 0xf017, 0xf005, 0xf012, 0xf014, 0xf019, 0xf015, 0xf009,
185- 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf702, 0xf001, 0xf013,
186+ 0xf00f, 0xf010, 0xf200, 0xf200, 0xf201, 0xf706, 0xf001, 0xf013,
187     0xf004, 0xf006, 0xf007, 0xf008, 0xf00a, 0xf00b, 0xf00c, 0xf200,
188     0xf200, 0xf200, 0xf700, 0xf200, 0xf01a, 0xf018, 0xf003, 0xf016,
189- 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
190+ 0xf002, 0xf00e, 0xf00d, 0xf200, 0xf200, 0xf200, 0xf701, 0xf30c,
191     0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
192     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
193     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
194     0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
195     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
196- 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
197+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
198     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
199- 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
200+ 0xf11a, 0xf10c, 0xf200, 0xf200, 0xf11c, 0xf110, 0xf311, 0xf11d,
201+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
202+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
203+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
204+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
205+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
206+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
207+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
208+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
209+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
210+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
211+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
212+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
213+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
214+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
215+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
216+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
217     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
218 };
219
220-u_short alt_map[NR_KEYS] = {
221+static u_short alt_map[NR_KEYS] = {
222     0xf200, 0xf81b, 0xf831, 0xf832, 0xf833, 0xf834, 0xf835, 0xf836,
223     0xf837, 0xf838, 0xf839, 0xf830, 0xf82d, 0xf83d, 0xf87f, 0xf809,
224     0xf871, 0xf877, 0xf865, 0xf872, 0xf874, 0xf879, 0xf875, 0xf869,
225- 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf702, 0xf861, 0xf873,
226+ 0xf86f, 0xf870, 0xf85b, 0xf85d, 0xf80d, 0xf706, 0xf861, 0xf873,
227     0xf864, 0xf866, 0xf867, 0xf868, 0xf86a, 0xf86b, 0xf86c, 0xf83b,
228     0xf827, 0xf860, 0xf700, 0xf85c, 0xf87a, 0xf878, 0xf863, 0xf876,
229- 0xf862, 0xf86e, 0xf86d, 0xf82c, 0xf82e, 0xf82f, 0xf700, 0xf30c,
230+ 0xf862, 0xf86e, 0xf86d, 0xf200, 0xf200, 0xf82f, 0xf701, 0xf30c,
231     0xf703, 0xf820, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
232     0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf209, 0xf907,
233     0xf908, 0xf909, 0xf30b, 0xf904, 0xf905, 0xf906, 0xf30a, 0xf901,
234@@ -115,37 +195,117 @@ u_short alt_map[NR_KEYS] = {
235     0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
236     0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
237     0xf118, 0xf210, 0xf211, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
238- 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
239+ 0xf11a, 0xf10c, 0xf50b, 0xf50a, 0xf11c, 0xf110, 0xf311, 0xf11d,
240+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
241+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
242+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
243+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
244+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
245+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
246+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
247+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
248+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
249+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
250+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
251+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
252+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
253+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
254+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
255+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
256     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
257 };
258
259-u_short ctrl_alt_map[NR_KEYS] = {
260+static u_short ctrl_alt_map[NR_KEYS] = {
261     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
262     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
263     0xf811, 0xf817, 0xf805, 0xf812, 0xf814, 0xf819, 0xf815, 0xf809,
264- 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf702, 0xf801, 0xf813,
265+ 0xf80f, 0xf810, 0xf200, 0xf200, 0xf201, 0xf706, 0xf801, 0xf813,
266     0xf804, 0xf806, 0xf807, 0xf808, 0xf80a, 0xf80b, 0xf80c, 0xf200,
267     0xf200, 0xf200, 0xf700, 0xf200, 0xf81a, 0xf818, 0xf803, 0xf816,
268- 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf700, 0xf30c,
269+ 0xf802, 0xf80e, 0xf80d, 0xf200, 0xf200, 0xf200, 0xf701, 0xf30c,
270     0xf703, 0xf200, 0xf207, 0xf500, 0xf501, 0xf502, 0xf503, 0xf504,
271     0xf505, 0xf506, 0xf507, 0xf508, 0xf509, 0xf208, 0xf200, 0xf307,
272     0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
273     0xf302, 0xf303, 0xf300, 0xf20c, 0xf206, 0xf200, 0xf200, 0xf50a,
274     0xf50b, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
275- 0xf30e, 0xf702, 0xf30d, 0xf200, 0xf701, 0xf205, 0xf114, 0xf603,
276+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
277     0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf20c,
278- 0xf11a, 0xf10c, 0xf10d, 0xf11b, 0xf11c, 0xf110, 0xf311, 0xf11d,
279+ 0xf11a, 0xf10c, 0xf50b, 0xf50a, 0xf11c, 0xf110, 0xf311, 0xf11d,
280+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
281+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
282+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
283+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
284+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
285+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
286+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
287+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
288+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
289+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
290+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
291+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
292+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
293+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
294+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
295+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
296+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
297+};
298+
299+static u_short ctl_map[NR_KEYS] = {
300+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
301+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf033, 0xf200, 0xf200,
302+ 0xfb71, 0xfb77, 0xfb65, 0xfb72, 0xfb74, 0xfb79, 0xf037, 0xf038,
303+ 0xf039, 0xfb70, 0xf200, 0xf200, 0xf201, 0xf706, 0xfb61, 0xfb73,
304+ 0xfb64, 0xfb66, 0xfb67, 0xfb68, 0xf034, 0xf035, 0xf036, 0xf200,
305+ 0xf200, 0xf200, 0xf700, 0xf200, 0xfb7a, 0xfb78, 0xfb63, 0xfb76,
306+ 0xfb62, 0xf031, 0xf032, 0xf200, 0xf200, 0xf030, 0xf701, 0xf30c,
307+ 0xf703, 0xf200, 0xf207, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
308+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf208, 0xf200, 0xf307,
309+ 0xf308, 0xf309, 0xf30b, 0xf304, 0xf305, 0xf306, 0xf30a, 0xf301,
310+ 0xf302, 0xf303, 0xf300, 0xf310, 0xf206, 0xf200, 0xf200, 0xf200,
311+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
312+ 0xf30e, 0xf702, 0xf30d, 0xf01c, 0xf701, 0xf205, 0xf114, 0xf603,
313+ 0xf118, 0xf601, 0xf602, 0xf117, 0xf600, 0xf119, 0xf115, 0xf116,
314+ 0xf11a, 0xf10c, 0xf200, 0xf200, 0xf11c, 0xf110, 0xf311, 0xf11d,
315+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
316+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
317+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
318+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
319+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
320+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
321+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
322+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
323+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
324+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
325+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
326+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
327+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
328+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
329+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
330+ 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
331     0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200, 0xf200,
332 };
333
334 ushort *key_maps[MAX_NR_KEYMAPS] = {
335- plain_map, shift_map, altgr_map, NULL,
336- ctrl_map, shift_ctrl_map, NULL, NULL,
337- alt_map, NULL, NULL, NULL,
338- ctrl_alt_map, NULL
339+ plain_map, shift_map, altgr_map, 0,
340+ ctrl_map, shift_ctrl_map, 0, 0,
341+ alt_map, 0, 0, 0,
342+ ctrl_alt_map, 0, 0, 0,
343+ 0, 0, 0, 0,
344+ 0, 0, 0, 0,
345+ 0, 0, 0, 0,
346+ 0, 0, 0, 0,
347+ 0, 0, 0, 0,
348+ 0, 0, 0, 0,
349+ 0, 0, 0, 0,
350+ 0, 0, 0, 0,
351+ 0, 0, 0, 0,
352+ 0, 0, 0, 0,
353+ 0, 0, 0, 0,
354+ 0, 0, 0, 0,
355+ ctl_map, 0
356 };
357
358-unsigned int keymap_count = 7;
359+unsigned int keymap_count = 8;
360
361 /*
362  * Philosophy: most people do not define more strings, but they who do
363@@ -216,47 +376,47 @@ char *func_table[MAX_NR_FUNC] = {
364     func_buf + 135,
365     func_buf + 140,
366     func_buf + 145,
367- NULL,
368- NULL,
369+ 0,
370+ 0,
371     func_buf + 149,
372- NULL,
373+ 0,
374 };
375
376-struct kbdiacruc accent_table[MAX_DIACR] = {
377- {'`', 'A', 0300}, {'`', 'a', 0340},
378- {'\'', 'A', 0301}, {'\'', 'a', 0341},
379- {'^', 'A', 0302}, {'^', 'a', 0342},
380- {'~', 'A', 0303}, {'~', 'a', 0343},
381- {'"', 'A', 0304}, {'"', 'a', 0344},
382- {'O', 'A', 0305}, {'o', 'a', 0345},
383- {'0', 'A', 0305}, {'0', 'a', 0345},
384- {'A', 'A', 0305}, {'a', 'a', 0345},
385- {'A', 'E', 0306}, {'a', 'e', 0346},
386- {',', 'C', 0307}, {',', 'c', 0347},
387- {'`', 'E', 0310}, {'`', 'e', 0350},
388- {'\'', 'E', 0311}, {'\'', 'e', 0351},
389- {'^', 'E', 0312}, {'^', 'e', 0352},
390- {'"', 'E', 0313}, {'"', 'e', 0353},
391- {'`', 'I', 0314}, {'`', 'i', 0354},
392- {'\'', 'I', 0315}, {'\'', 'i', 0355},
393- {'^', 'I', 0316}, {'^', 'i', 0356},
394- {'"', 'I', 0317}, {'"', 'i', 0357},
395- {'-', 'D', 0320}, {'-', 'd', 0360},
396- {'~', 'N', 0321}, {'~', 'n', 0361},
397- {'`', 'O', 0322}, {'`', 'o', 0362},
398- {'\'', 'O', 0323}, {'\'', 'o', 0363},
399- {'^', 'O', 0324}, {'^', 'o', 0364},
400- {'~', 'O', 0325}, {'~', 'o', 0365},
401- {'"', 'O', 0326}, {'"', 'o', 0366},
402- {'/', 'O', 0330}, {'/', 'o', 0370},
403- {'`', 'U', 0331}, {'`', 'u', 0371},
404- {'\'', 'U', 0332}, {'\'', 'u', 0372},
405- {'^', 'U', 0333}, {'^', 'u', 0373},
406- {'"', 'U', 0334}, {'"', 'u', 0374},
407- {'\'', 'Y', 0335}, {'\'', 'y', 0375},
408- {'T', 'H', 0336}, {'t', 'h', 0376},
409- {'s', 's', 0337}, {'"', 'y', 0377},
410- {'s', 'z', 0337}, {'i', 'j', 0377},
411+struct kbdiacr accent_table[MAX_DIACR] = {
412+ {'`', 'A', '\300'}, {'`', 'a', '\340'},
413+ {'\'', 'A', '\301'}, {'\'', 'a', '\341'},
414+ {'^', 'A', '\302'}, {'^', 'a', '\342'},
415+ {'~', 'A', '\303'}, {'~', 'a', '\343'},
416+ {'"', 'A', '\304'}, {'"', 'a', '\344'},
417+ {'O', 'A', '\305'}, {'o', 'a', '\345'},
418+ {'0', 'A', '\305'}, {'0', 'a', '\345'},
419+ {'A', 'A', '\305'}, {'a', 'a', '\345'},
420+ {'A', 'E', '\306'}, {'a', 'e', '\346'},
421+ {',', 'C', '\307'}, {',', 'c', '\347'},
422+ {'`', 'E', '\310'}, {'`', 'e', '\350'},
423+ {'\'', 'E', '\311'}, {'\'', 'e', '\351'},
424+ {'^', 'E', '\312'}, {'^', 'e', '\352'},
425+ {'"', 'E', '\313'}, {'"', 'e', '\353'},
426+ {'`', 'I', '\314'}, {'`', 'i', '\354'},
427+ {'\'', 'I', '\315'}, {'\'', 'i', '\355'},
428+ {'^', 'I', '\316'}, {'^', 'i', '\356'},
429+ {'"', 'I', '\317'}, {'"', 'i', '\357'},
430+ {'-', 'D', '\320'}, {'-', 'd', '\360'},
431+ {'~', 'N', '\321'}, {'~', 'n', '\361'},
432+ {'`', 'O', '\322'}, {'`', 'o', '\362'},
433+ {'\'', 'O', '\323'}, {'\'', 'o', '\363'},
434+ {'^', 'O', '\324'}, {'^', 'o', '\364'},
435+ {'~', 'O', '\325'}, {'~', 'o', '\365'},
436+ {'"', 'O', '\326'}, {'"', 'o', '\366'},
437+ {'/', 'O', '\330'}, {'/', 'o', '\370'},
438+ {'`', 'U', '\331'}, {'`', 'u', '\371'},
439+ {'\'', 'U', '\332'}, {'\'', 'u', '\372'},
440+ {'^', 'U', '\333'}, {'^', 'u', '\373'},
441+ {'"', 'U', '\334'}, {'"', 'u', '\374'},
442+ {'\'', 'Y', '\335'}, {'\'', 'y', '\375'},
443+ {'T', 'H', '\336'}, {'t', 'h', '\376'},
444+ {'s', 's', '\337'}, {'"', 'y', '\377'},
445+ {'s', 'z', '\337'}, {'i', 'j', '\377'},
446 };
447
448 unsigned int accent_table_size = 68;
449diff --git a/drivers/tty/vt/defkeymap.map b/drivers/tty/vt/defkeymap.map
450index 50b30ca..732f395 100644
451--- a/drivers/tty/vt/defkeymap.map
452@@ -1,5 +1,5 @@
453 # Default kernel keymap. This uses 7 modifier combinations.
454-keymaps 0-2,4-5,8,12
455+keymaps 0-2,4-5,8,12,64
456 # Change the above line into
457 # keymaps 0-2,4-6,8,12
458 # in case you want the entries
459@@ -45,24 +45,38 @@ keycode 12 = minus underscore backslash
460     control keycode 12 = Control_underscore
461     shift control keycode 12 = Control_underscore
462     alt keycode 12 = Meta_minus
463-keycode 13 = equal plus
464+keycode 13 = equal plus
465     alt keycode 13 = Meta_equal
466+ altgr keycode 13 = asciitilde
467+ ctrll keycode 13 = three
468 keycode 14 = Delete Delete
469- control keycode 14 = BackSpace
470+ altgr keycode 14 = Remove
471     alt keycode 14 = Meta_Delete
472 keycode 15 = Tab Tab
473     alt keycode 15 = Meta_Tab
474 keycode 16 = q
475+ altgr keycode 16 = exclam
476 keycode 17 = w
477+ altgr keycode 17 = at
478 keycode 18 = e
479- altgr keycode 18 = Hex_E
480+ altgr keycode 18 = numbersign
481 keycode 19 = r
482+ altgr keycode 19 = dollar
483 keycode 20 = t
484+ altgr keycode 20 = percent
485 keycode 21 = y
486+ altgr keycode 21 = asciicircum
487 keycode 22 = u
488+ altgr keycode 22 = ampersand
489+ ctrll keycode 22 = seven
490 keycode 23 = i
491+ altgr keycode 23 = asterisk
492+ ctrll keycode 23 = eight
493 keycode 24 = o
494+ altgr keycode 24 = parenleft
495+ ctrll keycode 24 = nine
496 keycode 25 = p
497+ altgr keycode 25 = parenright
498 keycode 26 = bracketleft braceleft
499     control keycode 26 = Escape
500     alt keycode 26 = Meta_bracketleft
501@@ -71,19 +85,28 @@ keycode 27 = bracketright braceright asciitilde
502     alt keycode 27 = Meta_bracketright
503 keycode 28 = Return
504     alt keycode 28 = Meta_Control_m
505-keycode 29 = Control
506+keycode 29 = CtrlL
507 keycode 30 = a
508- altgr keycode 30 = Hex_A
509+ altgr keycode 30 = U+00B0
510 keycode 31 = s
511+ altgr keycode 31 = U+00A8
512 keycode 32 = d
513- altgr keycode 32 = Hex_D
514+ altgr keycode 32 = U+20AC
515 keycode 33 = f
516- altgr keycode 33 = Hex_F
517+ altgr keycode 33 = minus
518 keycode 34 = g
519+ altgr keycode 34 = underscore
520 keycode 35 = h
521+ altgr keycode 35 = braceleft
522 keycode 36 = j
523+ altgr keycode 36 = bracketleft
524+ ctrll keycode 36 = four
525 keycode 37 = k
526+ altgr keycode 37 = bracketright
527+ ctrll keycode 37 = five
528 keycode 38 = l
529+ altgr keycode 38 = braceright
530+ ctrll keycode 38 = six
531 keycode 39 = semicolon colon
532     alt keycode 39 = Meta_semicolon
533 keycode 40 = apostrophe quotedbl
534@@ -97,58 +120,65 @@ keycode 43 = backslash bar
535     control keycode 43 = Control_backslash
536     alt keycode 43 = Meta_backslash
537 keycode 44 = z
538+ altgr keycode 44 = nine
539 keycode 45 = x
540+ altgr keycode 45 = zero
541 keycode 46 = c
542     altgr keycode 46 = Hex_C
543 keycode 47 = v
544 keycode 48 = b
545     altgr keycode 48 = Hex_B
546 keycode 49 = n
547+ altgr keycode 49 = less
548+ ctrll keycode 49 = one
549 keycode 50 = m
550-keycode 51 = comma less
551- alt keycode 51 = Meta_comma
552-keycode 52 = period greater
553+ altgr keycode 50 = greater
554+ ctrll keycode 50 = two
555+keycode 51 = comma semicolon
556+ altgr keycode 51 = apostrophe
557+keycode 52 = period colon
558     control keycode 52 = Compose
559- alt keycode 52 = Meta_period
560+ altgr keycode 52 = quotedbl
561 keycode 53 = slash question
562     control keycode 53 = Delete
563     alt keycode 53 = Meta_slash
564-keycode 54 = Shift
565+ ctrll keycode 53 = zero
566+keycode 54 = AltGr
567 keycode 55 = KP_Multiply
568 keycode 56 = Alt
569 keycode 57 = space space
570     control keycode 57 = nul
571     alt keycode 57 = Meta_space
572 keycode 58 = Caps_Lock
573-keycode 59 = F1 F11 Console_13
574+keycode 59 = F1 F11 one
575     control keycode 59 = F1
576     alt keycode 59 = Console_1
577     control alt keycode 59 = Console_1
578-keycode 60 = F2 F12 Console_14
579+keycode 60 = F2 F12 two
580     control keycode 60 = F2
581     alt keycode 60 = Console_2
582     control alt keycode 60 = Console_2
583-keycode 61 = F3 F13 Console_15
584+keycode 61 = F3 F13 three
585     control keycode 61 = F3
586     alt keycode 61 = Console_3
587     control alt keycode 61 = Console_3
588-keycode 62 = F4 F14 Console_16
589+keycode 62 = F4 F14 four
590     control keycode 62 = F4
591     alt keycode 62 = Console_4
592     control alt keycode 62 = Console_4
593-keycode 63 = F5 F15 Console_17
594+keycode 63 = F5 F15 five
595     control keycode 63 = F5
596     alt keycode 63 = Console_5
597     control alt keycode 63 = Console_5
598-keycode 64 = F6 F16 Console_18
599+keycode 64 = F6 F16 six
600     control keycode 64 = F6
601     alt keycode 64 = Console_6
602     control alt keycode 64 = Console_6
603-keycode 65 = F7 F17 Console_19
604+keycode 65 = F7 F17 seven
605     control keycode 65 = F7
606     alt keycode 65 = Console_7
607     control alt keycode 65 = Console_7
608-keycode 66 = F8 F18 Console_20
609+keycode 66 = F8 F18 eight
610     control keycode 66 = F8
611     alt keycode 66 = Console_8
612     control alt keycode 66 = Console_8
613@@ -204,11 +234,11 @@ keycode 84 = Last_Console
614 keycode 85 =
615 keycode 86 = less greater bar
616     alt keycode 86 = Meta_less
617-keycode 87 = F11 F11 Console_23
618+keycode 87 = F11 Scroll_Backward Console_23
619     control keycode 87 = F11
620     alt keycode 87 = Console_11
621     control alt keycode 87 = Console_11
622-keycode 88 = F12 F12 Console_24
623+keycode 88 = F12 Scroll_Forward Console_24
624     control keycode 88 = F12
625     alt keycode 88 = Console_12
626     control alt keycode 88 = Console_12
627@@ -220,7 +250,7 @@ keycode 93 =
628 keycode 94 =
629 keycode 95 =
630 keycode 96 = KP_Enter
631-keycode 97 = Control
632+keycode 97 = Control
633 keycode 98 = KP_Divide
634 keycode 99 = Control_backslash
635     control keycode 99 = Control_backslash
636@@ -245,8 +275,14 @@ keycode 111 = Remove
637     control alt keycode 111 = Boot
638 keycode 112 = Macro
639 keycode 113 = F13
640-keycode 114 = F14
641-keycode 115 = Help
642+keycode 114 = F12 Scroll_Forward Console_24
643+ control keycode 114 = F12
644+ alt keycode 114 = Console_12
645+ control alt keycode 114 = Console_12
646+keycode 115 = F11 Scroll_Backward Console_23
647+ control keycode 115 = F11
648+ alt keycode 115 = Console_11
649+ control alt keycode 115 = Console_11
650 keycode 116 = Do
651 keycode 117 = F17
652 keycode 118 = KP_MinPlus
653--
6541.7.4.1
655
target/linux/xburst/patches-3.1/0016-Add-n516-lpc-driver.patch
1From 1be727530a0d86e91b9efa7a0a376684370bc15a Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Wed, 12 May 2010 14:22:36 +0200
4Subject: [PATCH 16/24] Add n516 lpc driver
5
6---
7 drivers/misc/Kconfig | 8 +
8 drivers/misc/Makefile | 1 +
9 drivers/misc/n516-lpc.c | 471 +++++++++++++++++++++++++++++++++++++++++++++++
10 3 files changed, 480 insertions(+), 0 deletions(-)
11 create mode 100644 drivers/misc/n516-lpc.c
12
13diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
14index 0a4d86c..8baf052 100644
15--- a/drivers/misc/Kconfig
16@@ -498,6 +498,14 @@ config USB_SWITCH_FSA9480
17       stereo and mono audio, video, microphone and UART data to use
18       a common connector port.
19
20+config N516_LPC
21+ tristate "N516 keys & power controller"
22+ depends on I2C
23+ depends on INPUT
24+ depends on POWER_SUPPLY
25+ help
26+ N516 keyboard & power controller driver
27+
28 source "drivers/misc/c2port/Kconfig"
29 source "drivers/misc/eeprom/Kconfig"
30 source "drivers/misc/cb710/Kconfig"
31diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
32index 8f3efb6..de1861f 100644
33--- a/drivers/misc/Makefile
34@@ -47,3 +47,4 @@ obj-$(CONFIG_AB8500_PWM) += ab8500-pwm.o
35 obj-y += lis3lv02d/
36 obj-y += carma/
37 obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
38+obj-$(CONFIG_N516_LPC) += n516-lpc.o
39diff --git a/drivers/misc/n516-lpc.c b/drivers/misc/n516-lpc.c
40new file mode 100644
41index 0000000..2b7a5b3
42--- /dev/null
43@@ -0,0 +1,471 @@
44+#include <linux/module.h>
45+#include <linux/version.h>
46+#include <linux/init.h>
47+#include <linux/fs.h>
48+#include <linux/interrupt.h>
49+#include <linux/irq.h>
50+#include <linux/sched.h>
51+#include <linux/pm.h>
52+#include <linux/sysctl.h>
53+#include <linux/proc_fs.h>
54+#include <linux/delay.h>
55+#include <linux/platform_device.h>
56+#include <linux/input.h>
57+#include <linux/power_supply.h>
58+#include <linux/suspend.h>
59+
60+#include <linux/i2c.h>
61+
62+#include <asm/mach-jz4740/irq.h>
63+#include <asm/mach-jz4740/gpio.h>
64+#include <asm/mach-jz4740/board-n516.h>
65+
66+static int batt_level=0;
67+module_param(batt_level, int, 0);
68+
69+struct n516_lpc_chip {
70+ struct i2c_client *i2c_client;
71+ struct input_dev *input;
72+ unsigned int battery_level;
73+ unsigned int suspending:1, can_sleep:1;
74+};
75+
76+static struct n516_lpc_chip *the_lpc;
77+
78+struct i2c_device_id n516_lpc_i2c_ids[] = {
79+ {"LPC524", 0},
80+ {},
81+};
82+
83+MODULE_DEVICE_TABLE(i2c, n516_lpc_i2c_ids);
84+
85+static const unsigned short normal_i2c[] = I2C_ADDRS(0x54);
86+
87+static const unsigned int n516_lpc_keymap[] = {
88+ [0x01] = KEY_4,
89+ [0x02] = KEY_3,
90+ [0x03] = KEY_2,
91+ [0x04] = KEY_1,
92+ [0x05] = KEY_0,
93+ [0x07] = KEY_9,
94+ [0x08] = KEY_8,
95+ [0x09] = KEY_7,
96+ [0x0a] = KEY_6,
97+ [0x0b] = KEY_5,
98+ [0x0d] = KEY_PLAYPAUSE,
99+ [0x0e] = KEY_MENU,
100+ [0x0f] = KEY_SEARCH,
101+ [0x10] = KEY_DIRECTION,
102+ [0x11] = KEY_SPACE,
103+ [0x13] = KEY_ENTER,
104+ [0x14] = KEY_UP,
105+ [0x15] = KEY_DOWN,
106+ [0x16] = KEY_RIGHT,
107+ [0x17] = KEY_LEFT,
108+ [0x19] = KEY_PAGEDOWN,
109+ [0x1a] = KEY_PAGEUP,
110+ [0x1c] = KEY_POWER,
111+ [0x1d] = KEY_ESC,
112+ [0x1e] = KEY_SLEEP,
113+ [0x1f] = KEY_WAKEUP,
114+};
115+
116+static const unsigned int batt_charge[] = {0, 7, 20, 45, 65, 80, 100};
117+#define MAX_BAT_LEVEL 6
118+
119+static inline int n516_bat_charging(void)
120+{
121+ return !gpio_get_value(GPIO_CHARG_STAT_N);
122+}
123+
124+static int n516_bat_get_status(struct power_supply *b)
125+{
126+ if (power_supply_am_i_supplied(b)) {
127+ if (n516_bat_charging())
128+ return POWER_SUPPLY_STATUS_CHARGING;
129+ else
130+ return POWER_SUPPLY_STATUS_FULL;
131+ } else {
132+ return POWER_SUPPLY_STATUS_DISCHARGING;
133+ }
134+}
135+
136+static int n516_bat_get_charge(struct power_supply *b)
137+{
138+ return batt_charge[the_lpc->battery_level];
139+}
140+
141+static int n516_bat_get_property(struct power_supply *b,
142+ enum power_supply_property psp,
143+ union power_supply_propval *val)
144+{
145+ switch (psp) {
146+ case POWER_SUPPLY_PROP_STATUS:
147+ val->intval = n516_bat_get_status(b);
148+ break;
149+ case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
150+ val->intval = 100;
151+ break;
152+ case POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN:
153+ val->intval = 0;
154+ break;
155+ case POWER_SUPPLY_PROP_CHARGE_NOW:
156+ val->intval = n516_bat_get_charge(b);
157+ break;
158+ default:
159+ return -EINVAL;
160+ }
161+ return 0;
162+}
163+
164+static void n516_bat_power_changed(struct power_supply *p)
165+{
166+ if (power_supply_am_i_supplied(p) && !n516_bat_charging())
167+ the_lpc->battery_level = MAX_BAT_LEVEL;
168+
169+ power_supply_changed(p);
170+}
171+
172+static enum power_supply_property n516_bat_properties[] = {
173+ POWER_SUPPLY_PROP_STATUS,
174+ POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
175+ POWER_SUPPLY_PROP_CHARGE_EMPTY_DESIGN,
176+ POWER_SUPPLY_PROP_CHARGE_NOW,
177+};
178+
179+static struct power_supply n516_battery = {
180+ .name = "n516-battery",
181+ .get_property = n516_bat_get_property,
182+ .properties = n516_bat_properties,
183+ .num_properties = ARRAY_SIZE(n516_bat_properties),
184+ .external_power_changed = n516_bat_power_changed,
185+};
186+
187+static irqreturn_t n516_bat_charge_irq(int irq, void *dev)
188+{
189+ struct power_supply *psy = dev;
190+
191+ dev_dbg(psy->dev, "Battery charging IRQ\n");
192+
193+ if (power_supply_am_i_supplied(psy) && !n516_bat_charging())
194+ the_lpc->battery_level = MAX_BAT_LEVEL;
195+
196+ power_supply_changed(psy);
197+
198+ return IRQ_HANDLED;
199+}
200+
201+static int n516_lpc_send_message(struct n516_lpc_chip *chip, unsigned char val)
202+{
203+ struct i2c_client *client = chip->i2c_client;
204+ struct i2c_msg msg = {client->addr, client->flags, 1, &val};
205+ int ret = 0;
206+
207+ ret = i2c_transfer(client->adapter, &msg, 1);
208+ return ret > 0 ? 0 : ret;
209+}
210+
211+static void n516_key_event(struct n516_lpc_chip *chip, unsigned char keycode)
212+{
213+ struct i2c_client *client = chip->i2c_client;
214+ bool long_press = false;
215+
216+ if (keycode & 0x40) {
217+ keycode &= ~0x40;
218+ long_press = true;
219+ }
220+
221+ dev_dbg(&client->dev, "keycode: 0x%02x, long_press: 0x%02x\n", keycode, (unsigned int)long_press);
222+
223+ if (keycode >= ARRAY_SIZE(n516_lpc_keymap) || n516_lpc_keymap[keycode] == 0)
224+ return;
225+
226+ if (long_press)
227+ input_report_key(chip->input, KEY_LEFTALT, 1);
228+
229+ input_report_key(chip->input, n516_lpc_keymap[keycode], 1);
230+ input_sync(chip->input);
231+ input_report_key(chip->input, n516_lpc_keymap[keycode], 0);
232+
233+ if (long_press)
234+ input_report_key(chip->input, KEY_LEFTALT, 0);
235+ input_sync(chip->input);
236+}
237+
238+static void n516_battery_event(struct n516_lpc_chip *chip, unsigned char battery_level)
239+{
240+ if (battery_level != chip->battery_level) {
241+ chip->battery_level = battery_level;
242+ power_supply_changed(&n516_battery);
243+ }
244+}
245+
246+static irqreturn_t n516_lpc_irq_thread(int irq, void *devid)
247+{
248+ struct n516_lpc_chip *chip = (struct n516_lpc_chip*)devid;
249+ int ret;
250+ unsigned char raw_msg;
251+ struct i2c_client *client = chip->i2c_client;
252+ struct i2c_msg msg = {client->addr, client->flags | I2C_M_RD, 1, &raw_msg};
253+
254+ if (client->dev.power.status >= DPM_OFF)
255+ return IRQ_HANDLED;
256+
257+ ret = i2c_transfer(client->adapter, &msg, 1);
258+ if (ret != 1) {
259+ dev_dbg(&client->dev, "I2C error: %d\n", ret);
260+ return IRQ_HANDLED;
261+ }
262+
263+ dev_dbg(&client->dev, "msg: 0x%02x\n", raw_msg);
264+
265+ /* Ack wakeup event */
266+ if ((raw_msg & ~0x40) < ARRAY_SIZE(n516_lpc_keymap))
267+ n516_key_event(chip, raw_msg);
268+ else if ((raw_msg >= 0x81) && (raw_msg <= 0x87))
269+ n516_battery_event(chip, raw_msg - 0x81);
270+ else if (raw_msg == 0x7e)
271+ n516_lpc_send_message(chip, 0x00);
272+ else
273+ dev_warn(&client->dev, "Unknown message: %x\n", raw_msg);
274+
275+ if (chip->suspending)
276+ chip->can_sleep = 0;
277+
278+ return IRQ_HANDLED;
279+}
280+
281+static void n516_lpc_power_off(void)
282+{
283+ struct i2c_client *client = the_lpc->i2c_client;
284+ unsigned char val = 0x01;
285+ struct i2c_msg msg = {client->addr, client->flags, 1, &val};
286+
287+ printk("Issue LPC POWEROFF command...\n");
288+ while (1)
289+ i2c_transfer(client->adapter, &msg, 1);
290+}
291+
292+static int n516_lpc_detect(struct i2c_client *client, struct i2c_board_info *info)
293+{
294+ return 0;
295+}
296+
297+static int n516_lpc_suspend_notifier(struct notifier_block *nb,
298+ unsigned long event,
299+ void *dummy)
300+{
301+ switch(event) {
302+ case PM_SUSPEND_PREPARE:
303+ the_lpc->suspending = 1;
304+ the_lpc->can_sleep = 1;
305+ break;
306+ case PM_POST_SUSPEND:
307+ the_lpc->suspending = 0;
308+ the_lpc->can_sleep = 1;
309+ break;
310+ default:
311+ return NOTIFY_DONE;
312+ }
313+ return NOTIFY_OK;
314+}
315+
316+static struct notifier_block n516_lpc_notif_block = {
317+ .notifier_call = n516_lpc_suspend_notifier,
318+};
319+
320+static int __devinit n516_lpc_probe(struct i2c_client *client, const struct i2c_device_id *id)
321+{
322+ struct n516_lpc_chip *chip;
323+ struct input_dev *input;
324+ int ret = 0;
325+ int i;
326+
327+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
328+ if (!chip)
329+ return -ENOMEM;
330+
331+ the_lpc = chip;
332+ chip->i2c_client = client;
333+ if ((batt_level > 0) && (batt_level < ARRAY_SIZE(batt_charge)))
334+ chip->battery_level = batt_level;
335+ else
336+ chip->battery_level = 1;
337+
338+ i2c_set_clientdata(client, chip);
339+
340+ ret = gpio_request(GPIO_LPC_INT, "LPC interrupt request");
341+ if (ret) {
342+ dev_err(&client->dev, "Unable to reguest LPC INT GPIO\n");
343+ goto err_gpio_req_lpcint;
344+ }
345+
346+ ret = gpio_request(GPIO_CHARG_STAT_N, "LPC charging status");
347+ if (ret) {
348+ dev_err(&client->dev, "Unable to reguest CHARG STAT GPIO\n");
349+ goto err_gpio_req_chargstat;
350+ }
351+
352+ /* Enter normal mode */
353+ n516_lpc_send_message(chip, 0x2);
354+
355+ input = input_allocate_device();
356+ if (!input) {
357+ dev_err(&client->dev, "Unable to allocate input device\n");
358+ ret = -ENOMEM;
359+ goto err_input_alloc;
360+ }
361+
362+ chip->input = input;
363+
364+ __set_bit(EV_KEY, input->evbit);
365+
366+ for (i = 0; i < ARRAY_SIZE(n516_lpc_keymap); i++)
367+ __set_bit(n516_lpc_keymap[i], input->keybit);
368+
369+ __set_bit(KEY_LEFTALT, input->keybit);
370+
371+ input->name = "n516-keys";
372+ input->phys = "n516-keys/input0";
373+ input->dev.parent = &client->dev;
374+ input->id.bustype = BUS_I2C;
375+ input->id.vendor = 0x0001;
376+ input->id.product = 0x0001;
377+ input->id.version = 0x0100;
378+
379+ ret = input_register_device(input);
380+ if (ret < 0) {
381+ dev_err(&client->dev, "Unable to register input device\n");
382+ goto err_input_register;
383+ }
384+
385+ ret = power_supply_register(NULL, &n516_battery);
386+ if (ret) {
387+ dev_err(&client->dev, "Unable to register N516 battery\n");
388+ goto err_bat_reg;
389+ }
390+
391+ ret = request_threaded_irq(gpio_to_irq(GPIO_LPC_INT), NULL,
392+ n516_lpc_irq_thread,
393+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
394+ "lpc", chip);
395+ if (ret) {
396+ dev_err(&client->dev, "request_irq failed: %d\n", ret);
397+ goto err_request_lpc_irq;
398+ }
399+
400+ ret = request_irq(gpio_to_irq(GPIO_CHARG_STAT_N), n516_bat_charge_irq,
401+ IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
402+ "battery charging", &n516_battery);
403+ if (ret) {
404+ dev_err(&client->dev, "Unable to claim battery charging IRQ\n");
405+ goto err_request_chrg_irq;
406+ }
407+
408+ pm_power_off = n516_lpc_power_off;
409+ ret = register_pm_notifier(&n516_lpc_notif_block);
410+ if (ret) {
411+ dev_err(&client->dev, "Unable to register PM notify block\n");
412+ goto err_reg_pm_notifier;
413+ }
414+
415+ device_init_wakeup(&client->dev, 1);
416+
417+ return 0;
418+
419+ unregister_pm_notifier(&n516_lpc_notif_block);
420+err_reg_pm_notifier:
421+ free_irq(gpio_to_irq(GPIO_CHARG_STAT_N), &n516_battery);
422+err_request_chrg_irq:
423+ free_irq(gpio_to_irq(GPIO_LPC_INT), chip);
424+err_request_lpc_irq:
425+ power_supply_unregister(&n516_battery);
426+err_bat_reg:
427+ input_unregister_device(input);
428+err_input_register:
429+ input_free_device(input);
430+err_input_alloc:
431+ gpio_free(GPIO_CHARG_STAT_N);
432+err_gpio_req_chargstat:
433+ gpio_free(GPIO_LPC_INT);
434+err_gpio_req_lpcint:
435+ i2c_set_clientdata(client, NULL);
436+ kfree(chip);
437+
438+ return ret;
439+}
440+
441+static int __devexit n516_lpc_remove(struct i2c_client *client)
442+{
443+ struct n516_lpc_chip *chip = i2c_get_clientdata(client);
444+
445+ unregister_pm_notifier(&n516_lpc_notif_block);
446+ pm_power_off = NULL;
447+ free_irq(gpio_to_irq(GPIO_CHARG_STAT_N), &n516_battery);
448+ free_irq(gpio_to_irq(GPIO_LPC_INT), chip);
449+ power_supply_unregister(&n516_battery);
450+ input_unregister_device(chip->input);
451+ gpio_free(GPIO_CHARG_STAT_N);
452+ gpio_free(GPIO_LPC_INT);
453+ i2c_set_clientdata(client, NULL);
454+ kfree(chip);
455+
456+ return 0;
457+}
458+
459+#if CONFIG_PM
460+static int n516_lpc_suspend(struct i2c_client *client, pm_message_t msg)
461+{
462+ if (!the_lpc->can_sleep)
463+ return -EBUSY;
464+
465+ if (device_may_wakeup(&client->dev))
466+ enable_irq_wake(gpio_to_irq(GPIO_LPC_INT));
467+
468+ return 0;
469+}
470+
471+static int n516_lpc_resume(struct i2c_client *client)
472+{
473+ if (device_may_wakeup(&client->dev))
474+ disable_irq_wake(gpio_to_irq(GPIO_LPC_INT));
475+
476+ return 0;
477+}
478+#else
479+#define n516_lpc_suspend NULL
480+#define n516_lpc_resume NULL
481+#endif
482+
483+
484+static struct i2c_driver n516_lpc_driver = {
485+ .class = I2C_CLASS_HWMON,
486+ .driver = {
487+ .name = "n516-keys",
488+ .owner = THIS_MODULE,
489+ },
490+ .probe = n516_lpc_probe,
491+ .remove = __devexit_p(n516_lpc_remove),
492+ .detect = n516_lpc_detect,
493+ .id_table = n516_lpc_i2c_ids,
494+ .address_list = normal_i2c,
495+ .suspend = n516_lpc_suspend,
496+ .resume = n516_lpc_resume,
497+};
498+
499+static int __init n516_lpc_init(void)
500+{
501+ return i2c_add_driver(&n516_lpc_driver);
502+}
503+module_init(n516_lpc_init);
504+
505+static void __exit n516_lpc_exit(void)
506+{
507+ i2c_del_driver(&n516_lpc_driver);
508+}
509+module_exit(n516_lpc_exit);
510+
511+MODULE_AUTHOR("Yauhen Kharuzhy");
512+MODULE_LICENSE("GPL");
513+MODULE_DESCRIPTION("Keys and power controller driver for N516");
514+MODULE_ALIAS("platform:n516-keys");
515--
5161.7.4.1
517
target/linux/xburst/patches-3.1/0017-Add-n526-lpc-driver.patch
1From 2184cb0602da6ca16bab0edbc8fc55ff64c67416 Mon Sep 17 00:00:00 2001
2From: Lars-Peter Clausen <lars@metafoo.de>
3Date: Wed, 12 May 2010 14:23:43 +0200
4Subject: [PATCH 17/24] Add n526 lpc driver
5
6---
7 drivers/misc/Kconfig | 9 ++
8 drivers/misc/Makefile | 1 +
9 drivers/misc/n526-lpc.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++
10 3 files changed, 248 insertions(+), 0 deletions(-)
11 create mode 100644 drivers/misc/n526-lpc.c
12
13diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
14index 8baf052..0b47c9a 100644
15--- a/drivers/misc/Kconfig
16@@ -506,6 +506,15 @@ config N516_LPC
17     help
18       N516 keyboard & power controller driver
19
20+config N526_LPC
21+ tristate "N526 LPC934 coprocessor"
22+ depends on JZ4740_N526
23+ help
24+ If you say yes here you get support for the N526s NXP LPC934 coprocessor.
25+ It is used as a keyboard controllor and for power management.
26+
27+ If you have a N526 you probably want to say Y here.
28+
29 source "drivers/misc/c2port/Kconfig"
30 source "drivers/misc/eeprom/Kconfig"
31